Completed
Pull Request — master (#771)
by
unknown
03:47
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 434
    public function __construct(Reader $reader)
68
    {
69 434
        $this->reader = $reader;
70 434
    }
71
72 264
    public function loadMetadataForClass(\ReflectionClass $class)
73
    {
74 264
        $classMetadata = new ClassMetadata($name = $class->name);
75 264
        $classMetadata->fileResources[] = $class->getFilename();
76
77 264
        $propertiesMetadata = array();
78 264
        $propertiesAnnotations = array();
79
80 264
        $exclusionPolicy = 'NONE';
81 264
        $excludeAll = false;
82 264
        $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY;
83 264
        $readOnlyClass = false;
84 264
        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 264
        }
116
117 264
        foreach ($class->getMethods() as $method) {
118 206
            if ($method->class !== $name) {
119 18
                continue;
120
            }
121
122 205
            $methodAnnotations = $this->reader->getMethodAnnotations($method);
123
124 205
            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 177
            }
144 264
        }
145
146 264
        if (!$excludeAll) {
147 264
            foreach ($class->getProperties() as $property) {
148 243
                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 20
                    continue;
150
                }
151 242
                $propertiesMetadata[] = new PropertyMetadata($name, $property->getName());
152 242
                $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property);
153 264
            }
154
155 264
            foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) {
156 251
                $isExclude = false;
157
                $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata
158 251
                    || $propertyMetadata instanceof ExpressionPropertyMetadata;
159 251
                $propertyMetadata->readOnly = $propertyMetadata->readOnly || $readOnlyClass;
160 251
                $accessType = $classAccessType;
161 251
                $accessor = array(null, null);
162
163 251
                $propertyAnnotations = $propertiesAnnotations[$propertyKey];
164
165 251
                foreach ($propertyAnnotations as $annot) {
166 243
                    if ($annot instanceof Since) {
167 7
                        $propertyMetadata->sinceVersion = $annot->version;
168 243
                    } elseif ($annot instanceof Until) {
169 7
                        $propertyMetadata->untilVersion = $annot->version;
170 243
                    } elseif ($annot instanceof SerializedName) {
171 84
                        $propertyMetadata->serializedName = $annot->name;
172 243
                    } elseif ($annot instanceof SkipWhenEmpty) {
173 7
                        $propertyMetadata->skipWhenEmpty = true;
174 243
                    } elseif ($annot instanceof Expose) {
175 36
                        $isExpose = true;
176 36
                        if (null !== $annot->if) {
177 33
                            $propertyMetadata->excludeIf = "!(" . $annot->if . ")";
178 33
                        }
179 242
                    } 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 242
                    } elseif ($annot instanceof Type) {
186 200
                        $propertyMetadata->setType($annot->name);
187 242
                    } 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 248
                }
238
239
240 248
                if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
241 39
                    || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)
242 248
                ) {
243 248
                    $propertyMetadata->setAccessor($accessType, $accessor[0], $accessor[1]);
244 248
                    $classMetadata->addPropertyMetadata($propertyMetadata);
245 248
                }
246 261
            }
247 261
        }
248
249 261
        return $classMetadata;
250
    }
251
}
252