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

JsonxTypeEncoder   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 230
Duplicated Lines 8.7 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 88.37%

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 0
dl 20
loc 230
ccs 76
cts 86
cp 0.8837
rs 9.52
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getContentType() 0 4 1
A encode() 0 19 2
B createObjectNode() 0 29 8
B createArrayNode() 0 29 8
A createBooleanNode() 10 10 3
A createStringNode() 0 10 2
A createNumberNode() 10 10 2
A createNullNode() 0 10 2
B getType() 0 24 7

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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