[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Amf/Parse/Amf3/ -> Serializer.php (source)

   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  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1