Passed
Push — master ( 157368...699e44 )
by Adam
01:05 queued 10s
created

DoctrineBlameableExtension::loadConfiguration()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 22
cts 22
cp 1
rs 9.0488
c 0
b 0
f 0
cc 5
nc 5
nop 0
crap 5
1
<?php
2
/**
3
 * DoctrineBlameableExtension.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec <[email protected]>
8
 * @package        iPublikuj:DoctrineBlameable!
9
 * @subpackage     DI
10
 * @since          1.0.0
11
 *
12
 * @date           01.01.16
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\DoctrineBlameable\DI;
18
19
use Nette;
20
use Nette\DI;
21
use Nette\Schema;
22
23
use IPub\DoctrineBlameable;
24
use IPub\DoctrineBlameable\Events;
25
use IPub\DoctrineBlameable\Mapping;
26
use IPub\DoctrineBlameable\Security;
27
28
/**
29
 * Doctrine blameable extension container
30
 *
31
 * @package        iPublikuj:DoctrineBlameable!
32
 * @subpackage     DI
33
 *
34
 * @author         Adam Kadlec <[email protected]>
35
 */
36 1
final class DoctrineBlameableExtension extends DI\CompilerExtension
37
{
38
	/**
39
	 * {@inheritdoc}
40
	 */
41
	public function getConfigSchema() : Schema\Schema
42
	{
43 1
		return Schema\Expect::structure([
44 1
			'lazyAssociation' => Schema\Expect::bool(FALSE),
45 1
			'userEntity'      => Schema\Expect::anyOf(Schema\Expect::string(), Schema\Expect::type(DI\Definitions\Statement::class))->nullable(),
46 1
			'automapField'    => Schema\Expect::bool(TRUE),
47 1
			'userCallable'    => Schema\Expect::anyOf(Schema\Expect::string(), Schema\Expect::type(DI\Definitions\Statement::class))->default(Security\UserCallable::class),
48
		]);
49
	}
50
51
	/**
52
	 * {@inheritdoc}
53
	 */
54
	public function loadConfiguration() : void
55
	{
56 1
		$builder = $this->getContainerBuilder();
57 1
		$configuration = $this->getConfig();
58
59 1
		$builder->addDefinition($this->prefix('configuration'))
60 1
			->setType(DoctrineBlameable\Configuration::class)
61 1
			->setArguments([
62 1
				$configuration->userEntity,
63 1
				$configuration->lazyAssociation,
64 1
				$configuration->automapField,
65
			]);
66
67 1
		$userCallableDefinition = NULL;
68
69 1
		if ($configuration->userCallable !== NULL) {
70 1
			$userCallableDefinition = $builder->addDefinition($this->prefix('userCallable'));
71
72 1
			$factory = is_string($configuration->userCallable) ? new DI\Definitions\Statement($configuration->userCallable) : $configuration->userCallable;
73 1
			$userCallableDefinition->setFactory($factory);
74
75 1
			list($resolverClass) = (array) $this->normalizeEntity($userCallableDefinition->getFactory()->getEntity());
76
77 1
			if (class_exists($resolverClass)) {
78 1
				$userCallableDefinition->setType($resolverClass);
79
			}
80
		}
81
82 1
		$builder->addDefinition($this->prefix('driver'))
83 1
			->setType(Mapping\Driver\Blameable::class);
84
85 1
		$builder->addDefinition($this->prefix('subscriber'))
86 1
			->setType(Events\BlameableSubscriber::class)
87 1
			->setArguments([$userCallableDefinition instanceof DI\Definitions\ServiceDefinition ? $userCallableDefinition : NULL]);
88 1
	}
89
90
	/**
91
	 * {@inheritdoc}
92
	 */
93
	public function beforeCompile() : void
94
	{
95 1
		parent::beforeCompile();
96
97 1
		$builder = $this->getContainerBuilder();
98
99 1
		$builder->getDefinition($builder->getByType('Doctrine\ORM\EntityManagerInterface', TRUE))
100 1
			->addSetup('?->getEventManager()->addEventSubscriber(?)', ['@self', $builder->getDefinition($this->prefix('subscriber'))]);
101 1
	}
102
103
	/**
104
	 * @param Nette\Configurator $config
105
	 * @param string $extensionName
106
	 *
107
	 * @return void
108
	 */
109
	public static function register(
110
		Nette\Configurator $config,
111
		string $extensionName = 'doctrineBlameable'
112
	) : void {
113 1
		$config->onCompile[] = function (Nette\Configurator $config, Nette\DI\Compiler $compiler) use ($extensionName) {
114 1
			$compiler->addExtension($extensionName, new DoctrineBlameableExtension);
115 1
		};
116 1
	}
117
118
	/**
119
	 * @param $entity
120
	 *
121
	 * @return string|array  Class, @service, [Class, member], [@service, member], [, globalFunc], [Statement, member]
122
	 */
123
	private function normalizeEntity($entity)
124
	{
125
		// Get container builder
126 1
		$builder = $this->getContainerBuilder();
127
128
		if (
129 1
			is_string($entity)
130 1
			&& Nette\Utils\Strings::contains($entity, '::')
131 1
			&& !Nette\Utils\Strings::contains($entity, '?')
132
		) { // Class::method -> [Class, method]
133
			$entity = explode('::', $entity);
134
		}
135
136
		if (
137 1
			is_array($entity)
138 1
			&& $entity[0] instanceof DI\Definitions\ServiceDefinition
139
		) { // [ServiceDefinition, ...] -> [@serviceName, ...]
140
			$entity[0] = '@' . current(array_keys($builder->getDefinitions(), $entity[0], TRUE));
141
142
		} elseif (
143 1
			$entity instanceof DI\Definitions\ServiceDefinition
144
		) { // ServiceDefinition -> @serviceName
145
			$entity = '@' . current(array_keys($builder->getDefinitions(), $entity, TRUE));
146
147
		} elseif (
148 1
			is_array($entity)
149 1
			&& $entity[0] === $builder
150
		) { // [$builder, ...] -> [@container, ...]
151
			trigger_error("Replace object ContainerBuilder in Statement entity with '@container'.", E_USER_DEPRECATED);
152
153
			$entity[0] = '@' . md5($entity);
154
		}
155
156 1
		return $entity;
157
	}
158
}
159