Skip to content

Commit 2ccbeae

Browse files
committed
Use context in checks
1 parent 305b327 commit 2ccbeae

18 files changed

+240
-301
lines changed

Diff for: src/Check/CodeExistsCheck.php

+6-9
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,16 @@
1111
use PhpParser\Parser;
1212
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1313
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
14+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
1415
use PhpSchool\PhpWorkshop\Input\Input;
1516
use PhpSchool\PhpWorkshop\Result\Failure;
1617
use PhpSchool\PhpWorkshop\Result\ResultInterface;
1718
use PhpSchool\PhpWorkshop\Result\Success;
1819

1920
class CodeExistsCheck implements SimpleCheckInterface
2021
{
21-
/**
22-
* @var Parser
23-
*/
24-
private $parser;
25-
26-
public function __construct(Parser $parser)
22+
public function __construct(private Parser $parser)
2723
{
28-
$this->parser = $parser;
2924
}
3025

3126
public function getName(): string
@@ -34,18 +29,20 @@ public function getName(): string
3429
}
3530

3631
/**
32+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
33+
*
3734
* Check solution provided contains code
3835
* Note: We don't care if it's valid code at this point
3936
*/
40-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
37+
public function check(ExecutionContext $context): ResultInterface
4138
{
4239
$noopHandler = new class implements ErrorHandler {
4340
public function handleError(Error $error): void
4441
{
4542
}
4643
};
4744

48-
$code = (string) file_get_contents($input->getRequiredArgument('program'));
45+
$code = (string) file_get_contents($context->getEntryPoint());
4946
$statements = $this->parser->parse($code, $noopHandler);
5047

5148
$empty = null === $statements || empty($statements);

Diff for: src/Check/CodeParseCheck.php

+6-15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpParser\Parser;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
11+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
1112
use PhpSchool\PhpWorkshop\Input\Input;
1213
use PhpSchool\PhpWorkshop\Result\Failure;
1314
use PhpSchool\PhpWorkshop\Result\ResultInterface;
@@ -19,17 +20,8 @@
1920
*/
2021
class CodeParseCheck implements SimpleCheckInterface
2122
{
22-
/**
23-
* @var Parser
24-
*/
25-
private $parser;
26-
27-
/**
28-
* @param Parser $parser
29-
*/
30-
public function __construct(Parser $parser)
23+
public function __construct(private Parser $parser)
3124
{
32-
$this->parser = $parser;
3325
}
3426

3527
/**
@@ -45,18 +37,17 @@ public function getName(): string
4537
* attempts to parse it with `nikic/php-parser`. If any exceptions are thrown
4638
* by the parser, it is treated as a failure.
4739
*
48-
* @param ExerciseInterface $exercise The exercise to check against.
49-
* @param Input $input The command line arguments passed to the command.
40+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
5041
* @return ResultInterface The result of the check.
5142
*/
52-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
43+
public function check(ExecutionContext $context): ResultInterface
5344
{
54-
$code = (string) file_get_contents($input->getRequiredArgument('program'));
45+
$code = (string) file_get_contents($context->getEntryPoint());
5546

5647
try {
5748
$this->parser->parse($code);
5849
} catch (Error $e) {
59-
return Failure::fromCheckAndCodeParseFailure($this, $e, $input->getRequiredArgument('program'));
50+
return Failure::fromCheckAndCodeParseFailure($this, $e, $context->getEntryPoint());
6051
}
6152

6253
return Success::fromCheck($this);

Diff for: src/Check/ComposerCheck.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1111
use PhpSchool\PhpWorkshop\ExerciseCheck\ComposerExerciseCheck;
12+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
1213
use PhpSchool\PhpWorkshop\Input\Input;
1314
use PhpSchool\PhpWorkshop\Result\ComposerFailure;
1415
use PhpSchool\PhpWorkshop\Result\Failure;
@@ -34,30 +35,29 @@ public function getName(): string
3435
* installed a set of required packages. If they did not a failure is returned, otherwise,
3536
* a success is returned.
3637
*
37-
* @param ExerciseInterface $exercise The exercise to check against.
38-
* @param Input $input The command line arguments passed to the command.
38+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
3939
* @return ResultInterface The result of the check.
40-
* @noinspection SpellCheckingInspection
4140
*/
42-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
41+
public function check(ExecutionContext $context): ResultInterface
4342
{
43+
$exercise = $context->getExercise();
4444
if (!$exercise instanceof ComposerExerciseCheck) {
4545
throw new InvalidArgumentException();
4646
}
4747

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

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

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

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

Diff for: src/Check/DatabaseCheck.php

+5-24
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,11 @@ class DatabaseCheck implements ListenableCheckInterface
2525
{
2626
use TemporaryDirectoryTrait;
2727

28-
/**
29-
* @var string
30-
*/
31-
private $databaseDirectory;
32-
33-
/**
34-
* @var string
35-
*/
36-
private $userDatabasePath;
37-
38-
/**
39-
* @var string
40-
*/
41-
private $solutionDatabasePath;
42-
43-
/**
44-
* @var string
45-
*/
46-
private $userDsn;
47-
48-
/**
49-
* @var string
50-
*/
51-
private $solutionDsn;
28+
private string $databaseDirectory;
29+
private string $userDatabasePath;
30+
private string $solutionDatabasePath;
31+
private string $userDsn;
32+
private string $solutionDsn;
5233

5334
/**
5435
* Setup paths and DSN's.

Diff for: src/Check/FileComparisonCheck.php

+6-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1111
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution;
1212
use PhpSchool\PhpWorkshop\ExerciseCheck\FileComparisonExerciseCheck;
13+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
1314
use PhpSchool\PhpWorkshop\Input\Input;
1415
use PhpSchool\PhpWorkshop\Result\Failure;
1516
use PhpSchool\PhpWorkshop\Result\FileComparisonFailure;
@@ -34,21 +35,21 @@ public function getName(): string
3435
/**
3536
* Simply check that the file exists.
3637
*
37-
* @param ExerciseInterface&ProvidesSolution $exercise The exercise to check against.
38-
* @param Input $input The command line arguments passed to the command.
38+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
3939
* @return ResultInterface The result of the check.
4040
*/
41-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
41+
public function check(ExecutionContext $context): ResultInterface
4242
{
43+
$exercise = $context->getExercise();
4344
if (!$exercise instanceof FileComparisonExerciseCheck) {
4445
throw new InvalidArgumentException();
4546
}
4647

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

50-
$studentFile = Path::join(dirname($input->getRequiredArgument('program')), $file);
51-
$referenceFile = Path::join($exercise->getSolution()->getBaseDirectory(), $file);
51+
$studentFile = Path::join($context->getStudentExecutionDirectory(), $file);
52+
$referenceFile = Path::join($context->getReferenceExecutionDirectory(), $file);
5253

5354
if (!file_exists($referenceFile)) {
5455
throw SolutionFileDoesNotExistException::fromExpectedFile($file);

Diff for: src/Check/FileExistsCheck.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
88
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
9+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
910
use PhpSchool\PhpWorkshop\Input\Input;
1011
use PhpSchool\PhpWorkshop\Result\Failure;
1112
use PhpSchool\PhpWorkshop\Result\ResultInterface;
@@ -27,19 +28,18 @@ public function getName(): string
2728
/**
2829
* Simply check that the file exists.
2930
*
30-
* @param ExerciseInterface $exercise The exercise to check against.
31-
* @param Input $input The command line arguments passed to the command.
31+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
3232
* @return ResultInterface The result of the check.
3333
*/
34-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
34+
public function check(ExecutionContext $context): ResultInterface
3535
{
36-
if (file_exists($input->getRequiredArgument('program'))) {
36+
if (file_exists($context->getEntryPoint())) {
3737
return Success::fromCheck($this);
3838
}
3939

4040
return Failure::fromCheckAndReason(
4141
$this,
42-
sprintf('File: "%s" does not exist', $input->getRequiredArgument('program'))
42+
sprintf('File: "%s" does not exist', $context->getEntryPoint())
4343
);
4444
}
4545

Diff for: src/Check/FunctionRequirementsCheck.php

+7-15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1313
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1414
use PhpSchool\PhpWorkshop\ExerciseCheck\FunctionRequirementsExerciseCheck;
15+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
1516
use PhpSchool\PhpWorkshop\Input\Input;
1617
use PhpSchool\PhpWorkshop\NodeVisitor\FunctionVisitor;
1718
use PhpSchool\PhpWorkshop\Result\Failure;
@@ -25,17 +26,8 @@
2526
*/
2627
class FunctionRequirementsCheck implements SimpleCheckInterface
2728
{
28-
/**
29-
* @var Parser
30-
*/
31-
private $parser;
32-
33-
/**
34-
* @param Parser $parser
35-
*/
36-
public function __construct(Parser $parser)
29+
public function __construct(private Parser $parser)
3730
{
38-
$this->parser = $parser;
3931
}
4032

4133
/**
@@ -51,25 +43,25 @@ public function getName(): string
5143
* required functions and that banned functions are not used. The requirements
5244
* are pulled from the exercise.
5345
*
54-
* @param ExerciseInterface $exercise The exercise to check against.
55-
* @param Input $input The command line arguments passed to the command.
46+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
5647
* @return ResultInterface The result of the check.
5748
*/
58-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
49+
public function check(ExecutionContext $context): ResultInterface
5950
{
51+
$exercise = $context->getExercise();
6052
if (!$exercise instanceof FunctionRequirementsExerciseCheck) {
6153
throw new InvalidArgumentException();
6254
}
6355

6456
$requiredFunctions = $exercise->getRequiredFunctions();
6557
$bannedFunctions = $exercise->getBannedFunctions();
6658

67-
$code = (string) file_get_contents($input->getRequiredArgument('program'));
59+
$code = (string) file_get_contents($context->getEntryPoint());
6860

6961
try {
7062
$ast = $this->parser->parse($code) ?? [];
7163
} catch (Error $e) {
72-
return Failure::fromCheckAndCodeParseFailure($this, $e, $input->getRequiredArgument('program'));
64+
return Failure::fromCheckAndCodeParseFailure($this, $e, $context->getEntryPoint());
7365
}
7466

7567
$visitor = new FunctionVisitor($requiredFunctions, $bannedFunctions);

Diff for: src/Check/PhpLintCheck.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
88
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
9+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
910
use PhpSchool\PhpWorkshop\Input\Input;
1011
use PhpSchool\PhpWorkshop\Result\ResultInterface;
1112
use PhpSchool\PhpWorkshop\Result\Success;
@@ -30,14 +31,13 @@ public function getName(): string
3031
/**
3132
* Simply check the student's solution can be linted with `php -l`.
3233
*
33-
* @param ExerciseInterface $exercise The exercise to check against.
34-
* @param Input $input The command line arguments passed to the command.
34+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
3535
* @return ResultInterface The result of the check.
3636
*/
37-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface
37+
public function check(ExecutionContext $context): ResultInterface
3838
{
3939
$finder = new ExecutableFinder();
40-
$process = new Process([$finder->find('php'), '-l', $input->getArgument('program')]);
40+
$process = new Process([$finder->find('php'), '-l', $context->getEntryPoint()]);
4141
$process->run();
4242

4343
if ($process->isSuccessful()) {

Diff for: src/Check/SimpleCheckInterface.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
88
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
9+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
910
use PhpSchool\PhpWorkshop\Input\Input;
1011
use PhpSchool\PhpWorkshop\Result\ResultInterface;
1112

@@ -46,11 +47,10 @@ public function canRun(ExerciseType $exerciseType): bool;
4647
* successful then an instance of `PhpSchool\PhpWorkshop\Result\FailureInterface`
4748
* should be returned.
4849
*
49-
* @param ExerciseInterface $exercise The exercise to check against.
50-
* @param Input $input The command line arguments passed to the command.
50+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
5151
* @return ResultInterface The result of the check.
5252
*/
53-
public function check(ExerciseInterface $exercise, Input $input): ResultInterface;
53+
public function check(ExecutionContext $context): ResultInterface;
5454

5555
/**
5656
* Either `static::CHECK_BEFORE` | `static::CHECK_AFTER`.

Diff for: src/ExerciseDispatcher.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
123123
$this->validateChecks($this->checksToRunAfter, $exercise);
124124

125125
foreach ($this->checksToRunBefore as $check) {
126-
$this->results->add($check->check($context->getExercise(), $context->getInput()));
126+
$this->results->add($check->check($context));
127127

128128
if (!$this->results->isSuccessful()) {
129129
return $this->results;
@@ -139,7 +139,7 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
139139
}
140140

141141
foreach ($this->checksToRunAfter as $check) {
142-
$this->results->add($check->check($context->getExercise(), $context->getInput()));
142+
$this->results->add($check->check($context));
143143
}
144144

145145
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.post.check', $exercise, $input));
@@ -167,7 +167,7 @@ public function run(ExerciseInterface $exercise, Input $input, OutputInterface $
167167

168168
/** @var PhpLintCheck $lint */
169169
$lint = $this->checkRepository->getByClass(PhpLintCheck::class);
170-
$result = $lint->check($context->getExercise(), $context->getInput());
170+
$result = $lint->check($context);
171171

172172
if ($result instanceof FailureInterface) {
173173
throw CouldNotRunException::fromFailure($result);

0 commit comments

Comments
 (0)