[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Zend Framework 4 * 5 * LICENSE 6 * 7 * This source file is subject to the new BSD license that is bundled 8 * with this package in the file LICENSE.txt. 9 * It is also available through the world-wide-web at this URL: 10 * http://framework.zend.com/license/new-bsd 11 * If you did not receive a copy of the license and are unable to 12 * obtain it through the world-wide-web, please send an email 13 * to [email protected] so we can send you a copy immediately. 14 * 15 * @category Zend 16 * @package Zend_Amf 17 * @subpackage Parse_Amf3 18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 19 * @license http://framework.zend.com/license/new-bsd New BSD License 20 * @version $Id$ 21 */ 22 23 /** Zend_Amf_Constants */ 24 require_once 'Zend/Amf/Constants.php'; 25 26 27 /** Zend_Amf_Parse_Serializer */ 28 require_once 'Zend/Amf/Parse/Serializer.php'; 29 30 /** Zend_Amf_Parse_TypeLoader */ 31 require_once 'Zend/Amf/Parse/TypeLoader.php'; 32 33 /** 34 * Detect PHP object type and convert it to a corresponding AMF3 object type 35 * 36 * @package Zend_Amf 37 * @subpackage Parse_Amf3 38 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 39 * @license http://framework.zend.com/license/new-bsd New BSD License 40 */ 41 class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer 42 { 43 /** 44 * A constant empty string 45 * @var string 46 */ 47 protected $_strEmpty = ''; 48 49 /** 50 * An array of reference objects per amf body 51 * @var array 52 */ 53 protected $_referenceObjects = array(); 54 55 /** 56 * An array of reference strings per amf body 57 * @var array 58 */ 59 protected $_referenceStrings = array(); 60 61 /** 62 * An array of reference class definitions, indexed by classname 63 * @var array 64 */ 65 protected $_referenceDefinitions = array(); 66 67 /** 68 * Serialize PHP types to AMF3 and write to stream 69 * 70 * Checks to see if the type was declared and then either 71 * auto negotiates the type or use the user defined markerType to 72 * serialize the data from php back to AMF3 73 * 74 * @param mixed $data 75 * @param int $markerType 76 * @param mixed $dataByVal 77 * @return void 78 */ 79 public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false) 80 { 81 // Workaround for PHP5 with E_STRICT enabled complaining about "Only 82 // variables should be passed by reference" 83 if ((null === $data) && ($dataByVal !== false)) { 84 $data = &$dataByVal; 85 } 86 if (null !== $markerType) { 87 // Write the Type Marker to denote the following action script data type 88 $this->_stream->writeByte($markerType); 89 90 switch ($markerType) { 91 case Zend_Amf_Constants::AMF3_NULL: 92 break; 93 case Zend_Amf_Constants::AMF3_BOOLEAN_FALSE: 94 break; 95 case Zend_Amf_Constants::AMF3_BOOLEAN_TRUE: 96 break; 97 case Zend_Amf_Constants::AMF3_INTEGER: 98 $this->writeInteger($data); 99 break; 100 case Zend_Amf_Constants::AMF3_NUMBER: 101 $this->_stream->writeDouble($data); 102 break; 103 case Zend_Amf_Constants::AMF3_STRING: 104 $this->writeString($data); 105 break; 106 case Zend_Amf_Constants::AMF3_DATE: 107 $this->writeDate($data); 108 break; 109 case Zend_Amf_Constants::AMF3_ARRAY: 110 $this->writeArray($data); 111 break; 112 case Zend_Amf_Constants::AMF3_OBJECT: 113 $this->writeObject($data); 114 break; 115 case Zend_Amf_Constants::AMF3_BYTEARRAY: 116 $this->writeByteArray($data); 117 break; 118 case Zend_Amf_Constants::AMF3_XMLSTRING; 119 $this->writeXml($data); 120 break; 121 default: 122 require_once 'Zend/Amf/Exception.php'; 123 throw new Zend_Amf_Exception('Unknown Type Marker: ' . $markerType); 124 } 125 } else { 126 // Detect Type Marker 127 if (is_resource($data)) { 128 $data = Zend_Amf_Parse_TypeLoader::handleResource($data); 129 } 130 switch (true) { 131 case (null === $data): 132 $markerType = Zend_Amf_Constants::AMF3_NULL; 133 break; 134 case (is_bool($data)): 135 if ($data){ 136 $markerType = Zend_Amf_Constants::AMF3_BOOLEAN_TRUE; 137 } else { 138 $markerType = Zend_Amf_Constants::AMF3_BOOLEAN_FALSE; 139 } 140 break; 141 case (is_int($data)): 142 if (($data > 0xFFFFFFF) || ($data < -268435456)) { 143 $markerType = Zend_Amf_Constants::AMF3_NUMBER; 144 } else { 145 $markerType = Zend_Amf_Constants::AMF3_INTEGER; 146 } 147 break; 148 case (is_float($data)): 149 $markerType = Zend_Amf_Constants::AMF3_NUMBER; 150 break; 151 case (is_string($data)): 152 $markerType = Zend_Amf_Constants::AMF3_STRING; 153 break; 154 case (is_array($data)): 155 $markerType = Zend_Amf_Constants::AMF3_ARRAY; 156 break; 157 case (is_object($data)): 158 // Handle object types. 159 if (($data instanceof DateTime) || ($data instanceof Zend_Date)) { 160 $markerType = Zend_Amf_Constants::AMF3_DATE; 161 } else if ($data instanceof Zend_Amf_Value_ByteArray) { 162 $markerType = Zend_Amf_Constants::AMF3_BYTEARRAY; 163 } else if (($data instanceof DOMDocument) || ($data instanceof SimpleXMLElement)) { 164 $markerType = Zend_Amf_Constants::AMF3_XMLSTRING; 165 } else { 166 $markerType = Zend_Amf_Constants::AMF3_OBJECT; 167 } 168 break; 169 default: 170 require_once 'Zend/Amf/Exception.php'; 171 throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data)); 172 } 173 $this->writeTypeMarker($data, $markerType); 174 } 175 } 176 177 /** 178 * Write an AMF3 integer 179 * 180 * @param int|float $data 181 * @return Zend_Amf_Parse_Amf3_Serializer 182 */ 183 public function writeInteger($int) 184 { 185 if (($int & 0xffffff80) == 0) { 186 $this->_stream->writeByte($int & 0x7f); 187 return $this; 188 } 189 190 if (($int & 0xffffc000) == 0 ) { 191 $this->_stream->writeByte(($int >> 7 ) | 0x80); 192 $this->_stream->writeByte($int & 0x7f); 193 return $this; 194 } 195 196 if (($int & 0xffe00000) == 0) { 197 $this->_stream->writeByte(($int >> 14 ) | 0x80); 198 $this->_stream->writeByte(($int >> 7 ) | 0x80); 199 $this->_stream->writeByte($int & 0x7f); 200 return $this; 201 } 202 203 $this->_stream->writeByte(($int >> 22 ) | 0x80); 204 $this->_stream->writeByte(($int >> 15 ) | 0x80); 205 $this->_stream->writeByte(($int >> 8 ) | 0x80); 206 $this->_stream->writeByte($int & 0xff); 207 return $this; 208 } 209 210 /** 211 * Send string to output stream, without trying to reference it. 212 * The string is prepended with strlen($string) << 1 | 0x01 213 * 214 * @param string $string 215 * @return Zend_Amf_Parse_Amf3_Serializer 216 */ 217 protected function writeBinaryString(&$string){ 218 $ref = strlen($string) << 1 | 0x01; 219 $this->writeInteger($ref); 220 $this->_stream->writeBytes($string); 221 222 return $this; 223 } 224 225 /** 226 * Send string to output stream 227 * 228 * @param string $string 229 * @return Zend_Amf_Parse_Amf3_Serializer 230 */ 231 public function writeString(&$string) 232 { 233 $len = strlen($string); 234 if(!$len){ 235 $this->writeInteger(0x01); 236 return $this; 237 } 238 239 $ref = array_search($string, $this->_referenceStrings, true); 240 if($ref === false){ 241 $this->_referenceStrings[] = $string; 242 $this->writeBinaryString($string); 243 } else { 244 $ref <<= 1; 245 $this->writeInteger($ref); 246 } 247 248 return $this; 249 } 250 251 /** 252 * Send ByteArray to output stream 253 * 254 * @param string|Zend_Amf_Value_ByteArray $data 255 * @return Zend_Amf_Parse_Amf3_Serializer 256 */ 257 public function writeByteArray(&$data) 258 { 259 if ($this->writeObjectReference($data)) { 260 return $this; 261 } 262 263 if (is_string($data)) { 264 //nothing to do 265 } else if ($data instanceof Zend_Amf_Value_ByteArray) { 266 $data = $data->getData(); 267 } else { 268 require_once 'Zend/Amf/Exception.php'; 269 throw new Zend_Amf_Exception('Invalid ByteArray specified; must be a string or Zend_Amf_Value_ByteArray'); 270 } 271 272 $this->writeBinaryString($data); 273 274 return $this; 275 } 276 277 /** 278 * Send xml to output stream 279 * 280 * @param DOMDocument|SimpleXMLElement $xml 281 * @return Zend_Amf_Parse_Amf3_Serializer 282 */ 283 public function writeXml($xml) 284 { 285 if ($this->writeObjectReference($xml)) { 286 return $this; 287 } 288 289 if(is_string($xml)) { 290 //nothing to do 291 } else if ($xml instanceof DOMDocument) { 292 $xml = $xml->saveXml(); 293 } else if ($xml instanceof SimpleXMLElement) { 294 $xml = $xml->asXML(); 295 } else { 296 require_once 'Zend/Amf/Exception.php'; 297 throw new Zend_Amf_Exception('Invalid xml specified; must be a DOMDocument or SimpleXMLElement'); 298 } 299 300 $this->writeBinaryString($xml); 301 302 return $this; 303 } 304 305 /** 306 * Convert DateTime/Zend_Date to AMF date 307 * 308 * @param DateTime|Zend_Date $date 309 * @return Zend_Amf_Parse_Amf3_Serializer 310 */ 311 public function writeDate($date) 312 { 313 if ($this->writeObjectReference($date)) { 314 return $this; 315 } 316 317 if ($date instanceof DateTime) { 318 $dateString = $date->format('U') * 1000; 319 } elseif ($date instanceof Zend_Date) { 320 $dateString = $date->toString('U') * 1000; 321 } else { 322 require_once 'Zend/Amf/Exception.php'; 323 throw new Zend_Amf_Exception('Invalid date specified; must be a string DateTime or Zend_Date object'); 324 } 325 326 $this->writeInteger(0x01); 327 // write time to stream minus milliseconds 328 $this->_stream->writeDouble($dateString); 329 return $this; 330 } 331 332 /** 333 * Write a PHP array back to the amf output stream 334 * 335 * @param array $array 336 * @return Zend_Amf_Parse_Amf3_Serializer 337 */ 338 public function writeArray(&$array) 339 { 340 // arrays aren't reference here but still counted 341 $this->_referenceObjects[] = $array; 342 343 // have to seperate mixed from numberic keys. 344 $numeric = array(); 345 $string = array(); 346 foreach ($array as $key => &$value) { 347 if (is_int($key)) { 348 $numeric[] = $value; 349 } else { 350 $string[$key] = $value; 351 } 352 } 353 354 // write the preamble id of the array 355 $length = count($numeric); 356 $id = ($length << 1) | 0x01; 357 $this->writeInteger($id); 358 359 //Write the mixed type array to the output stream 360 foreach($string as $key => &$value) { 361 $this->writeString($key) 362 ->writeTypeMarker($value); 363 } 364 $this->writeString($this->_strEmpty); 365 366 // Write the numeric array to ouput stream 367 foreach($numeric as &$value) { 368 $this->writeTypeMarker($value); 369 } 370 return $this; 371 } 372 373 /** 374 * Check if the given object is in the reference table, write the reference if it exists, 375 * otherwise add the object to the reference table 376 * 377 * @param mixed $object object reference to check for reference 378 * @param mixed $objectByVal object to check for reference 379 * @return Boolean true, if the reference was written, false otherwise 380 */ 381 protected function writeObjectReference(&$object, $objectByVal = false) 382 { 383 // Workaround for PHP5 with E_STRICT enabled complaining about "Only 384 // variables should be passed by reference" 385 if ((null === $object) && ($objectByVal !== false)) { 386 $object = &$objectByVal; 387 } 388 389 $ref = array_search($object, $this->_referenceObjects,true); 390 391 // quickly handle object references 392 if ($ref !== false){ 393 $ref <<= 1; 394 $this->writeInteger($ref); 395 return true; 396 } 397 $this->_referenceObjects[] = $object; 398 return false; 399 } 400 401 /** 402 * Write object to ouput stream 403 * 404 * @param mixed $data 405 * @return Zend_Amf_Parse_Amf3_Serializer 406 */ 407 public function writeObject($object) 408 { 409 if($this->writeObjectReference($object)){ 410 return $this; 411 } 412 413 $className = ''; 414 415 //Check to see if the object is a typed object and we need to change 416 switch (true) { 417 // the return class mapped name back to actionscript class name. 418 case ($className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object))): 419 break; 420 421 // Check to see if the user has defined an explicit Action Script type. 422 case isset($object->_explicitType): 423 $className = $object->_explicitType; 424 break; 425 426 // Check if user has defined a method for accessing the Action Script type 427 case method_exists($object, 'getASClassName'): 428 $className = $object->getASClassName(); 429 break; 430 431 // No return class name is set make it a generic object 432 case ($object instanceof stdClass): 433 $className = ''; 434 break; 435 436 // By default, use object's class name 437 default: 438 $className = get_class($object); 439 break; 440 } 441 442 $writeTraits = true; 443 444 //check to see, if we have a corresponding definition 445 if(array_key_exists($className, $this->_referenceDefinitions)){ 446 $traitsInfo = $this->_referenceDefinitions[$className]['id']; 447 $encoding = $this->_referenceDefinitions[$className]['encoding']; 448 $propertyNames = $this->_referenceDefinitions[$className]['propertyNames']; 449 450 $traitsInfo = ($traitsInfo << 2) | 0x01; 451 452 $writeTraits = false; 453 } else { 454 $propertyNames = array(); 455 456 if($className == ''){ 457 //if there is no className, we interpret the class as dynamic without any sealed members 458 $encoding = Zend_Amf_Constants::ET_DYNAMIC; 459 } else { 460 $encoding = Zend_Amf_Constants::ET_PROPLIST; 461 462 foreach($object as $key => $value) { 463 if( $key[0] != "_") { 464 $propertyNames[] = $key; 465 } 466 } 467 } 468 469 $this->_referenceDefinitions[$className] = array( 470 'id' => count($this->_referenceDefinitions), 471 'encoding' => $encoding, 472 'propertyNames' => $propertyNames, 473 ); 474 475 $traitsInfo = Zend_Amf_Constants::AMF3_OBJECT_ENCODING; 476 $traitsInfo |= $encoding << 2; 477 $traitsInfo |= (count($propertyNames) << 4); 478 } 479 480 $this->writeInteger($traitsInfo); 481 482 if($writeTraits){ 483 $this->writeString($className); 484 foreach ($propertyNames as $value) { 485 $this->writeString($value); 486 } 487 } 488 489 try { 490 switch($encoding) { 491 case Zend_Amf_Constants::ET_PROPLIST: 492 //Write the sealed values to the output stream. 493 foreach ($propertyNames as $key) { 494 $this->writeTypeMarker($object->$key); 495 } 496 break; 497 case Zend_Amf_Constants::ET_DYNAMIC: 498 //Write the sealed values to the output stream. 499 foreach ($propertyNames as $key) { 500 $this->writeTypeMarker($object->$key); 501 } 502 503 //Write remaining properties 504 foreach($object as $key => $value){ 505 if(!in_array($key,$propertyNames) && $key[0] != "_"){ 506 $this->writeString($key); 507 $this->writeTypeMarker($value); 508 } 509 } 510 511 //Write an empty string to end the dynamic part 512 $this->writeString($this->_strEmpty); 513 break; 514 case Zend_Amf_Constants::ET_EXTERNAL: 515 require_once 'Zend/Amf/Exception.php'; 516 throw new Zend_Amf_Exception('External Object Encoding not implemented'); 517 break; 518 default: 519 require_once 'Zend/Amf/Exception.php'; 520 throw new Zend_Amf_Exception('Unknown Object Encoding type: ' . $encoding); 521 } 522 } catch (Exception $e) { 523 require_once 'Zend/Amf/Exception.php'; 524 throw new Zend_Amf_Exception('Unable to writeObject output: ' . $e->getMessage(), 0, $e); 525 } 526 527 return $this; 528 } 529 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |