Passed
Push — master ( 7defe8...edb967 )
by Vincent
25:00
created

JMSAnnotationDriver::isPropertyStatic()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.2559

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 10
ccs 3
cts 5
cp 0.6
crap 2.2559
rs 10
1
<?php
2
3
namespace Bdf\Serializer\Metadata\Driver;
4
5
use Bdf\Serializer\Metadata\Builder\ClassMetadataBuilder;
6
use Bdf\Serializer\Metadata\ClassMetadata;
7
use JMS\Serializer\Metadata\ClassMetadata as JMSClassMetadata;
8
use JMS\Serializer\Metadata\PropertyMetadata as JMSPropertyMetadata;
9
use Metadata\ClassMetadata as JMSBaseClassMetadata;
10
use Metadata\Driver\DriverInterface as JMSDriverInterface;
11
use ReflectionClass;
12
13
/**
14
 * The annotation driver use JMS annotation
15
 *
16
 * Works only with php 7.2
17
 */
18
class JMSAnnotationDriver implements DriverInterface
19
{
20
    /**
21
     * @var JMSDriverInterface
22
     */
23
    private $driver;
24
25
    /**
26
     * AnnotationDriver constructor.
27
     *
28
     * @param JMSDriverInterface $driver
29
     */
30 2
    public function __construct(JMSDriverInterface $driver)
31
    {
32 2
        $this->driver = $driver;
33 2
    }
34
35
    /**
36
     * {@inheritDoc}
37
     */
38 2
    public function getMetadataForClass(ReflectionClass $class): ?ClassMetadata
39
    {
40 2
        $builder = new ClassMetadataBuilder($class);
41 2
        $jmsMetadata = $this->getJmsMetadata($class);
42
43 2
        if ($this->isJmsMetadataEmpty($jmsMetadata)) {
44 1
            return null;
45
        }
46
47 1
        if ($jmsMetadata instanceof JMSClassMetadata) {
48 1
            if (isset($jmsMetadata->postSerializeMethods[0])) {
49
                $builder->postDenormalization($jmsMetadata->postSerializeMethods[0]->name);
50
            }
51
        }
52
53
        /** @var JMSPropertyMetadata $metadata */
54 1
        foreach ($jmsMetadata->propertyMetadata as $property => $metadata) {
55 1
            if ($this->isPropertyStatic($metadata)) {
56 1
                continue;
57
            }
58
59 1
            $propertyBuilder = $builder->add($property);
60 1
            $propertyBuilder->alias($metadata->serializedName);
61 1
            $propertyBuilder->readOnly($metadata->readOnly);
62 1
            $propertyBuilder->inline($metadata->inline);
63
64 1
            if ($metadata->sinceVersion) {
65 1
                $propertyBuilder->since($metadata->sinceVersion);
66
            }
67 1
            if ($metadata->untilVersion) {
68 1
                $propertyBuilder->until($metadata->untilVersion);
69
            }
70 1
            if ($metadata->getter) {
71
                $propertyBuilder->readWith($metadata->getter);
72
            }
73 1
            if ($metadata->setter) {
74
                $propertyBuilder->writeWith($metadata->setter);
75
            }
76 1
            if ($metadata->groups) {
77 1
                $propertyBuilder->groups($metadata->groups);
78
            }
79 1
            if ($metadata->type) {
80 1
                if (JMSPropertyMetadata::isCollectionList($metadata->type)) {
81 1
                    $propertyBuilder->type($metadata->type['params'][0]['name'])->collection();
82 1
                } elseif (JMSPropertyMetadata::isCollectionMap($metadata->type)) {
83
                    $propertyBuilder->type($metadata->type['params'][1]['name'])->collection();
84
                } else {
85 1
                    $propertyBuilder->type($metadata->type['name']);
86
                }
87
            }
88
        }
89
90 1
        return $builder->build();
91
    }
92
93
    /**
94
     * Gets all the annotations from this class
95
     *
96
     * @param ReflectionClass $reflection
97
     *
98
     * @return JMSBaseClassMetadata|null
99
     */
100 2
    private function getJmsMetadata(ReflectionClass $reflection): ?JMSBaseClassMetadata
101
    {
102 2
        $metadata = null;
103
104
        do {
105 2
            $current = $this->driver->loadMetadataForClass($reflection);
106
107 2
            if ($metadata && $current) {
108 1
                $current->merge($metadata);
0 ignored issues
show
Bug introduced by
The method merge() does not exist on Metadata\ClassMetadata. It seems like you code against a sub-type of Metadata\ClassMetadata such as Metadata\MergeableClassMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
                $current->/** @scrutinizer ignore-call */ 
109
                          merge($metadata);
Loading history...
109
            }
110
111 2
            $metadata = $current;
112 2
            $reflection = $reflection->getParentClass();
113 2
        } while ($reflection);
114
115 2
        return $metadata;
116
    }
117
118
    /**
119
     * Checks whether the property of this metadata is static.
120
     *
121
     * @param JMSPropertyMetadata $metadata
122
     *
123
     * @return bool
124
     */
125 1
    private function isPropertyStatic(JMSPropertyMetadata $metadata): bool
126
    {
127
        try {
128 1
            $reflection = new \ReflectionProperty($metadata->class, $metadata->name);
129
130 1
            return $reflection->isStatic();
131
        } catch (\ReflectionException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
132
        }
133
134
        return false;
135
    }
136
137
    /**
138
     * Check whether the jms metadata has been loaded by default
139
     *
140
     * @param JMSBaseClassMetadata|null $jmsMetadata
141
     *
142
     * @return bool
143
     */
144 2
    private function isJmsMetadataEmpty(?JMSBaseClassMetadata $jmsMetadata): bool
145
    {
146 2
        if (!$jmsMetadata) {
147
            return true;
148
        }
149
150 2
        foreach ($jmsMetadata->propertyMetadata as $metadata) {
151 2
            $class = get_class($metadata);
152 2
            $default = new $class($metadata->class, $metadata->name);
153 2
            $attributes = (array)$metadata;
154
155 2
            unset($attributes['serializedName']);
156
157 2
            foreach ($attributes as $attribute => $value) {
158 2
                if ($default->$attribute !== $value) {
159 1
                    return false;
160
                }
161
            }
162
        }
163
164 1
        return true;
165
    }
166
}
167