Completed
Push — master ( fc2d7f...dda5b7 )
by Eric
03:12
created

XmlClassMetadataLoader::loadProperty()   F

Complexity

Conditions 11
Paths 256

Size

Total Lines 38
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 3.8181
c 0
b 0
f 0
cc 11
eloc 19
nc 256
nop 1

How to fix   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
 * This file is part of the Ivory Serializer package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\Serializer\Mapping\Loader;
13
14
/**
15
 * @author GeLo <[email protected]>
16
 */
17
class XmlClassMetadataLoader extends AbstractFileClassMetadataLoader
18
{
19
    /**
20
     * {@inheritdoc}
21
     */
22
    protected function loadFile($file)
23
    {
24
        $data = [];
25
        $xml = simplexml_import_dom($this->loadDocument($file));
26
27
        if (isset($xml['exclusion-policy'])) {
28
            $data['exclusion_policy'] = (string) $xml['exclusion-policy'];
29
        }
30
31
        foreach ($xml->class as $class) {
32
            $properties = [];
33
34
            foreach ($class->property as $property) {
35
                $properties[(string) $property['name']] = $this->loadProperty($property);
36
            }
37
38
            $data[(string) $class['name']] = ['properties' => $properties];
39
        }
40
41
        return $data;
42
    }
43
44
    /**
45
     * @param \SimpleXMLElement $element
46
     *
47
     * @return mixed[]
48
     */
49
    private function loadProperty(\SimpleXMLElement $element)
50
    {
51
        $property = [];
52
53
        if (isset($element['alias'])) {
54
            $property['alias'] = (string) $element['alias'];
55
        }
56
57
        if (isset($element['type'])) {
58
            $property['type'] = (string) $element['type'];
59
        }
60
61
        if (isset($element['exclude']) && $element['exclude'] === 'true') {
62
            $property['exclude'] = true;
63
        }
64
65
        if (isset($element['expose']) && $element['expose'] === 'true') {
66
            $property['expose'] = true;
67
        }
68
69
        if (isset($element['since'])) {
70
            $property['since'] = (string) $element['since'];
71
        }
72
73
        if (isset($element['until'])) {
74
            $property['until'] = (string) $element['until'];
75
        }
76
77
        if (isset($element['max-depth'])) {
78
            $property['max_depth'] = (string) $element['max-depth'];
79
        }
80
81
        foreach ($element->group as $group) {
82
            $property['groups'][] = (string) $group;
83
        }
84
85
        return $property;
86
    }
87
88
    /**
89
     * @param string $file
90
     *
91
     * @return \DOMDocument
92
     */
93
    private function loadDocument($file)
94
    {
95
        $data = trim(file_get_contents($file));
96
97
        if (empty($data)) {
98
            throw new \InvalidArgumentException();
99
        }
100
101
        $internalErrors = libxml_use_internal_errors();
102
        $disableEntities = libxml_disable_entity_loader();
103
104
        $this->setState(true, true);
105
106
        $document = new \DOMDocument();
107
        $document->validateOnParse = true;
108
109
        if (!$document->loadXML($data, LIBXML_NONET | LIBXML_COMPACT)) {
110
            $this->setState($internalErrors, $disableEntities);
111
112
            throw new \InvalidArgumentException();
113
        }
114
115
        $document->normalizeDocument();
116
117
        foreach ($document->childNodes as $child) {
118
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
119
                throw new \InvalidArgumentException('The document type is not allowed.');
120
            }
121
        }
122
123
        $this->validateDocument($document, $internalErrors, $disableEntities);
124
        $this->setState($internalErrors, $disableEntities);
125
126
        return $document;
127
    }
128
129
    /**
130
     * @param \DOMDocument $document
131
     * @param bool         $internalErrors
132
     * @param bool         $disableEntities
133
     */
134
    private function validateDocument(\DOMDocument $document, $internalErrors, $disableEntities)
135
    {
136
        if (@$document->schemaValidateSource(file_get_contents(__DIR__.'/../Resource/mapping.xsd'))) {
137
            return;
138
        }
139
140
        $errors = [];
141
142
        foreach (libxml_get_errors() as $error) {
143
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
144
                LIBXML_ERR_WARNING === $error->level ? 'WARNING' : 'ERROR',
145
                $error->code,
146
                trim($error->message),
147
                $error->file ?: 'n/a',
148
                $error->line,
149
                $error->column
150
            );
151
        }
152
153
        $this->setState($internalErrors, $disableEntities);
154
155
        throw new \InvalidArgumentException(implode(PHP_EOL, $errors));
156
    }
157
158
    /**
159
     * @param bool $internalErrors
160
     * @param bool $disableEntities
161
     */
162
    private function setState($internalErrors, $disableEntities)
163
    {
164
        libxml_use_internal_errors($internalErrors);
165
        libxml_disable_entity_loader($disableEntities);
166
        libxml_clear_errors();
167
    }
168
}
169