Skip to content

Commit 9d08a52

Browse files
authored
Merge pull request #134 from php-school/exercise-selected-event
Dispatch event when an exercise is selected
2 parents 79aef98 + ca50272 commit 9d08a52

File tree

5 files changed

+82
-24
lines changed

5 files changed

+82
-24
lines changed

src/Exercise/AbstractExercise.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function getSolution()
4141
sprintf(
4242
'%s/../../exercises/%s/solution/solution.php',
4343
dirname((new ReflectionClass(static::class))->getFileName()),
44-
$this->normaliseName($this->getName())
44+
self::normaliseName($this->getName())
4545
)
4646
)
4747
);
@@ -55,7 +55,7 @@ public function getSolution()
5555
*/
5656
public function getProblem()
5757
{
58-
$name = $this->normaliseName($this->getName());
58+
$name = self::normaliseName($this->getName());
5959
$dir = dirname((new ReflectionClass(static::class))->getFileName());
6060
return sprintf('%s/../../exercises/%s/problem/problem.md', $dir, $name);
6161
}
@@ -74,7 +74,7 @@ public function tearDown()
7474
* @param string $name
7575
* @return string
7676
*/
77-
private function normaliseName($name)
77+
public static function normaliseName($name)
7878
{
7979
return preg_replace('/[^A-Za-z\-]+/', '', str_replace(' ', '-', strtolower($name)));
8080
}

src/Factory/EventDispatcherFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function __invoke(ContainerInterface $container)
4040
$dispatcher->listen('verify.post.check', $container->get(SelfCheckListener::class));
4141

4242
//add listeners from config
43-
$eventListeners = $container->get('eventListeners') ?: [];
43+
$eventListeners = $container->has('eventListeners') ? $container->get('eventListeners') : [];
4444

4545
if (!is_array($eventListeners)) {
4646
throw InvalidArgumentException::typeMisMatch('array', $eventListeners);

src/Factory/MenuFactory.php

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use PhpSchool\PhpWorkshop\Command\CreditsCommand;
1010
use PhpSchool\PhpWorkshop\Command\HelpCommand;
1111
use PhpSchool\PhpWorkshop\Command\MenuCommandInvoker;
12+
use PhpSchool\PhpWorkshop\Event\Event;
13+
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
14+
use PhpSchool\PhpWorkshop\Exercise\AbstractExercise;
1215
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1316
use PhpSchool\PhpWorkshop\ExerciseRenderer;
1417
use PhpSchool\PhpWorkshop\ExerciseRepository;
@@ -34,6 +37,7 @@ public function __invoke(ContainerInterface $c)
3437
$userState = $userStateSerializer->deSerialize();
3538
$exerciseRenderer = $c->get(ExerciseRenderer::class);
3639
$workshopType = $c->get(WorkshopType::class);
40+
$eventDispatcher = $c->get(EventDispatcher::class);
3741

3842
$builder = (new CliMenuBuilder)
3943
->addLineBreak();
@@ -46,17 +50,21 @@ public function __invoke(ContainerInterface $c)
4650
->addLineBreak('_')
4751
->addLineBreak()
4852
->addStaticItem('Exercises')
49-
->addStaticItem('---------')
50-
->addItems(
51-
array_map(function (ExerciseInterface $exercise) use ($exerciseRenderer, $userState, $workshopType) {
52-
return [
53-
$exercise->getName(),
54-
$exerciseRenderer,
55-
$userState->completedExercise($exercise->getName()),
56-
$this->isExerciseDisabled($exercise, $userState, $workshopType)
57-
];
58-
}, $exerciseRepository->findAll())
59-
)
53+
->addStaticItem('---------');
54+
55+
foreach ($exerciseRepository->findAll() as $exercise) {
56+
$builder->addItem(
57+
$exercise->getName(),
58+
function (CliMenu $menu) use ($exerciseRenderer, $eventDispatcher, $exercise) {
59+
$this->dispatchExerciseSelectedEvent($eventDispatcher, $exercise);
60+
$exerciseRenderer->__invoke($menu);
61+
},
62+
$userState->completedExercise($exercise->getName()),
63+
$this->isExerciseDisabled($exercise, $userState, $workshopType)
64+
);
65+
}
66+
67+
$builder
6068
->addLineBreak()
6169
->addLineBreak('-')
6270
->addLineBreak()
@@ -121,4 +129,20 @@ private function isExerciseDisabled(ExerciseInterface $exercise, UserState $user
121129
$previous = $exercise;
122130
return true;
123131
}
132+
133+
/**
134+
* @param EventDispatcher $eventDispatcher
135+
* @param ExerciseInterface $exercise
136+
*/
137+
private function dispatchExerciseSelectedEvent(EventDispatcher $eventDispatcher, ExerciseInterface $exercise)
138+
{
139+
$eventDispatcher->dispatch(
140+
new Event(
141+
sprintf(
142+
'exercise.selected.%s',
143+
AbstractExercise::normaliseName($exercise->getName())
144+
)
145+
)
146+
);
147+
}
124148
}

test/Factory/EventDispatcherFactoryTest.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ public function testConfigEventListenersThrowsExceptionIfEventsNotArray()
109109
->will($this->returnValue($selfCheckListener));
110110

111111
$c->expects($this->at(4))
112+
->method('has')
113+
->with('eventListeners')
114+
->willReturn(true);
115+
116+
$c->expects($this->at(5))
112117
->method('get')
113118
->with('eventListeners')
114119
->will($this->returnValue(new \stdClass));
@@ -150,6 +155,11 @@ public function testConfigEventListenersThrowsExceptionIfEventsListenersNotArray
150155
->will($this->returnValue($selfCheckListener));
151156

152157
$c->expects($this->at(4))
158+
->method('has')
159+
->with('eventListeners')
160+
->willReturn(true);
161+
162+
$c->expects($this->at(5))
153163
->method('get')
154164
->with('eventListeners')
155165
->will($this->returnValue([ 'someEvent' => new \stdClass]));
@@ -191,6 +201,11 @@ public function testConfigEventListenersThrowsExceptionIfEventsListenerNotCallab
191201
->will($this->returnValue($selfCheckListener));
192202

193203
$c->expects($this->at(4))
204+
->method('has')
205+
->with('eventListeners')
206+
->willReturn(true);
207+
208+
$c->expects($this->at(5))
194209
->method('get')
195210
->with('eventListeners')
196211
->will($this->returnValue([ 'someEvent' => [new \stdClass]]));
@@ -232,11 +247,16 @@ public function testConfigEventListenersThrowsExceptionIfEventsListenerContainer
232247
->will($this->returnValue($selfCheckListener));
233248

234249
$c->expects($this->at(4))
250+
->method('has')
251+
->with('eventListeners')
252+
->willReturn(true);
253+
254+
$c->expects($this->at(5))
235255
->method('get')
236256
->with('eventListeners')
237257
->will($this->returnValue([ 'someEvent' => ['nonExistingContainerEntry']]));
238258

239-
$c->expects($this->once())
259+
$c->expects($this->at(6))
240260
->method('has')
241261
->with('nonExistingContainerEntry')
242262
->will($this->returnValue(false));
@@ -278,16 +298,21 @@ public function testConfigEventListenersThrowsExceptionIfEventsListenerContainer
278298
->will($this->returnValue($selfCheckListener));
279299

280300
$c->expects($this->at(4))
301+
->method('has')
302+
->with('eventListeners')
303+
->willReturn(true);
304+
305+
$c->expects($this->at(5))
281306
->method('get')
282307
->with('eventListeners')
283308
->will($this->returnValue([ 'someEvent' => ['notCallableEntry']]));
284309

285-
$c->expects($this->once())
310+
$c->expects($this->at(6))
286311
->method('has')
287312
->with('notCallableEntry')
288313
->will($this->returnValue(true));
289314

290-
$c->expects($this->at(6))
315+
$c->expects($this->at(7))
291316
->method('get')
292317
->with('notCallableEntry')
293318
->will($this->returnValue(null));
@@ -332,11 +357,15 @@ public function testConfigEventListenersWithAnonymousFunction()
332357
};
333358

334359
$c->expects($this->at(4))
360+
->method('has')
361+
->with('eventListeners')
362+
->willReturn(true);
363+
364+
$c->expects($this->at(5))
335365
->method('get')
336366
->with('eventListeners')
337367
->will($this->returnValue([ 'someEvent' => [$callback]]));
338368

339-
340369
$dispatcher = (new EventDispatcherFactory)->__invoke($c);
341370
$this->assertInstanceOf(EventDispatcher::class, $dispatcher);
342371
$this->assertSame(
@@ -398,22 +427,25 @@ public function testConfigEventListenersWithContainerEntry()
398427
->with(SelfCheckListener::class)
399428
->will($this->returnValue($selfCheckListener));
400429

401-
402-
403430
$c->expects($this->at(4))
431+
->method('has')
432+
->with('eventListeners')
433+
->willReturn(true);
434+
435+
$c->expects($this->at(5))
404436
->method('get')
405437
->with('eventListeners')
406438
->will($this->returnValue([ 'someEvent' => ['containerEntry']]));
407439

408-
$c->expects($this->once())
440+
$c->expects($this->at(6))
409441
->method('has')
410442
->with('containerEntry')
411443
->will($this->returnValue(true));
412444

413445
$callback = function () {
414446
};
415447

416-
$c->expects($this->at(6))
448+
$c->expects($this->at(7))
417449
->method('get')
418450
->with('containerEntry')
419451
->will($this->returnValue($callback));

test/Factory/MenuFactoryTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PhpSchool\CliMenu\CliMenu;
77
use PhpSchool\PhpWorkshop\Command\CreditsCommand;
88
use PhpSchool\PhpWorkshop\Command\HelpCommand;
9+
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
910
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1011
use PhpSchool\PhpWorkshop\ExerciseRenderer;
1112
use PhpSchool\PhpWorkshop\ExerciseRepository;
@@ -53,7 +54,8 @@ public function testFactoryReturnsInstance()
5354
'bgColour' => 'black',
5455
'fgColour' => 'green',
5556
'workshopTitle' => 'TITLE',
56-
WorkshopType::class => WorkshopType::STANDARD()
57+
WorkshopType::class => WorkshopType::STANDARD(),
58+
EventDispatcher::class => $this->createMock(EventDispatcher::class),
5759
];
5860

5961
$container

0 commit comments

Comments
 (0)