Completed
Pull Request — master (#6)
by Patrik
10:14 queued 08:14
created

EventDispatcherExtension::bindNetteEvents()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 6
Bugs 0 Features 2
Metric Value
c 6
b 0
f 2
dl 0
loc 15
rs 9.2
ccs 11
cts 11
cp 1
cc 4
eloc 8
nc 4
nop 0
crap 4
1
<?php
2
3
/**
4
 * This file is part of Symnedi.
5
 * Copyright (c) 2014 Tomas Votruba (http://tomasvotruba.cz)
6
 */
7
8
namespace Symnedi\EventDispatcher\DI;
9
10
use Nette\DI\CompilerExtension;
11
use Nette\DI\ServiceDefinition;
12
use Nette\DI\Statement;
13
use Symfony\Component\EventDispatcher\EventDispatcher;
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
use Symnedi\EventDispatcher\Contract\DI\NetteEventItemInterface;
17
18
19
final class EventDispatcherExtension extends CompilerExtension
20
{
21
22
	/**
23
	 * {@inheritdoc}
24
	 */
25 5
	public function loadConfiguration()
26
	{
27 5
		if ($this->isKdybyEventsRegistered()) {
28 2
			return;
29
		}
30
31 3
		$containerBuilder = $this->getContainerBuilder();
32 3
		$containerBuilder->addDefinition($this->prefix('eventDispatcher'))
33 3
			->setClass(EventDispatcher::class);
34 3
	}
35
36
37
	/**
38
	 * {@inheritdoc}
39
	 */
40 2
	public function beforeCompile()
41
	{
42 2
		$eventDispatcher = $this->getDefinitionByType(EventDispatcherInterface::class);
43
44 2
		if ($this->isKdybyEventsRegistered()) {
45
			$eventDispatcher->setClass(EventDispatcher::class)
46
				->setFactory(NULL);
47
		}
48
49 2
		$this->addSubscribersToEventDispatcher();
50 2
		$this->bindNetteEvents();
51 2
		$this->bindEventDispatcherToSymfonyConsole();
52 2
	}
53
54
55
	/**
56
	 * @return bool
57
	 */
58 5
	private function isKdybyEventsRegistered()
59
	{
60 5
		return (bool) $this->compiler->getExtensions('Kdyby\Events\DI\EventsExtension');
61
	}
62
63
64 2
	private function addSubscribersToEventDispatcher()
65
	{
66 2
		$containerBuilder = $this->getContainerBuilder();
67 2
		$eventDispatcher = $this->getDefinitionByType(EventDispatcherInterface::class);
68
69 2
		foreach ($containerBuilder->findByType(EventSubscriberInterface::class) as $eventSubscriberDefinition) {
70 2
			$eventDispatcher->addSetup('addSubscriber', ['@' . $eventSubscriberDefinition->getClass()]);
71 2
		}
72 2
	}
73
74
75
	/**
76
	 * @param string $type
77
	 * @return ServiceDefinition
78
	 */
79 2
	private function getDefinitionByType($type)
80
	{
81 2
		$containerBuilder = $this->getContainerBuilder();
82 2
		$definitionName = $containerBuilder->getByType($type);
83 2
		return $containerBuilder->getDefinition($definitionName);
84
	}
85
86
87 2
	private function bindNetteEvents()
88
	{
89 2
		$containerBuilder = $this->getContainerBuilder();
90
91 2
		$netteEventList = (new NetteEventListFactory)->create();
92 2
		foreach ($netteEventList as $netteEvent) {
93 2
			if ( ! $serviceDefinitions = $containerBuilder->findByType($netteEvent->getClass())) {
94 1
				return;
95
			}
96
97 1
			foreach ($serviceDefinitions as $serviceDefinition) {
98 1
				$this->decorateServiceDefinitionWithNetteEvent($serviceDefinition, $netteEvent);
99 1
			}
100 1
		}
101 1
	}
102
103
104 1
	private function decorateServiceDefinitionWithNetteEvent(
105
		ServiceDefinition $serviceDefinition,
106
		NetteEventItemInterface $netteEvent
107
	) {
108 1
		$propertyStatement = new Statement('function () {
109
			$class = ?;
110
			$event = new $class(...func_get_args());
111
			?->dispatch(?, $event);
112 1
		}', [$netteEvent->getEventClass(), '@' . EventDispatcherInterface::class, $netteEvent->getEventName()]);
113
114 1
		$serviceDefinition->addSetup('$service->?[] = ?;', [$netteEvent->getProperty(), $propertyStatement]);
115 1
	}
116
117
118 2
	private function bindEventDispatcherToSymfonyConsole()
119
	{
120 2
		$containerBuilder = $this->getContainerBuilder();
121 2
		if ($consoleApplicationName = $containerBuilder->getByType('Symfony\Component\Console\Application')) {
122
			$consoleApplicationDefinition = $containerBuilder->getDefinition($consoleApplicationName);
123
			$consoleApplicationDefinition->addSetup('setDispatcher');
124
		}
125 2
	}
126
127
}
128