Completed
Push — master ( 2b323a...f14e7e )
by Asmir
11:51
created

YamlDriver::addClassProperties()   F

Complexity

Conditions 19
Paths 512

Size

Total Lines 52
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 26.7393

Importance

Changes 0
Metric Value
dl 0
loc 52
ccs 26
cts 36
cp 0.7221
rs 3.7793
c 0
b 0
f 0
cc 19
eloc 27
nc 512
nop 2
crap 26.7393

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