[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |