XmlStrategy::getNumericKeyValue()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 11
rs 9.4286
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
3
/**
4
 * Author: Nil Portugués Calderó <[email protected]>
5
 * Date: 8/29/15
6
 * Time: 12:46 PM.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace NilPortugues\Serializer\Strategy;
12
13
use NilPortugues\Serializer\Serializer;
14
use SimpleXMLElement;
15
16
class XmlStrategy implements StrategyInterface
17
{
18
    /**
19
     * @var array
20
     */
21
    private $replacements = [
22
        Serializer::CLASS_IDENTIFIER_KEY => 'np_serializer_type',
23
        Serializer::SCALAR_TYPE => 'np_serializer_scalar',
24
        Serializer::SCALAR_VALUE => 'np_serializer_value',
25
        Serializer::MAP_TYPE => 'np_serializer_map',
26
    ];
27
28
    /**
29
     * @param mixed $value
30
     *
31
     * @return string
32
     */
33
    public function serialize($value)
34
    {
35
        $value = self::replaceKeys($this->replacements, $value);
36
        $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><data></data>');
37
        $this->arrayToXml($value, $xml);
38
39
        return $xml->asXML();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $xml->asXML(); of type string|false adds false to the return on line 39 which is incompatible with the return type declared by the interface NilPortugues\Serializer\...egyInterface::serialize of type string. It seems like you forgot to handle an error condition.
Loading history...
40
    }
41
42
    /**
43
     * @param array $replacements
44
     * @param array $input
45
     *
46
     * @return array
47
     */
48
    private static function replaceKeys(array &$replacements, array $input)
49
    {
50
        $return = [];
51
        foreach ($input as $key => $value) {
52
            $key = \str_replace(\array_keys($replacements), \array_values($replacements), $key);
53
54
            if (\is_array($value)) {
55
                $value = self::replaceKeys($replacements, $value);
56
            }
57
58
            $return[$key] = $value;
59
        }
60
61
        return $return;
62
    }
63
64
    /**
65
     * Converts an array to XML using SimpleXMLElement.
66
     *
67
     * @param array            $data
68
     * @param SimpleXMLElement $xmlData
69
     */
70
    private function arrayToXml(array &$data, SimpleXMLElement $xmlData)
71
    {
72
        foreach ($data as $key => $value) {
73
            if (\is_array($value)) {
74
                if (\is_numeric($key)) {
75
                    $key = 'np_serializer_element_'.gettype($key).'_'.$key;
76
                }
77
                $subnode = $xmlData->addChild($key);
78
                $this->arrayToXml($value, $subnode);
79
            } else {
80
                $xmlData->addChild("$key", "$value");
81
            }
82
        }
83
    }
84
85
    /**
86
     * @param $value
87
     *
88
     * @return array
89
     */
90
    public function unserialize($value)
91
    {
92
        $array = (array) \simplexml_load_string($value);
93
        self::castToArray($array);
94
        self::recoverArrayNumericKeyValues($array);
95
        $replacements = \array_flip($this->replacements);
96
        $array = self::replaceKeys($replacements, $array);
97
98
        return $array;
99
    }
100
101
    /**
102
     * @param array $array
103
     */
104
    private static function castToArray(array &$array)
105
    {
106
        foreach ($array as &$value) {
107
            if ($value instanceof SimpleXMLElement) {
108
                $value = (array) $value;
109
            }
110
111
            if (\is_array($value)) {
112
                self::castToArray($value);
113
            }
114
        }
115
    }
116
117
    /**
118
     * @param array $array
119
     */
120
    private static function recoverArrayNumericKeyValues(array &$array)
121
    {
122
        $newArray = [];
123
        foreach ($array as $key => &$value) {
124
            if (false !== \strpos($key, 'np_serializer_element_')) {
125
                $key = self::getNumericKeyValue($key);
126
            }
127
128
            $newArray[$key] = $value;
129
130
            if (\is_array($newArray[$key])) {
131
                self::recoverArrayNumericKeyValues($newArray[$key]);
132
            }
133
        }
134
        $array = $newArray;
135
    }
136
137
    /**
138
     * @param $key
139
     *
140
     * @return float|int
141
     */
142
    private static function getNumericKeyValue($key)
143
    {
144
        $newKey = \str_replace('np_serializer_element_', '', $key);
145
        list($type, $index) = \explode('_', $newKey);
146
147
        if ('integer' === $type) {
148
            $index = (int) $index;
149
        }
150
151
        return $index;
152
    }
153
}
154