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

JMSAnnotationDriver::getMetadataForClass()   F

Complexity

Conditions 14
Paths 391

Size

Total Lines 53
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 14.3828

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 32
c 1
b 0
f 0
nc 391
nop 1
dl 0
loc 53
ccs 28
cts 32
cp 0.875
crap 14.3828
rs 3.0458

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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