Вход Регистрация
Файл: vendor/symfony/var-dumper/Cloner/VarCloner.php
Строк: 177
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentVarDumperCloner;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
class VarCloner extends AbstractCloner
{
    private static array 
$arrayCache = [];

    protected function 
doClone(mixed $var): array
    {
        
$len 1;                       // Length of $queue
        
$pos 0;                       // Number of cloned items past the minimum depth
        
$refsCounter 0;               // Hard references counter
        
$queue = [[$var]];              // This breadth-first queue is the return value
        
$hardRefs = [];                 // Map of original zval ids to stub objects
        
$objRefs = [];                  // Map of original object handles to their stub object counterpart
        
$objects = [];                  // Keep a ref to objects to ensure their handle cannot be reused while cloning
        
$resRefs = [];                  // Map of original resource handles to their stub object counterpart
        
$values = [];                   // Map of stub objects' ids to original values
        
$maxItems $this->maxItems;
        
$maxString $this->maxString;
        
$minDepth $this->minDepth;
        
$currentDepth 0;              // Current tree depth
        
$currentDepthFinalIndex 0;    // Final $queue index for current tree depth
        
$minimumDepthReached === $minDepth// Becomes true when minimum tree depth has been reached
        
$cookie = (object) [];          // Unique object used to detect hard references
        
$a null;                      // Array cast for nested structures
        
$stub null;                   // Stub capturing the main properties of an original item value
                                        // or null if the original value is used directly

        
$arrayStub = new Stub();
        
$arrayStub->type Stub::TYPE_ARRAY;
        
$fromObjCast false;

        for (
$i 0$i $len; ++$i) {
            
// Detect when we move on to the next tree depth
            
if ($i $currentDepthFinalIndex) {
                ++
$currentDepth;
                
$currentDepthFinalIndex $len 1;
                if (
$currentDepth >= $minDepth) {
                    
$minimumDepthReached true;
                }
            }

            
$refs $vals $queue[$i];
            foreach (
$vals as $k => $v) {
                
// $v is the original value or a stub object in case of hard references

                
$zvalRef = ($r ReflectionReference::fromArrayElement($vals$k)) ? $r->getId() : null;

                if (
$zvalRef) {
                    
$vals[$k] = &$stub;         // Break hard references to make $queue completely
                    
unset($stub);               // independent from the original structure
                    
if (null !== $vals[$k] = $hardRefs[$zvalRef] ?? null) {
                        
$v $vals[$k];
                        if (
$v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
                            ++
$v->value->refCount;
                        }
                        ++
$v->refCount;
                        continue;
                    }
                    
$vals[$k] = new Stub();
                    
$vals[$k]->value $v;
                    
$vals[$k]->handle = ++$refsCounter;
                    
$hardRefs[$zvalRef] = $vals[$k];
                }
                
// Create $stub when the original value $v cannot be used directly
                // If $v is a nested structure, put that structure in array $a
                
switch (true) {
                    case 
null === $v:
                    case 
is_bool($v):
                    case 
is_int($v):
                    case 
is_float($v):
                        continue 
2;
                    case 
is_string($v):
                        if (
'' === $v) {
                            continue 
2;
                        }
                        if (!
preg_match('//u'$v)) {
                            
$stub = new Stub();
                            
$stub->type Stub::TYPE_STRING;
                            
$stub->class Stub::STRING_BINARY;
                            if (
<= $maxString && $cut strlen($v) - $maxString) {
                                
$stub->cut $cut;
                                
$stub->value substr($v0, -$cut);
                            } else {
                                
$stub->value $v;
                            }
                        } elseif (
<= $maxString && isset($v[+ ($maxString >> 2)]) && $cut mb_strlen($v'UTF-8') - $maxString) {
                            
$stub = new Stub();
                            
$stub->type Stub::TYPE_STRING;
                            
$stub->class Stub::STRING_UTF8;
                            
$stub->cut $cut;
                            
$stub->value mb_substr($v0$maxString'UTF-8');
                        } else {
                            continue 
2;
                        }
                        
$a null;
                        break;

                    case 
is_array($v):
                        if (!
$v) {
                            continue 
2;
                        }
                        
$stub $arrayStub;

                        
$stub->class array_is_list($v) ? Stub::ARRAY_INDEXED Stub::ARRAY_ASSOC;
                        
$a $v;
                        break;

                    case 
is_object($v):
                        if (empty(
$objRefs[$h spl_object_id($v)])) {
                            
$stub = new Stub();
                            
$stub->type Stub::TYPE_OBJECT;
                            
$stub->class $v::class;
                            
$stub->value $v;
                            
$stub->handle $h;
                            
$a $this->castObject($stub$i);
                            if (
$v !== $stub->value) {
                                if (
Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
                                    break;
                                }
                                
$stub->handle $h spl_object_id($stub->value);
                            }
                            
$stub->value null;
                            if (
<= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
                                
$stub->cut count($a);
                                
$a null;
                            }
                        }
                        if (empty(
$objRefs[$h])) {
                            
$objRefs[$h] = $stub;
                            
$objects[] = $v;
                        } else {
                            
$stub $objRefs[$h];
                            ++
$stub->refCount;
                            
$a null;
                        }
                        break;

                    default: 
// resource
                        
if (empty($resRefs[$h = (int) $v])) {
                            
$stub = new Stub();
                            
$stub->type Stub::TYPE_RESOURCE;
                            if (
'Unknown' === $stub->class = @get_resource_type($v)) {
                                
$stub->class 'Closed';
                            }
                            
$stub->value $v;
                            
$stub->handle $h;
                            
$a $this->castResource($stub$i);
                            
$stub->value null;
                            if (
<= $maxItems && $maxItems <= $pos && $minimumDepthReached) {
                                
$stub->cut count($a);
                                
$a null;
                            }
                        }
                        if (empty(
$resRefs[$h])) {
                            
$resRefs[$h] = $stub;
                        } else {
                            
$stub $resRefs[$h];
                            ++
$stub->refCount;
                            
$a null;
                        }
                        break;
                }

                if (
$a) {
                    if (!
$minimumDepthReached || $maxItems) {
                        
$queue[$len] = $a;
                        
$stub->position $len++;
                    } elseif (
$pos $maxItems) {
                        if (
$maxItems $pos += count($a)) {
                            
$a array_slice($a0$maxItems $postrue);
                            if (
$stub->cut >= 0) {
                                
$stub->cut += $pos $maxItems;
                            }
                        }
                        
$queue[$len] = $a;
                        
$stub->position $len++;
                    } elseif (
$stub->cut >= 0) {
                        
$stub->cut += count($a);
                        
$stub->position 0;
                    }
                }

                if (
$arrayStub === $stub) {
                    if (
$arrayStub->cut) {
                        
$stub = [$arrayStub->cut$arrayStub->class => $arrayStub->position];
                        
$arrayStub->cut 0;
                    } elseif (isset(
self::$arrayCache[$arrayStub->class][$arrayStub->position])) {
                        
$stub self::$arrayCache[$arrayStub->class][$arrayStub->position];
                    } else {
                        
self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position];
                    }
                }

                if (!
$zvalRef) {
                    
$vals[$k] = $stub;
                } else {
                    
$hardRefs[$zvalRef]->value $stub;
                }
            }

            if (
$fromObjCast) {
                
$fromObjCast false;
                
$refs $vals;
                
$vals = [];
                
$j = -1;
                foreach (
$queue[$i] as $k => $v) {
                    foreach ([
$k => true] as $gk => $gv) {
                    }
                    if (
$gk !== $k) {
                        
$vals = (object) $vals;
                        
$vals->{$k} = $refs[++$j];
                        
$vals = (array) $vals;
                    } else {
                        
$vals[$k] = $refs[++$j];
                    }
                }
            }

            
$queue[$i] = $vals;
        }

        foreach (
$values as $h => $v) {
            
$hardRefs[$h] = $v;
        }

        return 
$queue;
    }
}
Онлайн: 3
Реклама