Passed
Pull Request — master (#143)
by Federico
02:13
created

AuditConfiguration::isAuditedField()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 32
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
c 0
b 0
f 0
nc 8
nop 2
dl 0
loc 32
rs 8.8333
1
<?php
2
3
namespace DH\DoctrineAuditBundle;
4
5
use DH\DoctrineAuditBundle\Annotation\AnnotationLoader;
6
use DH\DoctrineAuditBundle\Helper\ClassInfoTrait;
7
use DH\DoctrineAuditBundle\User\UserProviderInterface;
8
use Doctrine\ORM\EntityManagerInterface;
9
use ReflectionMethod;
10
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
11
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
12
use Symfony\Component\HttpFoundation\RequestStack;
13
14
class AuditConfiguration
15
{
16
    use ClassInfoTrait;
17
18
    /**
19
     * @var UserProviderInterface
20
     */
21
    protected $userProvider;
22
23
    /**
24
     * @var RequestStack
25
     */
26
    protected $requestStack;
27
    /**
28
     * @var string
29
     */
30
    private $tablePrefix;
31
32
    /**
33
     * @var string
34
     */
35
    private $tableSuffix;
36
37
    /**
38
     * @var string
39
     */
40
    private $timezone;
41
42
    /**
43
     * @var array
44
     */
45
    private $ignoredColumns = [];
46
47
    /**
48
     * @var array
49
     */
50
    private $entities = [];
51
52
    /**
53
     * @var bool
54
     */
55
    private $enabled = true;
56
57
    /**
58
     * @var FirewallMap
59
     */
60
    private $firewallMap;
61
62
    /**
63
     * @var EntityManagerInterface
64
     */
65
    private $entityManager;
66
67
    /**
68
     * @var null|AnnotationLoader
69
     */
70
    private $annotationLoader;
71
72
    /**
73
     * @var EventDispatcherInterface
74
     */
75
    private $dispatcher;
76
77
    /**
78
     * @var bool
79
     */
80
    private $is_pre43_dispatcher;
81
82
    private $annotationLoaded = false;
83
84
    public function __construct(
85
        array $config,
86
        UserProviderInterface $userProvider,
87
        RequestStack $requestStack,
88
        FirewallMap $firewallMap,
89
        EntityManagerInterface $entityManager,
90
        ?AnnotationLoader $annotationLoader,
91
        EventDispatcherInterface $dispatcher
92
    ) {
93
        $this->userProvider = $userProvider;
94
        $this->requestStack = $requestStack;
95
        $this->firewallMap = $firewallMap;
96
        $this->entityManager = $entityManager;
97
        $this->annotationLoader = $annotationLoader;
98
        $this->dispatcher = $dispatcher;
99
100
        $r = new ReflectionMethod($this->dispatcher, 'dispatch');
101
        $p = $r->getParameters();
102
        $this->is_pre43_dispatcher = 2 === \count($p) && 'event' !== $p[0]->name;
103
104
        $this->enabled = $config['enabled'];
105
        $this->tablePrefix = $config['table_prefix'];
106
        $this->tableSuffix = $config['table_suffix'];
107
        $this->timezone = $config['timezone'];
108
        $this->ignoredColumns = $config['ignored_columns'];
109
110
        if (isset($config['entities']) && !empty($config['entities'])) {
111
            // use entity names as array keys for easier lookup
112
            foreach ($config['entities'] as $auditedEntity => $entityOptions) {
113
                $this->entities[$auditedEntity] = $entityOptions;
114
            }
115
        }
116
    }
117
118
    public function isPre43Dispatcher(): bool
119
    {
120
        return $this->is_pre43_dispatcher;
121
    }
122
123
    /**
124
     * Set the value of entities.
125
     *
126
     * This method completely overrides entities configuration
127
     * including annotation configuration
128
     *
129
     * @param array $entities
130
     */
131
    public function setEntities(array $entities): void
132
    {
133
        $this->annotationLoaded = true;
134
        $this->entities = $entities;
135
    }
136
137
    /**
138
     * enabled audit.
139
     *
140
     * @return $this
141
     */
142
    public function enable(): self
143
    {
144
        $this->enabled = true;
145
146
        return $this;
147
    }
148
149
    /**
150
     * disable audit.
151
     *
152
     * @return $this
153
     */
154
    public function disable(): self
155
    {
156
        $this->enabled = false;
157
158
        return $this;
159
    }
160
161
    /**
162
     * Get enabled flag.
163
     *
164
     * @return bool
165
     */
166
    public function isEnabled(): bool
167
    {
168
        return $this->enabled;
169
    }
170
171
    /**
172
     * Returns true if $entity is auditable.
173
     *
174
     * @param object|string $entity
175
     *
176
     * @return bool
177
     */
178
    public function isAuditable($entity): bool
179
    {
180
        $class = \is_object($entity) ? \get_class($entity) : $entity;
181
        $class = $this->getRealClassName($class);
182
183
        // is $entity part of audited entities?
184
        if (!\array_key_exists($class, $this->getEntities())) {
185
            // no => $entity is not audited
186
            return false;
187
        }
188
189
        return true;
190
    }
191
192
    /**
193
     * Returns true if $entity is audited.
194
     *
195
     * @param object|string $entity
196
     *
197
     * @return bool
198
     */
199
    public function isAudited($entity): bool
200
    {
201
        if (!$this->enabled) {
202
            return false;
203
        }
204
205
        $class = \is_object($entity) ? \get_class($entity) : $entity;
206
        $class = $this->getRealClassName($class);
207
208
        // is $entity part of audited entities?
209
        if (!\array_key_exists($class, $this->getEntities())) {
210
            // no => $entity is not audited
211
            return false;
212
        }
213
214
        $entityOptions = $this->getEntities()[$class];
215
216
        if (null === $entityOptions) {
217
            // no option defined => $entity is audited
218
            return true;
219
        }
220
221
        if (isset($entityOptions['enabled'])) {
222
            return (bool) $entityOptions['enabled'];
223
        }
224
225
        return true;
226
    }
227
228
    /**
229
     * Returns true if $field is audited.
230
     *
231
     * @param object|string $entity
232
     * @param string        $field
233
     *
234
     * @return bool
235
     */
236
    public function isAuditedField($entity, string $field): bool
237
    {
238
        // is $field is part of globally ignored columns?
239
        if (\in_array($field, $this->ignoredColumns, true)) {
240
            // yes => $field is not audited
241
            return false;
242
        }
243
244
        // is $entity audited?
245
        if (!$this->isAudited($entity)) {
246
            // no => $field is not audited
247
            return false;
248
        }
249
250
        $class = \is_object($entity) ? \get_class($entity) : $entity;
251
        $class = $this->getRealClassName($class);
252
253
        $entityOptions = $this->getEntities()[$class];
254
255
        if (null === $entityOptions) {
256
            // no option defined => $field is audited
257
            return true;
258
        }
259
260
        // are columns excluded and is field part of them?
261
        if (isset($entityOptions['ignored_columns']) &&
262
            \in_array($field, $entityOptions['ignored_columns'], true)) {
263
            // yes => $field is not audited
264
            return false;
265
        }
266
267
        return true;
268
    }
269
270
    /**
271
     * Get the value of tablePrefix.
272
     *
273
     * @return string
274
     */
275
    public function getTablePrefix(): string
276
    {
277
        return $this->tablePrefix;
278
    }
279
280
    /**
281
     * Get the value of tableSuffix.
282
     *
283
     * @return string
284
     */
285
    public function getTableSuffix(): string
286
    {
287
        return $this->tableSuffix;
288
    }
289
290
    /**
291
     * Get the value of timezone.
292
     *
293
     * @return string
294
     */
295
    public function getTimezone(): string
296
    {
297
        return $this->timezone;
298
    }
299
300
    /**
301
     * Get the value of excludedColumns.
302
     *
303
     * @return array
304
     */
305
    public function getIgnoredColumns(): array
306
    {
307
        return $this->ignoredColumns;
308
    }
309
310
    /**
311
     * Get the value of entities.
312
     *
313
     * @return array
314
     */
315
    public function getEntities(): array
316
    {
317
        if (false === $this->annotationLoaded && null !== $this->annotationLoader) {
318
            // Update config using annotations
319
            $config = $this->annotationLoader->load();
320
            $this->entities = array_merge($this->entities, $config);
321
            $this->annotationLoaded = true;
322
        }
323
324
        return $this->entities;
325
    }
326
327
    /**
328
     * Enables auditing for a specific entity.
329
     *
330
     * @param string $entity Entity class name
331
     *
332
     * @return $this
333
     */
334
    public function enableAuditFor(string $entity): self
335
    {
336
        if (isset($this->getEntities()[$entity])) {
337
            $this->entities[$entity]['enabled'] = true;
338
        }
339
340
        return $this;
341
    }
342
343
    /**
344
     * Disables auditing for a specific entity.
345
     *
346
     * @param string $entity Entity class name
347
     *
348
     * @return $this
349
     */
350
    public function disableAuditFor(string $entity): self
351
    {
352
        if (isset($this->getEntities()[$entity])) {
353
            $this->entities[$entity]['enabled'] = false;
354
        }
355
356
        return $this;
357
    }
358
359
    /**
360
     * Get the value of userProvider.
361
     *
362
     * @return UserProviderInterface
363
     */
364
    public function getUserProvider(): ?UserProviderInterface
365
    {
366
        return $this->userProvider;
367
    }
368
369
    /**
370
     * Get the value of requestStack.
371
     *
372
     * @return RequestStack
373
     */
374
    public function getRequestStack(): RequestStack
375
    {
376
        return $this->requestStack;
377
    }
378
379
    /**
380
     * Gets the value of firewallMap.
381
     *
382
     * @return FirewallMap
383
     */
384
    public function getFirewallMap(): FirewallMap
385
    {
386
        return $this->firewallMap;
387
    }
388
389
    /**
390
     * @return EntityManagerInterface
391
     */
392
    public function getEntityManager(): EntityManagerInterface
393
    {
394
        return $this->entityManager;
395
    }
396
397
    /**
398
     * @return null|AnnotationLoader
399
     */
400
    public function getAnnotationLoader(): ?AnnotationLoader
401
    {
402
        return $this->annotationLoader;
403
    }
404
405
    /**
406
     * @return EventDispatcherInterface
407
     */
408
    public function getEventDispatcher(): EventDispatcherInterface
409
    {
410
        return $this->dispatcher;
411
    }
412
}
413