EventDispatcherExtension::bindNetteEvents()   A
last analyzed

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 4
	public function loadConfiguration()
26
	{
27 4
		if ($this->isKdybyEventsRegistered()) {
28 1
			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 3
	public function beforeCompile()
41
	{
42 3
		$eventDispatcher = $this->getDefinitionByType(EventDispatcherInterface::class);
43
44 3
		if ($this->isKdybyEventsRegistered()) {
45 1
			$eventDispatcher->setClass(EventDispatcher::class)
46 1
				->setFactory(NULL);
47 1
		}
48
49 3
		$this->addSubscribersToEventDispatcher();
50 3
		$this->bindNetteEvents();
51 3
		$this->bindEventDispatcherToSymfonyConsole();
52 3
	}
53
54
55
	/**
56
	 * @return bool
57
	 */
58 4
	private function isKdybyEventsRegistered()
59
	{
60 4
		return (bool) $this->compiler->getExtensions('Kdyby\Events\DI\EventsExtension');
61
	}
62
63
64 3
	private function addSubscribersToEventDispatcher()
65
	{
66 3
		$containerBuilder = $this->getContainerBuilder();
67 3
		$eventDispatcher = $this->getDefinitionByType(EventDispatcherInterface::class);
68
69 3
		foreach ($containerBuilder->findByType(EventSubscriberInterface::class) as $eventSubscriberDefinition) {
70 2
			$eventDispatcher->addSetup('addSubscriber', ['@' . $eventSubscriberDefinition->getClass()]);
71 3
		}
72 3
	}
73
74
75
	/**
76
	 * @param string $type
77
	 * @return ServiceDefinition
78
	 */
79 3
	private function getDefinitionByType($type)
80
	{
81 3
		$containerBuilder = $this->getContainerBuilder();
82 3
		$definitionName = $containerBuilder->getByType($type);
83 3
		return $containerBuilder->getDefinition($definitionName);
84
	}
85
86
87 3
	private function bindNetteEvents()
88
	{
89 3
		$containerBuilder = $this->getContainerBuilder();
90
91 3
		$netteEventList = (new NetteEventListFactory)->create();
92 3
		foreach ($netteEventList as $netteEvent) {
93 3
			if ( ! $serviceDefinitions = $containerBuilder->findByType($netteEvent->getClass())) {
94 2
				return;
95
			}
96
97 2
			foreach ($serviceDefinitions as $serviceDefinition) {
98 2
				$this->decorateServiceDefinitionWithNetteEvent($serviceDefinition, $netteEvent);
99 2
			}
100 2
		}
101 1
	}
102
103
104 2
	private function decorateServiceDefinitionWithNetteEvent(
105
		ServiceDefinition $serviceDefinition,
106
		NetteEventItemInterface $netteEvent
107
	) {
108 2
		$propertyStatement = new Statement('function () {
109
			$class = ?;
110
			$event = new $class(...func_get_args());
111
			?->dispatch(?, $event);
112 2
		}', [$netteEvent->getEventClass(), '@' . EventDispatcherInterface::class, $netteEvent->getEventName()]);
113
114 2
		$serviceDefinition->addSetup('$service->?[] = ?;', [$netteEvent->getProperty(), $propertyStatement]);
115 2
	}
116
117
118 3
	private function bindEventDispatcherToSymfonyConsole()
119
	{
120 3
		$containerBuilder = $this->getContainerBuilder();
121 3
		if ($consoleApplicationName = $containerBuilder->getByType('Symfony\Component\Console\Application')) {
122 1
			$consoleApplicationDefinition = $containerBuilder->getDefinition($consoleApplicationName);
123 1
			$consoleApplicationDefinition->addSetup('setDispatcher');
124 1
		}
125 3
	}
126
127
}
128