Skip to content

Execution context #276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions app/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@

return [
'appName' => basename($_SERVER['argv'][0] ?? 'phpschool'),
'appName' => function (ContainerInterface $c) {
if (!isset($_SERVER['argv'][0])) {
return 'phpschool';
}

$name = basename($_SERVER['argv'][0]);

if ($name !== 'phpunit') {
return $name;
}

return 'phpschool';
},
'phpschoolGlobalDir' => sprintf('%s/.php-school', getenv('HOME')),
'currentWorkingDirectory' => function (ContainerInterface $c) {
return getcwd();
Expand Down Expand Up @@ -187,11 +200,20 @@
//Exercise Runners
RunnerManager::class => function (ContainerInterface $c) {
$manager = new RunnerManager();
$manager->addFactory(new CliRunnerFactory($c->get(EventDispatcher::class)));
$manager->addFactory(new CgiRunnerFactory($c->get(EventDispatcher::class)));
$manager->addFactory(new CliRunnerFactory($c->get(EventDispatcher::class), $c->get(\PhpSchool\PhpWorkshop\Process\ProcessFactory::class)));
$manager->addFactory(new CgiRunnerFactory($c->get(EventDispatcher::class), $c->get(\PhpSchool\PhpWorkshop\Process\ProcessFactory::class)));
$manager->addFactory(new CustomVerifyingRunnerFactory());
return $manager;
},
\PhpSchool\PhpWorkshop\Process\ProcessFactory::class => function (ContainerInterface $c) {
return new \PhpSchool\PhpWorkshop\Process\DockerProcessFactory(
$c->get('basePath'),
(new \Symfony\Component\Process\ExecutableFinder())->find('docker'),
$c->get('appName')
);

return new \PhpSchool\PhpWorkshop\Process\HostProcessFactory();
},

//commands
MenuCommand::class => function (ContainerInterface $c) {
Expand Down Expand Up @@ -249,7 +271,11 @@
InitialCodeListener::class => function (ContainerInterface $c) {
return new InitialCodeListener($c->get('currentWorkingDirectory'), $c->get(LoggerInterface::class));
},
PrepareSolutionListener::class => create(),
PrepareSolutionListener::class => function (ContainerInterface $c) {
return new PrepareSolutionListener(
$c->get(\PhpSchool\PhpWorkshop\Process\ProcessFactory::class)
);
},
CodePatchListener::class => function (ContainerInterface $c) {
return new CodePatchListener(
$c->get(CodePatcher::class),
Expand Down Expand Up @@ -454,13 +480,13 @@ function (CgiResult $result) use ($c) {
],
],
'prepare-solution' => [
'cli.verify.start' => [
'cli.verify.reference-execute.pre' => [
containerListener(PrepareSolutionListener::class),
],
'cli.run.start' => [
containerListener(PrepareSolutionListener::class),
],
'cgi.verify.start' => [
'cgi.verify.reference-execute.pre' => [
containerListener(PrepareSolutionListener::class),
],
'cgi.run.start' => [
Expand Down
12 changes: 6 additions & 6 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
parameters:
treatPhpDocTypesAsCertain: false
ignoreErrors:
-
message: '#PhpSchool\\PhpWorkshop\\ExerciseRunner\\CliRunner\:\:preserveOldArgFormat\(\) should return#'
path: src/ExerciseRunner/CliRunner.php
-
message: '#Call to an undefined method PhpParser\\Node\\Expr\|PhpParser\\Node\\Name\:\:__toString\(\)#'
path: src/Check/FunctionRequirementsCheck.php
Expand Down
6 changes: 4 additions & 2 deletions src/Check/CodeExistsCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use PhpParser\Parser;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\Failure;
use PhpSchool\PhpWorkshop\Result\ResultInterface;
Expand All @@ -37,15 +39,15 @@ public function getName(): string
* Check solution provided contains code
* Note: We don't care if it's valid code at this point
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
$noopHandler = new class implements ErrorHandler {
public function handleError(Error $error): void
{
}
};

$code = (string) file_get_contents($input->getRequiredArgument('program'));
$code = (string) file_get_contents($context->input->getRequiredArgument('program'));
$statements = $this->parser->parse($code, $noopHandler);

$empty = null === $statements || empty($statements);
Expand Down
8 changes: 5 additions & 3 deletions src/Check/CodeParseCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use PhpParser\Parser;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\Failure;
use PhpSchool\PhpWorkshop\Result\ResultInterface;
Expand Down Expand Up @@ -49,14 +51,14 @@ public function getName(): string
* @param Input $input The command line arguments passed to the command.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
$code = (string) file_get_contents($input->getRequiredArgument('program'));
$code = (string) file_get_contents($context->input->getRequiredArgument('program'));

try {
$this->parser->parse($code);
} catch (Error $e) {
return Failure::fromCheckAndCodeParseFailure($this, $e, $input->getRequiredArgument('program'));
return Failure::fromCheckAndCodeParseFailure($this, $e, $context->input->getRequiredArgument('program'));
}

return Success::fromCheck($this);
Expand Down
16 changes: 9 additions & 7 deletions src/Check/ComposerCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseCheck\ComposerExerciseCheck;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\ComposerFailure;
use PhpSchool\PhpWorkshop\Result\Failure;
Expand Down Expand Up @@ -39,26 +41,26 @@ public function getName(): string
* @return ResultInterface The result of the check.
* @noinspection SpellCheckingInspection
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
if (!$exercise instanceof ComposerExerciseCheck) {
if (!$context->exercise instanceof ComposerExerciseCheck) {
throw new InvalidArgumentException();
}

if (!file_exists(sprintf('%s/composer.json', dirname($input->getRequiredArgument('program'))))) {
if (!file_exists(sprintf('%s/composer.json', dirname($context->input->getRequiredArgument('program'))))) {
return ComposerFailure::fromCheckAndMissingFileOrFolder($this, 'composer.json');
}

if (!file_exists(sprintf('%s/composer.lock', dirname($input->getRequiredArgument('program'))))) {
if (!file_exists(sprintf('%s/composer.lock', dirname($context->input->getRequiredArgument('program'))))) {
return ComposerFailure::fromCheckAndMissingFileOrFolder($this, 'composer.lock');
}

if (!file_exists(sprintf('%s/vendor', dirname($input->getRequiredArgument('program'))))) {
if (!file_exists(sprintf('%s/vendor', dirname($context->input->getRequiredArgument('program'))))) {
return ComposerFailure::fromCheckAndMissingFileOrFolder($this, 'vendor');
}

$lockFile = new LockFileParser(sprintf('%s/composer.lock', dirname($input->getRequiredArgument('program'))));
$missingPackages = array_filter($exercise->getRequiredPackages(), function ($package) use ($lockFile) {
$lockFile = new LockFileParser(sprintf('%s/composer.lock', dirname($context->input->getRequiredArgument('program'))));
$missingPackages = array_filter($context->exercise->getRequiredPackages(), function ($package) use ($lockFile) {
return !$lockFile->hasInstalledPackage($package);
});

Expand Down
12 changes: 7 additions & 5 deletions src/Check/FileComparisonCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution;
use PhpSchool\PhpWorkshop\ExerciseCheck\FileComparisonExerciseCheck;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\Failure;
use PhpSchool\PhpWorkshop\Result\FileComparisonFailure;
Expand Down Expand Up @@ -38,17 +40,17 @@ public function getName(): string
* @param Input $input The command line arguments passed to the command.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
if (!$exercise instanceof FileComparisonExerciseCheck) {
if (!$context->exercise instanceof FileComparisonExerciseCheck) {
throw new InvalidArgumentException();
}

foreach ($exercise->getFilesToCompare() as $key => $file) {
foreach ($context->exercise->getFilesToCompare() as $key => $file) {
[$options, $file] = $this->getOptionsAndFile($key, $file);

$studentFile = Path::join(dirname($input->getRequiredArgument('program')), $file);
$referenceFile = Path::join($exercise->getSolution()->getBaseDirectory(), $file);
$studentFile = Path::join(dirname($context->input->getRequiredArgument('program')), $file);
$referenceFile = Path::join($context->referenceEnvironment->workingDirectory, $file);

if (!file_exists($referenceFile)) {
throw SolutionFileDoesNotExistException::fromExpectedFile($file);
Expand Down
8 changes: 5 additions & 3 deletions src/Check/FileExistsCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\Failure;
use PhpSchool\PhpWorkshop\Result\ResultInterface;
Expand All @@ -31,15 +33,15 @@ public function getName(): string
* @param Input $input The command line arguments passed to the command.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
if (file_exists($input->getRequiredArgument('program'))) {
if (file_exists($context->input->getRequiredArgument('program'))) {
return Success::fromCheck($this);
}

return Failure::fromCheckAndReason(
$this,
sprintf('File: "%s" does not exist', $input->getRequiredArgument('program'))
sprintf('File: "%s" does not exist', $context->input->getRequiredArgument('program'))
);
}

Expand Down
12 changes: 7 additions & 5 deletions src/Check/FunctionRequirementsCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseCheck\FunctionRequirementsExerciseCheck;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\NodeVisitor\FunctionVisitor;
use PhpSchool\PhpWorkshop\Result\Failure;
Expand Down Expand Up @@ -55,16 +57,16 @@ public function getName(): string
* @param Input $input The command line arguments passed to the command.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
if (!$exercise instanceof FunctionRequirementsExerciseCheck) {
if (!$context->exercise instanceof FunctionRequirementsExerciseCheck) {
throw new InvalidArgumentException();
}

$requiredFunctions = $exercise->getRequiredFunctions();
$bannedFunctions = $exercise->getBannedFunctions();
$requiredFunctions = $context->exercise->getRequiredFunctions();
$bannedFunctions = $context->exercise->getBannedFunctions();

$code = (string) file_get_contents($input->getRequiredArgument('program'));
$code = (string) file_get_contents($context->input->getRequiredArgument('program'));

try {
$ast = $this->parser->parse($code) ?? [];
Expand Down
6 changes: 4 additions & 2 deletions src/Check/PhpLintCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\ResultInterface;
use PhpSchool\PhpWorkshop\Result\Success;
Expand Down Expand Up @@ -34,10 +36,10 @@ public function getName(): string
* @param Input $input The command line arguments passed to the command.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
public function check(ExecutionContext $context): ResultInterface
{
$finder = new ExecutableFinder();
$process = new Process([$finder->find('php'), '-l', $input->getArgument('program')]);
$process = new Process([$finder->find('php'), '-l', $context->input->getArgument('program')]);
$process->run();

if ($process->isSuccessful()) {
Expand Down
7 changes: 4 additions & 3 deletions src/Check/SimpleCheckInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
use PhpSchool\PhpWorkshop\ExerciseRunner\Environment;
use PhpSchool\PhpWorkshop\Input\Input;
use PhpSchool\PhpWorkshop\Result\ResultInterface;

Expand Down Expand Up @@ -46,11 +48,10 @@ public function canRun(ExerciseType $exerciseType): bool;
* successful then an instance of `PhpSchool\PhpWorkshop\Result\FailureInterface`
* should be returned.
*
* @param ExerciseInterface $exercise The exercise to check against.
* @param Input $input The command line arguments passed to the command.
* @param ExecutionContext $context The current run context, containing the exercise, input and environments.
* @return ResultInterface The result of the check.
*/
public function check(ExerciseInterface $exercise, Input $input): ResultInterface;
public function check(ExecutionContext $context): ResultInterface;

/**
* Either `static::CHECK_BEFORE` | `static::CHECK_AFTER`.
Expand Down
7 changes: 4 additions & 3 deletions src/Event/CgiExecuteEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

namespace PhpSchool\PhpWorkshop\Event;

use PhpSchool\PhpWorkshop\ExerciseRunner\Context\CgiContext;
use Psr\Http\Message\RequestInterface;

/**
* An event to represent events which occur throughout the verification and running process in
* `\PhpSchool\PhpWorkshop\ExerciseRunner\CgiRunner`.
*/
class CgiExecuteEvent extends Event
class CgiExecuteEvent extends ExerciseRunnerEvent
{
/**
* @var RequestInterface
Expand All @@ -22,10 +23,10 @@ class CgiExecuteEvent extends Event
* @param RequestInterface $request The request that will be performed.
* @param array<mixed> $parameters The event parameters.
*/
public function __construct(string $name, RequestInterface $request, array $parameters = [])
public function __construct(string $name, CgiContext $context, RequestInterface $request, array $parameters = [])
{
$parameters['request'] = $request;
parent::__construct($name, $parameters);
parent::__construct($name, $context, $parameters);
$this->request = $request;
}

Expand Down
Loading
Loading