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 79aef98

Browse files
Merge pull request #133 from php-school/register-event-listeners-via-config
Register event listeners via config
2 parents 602dc82 + 71bc53a commit 79aef98

File tree

5 files changed

+525
-19
lines changed

5 files changed

+525
-19
lines changed

‎src/Application.php‎

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ final class Application
5959
*/
6060
private $bgColour = 'black';
6161

62+
/**
63+
* @var string
64+
*/
65+
private $frameworkConfigLocation = __DIR__ . '/../app/config.php';
66+
6267
/**
6368
* It should be instantiated with the title of
6469
* the workshop and the path to the DI configuration file.
@@ -156,24 +161,7 @@ public function setBgColour($colour)
156161
*/
157162
public function run()
158163
{
159-
$containerBuilder = new ContainerBuilder;
160-
$containerBuilder->addDefinitions(__DIR__ . '/../app/config.php');
161-
$containerBuilder->addDefinitions($this->diConfigFile);
162-
163-
$containerBuilder->addDefinitions(array_merge(
164-
[
165-
'workshopTitle' => $this->workshopTitle,
166-
'exercises' => $this->exercises,
167-
'workshopLogo' => $this->logo,
168-
'bgColour' => $this->bgColour,
169-
'fgColour' => $this->fgColour,
170-
]
171-
));
172-
173-
$containerBuilder->useAutowiring(false);
174-
$containerBuilder->useAnnotations(false);
175-
176-
$container = $containerBuilder->build();
164+
$container = $this->getContainer();
177165

178166
foreach ($this->exercises as $exercise) {
179167
if (false === $container->has($exercise)) {
@@ -229,4 +217,33 @@ public function run()
229217
}
230218
return $exitCode;
231219
}
220+
221+
/**
222+
* @return \DI\Container
223+
*/
224+
private function getContainer()
225+
{
226+
$containerBuilder = new ContainerBuilder;
227+
$containerBuilder->addDefinitions(
228+
array_merge_recursive(
229+
require $this->frameworkConfigLocation,
230+
require $this->diConfigFile
231+
)
232+
);
233+
234+
$containerBuilder->addDefinitions(
235+
[
236+
'workshopTitle' => $this->workshopTitle,
237+
'exercises' => $this->exercises,
238+
'workshopLogo' => $this->logo,
239+
'bgColour' => $this->bgColour,
240+
'fgColour' => $this->fgColour,
241+
]
242+
);
243+
244+
$containerBuilder->useAutowiring(false);
245+
$containerBuilder->useAnnotations(false);
246+
247+
return $containerBuilder->build();
248+
}
232249
}

‎src/CommandRouter.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private function addCommand(CommandDefinition $c)
8484
*
8585
* @param array $args
8686
* @return int
87-
* @throws CliRouteNotExists
87+
* @throws CliRouteNotExistsException
8888
*/
8989
public function route(array $args = null)
9090
{

‎src/Factory/EventDispatcherFactory.php‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Interop\Container\ContainerInterface;
66
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
7+
use PhpSchool\PhpWorkshop\Exception\InvalidArgumentException;
78
use PhpSchool\PhpWorkshop\Listener\CodePatchListener;
89
use PhpSchool\PhpWorkshop\Listener\PrepareSolutionListener;
910
use PhpSchool\PhpWorkshop\Listener\SelfCheckListener;
@@ -20,6 +21,7 @@ class EventDispatcherFactory
2021
/**
2122
* @param ContainerInterface $container
2223
* @return EventDispatcher
24+
* @throws InvalidArgumentException
2325
*/
2426
public function __invoke(ContainerInterface $container)
2527
{
@@ -37,6 +39,59 @@ public function __invoke(ContainerInterface $container)
3739

3840
$dispatcher->listen('verify.post.check', $container->get(SelfCheckListener::class));
3941

42+
//add listeners from config
43+
$eventListeners = $container->get('eventListeners') ?: [];
44+
45+
if (!is_array($eventListeners)) {
46+
throw InvalidArgumentException::typeMisMatch('array', $eventListeners);
47+
}
48+
49+
array_walk($eventListeners, function ($listeners, $eventName) use ($dispatcher, $container) {
50+
if (!is_array($listeners)) {
51+
throw InvalidArgumentException::typeMisMatch('array', $listeners);
52+
}
53+
54+
$this->attachListeners($eventName, $listeners, $container, $dispatcher);
55+
});
56+
4057
return $dispatcher;
4158
}
59+
60+
/**
61+
* @param string $eventName
62+
* @param array $listeners
63+
* @param ContainerInterface $container
64+
* @param EventDispatcher $dispatcher
65+
* @throws \PhpSchool\PhpWorkshop\Exception\InvalidArgumentException
66+
*/
67+
private function attachListeners(
68+
$eventName,
69+
array $listeners,
70+
ContainerInterface $container,
71+
EventDispatcher $dispatcher
72+
) {
73+
array_walk($listeners, function ($listener) use ($eventName, $dispatcher, $container) {
74+
if (is_callable($listener)) {
75+
return $dispatcher->listen($eventName, $listener);
76+
}
77+
78+
if (!is_string($listener)) {
79+
throw new InvalidArgumentException(
80+
sprintf('Listener must be a callable or a container entry for a callable service.')
81+
);
82+
}
83+
84+
if (!$container->has($listener)) {
85+
throw new InvalidArgumentException(sprintf('Container has no entry named: "%s"', $listener));
86+
}
87+
88+
$listener = $container->get($listener);
89+
90+
if (!is_callable($listener)) {
91+
throw InvalidArgumentException::typeMisMatch('callable', $listener);
92+
}
93+
94+
return $dispatcher->listen($eventName, $listener);
95+
});
96+
}
4297
}

‎test/ApplicationTest.php‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace PhpSchool\PhpWorkshopTest;
4+
5+
use PhpSchool\PhpWorkshop\Application;
6+
use PHPUnit_Framework_TestCase;
7+
8+
/**
9+
* @author Aydin Hassan <aydin@hotmail.co.uk>
10+
*/
11+
class ApplicationTest extends PHPUnit_Framework_TestCase
12+
{
13+
public function testEventListenersFromLocalAndWorkshopConfigAreMerged()
14+
{
15+
16+
$frameworkFileContent = '<?php return [';
17+
$frameworkFileContent .= " 'eventListeners' => [";
18+
$frameworkFileContent .= " 'event1' => [";
19+
$frameworkFileContent .= " 'entry1',";
20+
$frameworkFileContent .= " 'entry2',";
21+
$frameworkFileContent .= ' ]';
22+
$frameworkFileContent .= ' ]';
23+
$frameworkFileContent .= '];';
24+
25+
$localFileContent = '<?php return [';
26+
$localFileContent .= " 'eventListeners' => [";
27+
$localFileContent .= " 'event1' => [";
28+
$localFileContent .= " 'entry3',";
29+
$localFileContent .= ' ]';
30+
$localFileContent .= ' ]';
31+
$localFileContent .= '];';
32+
33+
$localFile = sprintf('%s/%s', sys_get_temp_dir(), uniqid($this->getName(), true));
34+
$frameworkFile = sprintf('%s/%s', sys_get_temp_dir(), uniqid($this->getName(), true));
35+
file_put_contents($frameworkFile, $frameworkFileContent);
36+
file_put_contents($localFile, $localFileContent);
37+
38+
$app = new Application('Test App', $localFile);
39+
40+
$rm = new \ReflectionMethod($app, 'getContainer');
41+
$rm->setAccessible(true);
42+
43+
$rp = new \ReflectionProperty(Application::class, 'frameworkConfigLocation');
44+
$rp->setAccessible(true);
45+
$rp->setValue($app, $frameworkFile);
46+
47+
$container = $rm->invoke($app);
48+
49+
$eventListeners = $container->get('eventListeners');
50+
51+
$this->assertEquals(
52+
[
53+
'event1' => [
54+
'entry1',
55+
'entry2',
56+
'entry3',
57+
]
58+
],
59+
$eventListeners
60+
);
61+
}
62+
}

0 commit comments

Comments
(0)

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