Passed
Pull Request — master (#11)
by Dominik
04:45
created

JsonxTypeEncoder::getType()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 12
cts 12
cp 1
rs 8.6026
c 0
b 0
f 0
cc 7
nc 6
nop 1
crap 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Serialization\Encoder;
6
7
final class JsonxTypeEncoder implements TypeEncoderInterface
8
{
9
    /**
10
     * @var bool
11
     */
12
    private $prettyPrint;
13
14
    const DATATYPE_OBJECT = 'object';
15
    const DATATYPE_ARRAY = 'array';
16
    const DATATYPE_BOOLEAN = 'boolean';
17
    const DATATYPE_STRING = 'string';
18
    const DATATYPE_NUMBER = 'number';
19
    const DATATYPE_NULL = 'null';
20
21
    /**
22
     * @param bool $prettyPrint
23
     */
24 2
    public function __construct(bool $prettyPrint = false)
25
    {
26 2
        $this->prettyPrint = $prettyPrint;
27 2
    }
28
29
    /**
30
     * @return string
31
     */
32 1
    public function getContentType(): string
33
    {
34 1
        return 'application/jsonx';
35
    }
36
37
    /**
38
     * @param array $data
39
     *
40
     * @return string
41
     */
42 1
    public function encode(array $data): string
43
    {
44 1
        $document = new \DOMDocument('1.0', 'UTF-8');
45 1
        $document->formatOutput = $this->prettyPrint;
46
47 1
        if (self::DATATYPE_OBJECT === $this->getType($data)) {
48 1
            $rootNode = $this->createObjectNode($document, $data);
49
        } else {
50
            $rootNode = $this->createArrayNode($document, $data);
51
        }
52
53 1
        $rootNode->setAttribute('xsi:schemaLocation', 'http://www.datapower.com/schemas/json jsonx.xsd');
54 1
        $rootNode->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
55 1
        $rootNode->setAttribute('xmlns:json', 'http://www.ibm.com/xmlns/prod/2009/jsonx');
56
57 1
        $document->appendChild($rootNode);
58
59 1
        return trim($document->saveXML($document));
60
    }
61
62
    /**
63
     * @param \DOMDocument $document
64
     * @param string       $name
65
     * @param array        $value
66
     *
67
     * @return \DOMNode
68
     */
69 1
    private function createObjectNode(\DOMDocument $document, array $value, string $name = null): \DOMNode
70
    {
71 1
        $node = $document->createElement('json:object');
72
73 1
        if (null !== $name) {
74 1
            $node->setAttribute('name', $name);
75
        }
76
77 1
        foreach ($value as $subName => $subValue) {
78 1
            $subValueType = $this->getType($subValue);
79 1
            if (self::DATATYPE_OBJECT === $subValueType) {
80 1
                $subNode = $this->createObjectNode($document, $subValue, (string) $subName);
81 1
            } elseif (self::DATATYPE_ARRAY === $subValueType) {
82 1
                $subNode = $this->createArrayNode($document, $subValue, (string) $subName);
83 1
            } elseif (self::DATATYPE_BOOLEAN === $subValueType) {
84 1
                $subNode = $this->createBooleanNode($document, $subValue, (string) $subName);
85 1
            } elseif (self::DATATYPE_STRING === $subValueType) {
86 1
                $subNode = $this->createStringNode($document, $subValue, (string) $subName);
87 1
            } elseif (self::DATATYPE_NUMBER === $subValueType) {
88 1
                $subNode = $this->createNumberNode($document, $subValue, (string) $subName);
89
            } else {
90 1
                $subNode = $this->createNullNode($document, (string) $subName);
91
            }
92
93 1
            $node->appendChild($subNode);
94
        }
95
96 1
        return $node;
97
    }
98
99
    /**
100
     * @param \DOMDocument $document
101
     * @param array        $value
102
     * @param string       $name
103
     *
104
     * @return \DOMNode
105
     */
106 1
    private function createArrayNode(\DOMDocument $document, array $value, string $name = null): \DOMNode
107
    {
108 1
        $node = $document->createElement('json:array');
109
110 1
        if (null !== $name) {
111 1
            $node->setAttribute('name', $name);
112
        }
113
114 1
        foreach ($value as $subValue) {
115 1
            $subValueType = $this->getType($subValue);
116 1
            if (self::DATATYPE_OBJECT === $subValueType) {
117 1
                $subNode = $this->createObjectNode($document, $subValue);
118
            } elseif (self::DATATYPE_ARRAY === $subValueType) {
119
                $subNode = $this->createArrayNode($document, $subValue);
120
            } elseif (self::DATATYPE_BOOLEAN === $subValueType) {
121
                $subNode = $this->createBooleanNode($document, $subValue);
122
            } elseif (self::DATATYPE_STRING === $subValueType) {
123
                $subNode = $this->createStringNode($document, $subValue);
124
            } elseif (self::DATATYPE_NUMBER === $subValueType) {
125
                $subNode = $this->createNumberNode($document, $subValue);
126
            } else {
127
                $subNode = $this->createNullNode($document);
128
            }
129
130 1
            $node->appendChild($subNode);
131
        }
132
133 1
        return $node;
134
    }
135
136
    /**
137
     * @param \DOMDocument $document
138
     * @param bool         $value
139
     * @param string       $name
140
     *
141
     * @return \DOMNode
142
     */
143 1 View Code Duplication
    private function createBooleanNode(\DOMDocument $document, bool $value, string $name = null): \DOMNode
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145 1
        $node = $document->createElement('json:boolean', $value ? 'true' : 'false');
146
147 1
        if (null !== $name) {
148 1
            $node->setAttribute('name', $name);
149
        }
150
151 1
        return $node;
152
    }
153
154
    /**
155
     * @param \DOMDocument $document
156
     * @param string       $value
157
     * @param string       $name
158
     *
159
     * @return \DOMNode
160
     */
161 1
    private function createStringNode(\DOMDocument $document, string $value, string $name = null): \DOMNode
162
    {
163 1
        $node = $document->createElement('json:string', htmlentities($value, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8'));
164
165 1
        if (null !== $name) {
166 1
            $node->setAttribute('name', $name);
167
        }
168
169 1
        return $node;
170
    }
171
172
    /**
173
     * @param \DOMDocument $document
174
     * @param int|float    $value
175
     * @param string       $name
176
     *
177
     * @return \DOMNode
178
     */
179 1 View Code Duplication
    private function createNumberNode(\DOMDocument $document, $value, string $name = null): \DOMNode
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
    {
181 1
        $node = $document->createElement('json:number', (string) $value);
182
183 1
        if (null !== $name) {
184 1
            $node->setAttribute('name', $name);
185
        }
186
187 1
        return $node;
188
    }
189
190
    /**
191
     * @param \DOMDocument $document
192
     * @param string       $name
193
     *
194
     * @return \DOMNode
195
     */
196 1
    private function createNullNode(\DOMDocument $document, string $name = null): \DOMNode
197
    {
198 1
        $node = $document->createElement('json:null');
199
200 1
        if (null !== $name) {
201 1
            $node->setAttribute('name', $name);
202
        }
203
204 1
        return $node;
205
    }
206
207
    /**
208
     * @param array|bool|string|int|float|null $value
209
     *
210
     * @return string
211
     */
212 1
    private function getType($value): string
213
    {
214 1
        if (is_array($value)) {
215 1
            if ($value !== array_values($value)) {
216 1
                return self::DATATYPE_OBJECT;
217
            }
218
219 1
            return self::DATATYPE_ARRAY;
220
        }
221
222 1
        if (is_bool($value)) {
223 1
            return self::DATATYPE_BOOLEAN;
224
        }
225
226 1
        if (is_string($value)) {
227 1
            return self::DATATYPE_STRING;
228
        }
229
230 1
        if (is_int($value) || is_float($value)) {
231 1
            return self::DATATYPE_NUMBER;
232
        }
233
234 1
        return self::DATATYPE_NULL;
235
    }
236
}
237