Skip to content

Commit 48e8f8e

Browse files
committed
Merge pull request #69 from php-school/depend-on-concrete-exercise
ExerciseRunners now depend on a concrete implementation of ExerciseIn…
2 parents b67411d + fa3cd25 commit 48e8f8e

File tree

9 files changed

+101
-168
lines changed

9 files changed

+101
-168
lines changed

src/ExerciseDispatcher.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public function verify(ExerciseInterface $exercise, $fileName)
132132
{
133133
$exercise->configure($this);
134134

135-
$runner = $this->runnerFactory->create($exercise->getType(), $this->eventDispatcher);
135+
$runner = $this->runnerFactory->create($exercise, $this->eventDispatcher);
136136
$this->eventDispatcher->dispatch(new Event('verify.start', compact('exercise', 'fileName')));
137137

138138
$this->validateChecks($this->checksToRunBefore, $exercise);
@@ -149,7 +149,7 @@ public function verify(ExerciseInterface $exercise, $fileName)
149149
$this->eventDispatcher->dispatch(new Event('verify.pre.execute', compact('exercise', 'fileName')));
150150

151151
try {
152-
$this->results->add($runner->verify($exercise, $fileName));
152+
$this->results->add($runner->verify($fileName));
153153
} finally {
154154
$this->eventDispatcher->dispatch(new Event('verify.post.execute', compact('exercise', 'fileName')));
155155
}
@@ -176,8 +176,8 @@ public function run(ExerciseInterface $exercise, $fileName, OutputInterface $out
176176
$this->eventDispatcher->dispatch(new Event('run.start', compact('exercise', 'fileName')));
177177

178178
$exitStatus = $this->runnerFactory
179-
->create($exercise->getType(), $this->eventDispatcher)
180-
->run($exercise, $fileName, $output);
179+
->create($exercise, $this->eventDispatcher)
180+
->run($fileName, $output);
181181

182182
$this->eventDispatcher->dispatch(new Event('run.finish', compact('exercise', 'fileName')));
183183
return $exitStatus;

src/ExerciseRunner/CgiRunner.php

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
use PhpSchool\PhpWorkshop\Exception\CodeExecutionException;
99
use PhpSchool\PhpWorkshop\Exception\SolutionExecutionException;
1010
use PhpSchool\PhpWorkshop\Exercise\CgiExercise;
11-
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
12-
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1311
use PhpSchool\PhpWorkshop\Output\OutputInterface;
1412
use PhpSchool\PhpWorkshop\Result\CgiOutFailure;
1513
use PhpSchool\PhpWorkshop\Result\CgiOutRequestFailure;
@@ -29,17 +27,24 @@
2927
class CgiRunner implements ExerciseRunnerInterface
3028
{
3129

30+
/**
31+
* @var CgiExercise
32+
*/
33+
private $exercise;
34+
3235
/**
3336
* @var EventDispatcher
3437
*/
3538
private $eventDispatcher;
3639

3740
/**
41+
* @param CgiExercise $exercise
3842
* @param EventDispatcher $eventDispatcher
3943
*/
40-
public function __construct(EventDispatcher $eventDispatcher)
44+
public function __construct(CgiExercise $exercise, EventDispatcher $eventDispatcher)
4145
{
4246
$this->eventDispatcher = $eventDispatcher;
47+
$this->exercise = $exercise;
4348
}
4449

4550
/**
@@ -51,17 +56,16 @@ public function getName()
5156
}
5257

5358
/**
54-
* @param ExerciseInterface $exercise
5559
* @param RequestInterface $request
5660
* @param string $fileName
5761
* @return ResultInterface
5862
*/
59-
private function checkRequest(ExerciseInterface $exercise, RequestInterface $request, $fileName)
63+
private function checkRequest(RequestInterface $request, $fileName)
6064
{
6165
try {
6266
$event = $this->eventDispatcher->dispatch(new CgiExecuteEvent('cgi.verify.solution-execute.pre', $request));
6367
$solutionResponse = $this->executePhpFile(
64-
$exercise->getSolution()->getEntryPoint(),
68+
$this->exercise->getSolution()->getEntryPoint(),
6569
$event->getRequest(),
6670
'solution'
6771
);
@@ -164,37 +168,31 @@ private function getProcess($fileName, RequestInterface $request)
164168
}
165169

166170
/**
167-
* @param ExerciseInterface $exercise
168171
* @param string $fileName
169172
* @return ResultInterface
170173
*/
171-
public function verify(ExerciseInterface $exercise, $fileName)
174+
public function verify($fileName)
172175
{
173-
$this->validateExercise($exercise);
174-
175176
return new CgiOutResult(
176177
$this->getName(),
177178
array_map(
178-
function (RequestInterface $request) use ($exercise, $fileName) {
179-
return $this->checkRequest($exercise, $request, $fileName);
179+
function (RequestInterface $request) use ($fileName) {
180+
return $this->checkRequest($request, $fileName);
180181
},
181-
$exercise->getRequests()
182+
$this->exercise->getRequests()
182183
)
183184
);
184185
}
185186

186187
/**
187-
* @param ExerciseInterface $exercise
188188
* @param string $fileName
189189
* @param OutputInterface $output
190190
* @return bool
191191
*/
192-
public function run(ExerciseInterface $exercise, $fileName, OutputInterface $output)
192+
public function run($fileName, OutputInterface $output)
193193
{
194-
$this->validateExercise($exercise);
195-
196194
$success = true;
197-
foreach ($exercise->getRequests() as $i => $request) {
195+
foreach ($this->exercise->getRequests() as $i => $request) {
198196
$event = $this->eventDispatcher->dispatch(new CgiExecuteEvent('cgi.run.usr-execute.pre', $request));
199197
$process = $this->getProcess($fileName, $event->getRequest());
200198

@@ -208,18 +206,4 @@ public function run(ExerciseInterface $exercise, $fileName, OutputInterface $out
208206
}
209207
return $success;
210208
}
211-
212-
/**
213-
* @param ExerciseInterface $exercise
214-
*/
215-
private function validateExercise(ExerciseInterface $exercise)
216-
{
217-
if ($exercise->getType()->getValue() !== ExerciseType::CGI) {
218-
throw new \InvalidArgumentException;
219-
}
220-
221-
if (!$exercise instanceof CgiExercise) {
222-
throw new \InvalidArgumentException;
223-
}
224-
}
225209
}

src/ExerciseRunner/CliRunner.php

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
99
use PhpSchool\PhpWorkshop\Exception\CodeExecutionException;
1010
use PhpSchool\PhpWorkshop\Exception\SolutionExecutionException;
11+
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
1112
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1213
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1314
use PhpSchool\PhpWorkshop\ExerciseCheck\StdOutExerciseCheck;
@@ -25,18 +26,24 @@
2526
*/
2627
class CliRunner implements ExerciseRunnerInterface
2728
{
29+
/**
30+
* @var CliExercise
31+
*/
32+
private $exercise;
2833

2934
/**
3035
* @var EventDispatcher
3136
*/
3237
private $eventDispatcher;
3338

3439
/**
40+
* @param CliExercise $exercise
3541
* @param EventDispatcher $eventDispatcher
3642
*/
37-
public function __construct(EventDispatcher $eventDispatcher)
43+
public function __construct(CliExercise $exercise, EventDispatcher $eventDispatcher)
3844
{
3945
$this->eventDispatcher = $eventDispatcher;
46+
$this->exercise = $exercise;
4047
}
4148

4249
/**
@@ -81,23 +88,18 @@ private function getPhpProcess($fileName, ArrayObject $args)
8188
}
8289

8390
/**
84-
* @param ExerciseInterface $exercise
8591
* @param string $fileName
8692
* @return ResultInterface
8793
*/
88-
public function verify(ExerciseInterface $exercise, $fileName)
94+
public function verify($fileName)
8995
{
90-
if ($exercise->getType()->getValue() !== ExerciseType::CLI) {
91-
throw new \InvalidArgumentException;
92-
}
93-
9496
//arrays are not pass-by-ref
95-
$args = new ArrayObject($exercise->getArgs());
97+
$args = new ArrayObject($this->exercise->getArgs());
9698

9799
try {
98100
$event = $this->eventDispatcher->dispatch(new CliExecuteEvent('cli.verify.solution-execute.pre', $args));
99101
$solutionOutput = $this->executePhpFile(
100-
$exercise->getSolution()->getEntryPoint(),
102+
$this->exercise->getSolution()->getEntryPoint(),
101103
$event->getArgs(),
102104
'solution'
103105
);
@@ -121,19 +123,14 @@ public function verify(ExerciseInterface $exercise, $fileName)
121123
}
122124

123125
/**
124-
* @param ExerciseInterface $exercise
125126
* @param string $fileName
126127
* @param OutputInterface $output
127128
* @return bool
128129
*/
129-
public function run(ExerciseInterface $exercise, $fileName, OutputInterface $output)
130+
public function run($fileName, OutputInterface $output)
130131
{
131-
if ($exercise->getType()->getValue() !== ExerciseType::CLI) {
132-
throw new \InvalidArgumentException;
133-
}
134-
135132
$event = $this->eventDispatcher->dispatch(
136-
new CliExecuteEvent('cli.run.user-execute.pre', new ArrayObject($exercise->getArgs()))
133+
new CliExecuteEvent('cli.run.user-execute.pre', new ArrayObject($this->exercise->getArgs()))
137134
);
138135

139136
$process = $this->getPhpProcess($fileName, $event->getArgs());

src/ExerciseRunner/ExerciseRunnerInterface.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,15 @@ interface ExerciseRunnerInterface
1919
public function getName();
2020

2121
/**
22-
* @param ExerciseInterface $exercise
2322
* @param string $fileName
2423
* @return ResultInterface
2524
*/
26-
public function verify(ExerciseInterface $exercise, $fileName);
25+
public function verify($fileName);
2726

2827
/**
29-
* @param ExerciseInterface $exercise
3028
* @param string $fileName
3129
* @param OutputInterface $output
3230
* @return bool
3331
*/
34-
public function run(ExerciseInterface $exercise, $fileName, OutputInterface $output);
32+
public function run($fileName, OutputInterface $output);
3533
}

src/Factory/RunnerFactory.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Interop\Container\ContainerInterface;
66
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
77
use PhpSchool\PhpWorkshop\Exception\InvalidArgumentException;
8+
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
89
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
910
use PhpSchool\PhpWorkshop\ExerciseRunner\CgiRunner;
1011
use PhpSchool\PhpWorkshop\ExerciseRunner\CliRunner;
@@ -18,19 +19,21 @@
1819
class RunnerFactory
1920
{
2021
/**
21-
* @param ExerciseType $exerciseType
22+
* @param ExerciseInterface $exercise
2223
* @param EventDispatcher $eventDispatcher
2324
* @return ExerciseRunnerInterface
2425
*/
25-
public function create(ExerciseType $exerciseType, EventDispatcher $eventDispatcher)
26+
public function create(ExerciseInterface $exercise, EventDispatcher $eventDispatcher)
2627
{
27-
switch ($exerciseType->getValue()) {
28+
switch ($exercise->getType()->getValue()) {
2829
case ExerciseType::CLI:
29-
return new CliRunner($eventDispatcher);
30+
return new CliRunner($exercise, $eventDispatcher);
3031
case ExerciseType::CGI:
31-
return new CgiRunner($eventDispatcher);
32+
return new CgiRunner($exercise, $eventDispatcher);
3233
}
3334

34-
throw new InvalidArgumentException(sprintf('Exercise Type: "%s" not supported', $exerciseType->getValue()));
35+
throw new InvalidArgumentException(
36+
sprintf('Exercise Type: "%s" not supported', $exercise->getType()->getValue())
37+
);
3538
}
3639
}

test/ExerciseDispatcherTest.php

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,25 @@ private function createExercise()
131131
$this->exercise = $this->getMock(ExerciseInterface::class);
132132
$this->solution = $this->getMock(SolutionInterface::class);
133133

134-
$this->exerciseType = ExerciseType::CLI();
135-
$this->exercise
136-
->expects($this->atLeastOnce())
137-
->method('getType')
138-
->will($this->returnValue($this->exerciseType));
139-
140134
$this->exercise
141135
->expects($this->any())
142136
->method('getName')
143137
->will($this->returnValue('Some Exercise'));
138+
139+
$this->exerciseType = new ExerciseType(ExerciseType::CLI);
140+
141+
$this->exercise
142+
->expects($this->any())
143+
->method('getType')
144+
->will($this->returnValue($this->exerciseType));
144145
}
145146

146-
private function mockRunner(ExerciseType $exerciseType = null)
147+
private function mockRunner(ExerciseInterface $exercise = null)
147148
{
148149
$this->runnerFactory
149150
->expects($this->once())
150151
->method('create')
151-
->with($exerciseType ? $exerciseType : $this->exerciseType, $this->eventDispatcher)
152+
->with($exercise ? $exercise : $this->exercise, $this->eventDispatcher)
152153
->will($this->returnValue($this->runner));
153154
}
154155

@@ -275,7 +276,7 @@ public function testVerify()
275276
$this->runner
276277
->expects($this->once())
277278
->method('verify')
278-
->with($this->exercise, $this->file)
279+
->with($this->file)
279280
->will($this->returnValue($this->getMock(SuccessInterface::class)));
280281

281282
$this->exerciseDispatcher->requireCheck(get_class($this->check), ExerciseDispatcher::CHECK_BEFORE);
@@ -313,7 +314,7 @@ public function testVerifyOnlyRunsRequiredChecks()
313314
$this->runner
314315
->expects($this->once())
315316
->method('verify')
316-
->with($this->exercise, $this->file)
317+
->with($this->file)
317318
->will($this->returnValue($this->getMock(SuccessInterface::class)));
318319

319320
$this->checkRepository->registerCheck($doNotRunMe);
@@ -326,7 +327,7 @@ public function testVerifyOnlyRunsRequiredChecks()
326327
$this->assertTrue($result->isSuccessful());
327328
}
328329

329-
public function testWhenBeforeChecksFailTheyReturnImmediatelyEarly()
330+
public function testWhenBeforeChecksFailTheyReturnImmediately()
330331
{
331332
$this->createExercise();
332333
$this->check
@@ -389,7 +390,7 @@ public function testAllEventsAreDispatched()
389390
$this->runner
390391
->expects($this->once())
391392
->method('verify')
392-
->with($this->exercise, $this->file)
393+
->with($this->file)
393394
->will($this->returnValue(new Success('test')));
394395

395396
$this->exerciseDispatcher->verify($this->exercise, $this->file);
@@ -411,7 +412,7 @@ public function testVerifyPostExecuteIsStillDispatchedEvenIfRunnerThrowsExceptio
411412
$this->runner
412413
->expects($this->once())
413414
->method('verify')
414-
->with($this->exercise, $this->file)
415+
->with($this->file)
415416
->will($this->throwException(new RuntimeException));
416417

417418
$this->setExpectedException(RuntimeException::class);
@@ -423,17 +424,11 @@ public function testRun()
423424
$exercise = $this->getMock(ExerciseInterface::class);
424425
$output = $this->getMock(OutputInterface::class);
425426

426-
$exerciseType = ExerciseType::CLI();
427-
$exercise
428-
->expects($this->atLeastOnce())
429-
->method('getType')
430-
->will($this->returnValue($exerciseType));
431-
432-
$this->mockRunner($exerciseType);
427+
$this->mockRunner($exercise);
433428
$this->runner
434429
->expects($this->once())
435430
->method('run')
436-
->with($exercise, $this->file, $output)
431+
->with($this->file, $output)
437432
->will($this->returnValue(true));
438433

439434
$this->assertTrue($this->exerciseDispatcher->run($exercise, $this->file, $output));

0 commit comments

Comments
 (0)