DoctrineBlameableExtension::getConfigSchema()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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