Completed
Push — master ( 2cf3b1...c0c568 )
by Asmir
04:58
created

YamlDriver::loadMetadataFromFile()   F

Complexity

Conditions 64
Paths 1169

Size

Total Lines 217
Code Lines 123

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 126
CRAP Score 114.9492

Importance

Changes 0
Metric Value
dl 0
loc 217
ccs 126
cts 164
cp 0.7683
rs 2
c 0
b 0
f 0
cc 64
eloc 123
nc 1169
nop 2
crap 114.9492

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 JMS\Serializer\GraphNavigator;
22
use JMS\Serializer\Exception\RuntimeException;
23
use JMS\Serializer\Annotation\ExclusionPolicy;
24
use JMS\Serializer\Metadata\ExpressionPropertyMetadata;
25
use Metadata\MethodMetadata;
26
use JMS\Serializer\Metadata\PropertyMetadata;
27
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
28
use JMS\Serializer\Metadata\ClassMetadata;
29
use Symfony\Component\Yaml\Yaml;
30
use Metadata\Driver\AbstractFileDriver;
31
32
class YamlDriver extends AbstractFileDriver
33
{
34 24
    protected function loadMetadataFromFile(\ReflectionClass $class, $file)
35
    {
36 24
        $config = Yaml::parse(file_get_contents($file));
37
38 24
        if ( ! isset($config[$name = $class->name])) {
39
            throw new RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file));
40
        }
41
42 24
        $config = $config[$name];
43 24
        $metadata = new ClassMetadata($name);
44 24
        $metadata->fileResources[] = $file;
45 24
        $metadata->fileResources[] = $class->getFileName();
46 24
        $exclusionPolicy = isset($config['exclusion_policy']) ? strtoupper($config['exclusion_policy']) : 'NONE';
47 24
        $excludeAll = isset($config['exclude']) ? (Boolean) $config['exclude'] : false;
48 24
        $classAccessType = isset($config['access_type']) ? $config['access_type'] : PropertyMetadata::ACCESS_TYPE_PROPERTY;
49 24
        $readOnlyClass = isset($config['read_only']) ? (Boolean) $config['read_only'] : false;
50 24
        $this->addClassProperties($metadata, $config);
51
52 24
        $propertiesMetadata = array();
53 24
        if (array_key_exists('virtual_properties', $config)) {
54 4
            foreach ($config['virtual_properties'] as $methodName => $propertySettings) {
55 4
                if (isset($propertySettings['exp'])) {
56 2
                    $virtualPropertyMetadata = new ExpressionPropertyMetadata( $name, $methodName, $propertySettings['exp']);
57 2
                    unset($propertySettings['exp']);
58
59 2
                } else {
60
61 3
                    if ( ! $class->hasMethod($methodName)) {
62
                        throw new RuntimeException('The method '.$methodName.' not found in class '.$class->name);
63
                    }
64 3
                    $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $methodName);
65
                }
66 4
                $propertiesMetadata[$methodName] = $virtualPropertyMetadata;
67 4
                $config['properties'][$methodName] = $propertySettings;
68 4
            }
69 4
        }
70
71 24
        if ( ! $excludeAll) {
72 24
            foreach ($class->getProperties() as $property) {
73 21
                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...
74 2
                    continue;
75
                }
76
77 20
                $pName = $property->getName();
78 20
                $propertiesMetadata[$pName] = new PropertyMetadata($name, $pName);
79 24
            }
80
81 24
            foreach ($propertiesMetadata as $pName => $pMetadata) {
82 22
                $isExclude = false;
83
                $isExpose = $pMetadata instanceof VirtualPropertyMetadata
84 22
                    || $pMetadata instanceof ExpressionPropertyMetadata
85 22
                    || (isset($config['properties']) && array_key_exists($pName, $config['properties']));
86
87 22
                if (isset($config['properties'][$pName])) {
88 19
                    $pConfig = $config['properties'][$pName];
89
90 19
                    if (isset($pConfig['exclude'])) {
91 1
                        $isExclude = (Boolean) $pConfig['exclude'];
92 1
                    }
93
94 19
                    if (isset($pConfig['expose'])) {
95 3
                        $isExpose = (Boolean) $pConfig['expose'];
96 3
                    }
97
98 19
                    if (isset($pConfig['since_version'])) {
99
                        $pMetadata->sinceVersion = (string) $pConfig['since_version'];
100
                    }
101
102 19
                    if (isset($pConfig['until_version'])) {
103
                        $pMetadata->untilVersion = (string) $pConfig['until_version'];
104
                    }
105
106 19
                    if (isset($pConfig['exclude_if'])) {
107 1
                        $pMetadata->excludeIf = (string) $pConfig['exclude_if'];
108 1
                    }
109
110 19
                    if (isset($pConfig['expose_if'])) {
111 1
                        $pMetadata->excludeIf = "!(" . $pConfig['expose_if'].")";
112 1
                    }
113
114 19
                    if (isset($pConfig['serialized_name'])) {
115 3
                        $pMetadata->serializedName = (string) $pConfig['serialized_name'];
116 3
                    }
117
118 19
                    if (isset($pConfig['type'])) {
119 14
                        $pMetadata->setType((string) $pConfig['type']);
120 14
                    }
121
122 19
                    if (isset($pConfig['groups'])) {
123 1
                        $pMetadata->groups = $pConfig['groups'];
124 1
                    }
125
126 19
                    if (isset($pConfig['xml_list'])) {
127 2
                        $pMetadata->xmlCollection = true;
128
129 2
                        $colConfig = $pConfig['xml_list'];
130 2
                        if (isset($colConfig['inline'])) {
131 2
                            $pMetadata->xmlCollectionInline = (Boolean)$colConfig['inline'];
132 2
                        }
133
134 2
                        if (isset($colConfig['entry_name'])) {
135 1
                            $pMetadata->xmlEntryName = (string)$colConfig['entry_name'];
136 1
                        }
137
138 2
                        if (isset($colConfig['skip_when_empty'])) {
139 1
                            $pMetadata->xmlCollectionSkipWhenEmpty = (Boolean)$colConfig['skip_when_empty'];
140 1
                        } else {
141 2
                            $pMetadata->xmlCollectionSkipWhenEmpty = true;
142
                        }
143
144 2
                        if (isset($colConfig['namespace'])) {
145
                            $pMetadata->xmlEntryNamespace = (string) $colConfig['namespace'];
146
                        }
147 2
                    }
148
149 19
                    if (isset($pConfig['xml_map'])) {
150
                        $pMetadata->xmlCollection = true;
151
152
                        $colConfig = $pConfig['xml_map'];
153
                        if (isset($colConfig['inline'])) {
154
                            $pMetadata->xmlCollectionInline = (Boolean) $colConfig['inline'];
155
                        }
156
157
                        if (isset($colConfig['entry_name'])) {
158
                            $pMetadata->xmlEntryName = (string) $colConfig['entry_name'];
159
                        }
160
161
                        if (isset($colConfig['namespace'])) {
162
                            $pMetadata->xmlEntryNamespace = (string) $colConfig['namespace'];
163
                        }
164
165
                        if (isset($colConfig['key_attribute_name'])) {
166
                            $pMetadata->xmlKeyAttribute = $colConfig['key_attribute_name'];
167
                        }
168
169
                    }
170
171 19
                    if (isset($pConfig['xml_element'])) {
172 4
                        $colConfig = $pConfig['xml_element'];
173 4
                        if (isset($colConfig['cdata'])) {
174 2
                            $pMetadata->xmlElementCData = (Boolean) $colConfig['cdata'];
175 2
                        }
176
177 4
                        if (isset($colConfig['namespace'])) {
178 3
                            $pMetadata->xmlNamespace = (string) $colConfig['namespace'];
179 3
                        }
180 4
                    }
181
182 19
                    if (isset($pConfig['xml_attribute'])) {
183 4
                        $pMetadata->xmlAttribute = (Boolean) $pConfig['xml_attribute'];
184 4
                    }
185
186 19
                    if (isset($pConfig['xml_attribute_map'])) {
187
                        $pMetadata->xmlAttributeMap = (Boolean) $pConfig['xml_attribute_map'];
188
                    }
189
190 19
                    if (isset($pConfig['xml_value'])) {
191 2
                        $pMetadata->xmlValue = (Boolean) $pConfig['xml_value'];
192 2
                    }
193
194 19
                    if (isset($pConfig['xml_key_value_pairs'])) {
195 1
                        $pMetadata->xmlKeyValuePairs = (Boolean) $pConfig['xml_key_value_pairs'];
196 1
                    }
197
198
                    //we need read_only before setter and getter set, because that method depends on flag being set
199 19
                    if (isset($pConfig['read_only'])) {
200 1
                          $pMetadata->readOnly = (Boolean) $pConfig['read_only'];
201 1
                    } else {
202 18
                        $pMetadata->readOnly = $pMetadata->readOnly || $readOnlyClass;
203
                    }
204
205 19
                    $pMetadata->setAccessor(
206 19
                        isset($pConfig['access_type']) ? $pConfig['access_type'] : $classAccessType,
207 19
                        isset($pConfig['accessor']['getter']) ? $pConfig['accessor']['getter'] : null,
208 19
                        isset($pConfig['accessor']['setter']) ? $pConfig['accessor']['setter'] : null
209 19
                    );
210
211 19
                    if (isset($pConfig['inline'])) {
212
                        $pMetadata->inline = (Boolean) $pConfig['inline'];
213
                    }
214
215 19
                    if (isset($pConfig['max_depth'])) {
216 1
                        $pMetadata->maxDepth = (int) $pConfig['max_depth'];
217 1
                    }
218 19
                }
219 22
                if ((ExclusionPolicy::NONE === $exclusionPolicy && ! $isExclude)
220 22
                        || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) {
221 22
                    $metadata->addPropertyMetadata($pMetadata);
222 22
                }
223 24
            }
224 24
        }
225
226 24
        if (isset($config['handler_callbacks'])) {
227 1
            foreach ($config['handler_callbacks'] as $directionName => $formats) {
228 1
                $direction = GraphNavigator::parseDirection($directionName);
229 1
                foreach ($formats as $format => $methodName) {
230 1
                    $metadata->addHandlerCallback($direction, $format, $methodName);
231 1
                }
232 1
            }
233 1
        }
234
235 24
        if (isset($config['callback_methods'])) {
236
            $cConfig = $config['callback_methods'];
237
238
            if (isset($cConfig['pre_serialize'])) {
239
                $metadata->preSerializeMethods = $this->getCallbackMetadata($class, $cConfig['pre_serialize']);
240
            }
241
            if (isset($cConfig['post_serialize'])) {
242
                $metadata->postSerializeMethods = $this->getCallbackMetadata($class, $cConfig['post_serialize']);
243
            }
244
            if (isset($cConfig['post_deserialize'])) {
245
                $metadata->postDeserializeMethods = $this->getCallbackMetadata($class, $cConfig['post_deserialize']);
246
            }
247
        }
248
249 24
        return $metadata;
250
    }
251
252 24
    protected function getExtension()
253
    {
254 24
        return 'yml';
255
    }
256
257 24
    private function addClassProperties(ClassMetadata $metadata, array $config)
258
    {
259 24
        if (isset($config['custom_accessor_order']) && ! isset($config['accessor_order'])) {
260 1
            $config['accessor_order'] = 'custom';
261 1
        }
262
263 24
        if (isset($config['accessor_order'])) {
264 1
            $metadata->setAccessorOrder($config['accessor_order'], isset($config['custom_accessor_order']) ? $config['custom_accessor_order'] : array());
265 1
        }
266
267 24
        if (isset($config['xml_root_name'])) {
268 9
            $metadata->xmlRootName = (string) $config['xml_root_name'];
269 9
        }
270
271 24
        if (isset($config['xml_root_namespace'])) {
272 1
            $metadata->xmlRootNamespace = (string) $config['xml_root_namespace'];
273 1
        }
274
275 24
        if (array_key_exists('xml_namespaces', $config)) {
276
277 3
            foreach ($config['xml_namespaces'] as $prefix => $uri) {
278 3
                $metadata->registerNamespace($uri, $prefix);
279 3
            }
280
281 3
        }
282
283 24
        if (isset($config['discriminator'])) {
284 3
            if (isset($config['discriminator']['disabled']) && true === $config['discriminator']['disabled']) {
285
                $metadata->discriminatorDisabled = true;
286
            } else {
287 3
                if ( ! isset($config['discriminator']['field_name'])) {
288
                    throw new RuntimeException('The "field_name" attribute must be set for discriminators.');
289
                }
290
291 3
                if ( ! isset($config['discriminator']['map']) || ! is_array($config['discriminator']['map'])) {
292
                    throw new RuntimeException('The "map" attribute must be set, and be an array for discriminators.');
293
                }
294 3
                $groups = isset($config['discriminator']['groups']) ? $config['discriminator']['groups'] : array();
295 3
                $metadata->setDiscriminator($config['discriminator']['field_name'], $config['discriminator']['map'], $groups);
296
297 3
                if (isset($config['discriminator']['xml_attribute'])) {
298 1
                    $metadata->xmlDiscriminatorAttribute = (bool) $config['discriminator']['xml_attribute'];
299 1
                }
300 3
                if (isset($config['discriminator']['xml_element'])) {
301 1
                    if (isset($config['discriminator']['xml_element']['cdata'])) {
302 1
                        $metadata->xmlDiscriminatorCData = (bool) $config['discriminator']['xml_element']['cdata'];
303 1
                    }
304 1
                }
305
306
            }
307 3
        }
308 24
    }
309
310
    private function getCallbackMetadata(\ReflectionClass $class, $config)
311
    {
312
        if (is_string($config)) {
313
            $config = array($config);
314
        } elseif ( ! is_array($config)) {
315
            throw new RuntimeException(sprintf('callback methods expects a string, or an array of strings that represent method names, but got %s.', json_encode($config['pre_serialize'])));
316
        }
317
318
        $methods = array();
319
        foreach ($config as $name) {
320
            if ( ! $class->hasMethod($name)) {
321
                throw new RuntimeException(sprintf('The method %s does not exist in class %s.', $name, $class->name));
322
            }
323
324
            $methods[] = new MethodMetadata($class->name, $name);
325
        }
326
327
        return $methods;
328
    }
329
}
330