File: Serializer.php

package info (click to toggle)
zendframework 1.10.6-1squeeze2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 29,480 kB
  • ctags: 46,247
  • sloc: xml: 233,973; php: 195,700; sql: 90; sh: 19; makefile: 10
file content (362 lines) | stat: -rw-r--r-- 13,710 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Amf
 * @subpackage Parse_Amf0
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Serializer.php 21969 2010-04-22 03:54:59Z matthew $
 */

/** Zend_Amf_Constants */
require_once 'Zend/Amf/Constants.php';

/** @see Zend_Amf_Parse_Serializer */
require_once 'Zend/Amf/Parse/Serializer.php';

/**
 * Serializer PHP misc types back to there corresponding AMF0 Type Marker.
 *
 * @uses       Zend_Amf_Parse_Serializer
 * @package    Zend_Amf
 * @subpackage Parse_Amf0
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
{
    /**
     * @var string Name of the class to be returned
     */
    protected $_className = '';

    /**
     * An array of reference objects
     * @var array
     */
    protected $_referenceObjects = array();

    /**
     * Determine type and serialize accordingly
     *
     * Checks to see if the type was declared and then either
     * auto negotiates the type or relies on the user defined markerType to
     * serialize the data into amf
     *
     * @param  mixed $data
     * @param  mixed $markerType
     * @param  mixed $dataByVal
     * @return Zend_Amf_Parse_Amf0_Serializer
     * @throws Zend_Amf_Exception for unrecognized types or data
     */
    public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
    {
        // Workaround for PHP5 with E_STRICT enabled complaining about "Only 
        // variables should be passed by reference" 
        if ((null === $data) && ($dataByVal !== false)) {
            $data = &$dataByVal;
        }
        if (null !== $markerType) {
            //try to reference the given object
            if (!$this->writeObjectReference($data, $markerType)) {
                // Write the Type Marker to denote the following action script data type
                $this->_stream->writeByte($markerType);
                switch($markerType) {
                    case Zend_Amf_Constants::AMF0_NUMBER:
                        $this->_stream->writeDouble($data);
                        break;
                    case Zend_Amf_Constants::AMF0_BOOLEAN:
                        $this->_stream->writeByte($data);
                        break;
                    case Zend_Amf_Constants::AMF0_STRING:
                        $this->_stream->writeUTF($data);
                        break;
                    case Zend_Amf_Constants::AMF0_OBJECT:
                        $this->writeObject($data);
                        break;
                    case Zend_Amf_Constants::AMF0_NULL:
                        break;
                    case Zend_Amf_Constants::AMF0_REFERENCE:
                        $this->_stream->writeInt($data);
                        break;
                    case Zend_Amf_Constants::AMF0_MIXEDARRAY:
                        // Write length of numeric keys as zero.
                        $this->_stream->writeLong(0);
                        $this->writeObject($data);
                        break;
                    case Zend_Amf_Constants::AMF0_ARRAY:
                        $this->writeArray($data);
                        break;
                    case Zend_Amf_Constants::AMF0_DATE:
                        $this->writeDate($data);
                        break;
                    case Zend_Amf_Constants::AMF0_LONGSTRING:
                        $this->_stream->writeLongUTF($data);
                        break;
                    case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
                        $this->writeTypedObject($data);
                        break;
                    case Zend_Amf_Constants::AMF0_AMF3:
                        $this->writeAmf3TypeMarker($data);
                        break;
                    default:
                        require_once 'Zend/Amf/Exception.php';
                        throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
                }
            }
        } else {
            if (is_resource($data)) {
                $data = Zend_Amf_Parse_TypeLoader::handleResource($data);
            }
            switch (true) {
                case (is_int($data) || is_float($data)):
                    $markerType = Zend_Amf_Constants::AMF0_NUMBER;
                    break;
                case (is_bool($data)):
                    $markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
                    break;
                case (is_string($data) && (strlen($data) > 65536)):
                    $markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
                    break;
                case (is_string($data)):
                    $markerType = Zend_Amf_Constants::AMF0_STRING;
                    break;
                case (is_object($data)):
                    if (($data instanceof DateTime) || ($data instanceof Zend_Date)) {
                        $markerType = Zend_Amf_Constants::AMF0_DATE;
                    } else {

                        if($className = $this->getClassName($data)){
                            //Object is a Typed object set classname
                            $markerType = Zend_Amf_Constants::AMF0_TYPEDOBJECT;
                            $this->_className = $className;
                        } else {
                            // Object is a generic classname
                            $markerType = Zend_Amf_Constants::AMF0_OBJECT;
                        }
                        break;
                    }
                    break;
                case (null === $data):
                    $markerType = Zend_Amf_Constants::AMF0_NULL;
                    break;
                case (is_array($data)):
                    // check if it is an associative array
                    $i = 0;
                    foreach (array_keys($data) as $key) {
                        // check if it contains non-integer keys
                        if (!is_numeric($key) || intval($key) != $key) {
                            $markerType = Zend_Amf_Constants::AMF0_OBJECT;
                            break;
                            // check if it is a sparse indexed array
                         } else if ($key != $i) {
                             $markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
                             break;
                         }
                         $i++;
                    }
                    // Dealing with a standard numeric array
                    if(!$markerType){
                        $markerType = Zend_Amf_Constants::AMF0_ARRAY;
                        break;
                    }
                    break;
                default:
                    require_once 'Zend/Amf/Exception.php';
                    throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data));
            }

            $this->writeTypeMarker($data, $markerType);
        }
        return $this;
    }

    /**
     * Check if the given object is in the reference table, write the reference if it exists,
     * otherwise add the object to the reference table
     *
     * @param mixed $object object reference to check for reference
     * @param $markerType AMF type of the object to write
     * @param mixed $objectByVal object to check for reference
     * @return Boolean true, if the reference was written, false otherwise
     */
    protected function writeObjectReference(&$object, $markerType, $objectByVal = false) 
    {
        // Workaround for PHP5 with E_STRICT enabled complaining about "Only 
        // variables should be passed by reference"
        if ((null === $object) && ($objectByVal !== false)) {
            $object = &$objectByVal;
        }

        if ($markerType == Zend_Amf_Constants::AMF0_OBJECT 
            || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY 
            || $markerType == Zend_Amf_Constants::AMF0_ARRAY 
            || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT 
        ) {
            $ref = array_search($object, $this->_referenceObjects, true);
            //handle object reference
            if($ref !== false){
                $this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE);
                return true;
            }

            $this->_referenceObjects[] = $object;
        }

        return false;
    }

    /**
     * Write a PHP array with string or mixed keys.
     *
     * @param object $data
     * @return Zend_Amf_Parse_Amf0_Serializer
     */
    public function writeObject($object)
    {
        // Loop each element and write the name of the property.
        foreach ($object as $key => &$value) {
            // skip variables starting with an _ private transient
            if( $key[0] == "_") continue;
            $this->_stream->writeUTF($key);
            $this->writeTypeMarker($value);
        }

        // Write the end object flag
        $this->_stream->writeInt(0);
        $this->_stream->writeByte(Zend_Amf_Constants::AMF0_OBJECTTERM);
        return $this;
    }

    /**
     * Write a standard numeric array to the output stream. If a mixed array
     * is encountered call writeTypeMarker with mixed array.
     *
     * @param array $array
     * @return Zend_Amf_Parse_Amf0_Serializer
     */
    public function writeArray(&$array)
    {
        $length = count($array);
        if (!$length < 0) {
            // write the length of the array
            $this->_stream->writeLong(0);
        } else {
            // Write the length of the numeric array
            $this->_stream->writeLong($length);
            for ($i=0; $i<$length; $i++) {
                $value = isset($array[$i]) ? $array[$i] : null;
                $this->writeTypeMarker($value);
            }
        }
        return $this;
    }

    /**
     * Convert the DateTime into an AMF Date
     *
     * @param  DateTime|Zend_Date $data
     * @return Zend_Amf_Parse_Amf0_Serializer
     */
    public function writeDate($data)
    {
        if ($data instanceof DateTime) {
            $dateString = $data->format('U');
        } elseif ($data instanceof Zend_Date) {
            $dateString = $data->toString('U');
        } else {
            require_once 'Zend/Amf/Exception.php';
            throw new Zend_Amf_Exception('Invalid date specified; must be a DateTime or Zend_Date object');
        }
        $dateString *= 1000;

        // Make the conversion and remove milliseconds.
        $this->_stream->writeDouble($dateString);

        // Flash does not respect timezone but requires it.
        $this->_stream->writeInt(0);

        return $this;
    }

    /**
     * Write a class mapped object to the output stream.
     *
     * @param  object $data
     * @return Zend_Amf_Parse_Amf0_Serializer
     */
    public function writeTypedObject($data)
    {
        $this->_stream->writeUTF($this->_className);
        $this->writeObject($data);
        return $this;
    }

    /**
     * Encountered and AMF3 Type Marker use AMF3 serializer. Once AMF3 is
     * encountered it will not return to AMf0.
     *
     * @param  string $data
     * @return Zend_Amf_Parse_Amf0_Serializer
     */
    public function writeAmf3TypeMarker(&$data)
    {
        require_once 'Zend/Amf/Parse/Amf3/Serializer.php';
        $serializer = new Zend_Amf_Parse_Amf3_Serializer($this->_stream);
        $serializer->writeTypeMarker($data);
        return $this;
    }

    /**
     * Find if the class name is a class mapped name and return the
     * respective classname if it is.
     *
     * @param object $object
     * @return false|string $className
     */
    protected function getClassName($object)
    {
        require_once 'Zend/Amf/Parse/TypeLoader.php';
        //Check to see if the object is a typed object and we need to change
        $className = '';
        switch (true) {
            // the return class mapped name back to actionscript class name.
            case Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)):
                $className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object));
                break;
                // Check to see if the user has defined an explicit Action Script type.
            case isset($object->_explicitType):
                $className = $object->_explicitType;
                break;
                // Check if user has defined a method for accessing the Action Script type
            case method_exists($object, 'getASClassName'):
                $className = $object->getASClassName();
                break;
                // No return class name is set make it a generic object
            case ($object instanceof stdClass):
                $className = '';
                break;
        // By default, use object's class name
            default:
        $className = get_class($object);
                break;
        }
        if(!$className == '') {
            return $className;
        } else {
            return false;
        }
    }
}