Completed
Push — master ( a11a2f...a1ae8b )
by Asmir
03:55
created

AnnotationDriver::loadMetadataForClass()   F

Complexity

Conditions 60
Paths 756

Size

Total Lines 179
Code Lines 145

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 154
CRAP Score 60.0582

Importance

Changes 0
Metric Value
dl 0
loc 179
ccs 154
cts 158
cp 0.9747
rs 2
c 0
b 0
f 0
cc 60
eloc 145
nc 756
nop 1
crap 60.0582

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
/*
4
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Serializer\Metadata\Driver;
20
21
use Doctrine\Common\Annotations\Reader;
22
use JMS\Serializer\Annotation\Accessor;
23
use JMS\Serializer\Annotation\AccessorOrder;
24
use JMS\Serializer\Annotation\AccessType;
25
use JMS\Serializer\Annotation\Discriminator;
26
use JMS\Serializer\Annotation\Exclude;
27
use JMS\Serializer\Annotation\ExcludeIf;
28
use JMS\Serializer\Annotation\ExclusionPolicy;
29
use JMS\Serializer\Annotation\Expose;
30
use JMS\Serializer\Annotation\Groups;
31
use JMS\Serializer\Annotation\HandlerCallback;
32
use JMS\Serializer\Annotation\Inline;
33
use JMS\Serializer\Annotation\MaxDepth;
34
use JMS\Serializer\Annotation\PostDeserialize;
35
use JMS\Serializer\Annotation\PostSerialize;
36
use JMS\Serializer\Annotation\PreSerialize;
37
use JMS\Serializer\Annotation\ReadOnly;
38
use JMS\Serializer\Annotation\SerializedName;
39
use JMS\Serializer\Annotation\Since;
40
use JMS\Serializer\Annotation\SkipWhenEmpty;
41
use JMS\Serializer\Annotation\Type;
42
use JMS\Serializer\Annotation\Until;
43
use JMS\Serializer\Annotation\VirtualProperty;
44
use JMS\Serializer\Annotation\XmlAttribute;
45
use JMS\Serializer\Annotation\XmlAttributeMap;
46
use JMS\Serializer\Annotation\XmlDiscriminator;
47
use JMS\Serializer\Annotation\XmlElement;
48
use JMS\Serializer\Annotation\XmlKeyValuePairs;
49
use JMS\Serializer\Annotation\XmlList;
50
use JMS\Serializer\Annotation\XmlMap;
51
use JMS\Serializer\Annotation\XmlNamespace;
52
use JMS\Serializer\Annotation\XmlRoot;
53
use JMS\Serializer\Annotation\XmlValue;
54
use JMS\Serializer\Exception\InvalidArgumentException;
55
use JMS\Serializer\GraphNavigator;
56
use JMS\Serializer\Metadata\ClassMetadata;
57
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
58
use JMS\Serializer\Metadata\PropertyMetadata;
59
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
60
use Metadata\Driver\DriverInterface;
61
use Metadata\MethodMetadata;
62
63
class AnnotationDriver implements DriverInterface
64
{
65
    private $reader;
66
67 428
    public function __construct(Reader $reader)
68
    {
69 428
        $this->reader = $reader;
70 428
    }
71
72 262
    public function loadMetadataForClass(\ReflectionClass $class)
73
    {
74 262
        $classMetadata = new ClassMetadata($name = $class->name);
75 262
        $classMetadata->fileResources[] = $class->getFilename();
76
77 262
        $propertiesMetadata = array();
78 262
        $propertiesAnnotations = array();
79
80 262
        $exclusionPolicy = 'NONE';
81 262
        $excludeAll = false;
82 262
        $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY;
83 262
        $readOnlyClass = false;
84 262
        foreach ($this->reader->getClassAnnotations($class) as $annot) {
85 150
            if ($annot instanceof ExclusionPolicy) {
86 35
                $exclusionPolicy = $annot->policy;
87 150
            } elseif ($annot instanceof XmlRoot) {
88 65
                $classMetadata->xmlRootName = $annot->name;
89 65
                $classMetadata->xmlRootNamespace = $annot->namespace;
90 149
            } elseif ($annot instanceof XmlNamespace) {
91 23
                $classMetadata->registerNamespace($annot->uri, $annot->prefix);
92 115
            } elseif ($annot instanceof Exclude) {
93
                $excludeAll = true;
94 94
            } elseif ($annot instanceof AccessType) {
95 3
                $classAccessType = $annot->type;
96 94
            } elseif ($annot instanceof ReadOnly) {
97 3
                $readOnlyClass = true;
98 91
            } elseif ($annot instanceof AccessorOrder) {
99 46
                $classMetadata->setAccessorOrder($annot->order, $annot->custom);
100 88
            } elseif ($annot instanceof Discriminator) {
101 21
                if ($annot->disabled) {
102
                    $classMetadata->discriminatorDisabled = true;
103
                } else {
104 21
                    $classMetadata->setDiscriminator($annot->field, $annot->map, $annot->groups);
105
                }
106 42
            } elseif ($annot instanceof XmlDiscriminator) {
107 5
                $classMetadata->xmlDiscriminatorAttribute = (bool)$annot->attribute;
108 5
                $classMetadata->xmlDiscriminatorCData = (bool)$annot->cdata;
109 5
                $classMetadata->xmlDiscriminatorNamespace = $annot->namespace ? (string)$annot->namespace : null;
110 26
            } elseif ($annot instanceof VirtualProperty) {
111 8
                $virtualPropertyMetadata = new ExpressionPropertyMetadata($name, $annot->name, $annot->exp);
112 8
                $propertiesMetadata[] = $virtualPropertyMetadata;
113 8
                $propertiesAnnotations[] = $annot->options;
114 8
            }
115 262
        }
116
117 262
        foreach ($class->getMethods() as $method) {
118 204
            if ($method->class !== $name) {
119 16
                continue;
120
            }
121
122 203
            $methodAnnotations = $this->reader->getMethodAnnotations($method);
123
124 203
            foreach ($methodAnnotations as $annot) {
125 50
                if ($annot instanceof PreSerialize) {
126 3
                    $classMetadata->addPreSerializeMethod(new MethodMetadata($name, $method->name));
127 3
                    continue 2;
128 50
                } elseif ($annot instanceof PostDeserialize) {
129 6
                    $classMetadata->addPostDeserializeMethod(new MethodMetadata($name, $method->name));
130 6
                    continue 2;
131 47
                } elseif ($annot instanceof PostSerialize) {
132 3
                    $classMetadata->addPostSerializeMethod(new MethodMetadata($name, $method->name));
133 3
                    continue 2;
134 44
                } elseif ($annot instanceof VirtualProperty) {
135 40
                    $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $method->name);
136 40
                    $propertiesMetadata[] = $virtualPropertyMetadata;
137 40
                    $propertiesAnnotations[] = $methodAnnotations;
138 40
                    continue 2;
139 7
                } elseif ($annot instanceof HandlerCallback) {
140 4
                    $classMetadata->addHandlerCallback(GraphNavigator::parseDirection($annot->direction), $annot->format, $method->name);
141 4
                    continue 2;
142
                }
143 175
            }
144 262
        }
145
146 262
        if (!$excludeAll) {
147 262
            foreach ($class->getProperties() as $property) {
148 241
                if ($property->class !== $name || (isset($property->info) && $property->info['class'] !== $name)) {
0 ignored issues
show
Bug introduced by
The property info does not seem to exist in ReflectionProperty.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
149 18
                    continue;
150
                }
151 240
                $propertiesMetadata[] = new PropertyMetadata($name, $property->getName());
152 240
                $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property);
153 262
            }
154
155 262
            foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) {
156 249
                $isExclude = false;
157
                $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata
158 249
                    || $propertyMetadata instanceof ExpressionPropertyMetadata;
159 249
                $propertyMetadata->readOnly = $propertyMetadata->readOnly || $readOnlyClass;
160 249
                $accessType = $classAccessType;
161 249
                $accessor = array(null, null);
162
163 249
                $propertyAnnotations = $propertiesAnnotations[$propertyKey];
164
165 249
                foreach ($propertyAnnotations as $annot) {
166 241
                    if ($annot instanceof Since) {
167 7
                        $propertyMetadata->sinceVersion = $annot->version;
168 241
                    } elseif ($annot instanceof Until) {
169 7
                        $propertyMetadata->untilVersion = $annot->version;
170 241
                    } elseif ($annot instanceof SerializedName) {
171 82
                        $propertyMetadata->serializedName = $annot->name;
172 241
                    } elseif ($annot instanceof SkipWhenEmpty) {
173 7
                        $propertyMetadata->skipWhenEmpty = true;
174 241
                    } elseif ($annot instanceof Expose) {
175 36
                        $isExpose = true;
176 36
                        if (null !== $annot->if) {
177 33
                            $propertyMetadata->excludeIf = "!(" . $annot->if . ")";
178 33
                        }
179 240
                    } elseif ($annot instanceof Exclude) {
180 40
                        if (null !== $annot->if) {
181 21
                            $propertyMetadata->excludeIf = $annot->if;
182 21
                        } else {
183 25
                            $isExclude = true;
184
                        }
185 240
                    } elseif ($annot instanceof Type) {
186 198
                        $propertyMetadata->setType($annot->name);
187 240
                    } elseif ($annot instanceof XmlElement) {
188 21
                        $propertyMetadata->xmlAttribute = false;
189 21
                        $propertyMetadata->xmlElementCData = $annot->cdata;
190 21
                        $propertyMetadata->xmlNamespace = $annot->namespace;
191 160
                    } elseif ($annot instanceof XmlList) {
192 43
                        $propertyMetadata->xmlCollection = true;
193 43
                        $propertyMetadata->xmlCollectionInline = $annot->inline;
194 43
                        $propertyMetadata->xmlEntryName = $annot->entry;
195 43
                        $propertyMetadata->xmlEntryNamespace = $annot->namespace;
196 43
                        $propertyMetadata->xmlCollectionSkipWhenEmpty = $annot->skipWhenEmpty;
197 154
                    } elseif ($annot instanceof XmlMap) {
198 23
                        $propertyMetadata->xmlCollection = true;
199 23
                        $propertyMetadata->xmlCollectionInline = $annot->inline;
200 23
                        $propertyMetadata->xmlEntryName = $annot->entry;
201 23
                        $propertyMetadata->xmlEntryNamespace = $annot->namespace;
202 23
                        $propertyMetadata->xmlKeyAttribute = $annot->keyAttribute;
203 146
                    } elseif ($annot instanceof XmlKeyValuePairs) {
204 7
                        $propertyMetadata->xmlKeyValuePairs = true;
205 138
                    } elseif ($annot instanceof XmlAttribute) {
206 41
                        $propertyMetadata->xmlAttribute = true;
207 41
                        $propertyMetadata->xmlNamespace = $annot->namespace;
208 131
                    } elseif ($annot instanceof XmlValue) {
209 26
                        $propertyMetadata->xmlValue = true;
210 26
                        $propertyMetadata->xmlElementCData = $annot->cdata;
211 125
                    } elseif ($annot instanceof XmlElement) {
212
                        $propertyMetadata->xmlElementCData = $annot->cdata;
213 105
                    } elseif ($annot instanceof AccessType) {
214 3
                        $accessType = $annot->type;
215 105
                    } elseif ($annot instanceof ReadOnly) {
216 10
                        $propertyMetadata->readOnly = $annot->readOnly;
217 105
                    } elseif ($annot instanceof Accessor) {
218 11
                        $accessor = array($annot->getter, $annot->setter);
219 102
                    } elseif ($annot instanceof Groups) {
220 42
                        $propertyMetadata->groups = $annot->groups;
221 42
                        foreach ((array)$propertyMetadata->groups as $groupName) {
222 42
                            if (false !== strpos($groupName, ',')) {
223 3
                                throw new InvalidArgumentException(sprintf(
224 3
                                    'Invalid group name "%s" on "%s", did you mean to create multiple groups?',
225 3
                                    implode(', ', $propertyMetadata->groups),
226 3
                                    $propertyMetadata->class . '->' . $propertyMetadata->name
227 3
                                ));
228
                            }
229 39
                        }
230 88
                    } elseif ($annot instanceof Inline) {
231 6
                        $propertyMetadata->inline = true;
232 66
                    } elseif ($annot instanceof XmlAttributeMap) {
233 4
                        $propertyMetadata->xmlAttributeMap = true;
234 60
                    } elseif ($annot instanceof MaxDepth) {
235 9
                        $propertyMetadata->maxDepth = $annot->depth;
236 9
                    }
237 246
                }
238
239
240 246
                if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
241 39
                    || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)
242 246
                ) {
243 246
                    $propertyMetadata->setAccessor($accessType, $accessor[0], $accessor[1]);
244 246
                    $classMetadata->addPropertyMetadata($propertyMetadata);
245 246
                }
246 259
            }
247 259
        }
248
249 259
        return $classMetadata;
250
    }
251
}
252