-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathAttributesLoader.php
More file actions
125 lines (113 loc) · 5.56 KB
/
AttributesLoader.php
File metadata and controls
125 lines (113 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
declare(strict_types=1);
namespace MakinaCorpus\DbToolsBundle\Anonymization\Config\Loader;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\Console\EntityManagerProvider;
use MakinaCorpus\DbToolsBundle\Anonymization\Config\AnonymizationConfig;
use MakinaCorpus\DbToolsBundle\Anonymization\Config\AnonymizerConfig;
use MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Options;
use MakinaCorpus\DbToolsBundle\Attribute\Anonymize;
class AttributesLoader implements LoaderInterface
{
public function __construct(
private EntityManagerProvider $entityManagerProvider,
/**
* Root directory from which the configuration was loaded. It allows
* later file loading (for example, when sources are CSV or TXT files).
*/
private readonly string $basePath,
) {}
#[\Override]
public function load(AnonymizationConfig $config): void
{
try {
$entityManager = $this->entityManagerProvider->getManager($config->connectionName);
} catch (\InvalidArgumentException) {
// Entity manager on the given connection does not exists.
// Simply pass attribute lookup.
return;
}
$metadataFactory = $entityManager->getMetadataFactory();
$metadatas = $metadataFactory->getAllMetadata();
foreach ($metadatas as $metadata) {
\assert($metadata instanceof ClassMetadata);
if ($metadata->isMappedSuperclass || $metadata->isEmbeddedClass) {
continue;
}
$embeddedClassesConfig = [];
foreach ($metadata->embeddedClasses as $name => $embeddedClass) {
$className = $embeddedClass['class'];
$embeddedClassesConfig[$className] = [];
$reflexionClass = new \ReflectionClass($className);
foreach ($reflexionClass->getProperties() as $reflexionProperty) {
if ($attributes = $reflexionProperty->getAttributes(Anonymize::class)) {
$anonymization = $attributes[0]->newInstance();
$embeddedClassesConfig[$className][$reflexionProperty->getName()] = $anonymization;
}
}
}
$reflexionClass = $metadata->getReflectionClass();
if ($attributes = $reflexionClass->getAttributes(Anonymize::class)) {
// There can only be one of those attributes, foreach() is
// required because of reflection API signature.
foreach ($attributes as $key => $attribute) {
$anonymization = $attribute->newInstance();
$config->add(new AnonymizerConfig(
$metadata->getTableName(),
// For a anonymization setted on table, we give an arbitrary name.
$anonymization->type . '_' . $key,
$anonymization->type,
new Options($anonymization->options),
$this->basePath,
));
}
}
foreach ($metadata->fieldMappings as $fieldName => $fieldValues) {
// Field name with dot are part of Embeddables.
if (\str_contains($fieldName, '.')) {
if (\key_exists($fieldValues['originalClass'], $embeddedClassesConfig)) {
$embeddedClassConfig = $embeddedClassesConfig[$fieldValues['originalClass']];
if (\key_exists($fieldValues['originalField'], $embeddedClassConfig)) {
$propertyConfig = $embeddedClassConfig[$fieldValues['originalField']];
$config->add(new AnonymizerConfig(
$metadata->getTableName(),
$metadata->getColumnName($fieldName),
$propertyConfig->type,
new Options($propertyConfig->options),
$this->basePath,
));
}
}
continue;
}
$columnName = $metadata->getColumnName($fieldName);
if ($metadata->isInheritedField($fieldName)) {
$fieldMapping = $metadata->getFieldMapping($fieldName);
// @phpstan-ignore-next-line
if (\is_array($fieldMapping)) {
// Code for doctrine/orm:^2.0.
$ownerClass = $fieldMapping['inherited'];
} else {
// Code for doctrine/orm:^3.0.
$ownerClass = $fieldMapping->inherited;
}
$parentMetadata = $metadataFactory->getMetadataFor($ownerClass);
\assert($parentMetadata instanceof ClassMetadata);
$tableName = $parentMetadata->getTableName();
} else {
$tableName = $metadata->getTableName();
}
if ($attributes = $metadata->getReflectionProperty($fieldName)->getAttributes(Anonymize::class)) {
$anonymization = $attributes[0]->newInstance();
$config->add(new AnonymizerConfig(
$tableName,
$columnName,
$anonymization->type,
new Options($anonymization->options),
$this->basePath,
));
}
}
}
}
}