Completed
Pull Request — master (#34)
by
unknown
09:45
created

EventResolverFactory::getResolver()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 1
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\Document\BaseAuditLog;
19
use Xiidea\EasyAuditBundle\Events\DoctrineEvents;
20
use Xiidea\EasyAuditBundle\Exception\InvalidServiceException;
21
use Xiidea\EasyAuditBundle\Exception\UnrecognizedDocumentException;
22
use Xiidea\EasyAuditBundle\Exception\UnrecognizedEventInfoException;
23
24
class EventResolverFactory extends UserAwareComponent
25
{
26
    private $customResolvers = [];
27
28
    private $commonResolver;
29
30
    /**
31
     * @var EventResolverInterface
32
     */
33
    private $documentEventResolver;
34
35
    private $resolverEventMap;
36
37
    private $debug = false;
38
39
    private $userProperty;
40
41
    private $documentClass;
42
43
    /**
44
     * EventResolverFactory constructor.
45
     *
46
     * @param array $resolverEventMap
47
     * @param $userProperty
48
     * @param $documentClass
49
     */
50
    public function __construct(
51
        array $resolverEventMap = [],
52
        $userProperty = 'username',
53
        $documentClass = BaseAuditLog::class
54
    )
55
    {
56
        $this->resolverEventMap = $resolverEventMap;
57
        $this->userProperty = $userProperty;
58
        $this->documentClass = $documentClass;
59
    }
60
61
    /**
62
     * @param Event $event
63
     * @param string $eventName
64
     * @return null|BaseAuditLog
65
     * @throws UnrecognizedEventInfoException
66
     * @throws \Exception
67
     */
68
    public function getEventLog(Event $event, $eventName)
69
    {
70
        $eventLog = $this->getEventLogObject($this->getEventLogInfo($event, $eventName));
71
72
        if ($eventLog === null) {
73
            return null;
74
        }
75
76
        $eventLog->setTypeId($eventName);
77
        $eventLog->setIp($this->getClientIp());
78
        $eventLog->setEventTime(new \DateTime());
79
        $this->setUser($eventLog);
80
81
        return $eventLog;
82
    }
83
84
    /**
85
     * @param $eventInfo
86
     *
87
     * @return null|BaseAuditLog
88
     * @throws UnrecognizedEventInfoException
89
     * @throws \Exception
90
     */
91
    protected function getEventLogObject($eventInfo)
92
    {
93
        if (empty($eventInfo)) {
94
            return null;
95
        }
96
97
        if ($eventInfo instanceof BaseAuditLog) {
98
            return $eventInfo;
99
        }
100
101
        return $this->createEventObjectFromArray($eventInfo);
102
    }
103
104
    /**
105
     * @param string $eventName
106
     *
107
     * @return EventResolverInterface
108
     */
109
    protected function getResolver($eventName)
110
    {
111
        if ($this->isDocumentEvent($eventName)) {
112
            return $this->documentEventResolver;
113
        }
114
115
        if (isset($this->resolverEventMap[$eventName], $this->customResolvers[$this->resolverEventMap[$eventName]])) {
116
            return $this->customResolvers[$this->resolverEventMap[$eventName]];
117
        }
118
119
        return $this->commonResolver;
120
    }
121
122
    /**
123
     * @param string $eventName
124
     * @return bool
125
     */
126
    protected function isDocumentEvent($eventName)
127
    {
128
        return \in_array($eventName, DoctrineEvents::getConstants(), true);
129
    }
130
131
    /**
132
     * @param Event $event
133
     * @param string $eventName
134
     * @return null
135
     * @throws InvalidServiceException
136
     */
137
    protected function getEventLogInfo(Event $event, $eventName)
138
    {
139
        if ($event instanceof EmbeddedEventResolverInterface) {
140
            return $event->getEventLogInfo($eventName);
141
        }
142
143
        if (null === $eventResolver = $this->getResolver($eventName)) {
144
            return null;
145
        }
146
147
        return $eventResolver->getEventLogInfo($event, $eventName);
148
    }
149
150
    /**
151
     * @param BaseAuditLog $document
152
     * @throws \Exception
153
     */
154
    protected function setUser(BaseAuditLog $document)
155
    {
156
        if (null === $user = $this->getUser()) {
157
            $document->setUser($this->getAnonymousUserName());
158
159
            return;
160
        }
161
162
        $document->setUser($this->getSettablePropertyValue($this->userProperty, $user));
163
164
        $this->setImpersonatingUser($document, $this->userProperty);
165
    }
166
167
    /**
168
     * @return string
169
     */
170
    protected function getClientIp()
171
    {
172
        $request = $this->getRequest();
173
174
        if ($request) {
175
            return $request->getClientIp();
176
        }
177
178
        return "";
179
    }
180
181
    /**
182
     * @param $id
183
     * @param EventResolverInterface $resolver
184
     *
185
     * @throws \Exception|InvalidServiceException
186
     */
187 View Code Duplication
    public function addCustomResolver($id, $resolver)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
188
    {
189
        if (!$resolver instanceof EventResolverInterface) {
190
            $this->handleException(
191
                new InvalidServiceException(
192
                    'Resolver Service must implement' . EventResolverInterface::class
193
                )
194
            );
195
196
            return;
197
        }
198
199
        $this->customResolvers[$id] = $resolver;
200
    }
201
202
    /**
203
     * @param mixed $resolver
204
     *
205
     * @throws \Exception
206
     */
207 View Code Duplication
    public function setCommonResolver($resolver)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
208
    {
209
        if (!$resolver instanceof EventResolverInterface) {
210
            $this->commonResolver = $this->handleException(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $this->commonResolver is correct as $this->handleException(n...olverInterface::class)) (which targets Xiidea\EasyAuditBundle\R...tory::handleException()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
211
                new InvalidServiceException(
212
                    'Resolver Service must implement' . EventResolverInterface::class
213
                )
214
            );
215
216
            return;
217
        }
218
219
        $this->commonResolver = $resolver;
220
    }
221
222
    /**
223
     * @param \Exception $e
224
     * @throws \Exception
225
     * @return null
226
     */
227
    protected function handleException(\Exception $e)
228
    {
229
        if ($this->isDebug()) {
230
            throw $e;
231
        }
232
233
        return null;
234
    }
235
236
    /**
237
     * @param $eventInfo
238
     * @return null|BaseAuditLog
239
     * @throws \Exception
240
     */
241
    protected function createEventObjectFromArray($eventInfo)
242
    {
243
        if (!is_array($eventInfo)) {
244
            return $this->handleException(new UnrecognizedEventInfoException());
245
        }
246
247
        $auditLogClass = $this->documentClass;
248
        $eventObject = new $auditLogClass();
249
250
        if (!$eventObject instanceof BaseAuditLog) {
251
            return $this->handleException(new UnrecognizedDocumentException());
252
        }
253
254
        return $eventObject->fromArray($eventInfo);
255
    }
256
257
    /**
258
     * @param $userProperty
259
     * @param $user
260
     * @return mixed
261
     */
262
    protected function getSettablePropertyValue($userProperty, $user)
263
    {
264
        if (empty($userProperty)) {
265
            return $user;
266
        }
267
268
        try {
269
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
270
271
            return $propertyAccessor->getValue($user, $userProperty);
272
        } catch (NoSuchPropertyException $e) {
273
            return $this->handleException($e);
274
        }
275
    }
276
277
    /**
278
     * @param BaseAuditLog $document
279
     * @param $userProperty
280
     */
281
    protected function setImpersonatingUser(BaseAuditLog $document, $userProperty)
282
    {
283
        if (null !== $user = $this->getImpersonatingUser()) {
284
            $document->setImpersonatingUser($this->getSettablePropertyValue($userProperty, $user));
285
        }
286
    }
287
288
    /**
289
     * @param mixed $debug
290
     */
291
    public function setDebug($debug)
292
    {
293
        $this->debug = $debug;
294
    }
295
296
    /**
297
     * @param EventResolverInterface $documentEventResolver
298
     */
299
    public function setDocumentEventResolver($documentEventResolver)
300
    {
301
        $this->documentEventResolver = $documentEventResolver;
302
    }
303
304
    private function isDebug()
305
    {
306
        return $this->debug;
307
    }
308
}
309