Skip to content

Commit 5f4c01f

Browse files
committed
Use context objects in dispatcher and runners
1 parent 4f58bfa commit 5f4c01f

13 files changed

+496
-533
lines changed

Diff for: src/ExerciseDispatcher.php

+18-35
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PhpSchool\PhpWorkshop\Exception\ExerciseNotConfiguredException;
1515
use PhpSchool\PhpWorkshop\Exception\InvalidArgumentException;
1616
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
17+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContextFactory;
1718
use PhpSchool\PhpWorkshop\ExerciseRunner\RunnerManager;
1819
use PhpSchool\PhpWorkshop\Input\Input;
1920
use PhpSchool\PhpWorkshop\Output\OutputInterface;
@@ -29,49 +30,27 @@ class ExerciseDispatcher
2930
/**
3031
* @var array<SimpleCheckInterface>
3132
*/
32-
private $checksToRunBefore = [];
33+
private array $checksToRunBefore = [];
3334

3435
/**
3536
* @var array<SimpleCheckInterface>
3637
*/
37-
private $checksToRunAfter = [];
38+
private array $checksToRunAfter = [];
3839

39-
/**
40-
* @var RunnerManager
41-
*/
42-
private $runnerManager;
43-
44-
/**
45-
* @var ResultAggregator
46-
*/
47-
private $results;
48-
49-
/**
50-
* @var EventDispatcher
51-
*/
52-
private $eventDispatcher;
53-
54-
/**
55-
* @var CheckRepository
56-
*/
57-
private $checkRepository;
5840

5941
/**
6042
* @param RunnerManager $runnerManager Factory capable of building an exercise runner based on the exercise type.
61-
* @param ResultAggregator $resultAggregator
43+
* @param ResultAggregator $results
6244
* @param EventDispatcher $eventDispatcher
6345
* @param CheckRepository $checkRepository
6446
*/
6547
public function __construct(
66-
RunnerManager $runnerManager,
67-
ResultAggregator $resultAggregator,
68-
EventDispatcher $eventDispatcher,
69-
CheckRepository $checkRepository
48+
private RunnerManager $runnerManager,
49+
private ResultAggregator $results,
50+
private EventDispatcher $eventDispatcher,
51+
private CheckRepository $checkRepository,
52+
private ExecutionContextFactory $executionContextFactory,
7053
) {
71-
$this->runnerManager = $runnerManager;
72-
$this->results = $resultAggregator;
73-
$this->eventDispatcher = $eventDispatcher;
74-
$this->checkRepository = $checkRepository;
7554
}
7655

7756
/**
@@ -129,6 +108,7 @@ public function requireCheck(string $requiredCheck): void
129108
*/
130109
public function verify(ExerciseInterface $exercise, Input $input): ResultAggregator
131110
{
111+
$context = $this->executionContextFactory->fromInputAndExercise($input, $exercise);
132112
$runner = $this->runnerManager->getRunner($exercise);
133113

134114
$exercise->defineListeners($this->eventDispatcher);
@@ -143,7 +123,7 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
143123
$this->validateChecks($this->checksToRunAfter, $exercise);
144124

145125
foreach ($this->checksToRunBefore as $check) {
146-
$this->results->add($check->check($exercise, $input));
126+
$this->results->add($check->check($context->getExercise(), $context->getInput()));
147127

148128
if (!$this->results->isSuccessful()) {
149129
return $this->results;
@@ -153,13 +133,13 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
153133
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.pre.execute', $exercise, $input));
154134

155135
try {
156-
$this->results->add($runner->verify($input));
136+
$this->results->add($runner->verify($context));
157137
} finally {
158138
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.post.execute', $exercise, $input));
159139
}
160140

161141
foreach ($this->checksToRunAfter as $check) {
162-
$this->results->add($check->check($exercise, $input));
142+
$this->results->add($check->check($context->getExercise(), $context->getInput()));
163143
}
164144

165145
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('verify.post.check', $exercise, $input));
@@ -181,13 +161,16 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
181161
*/
182162
public function run(ExerciseInterface $exercise, Input $input, OutputInterface $output): bool
183163
{
164+
$context = $this->executionContextFactory->fromInputAndExercise($input, $exercise);
165+
184166
$exercise->defineListeners($this->eventDispatcher);
185167

186168
/** @var PhpLintCheck $lint */
187169
$lint = $this->checkRepository->getByClass(PhpLintCheck::class);
188-
$result = $lint->check($exercise, $input);
170+
$result = $lint->check($context->getExercise(), $context->getInput());
189171

190172
if ($result instanceof FailureInterface) {
173+
var_dump($result);
191174
throw CouldNotRunException::fromFailure($result);
192175
}
193176

@@ -196,7 +179,7 @@ public function run(ExerciseInterface $exercise, Input $input, OutputInterface $
196179
try {
197180
$exitStatus = $this->runnerManager
198181
->getRunner($exercise)
199-
->run($input, $output);
182+
->run($context, $output);
200183
} finally {
201184
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('run.finish', $exercise, $input));
202185
}

Diff for: src/ExerciseRunner/CgiRunner.php

+30-26
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PhpSchool\PhpWorkshop\Exception\SolutionExecutionException;
1919
use PhpSchool\PhpWorkshop\Exercise\CgiExercise;
2020
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
21+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContext;
2122
use PhpSchool\PhpWorkshop\Input\Input;
2223
use PhpSchool\PhpWorkshop\Output\OutputInterface;
2324
use PhpSchool\PhpWorkshop\Process\ProcessFactory;
@@ -99,33 +100,34 @@ public function getRequiredChecks(): array
99100
* * cgi.verify.student.executing
100101
* * cgi.verify.student-execute.fail (if the student's solution fails to execute)
101102
*
102-
* @param Input $input The command line arguments passed to the command.
103+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
103104
* @return CgiResult The result of the check.
104105
*/
105-
public function verify(Input $input): ResultInterface
106+
public function verify(ExecutionContext $context): ResultInterface
106107
{
107-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $input));
108+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $context->getInput()));
108109
$result = new CgiResult(
109110
array_map(
110-
function (RequestInterface $request) use ($input) {
111-
return $this->doVerify($request, $input);
111+
function (RequestInterface $request) use ($context) {
112+
return $this->doVerify($request, $context);
112113
},
113114
$this->exercise->getRequests()
114115
)
115116
);
116-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $input));
117+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $context->getInput()));
117118
return $result;
118119
}
119120

120-
private function doVerify(RequestInterface $request, Input $input): CgiResultInterface
121+
private function doVerify(RequestInterface $request, ExecutionContext $context): CgiResultInterface
121122
{
122123
try {
123124
/** @var CgiExecuteEvent $event */
124125
$event = $this->eventDispatcher->dispatch(
125-
new CgiExecuteEvent('cgi.verify.reference-execute.pre', $this->exercise, $input, $request)
126+
new CgiExecuteEvent('cgi.verify.reference-execute.pre', $this->exercise, $context->getInput(), $request)
126127
);
127128
$solutionResponse = $this->executePhpFile(
128-
$input,
129+
$context,
130+
$context->getReferenceExecutionDirectory(),
129131
$this->exercise->getSolution()->getEntryPoint()->getAbsolutePath(),
130132
$event->getRequest(),
131133
'reference'
@@ -135,7 +137,7 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
135137
new CgiExecuteEvent(
136138
'cgi.verify.reference-execute.fail',
137139
$this->exercise,
138-
$input,
140+
$context->getInput(),
139141
$request,
140142
['exception' => $e]
141143
)
@@ -146,11 +148,12 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
146148
try {
147149
/** @var CgiExecuteEvent $event */
148150
$event = $this->eventDispatcher->dispatch(
149-
new CgiExecuteEvent('cgi.verify.student-execute.pre', $this->exercise, $input, $request)
151+
new CgiExecuteEvent('cgi.verify.student-execute.pre', $this->exercise, $context->getInput(), $request)
150152
);
151153
$userResponse = $this->executePhpFile(
152-
$input,
153-
$input->getRequiredArgument('program'),
154+
$context,
155+
$context->getStudentExecutionDirectory(),
156+
$context->getEntryPoint(),
154157
$event->getRequest(),
155158
'student'
156159
);
@@ -159,7 +162,7 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
159162
new CgiExecuteEvent(
160163
'cgi.verify.student-execute.fail',
161164
$this->exercise,
162-
$input,
165+
$context->getInput(),
163166
$request,
164167
['exception' => $e]
165168
)
@@ -199,16 +202,17 @@ private function getHeaders(ResponseInterface $response): array
199202
* @return ResponseInterface
200203
*/
201204
private function executePhpFile(
202-
Input $input,
205+
ExecutionContext $context,
206+
string $workingDirectory,
203207
string $fileName,
204208
RequestInterface $request,
205209
string $type
206210
): ResponseInterface {
207-
$process = $this->getPhpProcess(dirname($fileName), basename($fileName), $request);
211+
$process = $this->getPhpProcess($workingDirectory, $fileName, $request);
208212

209213
$process->start();
210214
$this->eventDispatcher->dispatch(
211-
new CgiExecuteEvent(sprintf('cgi.verify.%s.executing', $type), $this->exercise, $input, $request)
215+
new CgiExecuteEvent(sprintf('cgi.verify.%s.executing', $type), $this->exercise, $context->getInput(), $request)
212216
);
213217
$process->wait();
214218

@@ -277,22 +281,22 @@ private function getPhpProcess(string $workingDirectory, string $fileName, Reque
277281
* * cgi.run.student-execute.pre
278282
* * cgi.run.student.executing
279283
*
280-
* @param Input $input The command line arguments passed to the command.
284+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
281285
* @param OutputInterface $output A wrapper around STDOUT.
282286
* @return bool If the solution was successfully executed, eg. exit code was 0.
283287
*/
284-
public function run(Input $input, OutputInterface $output): bool
288+
public function run(ExecutionContext $context, OutputInterface $output): bool
285289
{
286-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $input));
290+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $context->getInput()));
287291
$success = true;
288292
foreach ($this->exercise->getRequests() as $i => $request) {
289293
/** @var CgiExecuteEvent $event */
290294
$event = $this->eventDispatcher->dispatch(
291-
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $input, $request)
295+
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $context->getInput(), $request)
292296
);
293297
$process = $this->getPhpProcess(
294-
dirname($input->getRequiredArgument('program')),
295-
$input->getRequiredArgument('program'),
298+
$context->getStudentExecutionDirectory(),
299+
$context->getEntryPoint(),
296300
$event->getRequest()
297301
);
298302

@@ -301,7 +305,7 @@ public function run(Input $input, OutputInterface $output): bool
301305
new CgiExecuteEvent(
302306
'cgi.run.student.executing',
303307
$this->exercise,
304-
$input,
308+
$context->getInput(),
305309
$request,
306310
['output' => $output]
307311
)
@@ -318,10 +322,10 @@ public function run(Input $input, OutputInterface $output): bool
318322
$output->lineBreak();
319323

320324
$this->eventDispatcher->dispatch(
321-
new CgiExecuteEvent('cgi.run.student-execute.post', $this->exercise, $input, $request)
325+
new CgiExecuteEvent('cgi.run.student-execute.post', $this->exercise, $context->getInput(), $request)
322326
);
323327
}
324-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.finish', $this->exercise, $input));
328+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.finish', $this->exercise, $context->getInput()));
325329
return $success;
326330
}
327331
}

0 commit comments

Comments
 (0)