Passed
Push — issue101 ( 331f7b )
by Damien
07:27
created

AnnotationLoader::getAllProperties()   B

Complexity

Conditions 9
Paths 50

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 23
rs 8.0555
cc 9
nc 50
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DH\Auditor\Provider\Doctrine\Auditing\Annotation;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\Mapping\Entity;
10
use Doctrine\Persistence\Mapping\ClassMetadata;
11
use ReflectionClass;
12
13
class AnnotationLoader
14
{
15
    private ?AnnotationReader $reader = null;
16
17
    private EntityManagerInterface $entityManager;
18
19
    public function __construct(EntityManagerInterface $entityManager, bool $useAttributesOnly = false)
20
    {
21
        $this->entityManager = $entityManager;
22
        $this->reader = class_exists(AnnotationReader::class) && !$useAttributesOnly ? new AnnotationReader() : null;
23
    }
24
25
    public function load(): array
26
    {
27
        $configuration = [];
28
29
        $metadatas = $this->entityManager->getMetadataFactory()->getAllMetadata();
30
        foreach ($metadatas as $metadata) {
31
            $config = $this->getEntityConfiguration($metadata);
32
            if (null !== $config) {
33
                $configuration[$metadata->getName()] = $config;
34
            }
35
        }
36
37
        return $configuration;
38
    }
39
40
    private function getEntityConfiguration(ClassMetadata $metadata): ?array
41
    {
42
        $annotation = null;
43
        $auditableAnnotation = null;
44
        $securityAnnotation = null;
45
        $reflection = $metadata->getReflectionClass();
46
47
        // Check that we have an Entity annotation or attribute
48
        $attributes = \PHP_VERSION_ID >= 80000 && method_exists($reflection, 'getAttributes') ? $reflection->getAttributes(Entity::class) : null;
49
        if (\is_array($attributes) && \count($attributes) > 0) {
50
            $annotation = $attributes[0]->newInstance();
51
        } elseif (null !== $this->reader) {
52
            $annotation = $this->reader->getClassAnnotation($reflection, Entity::class);
53
        }
54
55
        if (null === $annotation) {
56
            return null;
57
        }
58
59
        // Check that we have an Auditable annotation or attribute
60
        $attributes = \PHP_VERSION_ID >= 80000 && method_exists($reflection, 'getAttributes') ? $reflection->getAttributes(Auditable::class) : null;
61
        if (\is_array($attributes) && \count($attributes) > 0) {
62
            $auditableAnnotation = $attributes[0]->newInstance();
63
        } elseif (null !== $this->reader) {
64
            $auditableAnnotation = $this->reader->getClassAnnotation($reflection, Auditable::class);
65
        }
66
67
        if (null === $auditableAnnotation) {
68
            return null;
69
        }
70
71
        // Check that we have a Security annotation or attribute
72
        $attributes = \PHP_VERSION_ID >= 80000 && method_exists($reflection, 'getAttributes') ? $reflection->getAttributes(Security::class) : null;
73
        if (\is_array($attributes) && \count($attributes) > 0) {
74
            $securityAnnotation = $attributes[0]->newInstance();
75
        } elseif (null !== $this->reader) {
76
            $securityAnnotation = $this->reader->getClassAnnotation($reflection, Security::class);
77
        }
78
79
        $roles = null === $securityAnnotation ? null : [Security::VIEW_SCOPE => $securityAnnotation->view];
80
81
        // Are there any Ignore annotation or attribute?
82
        $ignoredColumns = $this->getAllProperties($reflection);
83
84
        return [
85
            'ignored_columns' => $ignoredColumns,
86
            'enabled' => $auditableAnnotation->enabled,
87
            'roles' => $roles,
88
        ];
89
    }
90
91
    private function getAllProperties(ReflectionClass $reflection): array
92
    {
93
        $annotationProperty = null;
94
        $properties = [];
95
96
        foreach ($reflection->getProperties() as $property) {
97
            $attributes = \PHP_VERSION_ID >= 80000 && method_exists($property, 'getAttributes') ? $property->getAttributes(Ignore::class) : null;
98
            if (\is_array($attributes) && \count($attributes) > 0) {
99
                $annotationProperty = $attributes[0]->newInstance();
100
            } elseif (null !== $this->reader) {
101
                $annotationProperty = $this->reader->getPropertyAnnotation($property, Ignore::class);
102
            }
103
104
            if (null !== $annotationProperty) {
105
                $properties[] = $property->getName();
106
            }
107
        }
108
109
        if (false !== $reflection->getParentClass()) {
110
            $properties = array_unique(array_merge($this->getAllProperties($reflection->getParentClass()), $properties));
111
        }
112
113
        return $properties;
114
    }
115
}
116