Configuration   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 258
Duplicated Lines 0 %

Importance

Changes 5
Bugs 3 Features 0
Metric Value
wmc 28
eloc 93
dl 0
loc 258
rs 10
c 5
b 3
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getStorageMapper() 0 3 1
A setStorageMapper() 0 5 1
A isViewerEnabled() 0 3 1
A setProvider() 0 4 1
A getProvider() 0 3 1
A disableViewer() 0 5 1
A getIgnoredColumns() 0 3 1
A enableViewer() 0 5 1
A configureOptions() 0 22 1
A getTablePrefix() 0 3 1
A __construct() 0 21 4
A enableAuditFor() 0 7 2
B getEntities() 0 46 8
A setEntities() 0 6 1
A getTableSuffix() 0 3 1
A disableAuditFor() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DH\Auditor\Provider\Doctrine;
6
7
use DH\Auditor\Provider\ConfigurationInterface;
8
use DH\Auditor\Provider\Doctrine\Persistence\Helper\DoctrineHelper;
9
use DH\Auditor\Provider\Doctrine\Persistence\Schema\SchemaManager;
10
use DH\Auditor\Provider\Doctrine\Service\AuditingService;
11
use Symfony\Component\OptionsResolver\OptionsResolver;
12
13
/**
14
 * @see \DH\Auditor\Tests\Provider\Doctrine\ConfigurationTest
15
 */
16
final class Configuration implements ConfigurationInterface
17
{
18
    private ?DoctrineProvider $provider = null;
19
20
    private string $tablePrefix;
21
22
    private string $tableSuffix;
23
24
    /**
25
     * @var array<string>
26
     */
27
    private array $ignoredColumns = [];
28
29
    private ?array $entities = null;
30
31
    private array $storageServices = [];
32
33
    private array $auditingServices = [];
34
35
    private bool $isViewerEnabled;
36
37
    private bool $initialized = false;
38
39
    /**
40
     * @var null|callable
41
     */
42
    private $storageMapper;
43
44
    private array $annotationLoaded = [];
45
46
    public function __construct(array $options)
47
    {
48
        $resolver = new OptionsResolver();
49
        $this->configureOptions($resolver);
50
        $config = $resolver->resolve($options);
51
52
        $this->tablePrefix = $config['table_prefix'];
53
        $this->tableSuffix = $config['table_suffix'];
54
        $this->ignoredColumns = $config['ignored_columns'];
55
56
        if (isset($config['entities']) && !empty($config['entities'])) {
57
            // use entity names as array keys for easier lookup
58
            foreach ($config['entities'] as $auditedEntity => $entityOptions) {
59
                $this->entities[$auditedEntity] = $entityOptions;
60
            }
61
        }
62
63
        $this->storageServices = $config['storage_services'];
64
        $this->auditingServices = $config['auditing_services'];
65
        $this->isViewerEnabled = $config['viewer'];
66
        $this->storageMapper = $config['storage_mapper'];
67
    }
68
69
    /**
70
     * Set the value of entities.
71
     *
72
     * This method completely overrides entities configuration
73
     * including annotation configuration
74
     *
75
     * @param array<int|string, mixed> $entities
76
     */
77
    public function setEntities(array $entities): self
78
    {
79
        $this->entities = $entities;
80
        $this->initialized = false;
81
82
        return $this;
83
    }
84
85
    /**
86
     * enable audit Controller and its routing.
87
     *
88
     * @return $this
89
     */
90
    public function enableViewer(): self
91
    {
92
        $this->isViewerEnabled = true;
93
94
        return $this;
95
    }
96
97
    /**
98
     * disable audit Controller and its routing.
99
     *
100
     * @return $this
101
     */
102
    public function disableViewer(): self
103
    {
104
        $this->isViewerEnabled = false;
105
106
        return $this;
107
    }
108
109
    /**
110
     * Get enabled flag.
111
     */
112
    public function isViewerEnabled(): bool
113
    {
114
        return $this->isViewerEnabled;
115
    }
116
117
    /**
118
     * Get the value of tablePrefix.
119
     */
120
    public function getTablePrefix(): string
121
    {
122
        return $this->tablePrefix;
123
    }
124
125
    /**
126
     * Get the value of tableSuffix.
127
     */
128
    public function getTableSuffix(): string
129
    {
130
        return $this->tableSuffix;
131
    }
132
133
    /**
134
     * Get the value of excludedColumns.
135
     *
136
     * @return array<string>
137
     */
138
    public function getIgnoredColumns(): array
139
    {
140
        return $this->ignoredColumns;
141
    }
142
143
    /**
144
     * Get the value of entities.
145
     */
146
    public function getEntities(): array
147
    {
148
        if ($this->initialized && null !== $this->entities) {
149
            return $this->entities;
150
        }
151
152
        if ($this->provider instanceof \DH\Auditor\Provider\Doctrine\DoctrineProvider) {
153
            $schemaManager = new SchemaManager($this->provider);
154
155
            /** @var array<AuditingService> $auditingServices */
156
            $auditingServices = $this->provider->getAuditingServices();
157
            foreach ($auditingServices as $auditingService) {
158
                $entityManager = $auditingService->getEntityManager();
159
                $platform = $entityManager->getConnection()->getDatabasePlatform();
160
161
                // do not load annotations if they're already loaded
162
                if (!isset($this->annotationLoaded[$auditingService->getName()]) || !$this->annotationLoaded[$auditingService->getName()]) {
163
                    $this->provider->loadAnnotations($entityManager, $this->entities ?? []);
164
                    $this->annotationLoaded[$auditingService->getName()] = true;
165
                }
166
167
                \assert(null !== $this->entities);
168
                foreach (array_keys($this->entities) as $entity) {
169
                    $meta = $entityManager->getClassMetadata(DoctrineHelper::getRealClassName($entity));
170
                    $entityTableName = $meta->getTableName();
171
                    $namespaceName = $meta->getSchemaName() ?? '';
172
173
                    $computedTableName = $schemaManager->resolveTableName($entityTableName, $namespaceName, $platform);
174
                    $this->entities[$entity]['table_schema'] = $namespaceName;
175
                    $this->entities[$entity]['table_name'] = $entityTableName;
176
                    //                    $this->entities[$entity]['computed_table_name'] = $entityTableName;
177
                    $this->entities[$entity]['computed_table_name'] = $computedTableName;
178
                    $this->entities[$entity]['audit_table_schema'] = $namespaceName;
179
                    $this->entities[$entity]['audit_table_name'] = $schemaManager->computeAuditTablename($entityTableName, $this);
180
                    //                    $this->entities[$entity]['computed_audit_table_name'] = $schemaManager->computeAuditTablename($this->entities[$entity], $this, $platform);
181
                    $this->entities[$entity]['computed_audit_table_name'] = $schemaManager->computeAuditTablename(
182
                        $computedTableName,
183
                        $this
184
                    );
185
                }
186
            }
187
188
            $this->initialized = true;
189
        }
190
191
        return $this->entities ?? [];
192
    }
193
194
    /**
195
     * Enables auditing for a specific entity.
196
     *
197
     * @param string $entity Entity class name
198
     *
199
     * @return $this
200
     */
201
    public function enableAuditFor(string $entity): self
202
    {
203
        if (isset($this->getEntities()[$entity])) {
204
            $this->entities[$entity]['enabled'] = true;
205
        }
206
207
        return $this;
208
    }
209
210
    /**
211
     * Disables auditing for a specific entity.
212
     *
213
     * @param string $entity Entity class name
214
     *
215
     * @return $this
216
     */
217
    public function disableAuditFor(string $entity): self
218
    {
219
        if (isset($this->getEntities()[$entity])) {
220
            $this->entities[$entity]['enabled'] = false;
221
        }
222
223
        return $this;
224
    }
225
226
    public function setStorageMapper(callable $mapper): self
227
    {
228
        $this->storageMapper = $mapper;
229
230
        return $this;
231
    }
232
233
    /**
234
     * @return null|callable|string
235
     */
236
    public function getStorageMapper(): mixed
237
    {
238
        return $this->storageMapper;
239
    }
240
241
    public function getProvider(): ?DoctrineProvider
242
    {
243
        return $this->provider;
244
    }
245
246
    public function setProvider(DoctrineProvider $provider): void
247
    {
248
        $this->provider = $provider;
249
        $this->initialized = false;
250
    }
251
252
    private function configureOptions(OptionsResolver $resolver): void
253
    {
254
        // https://symfony.com/doc/current/components/options_resolver.html
255
        $resolver
256
            ->setDefaults([
257
                'table_prefix' => '',
258
                'table_suffix' => '_audit',
259
                'ignored_columns' => [],
260
                'entities' => [],
261
                'storage_services' => [],
262
                'auditing_services' => [],
263
                'viewer' => true,
264
                'storage_mapper' => null,
265
            ])
266
            ->setAllowedTypes('table_prefix', 'string')
267
            ->setAllowedTypes('table_suffix', 'string')
268
            ->setAllowedTypes('ignored_columns', 'array')
269
            ->setAllowedTypes('entities', 'array')
270
            ->setAllowedTypes('storage_services', 'array')
271
            ->setAllowedTypes('auditing_services', 'array')
272
            ->setAllowedTypes('viewer', 'bool')
273
            ->setAllowedTypes('storage_mapper', ['null', 'string', 'callable'])
274
        ;
275
    }
276
}
277