Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Encoder.php
Go to the documentation of this file.
1 <?php
31 {
37  protected $_cycleCheck;
38 
44  protected $_options = array();
45 
51  protected $_visited = array();
52 
60  protected function __construct($cycleCheck = false, $options = array())
61  {
62  $this->_cycleCheck = $cycleCheck;
63  $this->_options = $options;
64  }
65 
74  public static function encode($value, $cycleCheck = false, $options = array())
75  {
76  $encoder = new self(($cycleCheck) ? true : false, $options);
77  return $encoder->_encodeValue($value);
78  }
79 
90  protected function _encodeValue(&$value)
91  {
92  if (is_object($value)) {
93  return $this->_encodeObject($value);
94  } else if (is_array($value)) {
95  return $this->_encodeArray($value);
96  }
97 
98  return $this->_encodeDatum($value);
99  }
100 
101 
102 
114  protected function _encodeObject(&$value)
115  {
116  if ($this->_cycleCheck) {
117  if ($this->_wasVisited($value)) {
118 
119  if (isset($this->_options['silenceCyclicalExceptions'])
120  && $this->_options['silenceCyclicalExceptions']===true) {
121 
122  return '"* RECURSION (' . get_class($value) . ') *"';
123 
124  } else {
125  #require_once 'Zend/Json/Exception.php';
126  throw new Zend_Json_Exception(
127  'Cycles not supported in JSON encoding, cycle introduced by '
128  . 'class "' . get_class($value) . '"'
129  );
130  }
131  }
132 
133  $this->_visited[] = $value;
134  }
135 
136  $props = '';
137  if (method_exists($value, 'toJson')) {
138  $props =',' . preg_replace("/^\{(.*)\}$/","\\1",$value->toJson());
139  } else {
140  if ($value instanceof IteratorAggregate) {
141  $propCollection = $value->getIterator();
142  } elseif ($value instanceof Iterator) {
143  $propCollection = $value;
144  } else {
145  $propCollection = get_object_vars($value);
146  }
147 
148  foreach ($propCollection as $name => $propValue) {
149  if (isset($propValue)) {
150  $props .= ','
151  . $this->_encodeString($name)
152  . ':'
153  . $this->_encodeValue($propValue);
154  }
155  }
156  }
157  $className = get_class($value);
158  return '{"__className":' . $this->_encodeString($className)
159  . $props . '}';
160  }
161 
162 
169  protected function _wasVisited(&$value)
170  {
171  if (in_array($value, $this->_visited, true)) {
172  return true;
173  }
174 
175  return false;
176  }
177 
178 
192  protected function _encodeArray(&$array)
193  {
194  $tmpArray = array();
195 
196  // Check for associative array
197  if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
198  // Associative array
199  $result = '{';
200  foreach ($array as $key => $value) {
201  $key = (string) $key;
202  $tmpArray[] = $this->_encodeString($key)
203  . ':'
204  . $this->_encodeValue($value);
205  }
206  $result .= implode(',', $tmpArray);
207  $result .= '}';
208  } else {
209  // Indexed array
210  $result = '[';
211  $length = count($array);
212  for ($i = 0; $i < $length; $i++) {
213  $tmpArray[] = $this->_encodeValue($array[$i]);
214  }
215  $result .= implode(',', $tmpArray);
216  $result .= ']';
217  }
218 
219  return $result;
220  }
221 
222 
232  protected function _encodeDatum(&$value)
233  {
234  $result = 'null';
235 
236  if (is_int($value) || is_float($value)) {
237  $result = (string) $value;
238  $result = str_replace(",", ".", $result);
239  } elseif (is_string($value)) {
240  $result = $this->_encodeString($value);
241  } elseif (is_bool($value)) {
242  $result = $value ? 'true' : 'false';
243  }
244 
245  return $result;
246  }
247 
248 
255  protected function _encodeString(&$string)
256  {
257  // Escape these characters with a backslash:
258  // " \ / \n \r \t \b \f
259  $search = array('\\', "\n", "\t", "\r", "\b", "\f", '"', '/');
260  $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"', '\\/');
261  $string = str_replace($search, $replace, $string);
262 
263  // Escape certain ASCII characters:
264  // 0x08 => \b
265  // 0x0c => \f
266  $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
267  $string = self::encodeUnicodeString($string);
268 
269  return '"' . $string . '"';
270  }
271 
272 
280  private static function _encodeConstants(ReflectionClass $cls)
281  {
282  $result = "constants : {";
283  $constants = $cls->getConstants();
284 
285  $tmpArray = array();
286  if (!empty($constants)) {
287  foreach ($constants as $key => $value) {
288  $tmpArray[] = "$key: " . self::encode($value);
289  }
290 
291  $result .= implode(', ', $tmpArray);
292  }
293 
294  return $result . "}";
295  }
296 
297 
306  private static function _encodeMethods(ReflectionClass $cls)
307  {
308  $methods = $cls->getMethods();
309  $result = 'methods:{';
310 
311  $started = false;
312  foreach ($methods as $method) {
313  if (! $method->isPublic() || !$method->isUserDefined()) {
314  continue;
315  }
316 
317  if ($started) {
318  $result .= ',';
319  }
320  $started = true;
321 
322  $result .= '' . $method->getName(). ':function(';
323 
324  if ('__construct' != $method->getName()) {
325  $parameters = $method->getParameters();
326  $paramCount = count($parameters);
327  $argsStarted = false;
328 
329  $argNames = "var argNames=[";
330  foreach ($parameters as $param) {
331  if ($argsStarted) {
332  $result .= ',';
333  }
334 
335  $result .= $param->getName();
336 
337  if ($argsStarted) {
338  $argNames .= ',';
339  }
340 
341  $argNames .= '"' . $param->getName() . '"';
342 
343  $argsStarted = true;
344  }
345  $argNames .= "];";
346 
347  $result .= "){"
348  . $argNames
349  . 'var result = ZAjaxEngine.invokeRemoteMethod('
350  . "this, '" . $method->getName()
351  . "',argNames,arguments);"
352  . 'return(result);}';
353  } else {
354  $result .= "){}";
355  }
356  }
357 
358  return $result . "}";
359  }
360 
361 
370  private static function _encodeVariables(ReflectionClass $cls)
371  {
372  $properties = $cls->getProperties();
373  $propValues = get_class_vars($cls->getName());
374  $result = "variables:{";
375  $cnt = 0;
376 
377  $tmpArray = array();
378  foreach ($properties as $prop) {
379  if (! $prop->isPublic()) {
380  continue;
381  }
382 
383  $tmpArray[] = $prop->getName()
384  . ':'
385  . self::encode($propValues[$prop->getName()]);
386  }
387  $result .= implode(',', $tmpArray);
388 
389  return $result . "}";
390  }
391 
405  public static function encodeClass($className, $package = '')
406  {
407  $cls = new ReflectionClass($className);
408  if (! $cls->isInstantiable()) {
409  #require_once 'Zend/Json/Exception.php';
410  throw new Zend_Json_Exception("$className must be instantiable");
411  }
412 
413  return "Class.create('$package$className',{"
414  . self::_encodeConstants($cls) .","
415  . self::_encodeMethods($cls) .","
416  . self::_encodeVariables($cls) .'});';
417  }
418 
419 
429  public static function encodeClasses(array $classNames, $package = '')
430  {
431  $result = '';
432  foreach ($classNames as $className) {
433  $result .= self::encodeClass($className, $package);
434  }
435 
436  return $result;
437  }
438 
450  public static function encodeUnicodeString($value)
451  {
452  $strlen_var = strlen($value);
453  $ascii = "";
454 
459  for($i = 0; $i < $strlen_var; $i++) {
460  $ord_var_c = ord($value[$i]);
461 
462  switch (true) {
463  case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
464  // characters U-00000000 - U-0000007F (same as ASCII)
465  $ascii .= $value[$i];
466  break;
467 
468  case (($ord_var_c & 0xE0) == 0xC0):
469  // characters U-00000080 - U-000007FF, mask 110XXXXX
470  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
471  $char = pack('C*', $ord_var_c, ord($value[$i + 1]));
472  $i += 1;
473  $utf16 = self::_utf82utf16($char);
474  $ascii .= sprintf('\u%04s', bin2hex($utf16));
475  break;
476 
477  case (($ord_var_c & 0xF0) == 0xE0):
478  // characters U-00000800 - U-0000FFFF, mask 1110XXXX
479  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
480  $char = pack('C*', $ord_var_c,
481  ord($value[$i + 1]),
482  ord($value[$i + 2]));
483  $i += 2;
484  $utf16 = self::_utf82utf16($char);
485  $ascii .= sprintf('\u%04s', bin2hex($utf16));
486  break;
487 
488  case (($ord_var_c & 0xF8) == 0xF0):
489  // characters U-00010000 - U-001FFFFF, mask 11110XXX
490  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
491  $char = pack('C*', $ord_var_c,
492  ord($value[$i + 1]),
493  ord($value[$i + 2]),
494  ord($value[$i + 3]));
495  $i += 3;
496  $utf16 = self::_utf82utf16($char);
497  $ascii .= sprintf('\u%04s', bin2hex($utf16));
498  break;
499 
500  case (($ord_var_c & 0xFC) == 0xF8):
501  // characters U-00200000 - U-03FFFFFF, mask 111110XX
502  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
503  $char = pack('C*', $ord_var_c,
504  ord($value[$i + 1]),
505  ord($value[$i + 2]),
506  ord($value[$i + 3]),
507  ord($value[$i + 4]));
508  $i += 4;
509  $utf16 = self::_utf82utf16($char);
510  $ascii .= sprintf('\u%04s', bin2hex($utf16));
511  break;
512 
513  case (($ord_var_c & 0xFE) == 0xFC):
514  // characters U-04000000 - U-7FFFFFFF, mask 1111110X
515  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
516  $char = pack('C*', $ord_var_c,
517  ord($value[$i + 1]),
518  ord($value[$i + 2]),
519  ord($value[$i + 3]),
520  ord($value[$i + 4]),
521  ord($value[$i + 5]));
522  $i += 5;
523  $utf16 = self::_utf82utf16($char);
524  $ascii .= sprintf('\u%04s', bin2hex($utf16));
525  break;
526  }
527  }
528 
529  return $ascii;
530  }
531 
545  protected static function _utf82utf16($utf8)
546  {
547  // Check for mb extension otherwise do by hand.
548  if( function_exists('mb_convert_encoding') ) {
549  return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
550  }
551 
552  switch (strlen($utf8)) {
553  case 1:
554  // this case should never be reached, because we are in ASCII range
555  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
556  return $utf8;
557 
558  case 2:
559  // return a UTF-16 character from a 2-byte UTF-8 char
560  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
561  return chr(0x07 & (ord($utf8{0}) >> 2))
562  . chr((0xC0 & (ord($utf8{0}) << 6))
563  | (0x3F & ord($utf8{1})));
564 
565  case 3:
566  // return a UTF-16 character from a 3-byte UTF-8 char
567  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
568  return chr((0xF0 & (ord($utf8{0}) << 4))
569  | (0x0F & (ord($utf8{1}) >> 2)))
570  . chr((0xC0 & (ord($utf8{1}) << 6))
571  | (0x7F & ord($utf8{2})));
572  }
573 
574  // ignoring UTF-32 for now, sorry
575  return '';
576  }
577 }
578 
_encodeDatum(&$value)
Definition: Encoder.php:232
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
static encodeUnicodeString($value)
Definition: Encoder.php:450
static encodeClasses(array $classNames, $package='')
Definition: Encoder.php:429
_encodeObject(&$value)
Definition: Encoder.php:114
$methods
Definition: billing.phtml:71
$value
Definition: gender.phtml:16
_encodeString(&$string)
Definition: Encoder.php:255
_encodeArray(&$array)
Definition: Encoder.php:192
_encodeValue(&$value)
Definition: Encoder.php:90
__construct($cycleCheck=false, $options=array())
Definition: Encoder.php:60
$method
Definition: info.phtml:13
static _utf82utf16($utf8)
Definition: Encoder.php:545
_wasVisited(&$value)
Definition: Encoder.php:169
static encodeClass($className, $package='')
Definition: Encoder.php:405
$properties
Definition: categories.php:26
$i
Definition: gallery.phtml:31
static encode($value, $cycleCheck=false, $options=array())
Definition: Encoder.php:74
if($currentSelectedMethod==$_code) $className
Definition: form.phtml:31
if(!isset($_GET['name'])) $name
Definition: log.php:14