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\Utils; |
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
|
|
|
* @var array |
40
|
|
|
*/ |
41
|
|
|
private $defaults = [ |
42
|
|
|
'lazyAssociation' => FALSE, |
43
|
|
|
'userEntity' => NULL, |
44
|
|
|
'automapField' => TRUE, |
45
|
|
|
'userCallable' => Security\UserCallable::class, |
46
|
|
|
]; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @return void |
50
|
|
|
* |
51
|
|
|
* @throws Utils\AssertionException |
52
|
|
|
*/ |
53
|
|
|
public function loadConfiguration() : void |
54
|
|
|
{ |
55
|
|
|
// Get container builder |
56
|
1 |
|
$builder = $this->getContainerBuilder(); |
57
|
|
|
|
58
|
|
|
// Merge extension default config |
59
|
1 |
|
$this->setConfig(DI\Config\Helpers::merge($this->config, DI\Helpers::expand($this->defaults, $builder->parameters))); |
|
|
|
|
60
|
|
|
|
61
|
|
|
// Get extension configuration |
62
|
1 |
|
$configuration = $this->getConfig(); |
63
|
|
|
|
64
|
1 |
|
Utils\Validators::assert($configuration['userEntity'], 'type|null', 'userEntity'); |
65
|
1 |
|
Utils\Validators::assert($configuration['lazyAssociation'], 'bool', 'lazyAssociation'); |
66
|
1 |
|
Utils\Validators::assert($configuration['automapField'], 'bool', 'automapField'); |
67
|
|
|
|
68
|
1 |
|
$builder->addDefinition($this->prefix('configuration')) |
69
|
1 |
|
->setType(DoctrineBlameable\Configuration::class) |
70
|
1 |
|
->setArguments([ |
71
|
1 |
|
$configuration['userEntity'], |
72
|
1 |
|
$configuration['lazyAssociation'], |
73
|
1 |
|
$configuration['automapField'] |
74
|
|
|
]); |
75
|
|
|
|
76
|
1 |
|
$userCallable = NULL; |
77
|
|
|
|
78
|
1 |
|
if ($configuration['userCallable'] !== NULL) { |
79
|
1 |
|
$definition = $builder->addDefinition($this->prefix(md5($configuration['userCallable']))); |
80
|
|
|
|
81
|
1 |
|
list($factory) = DI\Helpers::filterArguments([ |
82
|
1 |
|
is_string($configuration['userCallable']) ? new DI\Statement($configuration['userCallable']) : $configuration['userCallable'] |
83
|
|
|
]); |
84
|
|
|
|
85
|
1 |
|
$definition->setFactory($factory); |
86
|
|
|
|
87
|
1 |
|
list($resolverClass) = (array) $builder->normalizeEntity($definition->getFactory()->getEntity()); |
88
|
|
|
|
89
|
|
|
if (class_exists($resolverClass)) { |
90
|
|
|
$definition->setType($resolverClass); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
$userCallable = $definition; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
$builder->addDefinition($this->prefix('driver')) |
97
|
|
|
->setType(Mapping\Driver\Blameable::class); |
98
|
|
|
|
99
|
|
|
$builder->addDefinition($this->prefix('subscriber')) |
100
|
|
|
->setType(Events\BlameableSubscriber::class) |
101
|
|
|
->setArguments([$userCallable instanceof DI\ServiceDefinition ? '@' . $userCallable->getType() : NULL]); |
|
|
|
|
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* {@inheritdoc} |
106
|
|
|
*/ |
107
|
|
|
public function beforeCompile() : void |
108
|
|
|
{ |
109
|
|
|
parent::beforeCompile(); |
110
|
|
|
|
111
|
|
|
$builder = $this->getContainerBuilder(); |
112
|
|
|
|
113
|
|
|
$builder->getDefinition($builder->getByType('Doctrine\ORM\EntityManagerInterface', TRUE)) |
114
|
|
|
->addSetup('?->getEventManager()->addEventSubscriber(?)', ['@self', $builder->getDefinition($this->prefix('subscriber'))]); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @param Nette\Configurator $config |
119
|
|
|
* @param string $extensionName |
120
|
|
|
* |
121
|
|
|
* @return void |
122
|
|
|
*/ |
123
|
|
|
public static function register(Nette\Configurator $config, string $extensionName = 'doctrineBlameable') : void |
124
|
|
|
{ |
125
|
1 |
|
$config->onCompile[] = function (Nette\Configurator $config, Nette\DI\Compiler $compiler) use ($extensionName) { |
126
|
1 |
|
$compiler->addExtension($extensionName, new DoctrineBlameableExtension); |
127
|
1 |
|
}; |
128
|
1 |
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @return string|array Class, @service, [Class, member], [@service, member], [, globalFunc], [Statement, member] |
132
|
|
|
*/ |
133
|
|
|
private function normalizeEntity($entity) |
134
|
|
|
{ |
135
|
|
|
// Get container builder |
136
|
|
|
$builder = $this->getContainerBuilder(); |
137
|
|
|
|
138
|
|
|
if (is_string($entity) && Strings::contains($entity, '::') && !Strings::contains($entity, '?')) { // Class::method -> [Class, method] |
139
|
|
|
$entity = explode('::', $entity); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
if (is_array($entity) && $entity[0] instanceof ServiceDefinition) { // [ServiceDefinition, ...] -> [@serviceName, ...] |
|
|
|
|
143
|
|
|
$entity[0] = '@' . current(array_keys($builder->getDefinitions(), $entity[0], true)); |
144
|
|
|
|
145
|
|
|
} elseif ($entity instanceof ServiceDefinition) { // ServiceDefinition -> @serviceName |
|
|
|
|
146
|
|
|
$entity = '@' . current(array_keys($builder->getDefinitions(), $entity, true)); |
147
|
|
|
|
148
|
|
|
} elseif (is_array($entity) && $entity[0] === $builder) { // [$builder, ...] -> [@container, ...] |
149
|
|
|
trigger_error("Replace object ContainerBuilder in Statement entity with '@container'.", E_USER_DEPRECATED); |
150
|
|
|
|
151
|
|
|
$entity[0] = '@' . self::THIS_CONTAINER; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
return $entity; |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.