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 bb84725

Browse files
Merge pull request #289 from php-school/05-07-use_context_objects_in_dispatcher_and_runners
Use context objects in dispatcher and runners
2 parents 6515c60 + b86f356 commit bb84725

17 files changed

+265
-281
lines changed

‎app/config.php‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@
3838
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
3939
use PhpSchool\PhpWorkshop\ExerciseRenderer;
4040
use PhpSchool\PhpWorkshop\ExerciseRepository;
41+
use PhpSchool\PhpWorkshop\ExerciseRunner\EnvironmentManager;
4142
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CgiRunnerFactory;
4243
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CliRunnerFactory;
4344
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\CustomVerifyingRunnerFactory;
44-
use PhpSchool\PhpWorkshop\ExerciseRunner\Factory\ServerRunnerFactory;
4545
use PhpSchool\PhpWorkshop\ExerciseRunner\RunnerManager;
4646
use PhpSchool\PhpWorkshop\Factory\EventDispatcherFactory;
4747
use PhpSchool\PhpWorkshop\Factory\MenuFactory;
@@ -134,7 +134,7 @@
134134
$c->get(RunnerManager::class),
135135
$c->get(ResultAggregator::class),
136136
$c->get(EventDispatcher::class),
137-
$c->get(CheckRepository::class)
137+
$c->get(CheckRepository::class),
138138
);
139139
},
140140
ResultAggregator::class => create(ResultAggregator::class),
@@ -193,8 +193,16 @@
193193
//Exercise Runners
194194
RunnerManager::class => function (ContainerInterface $c) {
195195
$manager = new RunnerManager();
196-
$manager->addFactory(new CliRunnerFactory($c->get(EventDispatcher::class), $c->get(ProcessFactory::class)));
197-
$manager->addFactory(new CgiRunnerFactory($c->get(EventDispatcher::class), $c->get(ProcessFactory::class)));
196+
$manager->addFactory(new CliRunnerFactory(
197+
$c->get(EventDispatcher::class),
198+
$c->get(ProcessFactory::class),
199+
$c->get(EnvironmentManager::class)
200+
));
201+
$manager->addFactory(new CgiRunnerFactory(
202+
$c->get(EventDispatcher::class),
203+
$c->get(ProcessFactory::class),
204+
$c->get(EnvironmentManager::class)
205+
));
198206
$manager->addFactory(new CustomVerifyingRunnerFactory());
199207
return $manager;
200208
},

‎src/ExerciseDispatcher.php‎

Lines changed: 17 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\ExecutionContext;
1718
use PhpSchool\PhpWorkshop\ExerciseRunner\RunnerManager;
1819
use PhpSchool\PhpWorkshop\Input\Input;
1920
use PhpSchool\PhpWorkshop\Output\OutputInterface;
@@ -29,49 +30,26 @@ 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+
privateRunnerManager $runnerManager,
49+
privateResultAggregator $results,
50+
privateEventDispatcher $eventDispatcher,
51+
privateCheckRepository $checkRepository,
7052
) {
71-
$this->runnerManager = $runnerManager;
72-
$this->results = $resultAggregator;
73-
$this->eventDispatcher = $eventDispatcher;
74-
$this->checkRepository = $checkRepository;
7553
}
7654

7755
/**
@@ -129,6 +107,8 @@ public function requireCheck(string $requiredCheck): void
129107
*/
130108
public function verify(ExerciseInterface $exercise, Input $input): ResultAggregator
131109
{
110+
$context = ExecutionContext::fromInputAndExercise($input, $exercise);
111+
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,11 +161,13 @@ public function verify(ExerciseInterface $exercise, Input $input): ResultAggrega
181161
*/
182162
public function run(ExerciseInterface $exercise, Input $input, OutputInterface $output): bool
183163
{
164+
$context = ExecutionContext::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) {
191173
throw CouldNotRunException::fromFailure($result);
@@ -196,7 +178,7 @@ public function run(ExerciseInterface $exercise, Input $input, OutputInterface $
196178
try {
197179
$exitStatus = $this->runnerManager
198180
->getRunner($exercise)
199-
->run($input, $output);
181+
->run($context, $output);
200182
} finally {
201183
$this->eventDispatcher->dispatch(new ExerciseRunnerEvent('run.finish', $exercise, $input));
202184
}

‎src/ExerciseRunner/CgiRunner.php‎

Lines changed: 40 additions & 28 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;
@@ -63,7 +64,8 @@ class CgiRunner implements ExerciseRunnerInterface
6364
public function __construct(
6465
private CgiExercise $exercise,
6566
private EventDispatcher $eventDispatcher,
66-
private ProcessFactory $processFactory
67+
private ProcessFactory $processFactory,
68+
private EnvironmentManager $environmentManager
6769
) {
6870
}
6971

@@ -99,37 +101,42 @@ public function getRequiredChecks(): array
99101
* * cgi.verify.student.executing
100102
* * cgi.verify.student-execute.fail (if the student's solution fails to execute)
101103
*
102-
* @param Input $input The command line arguments passed to the command.
104+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
103105
* @return CgiResult The result of the check.
104106
*/
105-
public function verify(Input$input): ResultInterface
107+
public function verify(ExecutionContext$context): ResultInterface
106108
{
107109
$scenario = $this->exercise->defineTestScenario();
108110

109-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $input));
111+
$this->environmentManager->prepareStudent($context, $scenario);
112+
$this->environmentManager->prepareReference($context, $scenario);
113+
114+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $context->getInput()));
110115

111116
$result = new CgiResult(
112117
array_map(
113-
function (RequestInterface $request) use ($input) {
114-
return $this->doVerify($request, $input);
118+
function (RequestInterface $request) use ($context) {
119+
return $this->doVerify($request, $context);
115120
},
116121
$scenario->getExecutions()
117122
)
118123
);
119-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $input));
124+
125+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $context->getInput()));
120126
return $result;
121127
}
122128

123-
private function doVerify(RequestInterface $request, Input$input): CgiResultInterface
129+
private function doVerify(RequestInterface $request, ExecutionContext$context): CgiResultInterface
124130
{
125131
try {
126132
/** @var CgiExecuteEvent $event */
127133
$event = $this->eventDispatcher->dispatch(
128-
new CgiExecuteEvent('cgi.verify.reference-execute.pre', $this->exercise, $input, $request)
134+
new CgiExecuteEvent('cgi.verify.reference-execute.pre', $this->exercise, $context->getInput(), $request)
129135
);
130136
$solutionResponse = $this->executePhpFile(
131-
$input,
132-
$this->exercise->getSolution()->getEntryPoint()->getAbsolutePath(),
137+
$context,
138+
$context->getReferenceExecutionDirectory(),
139+
$this->exercise->getSolution()->getEntryPoint()->getRelativePath(),
133140
$event->getRequest(),
134141
'reference'
135142
);
@@ -138,7 +145,7 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
138145
new CgiExecuteEvent(
139146
'cgi.verify.reference-execute.fail',
140147
$this->exercise,
141-
$input,
148+
$context->getInput(),
142149
$request,
143150
['exception' => $e]
144151
)
@@ -149,11 +156,12 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
149156
try {
150157
/** @var CgiExecuteEvent $event */
151158
$event = $this->eventDispatcher->dispatch(
152-
new CgiExecuteEvent('cgi.verify.student-execute.pre', $this->exercise, $input, $request)
159+
new CgiExecuteEvent('cgi.verify.student-execute.pre', $this->exercise, $context->getInput(), $request)
153160
);
154161
$userResponse = $this->executePhpFile(
155-
$input,
156-
$input->getRequiredArgument('program'),
162+
$context,
163+
$context->getStudentExecutionDirectory(),
164+
$context->getEntryPoint(),
157165
$event->getRequest(),
158166
'student'
159167
);
@@ -162,7 +170,7 @@ private function doVerify(RequestInterface $request, Input $input): CgiResultInt
162170
new CgiExecuteEvent(
163171
'cgi.verify.student-execute.fail',
164172
$this->exercise,
165-
$input,
173+
$context->getInput(),
166174
$request,
167175
['exception' => $e]
168176
)
@@ -202,16 +210,17 @@ private function getHeaders(ResponseInterface $response): array
202210
* @return ResponseInterface
203211
*/
204212
private function executePhpFile(
205-
Input $input,
213+
ExecutionContext $context,
214+
string $workingDirectory,
206215
string $fileName,
207216
RequestInterface $request,
208217
string $type
209218
): ResponseInterface {
210-
$process = $this->getPhpProcess(dirname($fileName), basename($fileName), $request);
219+
$process = $this->getPhpProcess($workingDirectory, $fileName, $request);
211220

212221
$process->start();
213222
$this->eventDispatcher->dispatch(
214-
new CgiExecuteEvent(sprintf('cgi.verify.%s.executing', $type), $this->exercise, $input, $request)
223+
new CgiExecuteEvent(sprintf('cgi.verify.%s.executing', $type), $this->exercise, $context->getInput(), $request)
215224
);
216225
$process->wait();
217226

@@ -280,25 +289,27 @@ private function getPhpProcess(string $workingDirectory, string $fileName, Reque
280289
* * cgi.run.student-execute.pre
281290
* * cgi.run.student.executing
282291
*
283-
* @param Input $input The command line arguments passed to the command.
292+
* @param ExecutionContext $context The current execution context, containing the exercise, input and working directories.
284293
* @param OutputInterface $output A wrapper around STDOUT.
285294
* @return bool If the solution was successfully executed, eg. exit code was 0.
286295
*/
287-
public function run(Input$input, OutputInterface $output): bool
296+
public function run(ExecutionContext$context, OutputInterface $output): bool
288297
{
289298
$scenario = $this->exercise->defineTestScenario();
290299

291-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $input));
300+
$this->environmentManager->prepareStudent($context, $scenario);
301+
302+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $context->getInput()));
292303

293304
$success = true;
294305
foreach ($scenario->getExecutions() as $i => $request) {
295306
/** @var CgiExecuteEvent $event */
296307
$event = $this->eventDispatcher->dispatch(
297-
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $input, $request)
308+
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $context->getInput(), $request)
298309
);
299310
$process = $this->getPhpProcess(
300-
dirname($input->getRequiredArgument('program')),
301-
$input->getRequiredArgument('program'),
311+
$context->getStudentExecutionDirectory(),
312+
$context->getEntryPoint(),
302313
$event->getRequest()
303314
);
304315

@@ -307,7 +318,7 @@ public function run(Input $input, OutputInterface $output): bool
307318
new CgiExecuteEvent(
308319
'cgi.run.student.executing',
309320
$this->exercise,
310-
$input,
321+
$context->getInput(),
311322
$request,
312323
['output' => $output]
313324
)
@@ -324,10 +335,11 @@ public function run(Input $input, OutputInterface $output): bool
324335
$output->lineBreak();
325336

326337
$this->eventDispatcher->dispatch(
327-
new CgiExecuteEvent('cgi.run.student-execute.post', $this->exercise, $input, $request)
338+
new CgiExecuteEvent('cgi.run.student-execute.post', $this->exercise, $context->getInput(), $request)
328339
);
329340
}
330-
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.finish', $this->exercise, $input));
341+
342+
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.finish', $this->exercise, $context->getInput()));
331343
return $success;
332344
}
333345
}

0 commit comments

Comments
(0)

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