Completed
Push — master ( 59acb9...e938ca )
by Patrick
03:29
created

SerializableObject::serializeObject()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 2
dl 0
loc 20
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * An easily serializable class
4
 *
5
 * This file describes a serializable object
6
 *
7
 * PHP version 5 and 7
8
 *
9
 * @author Patrick Boyd / [email protected]
10
 * @copyright Copyright (c) 2015, Austin Artistic Reconstruction
11
 * @license http://www.apache.org/licenses/ Apache 2.0 License
12
 */
13
14
/**
15
 * An object that can be serialized and accessed as an array.
16
 *
17
 * This class can be serialized to various formats
18
 */
19
class SerializableObject implements ArrayAccess, JsonSerializable
20
{
21
    /**
22
     * Create the object from an array
23
     *
24
     * @param array $array The array of object properties
25
     */
26
    public function __construct($array = false)
27
    {
28
        if($array !== false)
29
        {
30
            if(is_object($array))
31
            {
32
                $array = get_object_vars($array);
33
            }
34
            if(is_array($array))
35
            {
36
                foreach($array as $key => $value)
37
                {
38
                    $this->{$key} = $value;
39
                }
40
            }
41
        }
42
    }
43
44
    /**
45
     * Serialize the object into a format consumable by json_encode
46
     *
47
     * @return array The object in a more serialized format
48
     */
49
    public function jsonSerialize()
50
    {
51
        return (array)$this;
52
    }
53
54
    /**
55
     * Convert the object into an XML string
56
     *
57
     * @return string The XML format of the object
58
     */
59
    public function xmlSerialize()
60
    {
61
        $xml = new XmlWriter();
62
        $xml->openMemory();
63
        $xml->startDocument('1.0');
64
        if(version_compare(PHP_VERSION, '7.0.0', '>='))
65
        {
66
            $this->php7XmlSerialize($xml);
67
        }
68
        else
69
        {
70
            $this->oldPhpSerialize($xml);
71
        }
72
        $xml->endElement();
73
        return $xml->outputMemory(true);
74
    }
75
76
    private function php7XmlSerialize(XMLWriter $xml)
77
    {
78
        if(isset($this[0]))
79
        {
80
            $xml->startElement('Array');
81
            $this->array2XML($xml, 'Entity', get_object_vars($this));
82
            $xml->endElement();
83
        }
84
        else
85
        {
86
            $this->object2XML($xml, $this);
87
        }
88
    }
89
90
    private function oldPhpSerialize(XMLWriter $xml)
91
    {
92
        $tmp = json_decode(json_encode($this), false);
93
        $tmpA = $tmp;
94
        if(is_object($tmp))
95
        {
96
            $tmpA = get_object_vars($tmp);
97
        }
98
        if(isset($tmpA[0]))
99
        {
100
            $xml->startElement('Array');
101
            $this->array2XML($xml, 'Entity', $tmpA);
102
            $xml->endElement();
103
        }
104
        else
105
        {
106
            $this->object2XML($xml, $tmp);
107
        }
108
    }
109
110
    /**
111
     * Convert an object to XML without document tags
112
     *
113
     * @param XmlWriter $xml The XMLWriter to write the object to
114
     * @param mixed $data The data to serialze to XML
115
     */
116
    private function object2XML(XMLWriter $xml, $data)
117
    {
118
        foreach($data as $key => $value)
119
        {
120
            if(is_array($value) || is_numeric($key))
121
            {
122
                $this->array2XML($xml, $key, (array)$value);
123
            }
124
            else if(is_object($value))
125
            {
126
                $xml->startElement($key);
127
                $this->object2XML($xml, $value);
128
                $xml->endElement();
129
            }
130
            else
131
            {
132
                if($key[0] === '$')
133
                {
134
                    $xml->writeElement(substr($key, 1), $value);
135
                }
136
                else
137
                {
138
                    $key = strtr($key, array(' '=>'', ','=>''));
139
                    $xml->writeElement($key, $value);
140
                }
141
            }
142
        }
143
    }
144
145
    /**
146
     * Determine if an array has any string keys
147
     *
148
     * @param array $array The array to test
149
     * 
150
     * @return boolean True if the array has string keys, false otherwise
151
     */
152
    private function arrayHasStringKeys(array $array)
153
    {
154
        return count(array_filter(array_keys($array), 'is_string')) > 0;
155
    }
156
157
    /**
158
     * Convert an array to XML without document tags
159
     *
160
     * @param XmlWriter $xml The XMLWriter to write the object to
161
     * @param string $keyParent The key of the parent object
162
     * @param mixed $data The data to serialze to XML
163
     */
164
    private function array2XML(XMLWriter $xml, $keyParent, $data)
165
    {
166
        $data = array_values($data);
167
        $count = count($data);
168
        for($i = 0; $i < $count; $i++)
169
        {
170
            $value = $data[$i];
171
            if(is_array($value) && isset($value[0]))
172
            {
173
                $xml->startElement($keyParent);
174
                $this->array2XML($xml, 'Child', $value);
175
                $xml->endElement();
176
            }
177
            else if(is_array($value) && $this->arrayHasStringKeys($value))
178
            {
179
                $xml->startElement($keyParent);
180
                $this->object2XML($xml, $value);
181
                $xml->endElement();
182
            }
183
            else if(is_object($value))
184
            {
185
                $xml->startElement($keyParent);
186
                $this->object2XML($xml, $value);
187
                $xml->endElement();
188
            }
189
            else
190
            {
191
                $xml->writeElement($keyParent, $value);
192
            }
193
        }
194
    }
195
196
    /**
197
     * Convert json back to an object
198
     *
199
     * @param string $json The JSON string to deserialize back into an object
200
     *
201
     * @return SerializableObject The object the json deserializes into 
202
     */
203
    public static function jsonDeserialize($json)
204
    {
205
        $array = json_decode($json, true);
206
        return new self($array);
207
    }
208
209
    /**
210
     * Convert the object to a serizlized string
211
     *
212
     * @param string $fmt The format to serialize into
213
     * @param array|false $select Which fields to include
214
     *
215
     * @return string The object in string format
216
     */
217
    public function serializeObject($fmt = 'json', $select = false)
218
    {
219
        $copy = $this;
220
        if($select !== false)
221
        {
222
            $copy = new self();
223
            $count = count($select);
224
            for($i = 0; $i < $count; $i++)
225
            {
226
                $copy->{$select[$i]} = $this->offsetGet($select[$i]);
227
            }
228
        }
229
        switch($fmt)
230
        {
231
            case 'json':
232
                return json_encode($copy);
233
            default:
234
                throw new Exception('Unsupported fmt '.$fmt);
235
        }
236
    }
237
238
    /**
239
     * Function to allow the caller to set a value in the object via object[offset] = value
240
     *
241
     * @param string $offset The key to set
242
     * @param mixed $value The value for the key
243
     */
244
    public function offsetSet($offset, $value)
245
    {
246
        $this->{$offset} = $value;
247
    }
248
249
    /**
250
     * Function to allow the caller to determin if a value in the object is set
251
     *
252
     * @param string $offset The key to determine if it has a value
253
     *
254
     * @return boolean Does the key have a value?
255
     */
256
    public function offsetExists($offset)
257
    {
258
        return isset($this->{$offset});
259
    }
260
261
    /**
262
     * Function to allow the caller to delete the value in the object for a key
263
     *
264
     * @param string $offset The key to unset
265
     */
266
    public function offsetUnset($offset)
267
    {
268
        unset($this->{$offset});
269
    }
270
271
    /**
272
     * Function to allow the caller to obtain the value for a key
273
     *
274
     * @param string $offset The key to return the value for
275
     *
276
     * @return mixed the value in the key
277
     */
278
    public function offsetGet($offset)
279
    {
280
        return $this->{$offset};
281
    }
282
}
283
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
284