[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/symfony/var-dumper/Cloner/ -> VarCloner.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the Symfony package.
   5   *
   6   * (c) Fabien Potencier <[email protected]>
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  namespace Symfony\Component\VarDumper\Cloner;
  13  
  14  /**
  15   * @author Nicolas Grekas <[email protected]>
  16   */
  17  class VarCloner extends AbstractCloner
  18  {
  19      private static $gid;
  20      private static $arrayCache = [];
  21  
  22      /**
  23       * {@inheritdoc}
  24       */
  25      protected function doClone($var)
  26      {
  27          $len = 1;                       // Length of $queue
  28          $pos = 0;                       // Number of cloned items past the minimum depth
  29          $refsCounter = 0;               // Hard references counter
  30          $queue = [[$var]];              // This breadth-first queue is the return value
  31          $hardRefs = [];                 // Map of original zval ids to stub objects
  32          $objRefs = [];                  // Map of original object handles to their stub object counterpart
  33          $objects = [];                  // Keep a ref to objects to ensure their handle cannot be reused while cloning
  34          $resRefs = [];                  // Map of original resource handles to their stub object counterpart
  35          $values = [];                   // Map of stub objects' ids to original values
  36          $maxItems = $this->maxItems;
  37          $maxString = $this->maxString;
  38          $minDepth = $this->minDepth;
  39          $currentDepth = 0;              // Current tree depth
  40          $currentDepthFinalIndex = 0;    // Final $queue index for current tree depth
  41          $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached
  42          $cookie = (object) [];          // Unique object used to detect hard references
  43          $a = null;                      // Array cast for nested structures
  44          $stub = null;                   // Stub capturing the main properties of an original item value
  45                                          // or null if the original value is used directly
  46  
  47          if (!$gid = self::$gid) {
  48              $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable
  49          }
  50          $arrayStub = new Stub();
  51          $arrayStub->type = Stub::TYPE_ARRAY;
  52          $fromObjCast = false;
  53  
  54          for ($i = 0; $i < $len; ++$i) {
  55              // Detect when we move on to the next tree depth
  56              if ($i > $currentDepthFinalIndex) {
  57                  ++$currentDepth;
  58                  $currentDepthFinalIndex = $len - 1;
  59                  if ($currentDepth >= $minDepth) {
  60                      $minimumDepthReached = true;
  61                  }
  62              }
  63  
  64              $refs = $vals = $queue[$i];
  65              foreach ($vals as $k => $v) {
  66                  // $v is the original value or a stub object in case of hard references
  67  
  68                  if (\PHP_VERSION_ID >= 70400) {
  69                      $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;
  70                  } else {
  71                      $refs[$k] = $cookie;
  72                      $zvalRef = $vals[$k] === $cookie;
  73                  }
  74  
  75                  if ($zvalRef) {
  76                      $vals[$k] = &$stub;         // Break hard references to make $queue completely
  77                      unset($stub);               // independent from the original structure
  78                      if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {
  79                          if (\PHP_VERSION_ID >= 70400) {
  80                              $v = $vals[$k];
  81                          } else {
  82                              $refs[$k] = $vals[$k] = $v;
  83                          }
  84                          if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
  85                              ++$v->value->refCount;
  86                          }
  87                          ++$v->refCount;
  88                          continue;
  89                      }
  90                      $vals[$k] = new Stub();
  91                      $vals[$k]->value = $v;
  92                      $vals[$k]->handle = ++$refsCounter;
  93  
  94                      if (\PHP_VERSION_ID >= 70400) {
  95                          $hardRefs[$zvalRef] = $vals[$k];
  96                      } else {
  97                          $refs[$k] = $vals[$k];
  98                          $h = spl_object_id($refs[$k]);
  99                          $hardRefs[$h] = &$refs[$k];
 100                          $values[$h] = $v;
 101                      }
 102                  }
 103                  // Create $stub when the original value $v cannot be used directly
 104                  // If $v is a nested structure, put that structure in array $a
 105                  switch (true) {
 106                      case null === $v:
 107                      case \is_bool($v):
 108                      case \is_int($v):
 109                      case \is_float($v):
 110                          continue 2;
 111                      case \is_string($v):
 112                          if ('' === $v) {
 113                              continue 2;
 114                          }
 115                          if (!preg_match('//u', $v)) {
 116                              $stub = new Stub();
 117                              $stub->type = Stub::TYPE_STRING;
 118                              $stub->class = Stub::STRING_BINARY;
 119                              if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) {
 120                                  $stub->cut = $cut;
 121                                  $stub->value = substr($v, 0, -$cut);
 122                              } else {
 123                                  $stub->value = $v;
 124                              }
 125                          } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
 126                              $stub = new Stub();
 127                              $stub->type = Stub::TYPE_STRING;
 128                              $stub->class = Stub::STRING_UTF8;
 129                              $stub->cut = $cut;
 130                              $stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
 131                          } else {
 132                              continue 2;
 133                          }
 134                          $a = null;
 135                          break;
 136  
 137                      case \is_array($v):
 138                          if (!$v) {
 139                              continue 2;
 140                          }
 141                          $stub = $arrayStub;
 142  
 143                          if (\PHP_VERSION_ID >= 80100) {
 144                              $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;
 145                              $a = $v;
 146                              break;
 147                          }
 148  
 149                          $stub->class = Stub::ARRAY_INDEXED;
 150  
 151                          $j = -1;
 152                          foreach ($v as $gk => $gv) {
 153                              if ($gk !== ++$j) {
 154                                  $stub->class = Stub::ARRAY_ASSOC;
 155                                  $a = $v;
 156                                  $a[$gid] = true;
 157                                  break;
 158                              }
 159                          }
 160  
 161                          // Copies of $GLOBALS have very strange behavior,
 162                          // let's detect them with some black magic
 163                          if (isset($v[$gid])) {
 164                              unset($v[$gid]);
 165                              $a = [];
 166                              foreach ($v as $gk => &$gv) {
 167                                  if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) {
 168                                      unset($v);
 169                                      $v = new Stub();
 170                                      $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0];
 171                                      $v->handle = -1;
 172                                      if (\PHP_VERSION_ID >= 70400) {
 173                                          $gv = &$a[$gk];
 174                                          $hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv;
 175                                      } else {
 176                                          $gv = &$hardRefs[spl_object_id($v)];
 177                                      }
 178                                      $gv = $v;
 179                                  }
 180  
 181                                  $a[$gk] = &$gv;
 182                              }
 183                              unset($gv);
 184                          } else {
 185                              $a = $v;
 186                          }
 187                          break;
 188  
 189                      case \is_object($v):
 190                          if (empty($objRefs[$h = spl_object_id($v)])) {
 191                              $stub = new Stub();
 192                              $stub->type = Stub::TYPE_OBJECT;
 193                              $stub->class = \get_class($v);
 194                              $stub->value = $v;
 195                              $stub->handle = $h;
 196                              $a = $this->castObject($stub, 0 < $i);
 197                              if ($v !== $stub->value) {
 198                                  if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
 199                                      break;
 200                                  }
 201                                  $stub->handle = $h = spl_object_id($stub->value);
 202                              }
 203                              $stub->value = null;
 204                              if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
 205                                  $stub->cut = \count($a);
 206                                  $a = null;
 207                              }
 208                          }
 209                          if (empty($objRefs[$h])) {
 210                              $objRefs[$h] = $stub;
 211                              $objects[] = $v;
 212                          } else {
 213                              $stub = $objRefs[$h];
 214                              ++$stub->refCount;
 215                              $a = null;
 216                          }
 217                          break;
 218  
 219                      default: // resource
 220                          if (empty($resRefs[$h = (int) $v])) {
 221                              $stub = new Stub();
 222                              $stub->type = Stub::TYPE_RESOURCE;
 223                              if ('Unknown' === $stub->class = @get_resource_type($v)) {
 224                                  $stub->class = 'Closed';
 225                              }
 226                              $stub->value = $v;
 227                              $stub->handle = $h;
 228                              $a = $this->castResource($stub, 0 < $i);
 229                              $stub->value = null;
 230                              if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
 231                                  $stub->cut = \count($a);
 232                                  $a = null;
 233                              }
 234                          }
 235                          if (empty($resRefs[$h])) {
 236                              $resRefs[$h] = $stub;
 237                          } else {
 238                              $stub = $resRefs[$h];
 239                              ++$stub->refCount;
 240                              $a = null;
 241                          }
 242                          break;
 243                  }
 244  
 245                  if ($a) {
 246                      if (!$minimumDepthReached || 0 > $maxItems) {
 247                          $queue[$len] = $a;
 248                          $stub->position = $len++;
 249                      } elseif ($pos < $maxItems) {
 250                          if ($maxItems < $pos += \count($a)) {
 251                              $a = \array_slice($a, 0, $maxItems - $pos, true);
 252                              if ($stub->cut >= 0) {
 253                                  $stub->cut += $pos - $maxItems;
 254                              }
 255                          }
 256                          $queue[$len] = $a;
 257                          $stub->position = $len++;
 258                      } elseif ($stub->cut >= 0) {
 259                          $stub->cut += \count($a);
 260                          $stub->position = 0;
 261                      }
 262                  }
 263  
 264                  if ($arrayStub === $stub) {
 265                      if ($arrayStub->cut) {
 266                          $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position];
 267                          $arrayStub->cut = 0;
 268                      } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) {
 269                          $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position];
 270                      } else {
 271                          self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];
 272                      }
 273                  }
 274  
 275                  if (!$zvalRef) {
 276                      $vals[$k] = $stub;
 277                  } elseif (\PHP_VERSION_ID >= 70400) {
 278                      $hardRefs[$zvalRef]->value = $stub;
 279                  } else {
 280                      $refs[$k]->value = $stub;
 281                  }
 282              }
 283  
 284              if ($fromObjCast) {
 285                  $fromObjCast = false;
 286                  $refs = $vals;
 287                  $vals = [];
 288                  $j = -1;
 289                  foreach ($queue[$i] as $k => $v) {
 290                      foreach ([$k => true] as $gk => $gv) {
 291                      }
 292                      if ($gk !== $k) {
 293                          $vals = (object) $vals;
 294                          $vals->{$k} = $refs[++$j];
 295                          $vals = (array) $vals;
 296                      } else {
 297                          $vals[$k] = $refs[++$j];
 298                      }
 299                  }
 300              }
 301  
 302              $queue[$i] = $vals;
 303          }
 304  
 305          foreach ($values as $h => $v) {
 306              $hardRefs[$h] = $v;
 307          }
 308  
 309          return $queue;
 310      }
 311  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer