Completed
Push — master ( 516597...0aeec3 )
by Dominik
04:41
created

XmlTypeEncoder   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 215
ccs 78
cts 78
cp 1
rs 9.92
c 0
b 0
f 0
wmc 31

10 Methods

Rating   Name   Duplication   Size   Complexity  
A encode() 0 14 1
A createMetadataNode() 0 8 2
A dataToArrayNode() 0 29 4
A getType() 0 11 3
A getContentType() 0 3 1
A dataToNodes() 0 18 6
A getMetaPrefix() 0 3 1
A __construct() 0 3 1
A getValueAsString() 0 20 6
A dataToScalarNode() 0 25 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Serialization\Encoder;
6
7
use Doctrine\Common\Inflector\Inflector;
8
9
/**
10
 * @deprecated use JsonxTypeEncoder instead
11
 */
12
final class XmlTypeEncoder implements TypeEncoderInterface
13
{
14
    /**
15
     * @var bool
16
     */
17
    private $prettyPrint;
18
19
    /**
20
     * @param bool $prettyPrint
21
     */
22 4
    public function __construct(bool $prettyPrint = false)
23
    {
24 4
        $this->prettyPrint = $prettyPrint;
25 4
    }
26
27
    /**
28
     * @return string
29
     */
30 1
    public function getContentType(): string
31
    {
32 1
        return 'application/xml';
33
    }
34
35
    /**
36
     * @param array $data
37
     *
38
     * @return string
39
     */
40 3
    public function encode(array $data): string
41
    {
42 3
        $document = new \DOMDocument('1.0', 'UTF-8');
43 3
        $document->formatOutput = $this->prettyPrint;
44
45 3
        $listNode = $this->createMetadataNode($document, $data['_type'] ?? null);
46
47 3
        unset($data['_type']);
48
49 3
        $document->appendChild($listNode);
50
51 3
        $this->dataToNodes($document, $listNode, $data);
52
53 2
        return trim($document->saveXML($document, LIBXML_NOEMPTYTAG));
54
    }
55
56
    /**
57
     * @param \DOMDocument $document
58
     * @param string|null  $type
59
     *
60
     * @return \DOMNode
61
     */
62 3
    private function createMetadataNode(\DOMDocument $document, string $type = null): \DOMNode
63
    {
64 3
        $node = $document->createElement('object');
65 3
        if (null !== $type) {
66 1
            $node->setAttribute('type', $type);
67
        }
68
69 3
        return $node;
70
    }
71
72
    /**
73
     * @param string $name
74
     *
75
     * @return string
76
     */
77 1
    private function getMetaPrefix(string $name)
78
    {
79 1
        return 'meta-'.$name;
80
    }
81
82
    /**
83
     * @param \DOMDocument $document
84
     * @param \DOMNode     $listNode
85
     * @param array        $data
86
     */
87 3
    private function dataToNodes(\DOMDocument $document, \DOMNode $listNode, array $data): void
88
    {
89 3
        foreach ($data as $key => $value) {
90 3
            if (is_string($key) && '_' === $key[0]) {
91 1
                $key = $this->getMetaPrefix(substr($key, 1));
92
            }
93
94 3
            if (is_array($value)) {
95 1
                $childNode = $this->dataToArrayNode($document, $listNode, $key, $value);
96
            } else {
97 3
                $childNode = $this->dataToScalarNode($document, $listNode, $key, $value);
98
            }
99
100 2
            if (is_int($key)) {
101 1
                $childNode->setAttribute('key', (string) $key);
102
            }
103
104 2
            $listNode->appendChild($childNode);
105
        }
106 2
    }
107
108
    /**
109
     * @param \DOMDocument $document
110
     * @param \DOMNode     $listNode
111
     * @param string|int   $key
112
     * @param array        $value
113
     *
114
     * @return \DOMElement|\DOMNode
115
     */
116 1
    private function dataToArrayNode(\DOMDocument $document, \DOMNode $listNode, $key, array $value)
117
    {
118 1
        if (!isset($value['_type'])) {
119 1
            $childNode = $document->createElement(is_int($key) ? Inflector::singularize($listNode->nodeName) : $key);
120 1
            $this->dataToNodes($document, $childNode, $value);
121
122 1
            return $childNode;
123
        }
124
125 1
        if (is_int($key)) {
126 1
            $childNode = $this->createMetadataNode($document, $value['_type']);
127
128 1
            unset($value['_type']);
129
130 1
            $this->dataToNodes($document, $childNode, $value);
131
132 1
            return $childNode;
133
        }
134
135 1
        $subChildNode = $this->createMetadataNode($document, $value['_type']);
136
137 1
        unset($value['_type']);
138
139 1
        $childNode = $document->createElement($key);
140 1
        $childNode->appendChild($subChildNode);
141
142 1
        $this->dataToNodes($document, $subChildNode, $value);
143
144 1
        return $childNode;
145
    }
146
147
    /**
148
     * @param \DOMDocument               $document
149
     * @param \DOMNode                   $listNode
150
     * @param string|int                 $key
151
     * @param string|bool|float|int|null $value
152
     *
153
     * @return \DOMNode
154
     */
155 3
    private function dataToScalarNode(\DOMDocument $document, \DOMNode $listNode, $key, $value): \DOMNode
156
    {
157 3
        $stringKey = is_int($key) ? Inflector::singularize($listNode->nodeName) : $key;
158
159 3
        if (is_string($value)) {
160 2
            if (false !== strpos($value, '<') || false !== strpos($value, '&')) {
161 1
                $childNode = $document->createElement($stringKey);
162 1
                $childNode->appendChild($document->createCDATASection($value));
163
            } else {
164 2
                $childNode = $document->createElement($stringKey, $value);
165
            }
166
167 2
            $childNode->setAttribute('type', 'string');
168
169 2
            return $childNode;
170
        }
171
172 2
        if (null === $value) {
173 1
            return $document->createElement($stringKey);
174
        }
175
176 2
        $childNode = $document->createElement($stringKey, $this->getValueAsString($value));
177 1
        $childNode->setAttribute('type', $this->getType($value));
178
179 1
        return $childNode;
180
    }
181
182
    /**
183
     * @param bool|float|int $value
184
     *
185
     * @throws \InvalidArgumentException
186
     *
187
     * @return string
188
     */
189 2
    private function getValueAsString($value): string
190
    {
191 2
        if (is_bool($value)) {
192 1
            return $value ? 'true' : 'false';
193
        }
194
195 2
        if (is_float($value)) {
196 1
            $value = (string) $value;
197 1
            if (false === strpos($value, '.')) {
198 1
                $value .= '.0';
199
            }
200
201 1
            return $value;
202
        }
203
204 2
        if (is_int($value)) {
0 ignored issues
show
introduced by
The condition is_int($value) is always true.
Loading history...
205 1
            return (string) $value;
206
        }
207
208 1
        throw new \InvalidArgumentException(sprintf('Unsupported data type: %s', gettype($value)));
209
    }
210
211
    /**
212
     * @param bool|float|int|string $value
213
     *
214
     * @return string
215
     */
216 1
    private function getType($value): string
217
    {
218 1
        if (is_bool($value)) {
219 1
            return 'boolean';
220
        }
221
222 1
        if (is_float($value)) {
223 1
            return 'float';
224
        }
225
226 1
        return 'integer';
227
    }
228
}
229