EventDispatcherExtension   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 13
Bugs 2 Features 3
Metric Value
wmc 15
c 13
b 2
f 3
lcom 1
cbo 8
dl 0
loc 109
rs 10
ccs 53
cts 53
cp 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
A isKdybyEventsRegistered() 0 4 1
A bindNetteEvents() 0 15 4
A loadConfiguration() 0 10 2
A beforeCompile() 0 13 2
A addSubscribersToEventDispatcher() 0 9 2
A getDefinitionByType() 0 6 1
A decorateServiceDefinitionWithNetteEvent() 0 12 1
A bindEventDispatcherToSymfonyConsole() 0 8 2
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