1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the XiideaEasyAuditBundle package. |
5
|
|
|
* |
6
|
|
|
* (c) Xiidea <http://www.xiidea.net> |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the MIT license that is bundled |
9
|
|
|
* with this source code in the file LICENSE. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Xiidea\EasyAuditBundle\Resolver; |
13
|
|
|
|
14
|
|
|
use Symfony\Component\EventDispatcher\Event; |
15
|
|
|
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; |
16
|
|
|
use Symfony\Component\PropertyAccess\PropertyAccess; |
17
|
|
|
use Xiidea\EasyAuditBundle\Common\UserAwareComponent; |
18
|
|
|
use Xiidea\EasyAuditBundle\Entity\BaseAuditLog; |
19
|
|
|
use Xiidea\EasyAuditBundle\Events\DoctrineEvents; |
20
|
|
|
use Xiidea\EasyAuditBundle\Exception\InvalidServiceException; |
21
|
|
|
use Xiidea\EasyAuditBundle\Exception\UnrecognizedEntityException; |
22
|
|
|
use Xiidea\EasyAuditBundle\Exception\UnrecognizedEventInfoException; |
23
|
|
|
|
24
|
|
|
class EventResolverFactory extends UserAwareComponent |
25
|
|
|
{ |
26
|
|
|
private $customResolvers = array(); |
27
|
|
|
private $commonResolver; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var EventResolverInterface |
31
|
|
|
*/ |
32
|
|
|
private $entityEventResolver; |
33
|
|
|
|
34
|
|
|
private $resolverEventMap = array(); |
35
|
|
|
|
36
|
|
|
private $debug = false; |
37
|
|
|
private $userProperty; |
38
|
|
|
private $entityClass; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* EventResolverFactory constructor. |
42
|
|
|
* |
43
|
|
|
* @param array $resolverEventMap |
44
|
|
|
* @param $userProperty |
45
|
|
|
* @param $entityClass |
46
|
|
|
*/ |
47
|
|
|
public function __construct(array $resolverEventMap = array(), $userProperty = 'username', $entityClass = BaseAuditLog::class) |
48
|
|
|
{ |
49
|
|
|
$this->resolverEventMap = $resolverEventMap; |
50
|
|
|
$this->userProperty = $userProperty; |
51
|
|
|
$this->entityClass = $entityClass; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param Event $event |
56
|
|
|
* @param string $eventName |
57
|
|
|
* @return null|BaseAuditLog |
58
|
|
|
* @throws UnrecognizedEventInfoException |
59
|
|
|
* @throws \Exception |
60
|
|
|
*/ |
61
|
|
|
public function getEventLog(Event $event, $eventName) |
62
|
|
|
{ |
63
|
|
|
$eventLog = $this->getEventLogObject($this->getEventLogInfo($event, $eventName)); |
64
|
|
|
|
65
|
|
|
if ($eventLog === null) { |
66
|
|
|
return null; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
$eventLog->setTypeId($eventName); |
70
|
|
|
$eventLog->setIp($this->getClientIp()); |
71
|
|
|
$eventLog->setEventTime(new \DateTime()); |
72
|
|
|
$this->setUser($eventLog); |
73
|
|
|
|
74
|
|
|
return $eventLog; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param $eventInfo |
79
|
|
|
* |
80
|
|
|
* @return null|BaseAuditLog |
81
|
|
|
* @throws UnrecognizedEventInfoException |
82
|
|
|
* @throws \Exception |
83
|
|
|
*/ |
84
|
|
|
protected function getEventLogObject($eventInfo) |
85
|
|
|
{ |
86
|
|
|
if (empty($eventInfo)) { |
87
|
|
|
return null; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if ($eventInfo instanceof BaseAuditLog) { |
91
|
|
|
return $eventInfo; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
return $this->createEventObjectFromArray($eventInfo); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @param string $eventName |
99
|
|
|
* |
100
|
|
|
* @return EventResolverInterface |
101
|
|
|
*/ |
102
|
|
|
protected function getResolver($eventName) |
103
|
|
|
{ |
104
|
|
|
|
105
|
|
|
if ($this->isEntityEvent($eventName)) { |
106
|
|
|
return $this->entityEventResolver; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
|
110
|
|
|
if (isset($this->resolverEventMap[$eventName]) && isset($this->customResolvers[$this->resolverEventMap[$eventName]])) { |
111
|
|
|
return $this->customResolvers[$this->resolverEventMap[$eventName]]; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
return $this->commonResolver; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @param string $eventName |
119
|
|
|
* @return bool |
120
|
|
|
*/ |
121
|
|
|
protected function isEntityEvent($eventName) |
122
|
|
|
{ |
123
|
|
|
return in_array($eventName, DoctrineEvents::getConstants()); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @param Event $event |
128
|
|
|
* @param string $eventName |
129
|
|
|
* @return null |
130
|
|
|
* @throws InvalidServiceException |
131
|
|
|
*/ |
132
|
|
|
protected function getEventLogInfo(Event $event, $eventName) |
133
|
|
|
{ |
134
|
|
|
if ($event instanceof EmbeddedEventResolverInterface) { |
135
|
|
|
return $event->getEventLogInfo($eventName); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
if (null === $eventResolver = $this->getResolver($eventName)) { |
139
|
|
|
return null; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $eventResolver->getEventLogInfo($event, $eventName); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @param BaseAuditLog $entity |
147
|
|
|
* @throws \Exception |
148
|
|
|
*/ |
149
|
|
|
protected function setUser(BaseAuditLog $entity) |
150
|
|
|
{ |
151
|
|
|
if (null === $user = $this->getUser()) { |
152
|
|
|
$entity->setUser($this->getAnonymousUserName()); |
153
|
|
|
return; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
$entity->setUser($this->getSettablePropertyValue($this->userProperty, $user)); |
157
|
|
|
|
158
|
|
|
$this->setImpersonatingUser($entity, $this->userProperty); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* @return string |
164
|
|
|
*/ |
165
|
|
|
protected function getClientIp() |
166
|
|
|
{ |
167
|
|
|
$request = $this->getRequest(); |
168
|
|
|
|
169
|
|
|
if ($request) { |
170
|
|
|
return $request->getClientIp(); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return ""; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* @param $id |
178
|
|
|
* @param EventResolverInterface $resolver |
179
|
|
|
* |
180
|
|
|
* @throws \Exception|InvalidServiceException |
181
|
|
|
*/ |
182
|
|
View Code Duplication |
public function addCustomResolver($id, $resolver) |
|
|
|
|
183
|
|
|
{ |
184
|
|
|
if (!$resolver instanceof EventResolverInterface) { |
185
|
|
|
$this->handleException(new InvalidServiceException( |
186
|
|
|
'Resolver Service must implement' . EventResolverInterface::class |
187
|
|
|
)); |
188
|
|
|
|
189
|
|
|
return; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
$this->customResolvers[$id] = $resolver; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @param mixed $resolver |
197
|
|
|
* |
198
|
|
|
* @throws \Exception |
199
|
|
|
*/ |
200
|
|
View Code Duplication |
public function setCommonResolver($resolver) |
|
|
|
|
201
|
|
|
{ |
202
|
|
|
if (!$resolver instanceof EventResolverInterface) { |
203
|
|
|
$this->commonResolver = $this->handleException(new InvalidServiceException( |
|
|
|
|
204
|
|
|
'Resolver Service must implement' . EventResolverInterface::class |
205
|
|
|
)); |
206
|
|
|
|
207
|
|
|
return; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
$this->commonResolver = $resolver; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* @param \Exception $e |
216
|
|
|
* @throws \Exception |
217
|
|
|
* @return null |
218
|
|
|
*/ |
219
|
|
|
protected function handleException(\Exception $e) |
220
|
|
|
{ |
221
|
|
|
if ($this->isDebug()) { |
222
|
|
|
throw $e; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
return null; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param $eventInfo |
230
|
|
|
* @return null|BaseAuditLog |
231
|
|
|
* @throws \Exception |
232
|
|
|
*/ |
233
|
|
|
protected function createEventObjectFromArray($eventInfo) |
234
|
|
|
{ |
235
|
|
|
if (!is_array($eventInfo)) { |
236
|
|
|
return $this->handleException(new UnrecognizedEventInfoException()); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
$auditLogClass = $this->entityClass; |
240
|
|
|
$eventObject = new $auditLogClass(); |
241
|
|
|
|
242
|
|
|
if (!$eventObject instanceof BaseAuditLog) { |
243
|
|
|
return $this->handleException(new UnrecognizedEntityException()); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
return $eventObject->fromArray($eventInfo); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* @param $userProperty |
251
|
|
|
* @param $user |
252
|
|
|
* @return mixed |
253
|
|
|
*/ |
254
|
|
|
protected function getSettablePropertyValue($userProperty, $user) |
255
|
|
|
{ |
256
|
|
|
if (empty($userProperty)) { |
257
|
|
|
return $user; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
try { |
261
|
|
|
$propertyAccessor = PropertyAccess::createPropertyAccessor(); |
262
|
|
|
return $propertyAccessor->getValue($user, $userProperty); |
263
|
|
|
} catch (NoSuchPropertyException $e) { |
264
|
|
|
return $this->handleException($e); |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* @param BaseAuditLog $entity |
270
|
|
|
* @param $userProperty |
271
|
|
|
*/ |
272
|
|
|
protected function setImpersonatingUser(BaseAuditLog $entity, $userProperty) |
273
|
|
|
{ |
274
|
|
|
if (null !== $user = $this->getImpersonatingUser()) { |
275
|
|
|
$entity->setImpersonatingUser($this->getSettablePropertyValue($userProperty, $user)); |
276
|
|
|
} |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* @param mixed $debug |
281
|
|
|
*/ |
282
|
|
|
public function setDebug($debug) |
283
|
|
|
{ |
284
|
|
|
$this->debug = $debug; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* @param EventResolverInterface $entityEventResolver |
289
|
|
|
*/ |
290
|
|
|
public function setEntityEventResolver($entityEventResolver) |
291
|
|
|
{ |
292
|
|
|
$this->entityEventResolver = $entityEventResolver; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
private function isDebug() |
296
|
|
|
{ |
297
|
|
|
return $this->debug; |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.