Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8cc9cce

Browse files
Use context objects in dispatcher and runners
1 parent 224fa1b commit 8cc9cce

14 files changed

+499
-534
lines changed

‎app/config.php‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
3939
use PhpSchool\PhpWorkshop\ExerciseRenderer;
4040
use PhpSchool\PhpWorkshop\ExerciseRepository;
41+
use PhpSchool\PhpWorkshop\ExerciseRunner\Context\ExecutionContextFactory;
4142
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CgiRunnerFactory;
4243
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CliRunnerFactory;
4344
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CustomVerifyingRunnerFactory;
@@ -134,7 +135,8 @@
134135
$c->get(RunnerManager::class),
135136
$c->get(ResultAggregator::class),
136137
$c->get(EventDispatcher::class),
137-
$c->get(CheckRepository::class)
138+
$c->get(CheckRepository::class),
139+
new ExecutionContextFactory()
138140
);
139141
},
140142
ResultAggregator::class => create(ResultAggregator::class),

‎src/ExerciseDispatcher.php‎

Lines changed: 18 additions & 35 deletions
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
}

‎src/ExerciseRunner/CgiRunner.php‎

Lines changed: 30 additions & 26 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /