[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/include/Zend/Json/ -> Encoder.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_Json
  17   * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  18   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  19   */
  20  
  21  
  22  /**
  23   * Zend_Json_Exception
  24   */
  25  require_once  'include/Zend/Json/Exception.php';
  26  
  27  
  28  /**
  29   * Encode PHP constructs to JSON
  30   *
  31   * @category   Zend
  32   * @package    Zend_Json
  33   * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  34   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  35   */
  36  class Zend_Json_Encoder
  37  {
  38      /**
  39       * Whether or not to check for possible cycling
  40       *
  41       * @var boolean
  42       */
  43      protected $_cycleCheck;
  44  
  45      /**
  46       * Array of visited objects; used to prevent cycling.
  47       *
  48       * @var array
  49       */
  50      protected $_visited = array();
  51  
  52      /**
  53       * Constructor
  54       *
  55       * @param boolean $cycleCheck Whether or not to check for recursion when encoding
  56       * @return void
  57       */
  58      protected function __construct($cycleCheck = false)
  59      {
  60          $this->_cycleCheck = $cycleCheck;
  61      }
  62  
  63      /**
  64       * Use the JSON encoding scheme for the value specified
  65       *
  66       * @param mixed $value The value to be encoded
  67       * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
  68       * @return string  The encoded value
  69       */
  70      public static function encode($value, $cycleCheck = false)
  71      {
  72          $encoder = new Zend_Json_Encoder(($cycleCheck) ? true : false);
  73  
  74          return $encoder->_encodeValue($value);
  75      }
  76  
  77      /**
  78       * Recursive driver which determines the type of value to be encoded
  79       * and then dispatches to the appropriate method. $values are either
  80       *    - objects (returns from {@link _encodeObject()})
  81       *    - arrays (returns from {@link _encodeArray()})
  82       *    - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
  83       *
  84       * @param $value mixed The value to be encoded
  85       * @return string Encoded value
  86       */
  87      protected function _encodeValue(&$value)
  88      {
  89          if (is_object($value)) {
  90              return $this->_encodeObject($value);
  91          } else if (is_array($value)) {
  92              return $this->_encodeArray($value);
  93          }
  94  
  95          return $this->_encodeDatum($value);
  96      }
  97  
  98  
  99  
 100      /**
 101       * Encode an object to JSON by encoding each of the public properties
 102       *
 103       * A special property is added to the JSON object called '__className'
 104       * that contains the name of the class of $value. This is used to decode
 105       * the object on the client into a specific class.
 106       *
 107       * @param $value object
 108       * @return string
 109       * @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
 110       */
 111      protected function _encodeObject(&$value)
 112      {
 113          if ($this->_cycleCheck) {
 114              if ($this->_wasVisited($value)) {
 115                  throw new Zend_Json_Exception(
 116                      'Cycles not supported in JSON encoding, cycle introduced by '
 117                      . 'class "' . get_class($value) . '"'
 118                  );
 119              }
 120  
 121              $this->_visited[] = $value;
 122          }
 123  
 124          $props = '';
 125          foreach (get_object_vars($value) as $name => $propValue) {
 126              if (isset($propValue)) {
 127                  $props .= ','
 128                          . $this->_encodeValue($name)
 129                          . ':'
 130                          . $this->_encodeValue($propValue);
 131              }
 132          }
 133  
 134          /*return '{"__className":"' . get_class($value) . '"'
 135                  . $props . '}';*/
 136          return '{'.substr($props,1).'}';
 137      }
 138  
 139  
 140      /**
 141       * Determine if an object has been serialized already
 142       *
 143       * @param mixed $value
 144       * @return boolean
 145       */
 146      protected function _wasVisited(&$value)
 147      {
 148          if (in_array($value, $this->_visited, true)) {
 149              return true;
 150          }
 151  
 152          return false;
 153      }
 154  
 155  
 156      /**
 157       * JSON encode an array value
 158       *
 159       * Recursively encodes each value of an array and returns a JSON encoded
 160       * array string.
 161       *
 162       * Arrays are defined as integer-indexed arrays starting at index 0, where
 163       * the last index is (count($array) -1); any deviation from that is
 164       * considered an associative array, and will be encoded as such.
 165       *
 166       * @param $array array
 167       * @return string
 168       */
 169      protected function _encodeArray(&$array)
 170      {
 171          $tmpArray = array();
 172  
 173          // Check for associative array
 174          if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
 175              // Associative array
 176              $result = '{';
 177              foreach ($array as $key => $value) {
 178                  $key = (string) $key;
 179                  $tmpArray[] = $this->_encodeString($key)
 180                              . ':'
 181                              . $this->_encodeValue($value);
 182              }
 183              $result .= implode(',', $tmpArray);
 184              $result .= '}';
 185          } else {
 186              // Indexed array
 187              $result = '[';
 188              $length = count($array);
 189              for ($i = 0; $i < $length; $i++) {
 190                  $tmpArray[] = $this->_encodeValue($array[$i]);
 191              }
 192              $result .= implode(',', $tmpArray);
 193              $result .= ']';
 194          }
 195  
 196          return $result;
 197      }
 198  
 199  
 200      /**
 201       * JSON encode a basic data type (string, number, boolean, null)
 202       *
 203       * If value type is not a string, number, boolean, or null, the string
 204       * 'null' is returned.
 205       *
 206       * @param $value mixed
 207       * @return string
 208       */
 209      protected function _encodeDatum(&$value)
 210      {
 211          $result = 'null';
 212  
 213          if (is_int($value) || is_float($value)) {
 214              $result = (string)$value;
 215          } elseif (is_string($value)) {
 216              $result = $this->_encodeString($value);
 217          } elseif (is_bool($value)) {
 218              $result = $value ? 'true' : 'false';
 219          }
 220  
 221          return $result;
 222      }
 223  
 224  
 225      /**
 226       * JSON encode a string value by escaping characters as necessary
 227       *
 228       * @param $value string
 229       * @return string
 230       */
 231      protected function _encodeString(&$string)
 232      {
 233          // Escape these characters with a backslash:
 234          // " \ / \n \r \t \b \f
 235          $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
 236          $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
 237          $string  = str_replace($search, $replace, $string);
 238  
 239          // Escape certain ASCII characters:
 240          // 0x08 => \b
 241          // 0x0c => \f
 242          $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
 243  
 244          return '"' . $string . '"';
 245      }
 246  
 247  
 248      /**
 249       * Encode the constants associated with the ReflectionClass
 250       * parameter. The encoding format is based on the class2 format
 251       *
 252       * @param $cls ReflectionClass
 253       * @return string Encoded constant block in class2 format
 254       */
 255      private static function _encodeConstants(ReflectionClass $cls)
 256      {
 257          $result    = "constants : {";
 258          $constants = $cls->getConstants();
 259  
 260          $tmpArray = array();
 261          if (!empty($constants)) {
 262              foreach ($constants as $key => $value) {
 263                  $tmpArray[] = "$key: " . self::encode($value);
 264              }
 265  
 266              $result .= implode(', ', $tmpArray);
 267          }
 268  
 269          return $result . "}";
 270      }
 271  
 272  
 273      /**
 274       * Encode the public methods of the ReflectionClass in the
 275       * class2 format
 276       *
 277       * @param $cls ReflectionClass
 278       * @return string Encoded method fragment
 279       *
 280       */
 281      private static function _encodeMethods(ReflectionClass $cls)
 282      {
 283          $methods = $cls->getMethods();
 284          $result = 'methods:{';
 285  
 286          $started = false;
 287          foreach ($methods as $method) {
 288              if (! $method->isPublic() || !$method->isUserDefined()) {
 289                  continue;
 290              }
 291  
 292              if ($started) {
 293                  $result .= ',';
 294              }
 295              $started = true;
 296  
 297              $result .= '' . $method->getName(). ':function(';
 298  
 299              if ('__construct' != $method->getName()) {
 300                  $parameters  = $method->getParameters();
 301                  $paramCount  = count($parameters);
 302                  $argsStarted = false;
 303  
 304                  $argNames = "var argNames=[";
 305                  foreach ($parameters as $param) {
 306                      if ($argsStarted) {
 307                          $result .= ',';
 308                      }
 309  
 310                      $result .= $param->getName();
 311  
 312                      if ($argsStarted) {
 313                          $argNames .= ',';
 314                      }
 315  
 316                      $argNames .= '"' . $param->getName() . '"';
 317  
 318                      $argsStarted = true;
 319                  }
 320                  $argNames .= "];";
 321  
 322                  $result .= "){"
 323                           . $argNames
 324                           . 'var result = ZAjaxEngine.invokeRemoteMethod('
 325                           . "this, '" . $method->getName()
 326                           . "',argNames,arguments);"
 327                           . 'return(result);}';
 328              } else {
 329                  $result .= "){}";
 330              }
 331          }
 332  
 333          return $result . "}";
 334      }
 335  
 336  
 337      /**
 338       * Encode the public properties of the ReflectionClass in the class2
 339       * format.
 340       *
 341       * @param $cls ReflectionClass
 342       * @return string Encode properties list
 343       *
 344       */
 345      private static function _encodeVariables(ReflectionClass $cls)
 346      {
 347          $properties = $cls->getProperties();
 348          $propValues = get_class_vars($cls->getName());
 349          $result = "variables:{";
 350          $cnt = 0;
 351  
 352          $tmpArray = array();
 353          foreach ($properties as $prop) {
 354              if (! $prop->isPublic()) {
 355                  continue;
 356              }
 357  
 358              $tmpArray[] = $prop->getName()
 359                          . ':'
 360                          . self::encode($propValues[$prop->getName()]);
 361          }
 362          $result .= implode(',', $tmpArray);
 363  
 364          return $result . "}";
 365      }
 366  
 367      /**
 368       * Encodes the given $className into the class2 model of encoding PHP
 369       * classes into JavaScript class2 classes.
 370       * NOTE: Currently only public methods and variables are proxied onto
 371       * the client machine
 372       *
 373       * @param $className string The name of the class, the class must be
 374       * instantiable using a null constructor
 375       * @param $package string Optional package name appended to JavaScript
 376       * proxy class name
 377       * @return string The class2 (JavaScript) encoding of the class
 378       * @throws Zend_Json_Exception
 379       */
 380      public static function encodeClass($className, $package = '')
 381      {
 382          $cls = new ReflectionClass($className);
 383          if (! $cls->isInstantiable()) {
 384              throw new Zend_Json_Exception("$className must be instantiable");
 385          }
 386  
 387          return "Class.create('$package$className',{"
 388                  . self::_encodeConstants($cls)    .","
 389                  . self::_encodeMethods($cls)      .","
 390                  . self::_encodeVariables($cls)    .'});';
 391      }
 392  
 393  
 394      /**
 395       * Encode several classes at once
 396       *
 397       * Returns JSON encoded classes, using {@link encodeClass()}.
 398       *
 399       * @param array $classNames
 400       * @param string $package
 401       * @return string
 402       */
 403      public static function encodeClasses(array $classNames, $package = '')
 404      {
 405          $result = '';
 406          foreach ($classNames as $className) {
 407              $result .= self::encodeClass($className, $package);
 408          }
 409  
 410          return $result;
 411      }
 412  
 413  }
 414  


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1