Вход Регистрация
Файл: vendor/symfony/var-dumper/Cloner/AbstractCloner.php
Строк: 971
<?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;

use 
SymfonyComponentVarDumperCasterCaster;
use 
SymfonyComponentVarDumperExceptionThrowingCasterException;

/**
 * AbstractCloner implements a generic caster mechanism for objects and resources.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
abstract class AbstractCloner implements ClonerInterface
{
    public static 
$defaultCasters = [
        
'__PHP_Incomplete_Class' => ['SymfonyComponentVarDumperCasterCaster''castPhpIncompleteClass'],

        
'SymfonyComponentVarDumperCasterCutStub' => ['SymfonyComponentVarDumperCasterStubCaster''castStub'],
        
'SymfonyComponentVarDumperCasterCutArrayStub' => ['SymfonyComponentVarDumperCasterStubCaster''castCutArray'],
        
'SymfonyComponentVarDumperCasterConstStub' => ['SymfonyComponentVarDumperCasterStubCaster''castStub'],
        
'SymfonyComponentVarDumperCasterEnumStub' => ['SymfonyComponentVarDumperCasterStubCaster''castEnum'],
        
'SymfonyComponentVarDumperCasterScalarStub' => ['SymfonyComponentVarDumperCasterStubCaster''castScalar'],

        
'Fiber' => ['SymfonyComponentVarDumperCasterFiberCaster''castFiber'],

        
'Closure' => ['SymfonyComponentVarDumperCasterReflectionCaster''castClosure'],
        
'Generator' => ['SymfonyComponentVarDumperCasterReflectionCaster''castGenerator'],
        
'ReflectionType' => ['SymfonyComponentVarDumperCasterReflectionCaster''castType'],
        
'ReflectionAttribute' => ['SymfonyComponentVarDumperCasterReflectionCaster''castAttribute'],
        
'ReflectionGenerator' => ['SymfonyComponentVarDumperCasterReflectionCaster''castReflectionGenerator'],
        
'ReflectionClass' => ['SymfonyComponentVarDumperCasterReflectionCaster''castClass'],
        
'ReflectionClassConstant' => ['SymfonyComponentVarDumperCasterReflectionCaster''castClassConstant'],
        
'ReflectionFunctionAbstract' => ['SymfonyComponentVarDumperCasterReflectionCaster''castFunctionAbstract'],
        
'ReflectionMethod' => ['SymfonyComponentVarDumperCasterReflectionCaster''castMethod'],
        
'ReflectionParameter' => ['SymfonyComponentVarDumperCasterReflectionCaster''castParameter'],
        
'ReflectionProperty' => ['SymfonyComponentVarDumperCasterReflectionCaster''castProperty'],
        
'ReflectionReference' => ['SymfonyComponentVarDumperCasterReflectionCaster''castReference'],
        
'ReflectionExtension' => ['SymfonyComponentVarDumperCasterReflectionCaster''castExtension'],
        
'ReflectionZendExtension' => ['SymfonyComponentVarDumperCasterReflectionCaster''castZendExtension'],

        
'DoctrineCommonPersistenceObjectManager' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'DoctrineCommonProxyProxy' => ['SymfonyComponentVarDumperCasterDoctrineCaster''castCommonProxy'],
        
'DoctrineORMProxyProxy' => ['SymfonyComponentVarDumperCasterDoctrineCaster''castOrmProxy'],
        
'DoctrineORMPersistentCollection' => ['SymfonyComponentVarDumperCasterDoctrineCaster''castPersistentCollection'],
        
'DoctrinePersistenceObjectManager' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],

        
'DOMException' => ['SymfonyComponentVarDumperCasterDOMCaster''castException'],
        
'DOMStringList' => ['SymfonyComponentVarDumperCasterDOMCaster''castLength'],
        
'DOMNameList' => ['SymfonyComponentVarDumperCasterDOMCaster''castLength'],
        
'DOMImplementation' => ['SymfonyComponentVarDumperCasterDOMCaster''castImplementation'],
        
'DOMImplementationList' => ['SymfonyComponentVarDumperCasterDOMCaster''castLength'],
        
'DOMNode' => ['SymfonyComponentVarDumperCasterDOMCaster''castNode'],
        
'DOMNameSpaceNode' => ['SymfonyComponentVarDumperCasterDOMCaster''castNameSpaceNode'],
        
'DOMDocument' => ['SymfonyComponentVarDumperCasterDOMCaster''castDocument'],
        
'DOMNodeList' => ['SymfonyComponentVarDumperCasterDOMCaster''castLength'],
        
'DOMNamedNodeMap' => ['SymfonyComponentVarDumperCasterDOMCaster''castLength'],
        
'DOMCharacterData' => ['SymfonyComponentVarDumperCasterDOMCaster''castCharacterData'],
        
'DOMAttr' => ['SymfonyComponentVarDumperCasterDOMCaster''castAttr'],
        
'DOMElement' => ['SymfonyComponentVarDumperCasterDOMCaster''castElement'],
        
'DOMText' => ['SymfonyComponentVarDumperCasterDOMCaster''castText'],
        
'DOMDocumentType' => ['SymfonyComponentVarDumperCasterDOMCaster''castDocumentType'],
        
'DOMNotation' => ['SymfonyComponentVarDumperCasterDOMCaster''castNotation'],
        
'DOMEntity' => ['SymfonyComponentVarDumperCasterDOMCaster''castEntity'],
        
'DOMProcessingInstruction' => ['SymfonyComponentVarDumperCasterDOMCaster''castProcessingInstruction'],
        
'DOMXPath' => ['SymfonyComponentVarDumperCasterDOMCaster''castXPath'],

        
'XMLReader' => ['SymfonyComponentVarDumperCasterXmlReaderCaster''castXmlReader'],

        
'ErrorException' => ['SymfonyComponentVarDumperCasterExceptionCaster''castErrorException'],
        
'Exception' => ['SymfonyComponentVarDumperCasterExceptionCaster''castException'],
        
'Error' => ['SymfonyComponentVarDumperCasterExceptionCaster''castError'],
        
'SymfonyBridgeMonologLogger' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'SymfonyComponentDependencyInjectionContainerInterface' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'SymfonyComponentEventDispatcherEventDispatcherInterface' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'SymfonyComponentHttpClientAmpHttpClient' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClient'],
        
'SymfonyComponentHttpClientCurlHttpClient' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClient'],
        
'SymfonyComponentHttpClientNativeHttpClient' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClient'],
        
'SymfonyComponentHttpClientResponseAmpResponse' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClientResponse'],
        
'SymfonyComponentHttpClientResponseCurlResponse' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClientResponse'],
        
'SymfonyComponentHttpClientResponseNativeResponse' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castHttpClientResponse'],
        
'SymfonyComponentHttpFoundationRequest' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castRequest'],
        
'SymfonyComponentUidUlid' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castUlid'],
        
'SymfonyComponentUidUuid' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castUuid'],
        
'SymfonyComponentVarExporterInternalLazyObjectState' => ['SymfonyComponentVarDumperCasterSymfonyCaster''castLazyObjectState'],
        
'SymfonyComponentVarDumperExceptionThrowingCasterException' => ['SymfonyComponentVarDumperCasterExceptionCaster''castThrowingCasterException'],
        
'SymfonyComponentVarDumperCasterTraceStub' => ['SymfonyComponentVarDumperCasterExceptionCaster''castTraceStub'],
        
'SymfonyComponentVarDumperCasterFrameStub' => ['SymfonyComponentVarDumperCasterExceptionCaster''castFrameStub'],
        
'SymfonyComponentVarDumperClonerAbstractCloner' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'SymfonyComponentErrorHandlerExceptionFlattenException' => ['SymfonyComponentVarDumperCasterExceptionCaster''castFlattenException'],
        
'SymfonyComponentErrorHandlerExceptionSilencedErrorContext' => ['SymfonyComponentVarDumperCasterExceptionCaster''castSilencedErrorContext'],

        
'ImagineImageImageInterface' => ['SymfonyComponentVarDumperCasterImagineCaster''castImage'],

        
'RamseyUuidUuidInterface' => ['SymfonyComponentVarDumperCasterUuidCaster''castRamseyUuid'],

        
'ProxyManagerProxyProxyInterface' => ['SymfonyComponentVarDumperCasterProxyManagerCaster''castProxy'],
        
'PHPUnit_Framework_MockObject_MockObject' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'PHPUnitFrameworkMockObjectMockObject' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'PHPUnitFrameworkMockObjectStub' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'ProphecyProphecyProphecySubjectInterface' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],
        
'MockeryMockInterface' => ['SymfonyComponentVarDumperCasterStubCaster''cutInternals'],

        
'PDO' => ['SymfonyComponentVarDumperCasterPdoCaster''castPdo'],
        
'PDOStatement' => ['SymfonyComponentVarDumperCasterPdoCaster''castPdoStatement'],

        
'AMQPConnection' => ['SymfonyComponentVarDumperCasterAmqpCaster''castConnection'],
        
'AMQPChannel' => ['SymfonyComponentVarDumperCasterAmqpCaster''castChannel'],
        
'AMQPQueue' => ['SymfonyComponentVarDumperCasterAmqpCaster''castQueue'],
        
'AMQPExchange' => ['SymfonyComponentVarDumperCasterAmqpCaster''castExchange'],
        
'AMQPEnvelope' => ['SymfonyComponentVarDumperCasterAmqpCaster''castEnvelope'],

        
'ArrayObject' => ['SymfonyComponentVarDumperCasterSplCaster''castArrayObject'],
        
'ArrayIterator' => ['SymfonyComponentVarDumperCasterSplCaster''castArrayIterator'],
        
'SplDoublyLinkedList' => ['SymfonyComponentVarDumperCasterSplCaster''castDoublyLinkedList'],
        
'SplFileInfo' => ['SymfonyComponentVarDumperCasterSplCaster''castFileInfo'],
        
'SplFileObject' => ['SymfonyComponentVarDumperCasterSplCaster''castFileObject'],
        
'SplHeap' => ['SymfonyComponentVarDumperCasterSplCaster''castHeap'],
        
'SplObjectStorage' => ['SymfonyComponentVarDumperCasterSplCaster''castObjectStorage'],
        
'SplPriorityQueue' => ['SymfonyComponentVarDumperCasterSplCaster''castHeap'],
        
'OuterIterator' => ['SymfonyComponentVarDumperCasterSplCaster''castOuterIterator'],
        
'WeakMap' => ['SymfonyComponentVarDumperCasterSplCaster''castWeakMap'],
        
'WeakReference' => ['SymfonyComponentVarDumperCasterSplCaster''castWeakReference'],

        
'Redis' => ['SymfonyComponentVarDumperCasterRedisCaster''castRedis'],
        
'RelayRelay' => ['SymfonyComponentVarDumperCasterRedisCaster''castRedis'],
        
'RedisArray' => ['SymfonyComponentVarDumperCasterRedisCaster''castRedisArray'],
        
'RedisCluster' => ['SymfonyComponentVarDumperCasterRedisCaster''castRedisCluster'],

        
'DateTimeInterface' => ['SymfonyComponentVarDumperCasterDateCaster''castDateTime'],
        
'DateInterval' => ['SymfonyComponentVarDumperCasterDateCaster''castInterval'],
        
'DateTimeZone' => ['SymfonyComponentVarDumperCasterDateCaster''castTimeZone'],
        
'DatePeriod' => ['SymfonyComponentVarDumperCasterDateCaster''castPeriod'],

        
'GMP' => ['SymfonyComponentVarDumperCasterGmpCaster''castGmp'],

        
'MessageFormatter' => ['SymfonyComponentVarDumperCasterIntlCaster''castMessageFormatter'],
        
'NumberFormatter' => ['SymfonyComponentVarDumperCasterIntlCaster''castNumberFormatter'],
        
'IntlTimeZone' => ['SymfonyComponentVarDumperCasterIntlCaster''castIntlTimeZone'],
        
'IntlCalendar' => ['SymfonyComponentVarDumperCasterIntlCaster''castIntlCalendar'],
        
'IntlDateFormatter' => ['SymfonyComponentVarDumperCasterIntlCaster''castIntlDateFormatter'],

        
'Memcached' => ['SymfonyComponentVarDumperCasterMemcachedCaster''castMemcached'],

        
'DsCollection' => ['SymfonyComponentVarDumperCasterDsCaster''castCollection'],
        
'DsMap' => ['SymfonyComponentVarDumperCasterDsCaster''castMap'],
        
'DsPair' => ['SymfonyComponentVarDumperCasterDsCaster''castPair'],
        
'SymfonyComponentVarDumperCasterDsPairStub' => ['SymfonyComponentVarDumperCasterDsCaster''castPairStub'],

        
'mysqli_driver' => ['SymfonyComponentVarDumperCasterMysqliCaster''castMysqliDriver'],

        
'CurlHandle' => ['SymfonyComponentVarDumperCasterResourceCaster''castCurl'],

        
':dba' => ['SymfonyComponentVarDumperCasterResourceCaster''castDba'],
        
':dba persistent' => ['SymfonyComponentVarDumperCasterResourceCaster''castDba'],

        
'GdImage' => ['SymfonyComponentVarDumperCasterResourceCaster''castGd'],
        
':gd' => ['SymfonyComponentVarDumperCasterResourceCaster''castGd'],

        
':pgsql large object' => ['SymfonyComponentVarDumperCasterPgSqlCaster''castLargeObject'],
        
':pgsql link' => ['SymfonyComponentVarDumperCasterPgSqlCaster''castLink'],
        
':pgsql link persistent' => ['SymfonyComponentVarDumperCasterPgSqlCaster''castLink'],
        
':pgsql result' => ['SymfonyComponentVarDumperCasterPgSqlCaster''castResult'],
        
':process' => ['SymfonyComponentVarDumperCasterResourceCaster''castProcess'],
        
':stream' => ['SymfonyComponentVarDumperCasterResourceCaster''castStream'],

        
'OpenSSLCertificate' => ['SymfonyComponentVarDumperCasterResourceCaster''castOpensslX509'],
        
':OpenSSL X.509' => ['SymfonyComponentVarDumperCasterResourceCaster''castOpensslX509'],

        
':persistent stream' => ['SymfonyComponentVarDumperCasterResourceCaster''castStream'],
        
':stream-context' => ['SymfonyComponentVarDumperCasterResourceCaster''castStreamContext'],

        
'XmlParser' => ['SymfonyComponentVarDumperCasterXmlResourceCaster''castXml'],
        
':xml' => ['SymfonyComponentVarDumperCasterXmlResourceCaster''castXml'],

        
'RdKafka' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castRdKafka'],
        
'RdKafkaConf' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castConf'],
        
'RdKafkaKafkaConsumer' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castKafkaConsumer'],
        
'RdKafkaMetadataBroker' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castBrokerMetadata'],
        
'RdKafkaMetadataCollection' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castCollectionMetadata'],
        
'RdKafkaMetadataPartition' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castPartitionMetadata'],
        
'RdKafkaMetadataTopic' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castTopicMetadata'],
        
'RdKafkaMessage' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castMessage'],
        
'RdKafkaTopic' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castTopic'],
        
'RdKafkaTopicPartition' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castTopicPartition'],
        
'RdKafkaTopicConf' => ['SymfonyComponentVarDumperCasterRdKafkaCaster''castTopicConf'],

        
'FFICData' => ['SymfonyComponentVarDumperCasterFFICaster''castCTypeOrCData'],
        
'FFICType' => ['SymfonyComponentVarDumperCasterFFICaster''castCTypeOrCData'],
    ];

    protected 
$maxItems 2500;
    protected 
$maxString = -1;
    protected 
$minDepth 1;

    
/**
     * @var array<string, list<callable>>
     */
    
private array $casters = [];

    
/**
     * @var callable|null
     */
    
private $prevErrorHandler;

    private array 
$classInfo = [];
    private 
int $filter 0;

    
/**
     * @param callable[]|null $casters A map of casters
     *
     * @see addCasters
     */
    
public function __construct(?array $casters null)
    {
        
$this->addCasters($casters ?? static::$defaultCasters);
    }

    
/**
     * Adds casters for resources and objects.
     *
     * Maps resources or objects types to a callback.
     * Types are in the key, with a callable caster for value.
     * Resource types are to be prefixed with a `:`,
     * see e.g. static::$defaultCasters.
     *
     * @param callable[] $casters A map of casters
     *
     * @return void
     */
    
public function addCasters(array $casters)
    {
        foreach (
$casters as $type => $callback) {
            
$this->casters[$type][] = $callback;
        }
    }

    
/**
     * Sets the maximum number of items to clone past the minimum depth in nested structures.
     *
     * @return void
     */
    
public function setMaxItems(int $maxItems)
    {
        
$this->maxItems $maxItems;
    }

    
/**
     * Sets the maximum cloned length for strings.
     *
     * @return void
     */
    
public function setMaxString(int $maxString)
    {
        
$this->maxString $maxString;
    }

    
/**
     * Sets the minimum tree depth where we are guaranteed to clone all the items.  After this
     * depth is reached, only setMaxItems items will be cloned.
     *
     * @return void
     */
    
public function setMinDepth(int $minDepth)
    {
        
$this->minDepth $minDepth;
    }

    
/**
     * Clones a PHP variable.
     *
     * @param int $filter A bit field of Caster::EXCLUDE_* constants
     */
    
public function cloneVar(mixed $varint $filter 0): Data
    
{
        
$this->prevErrorHandler set_error_handler(function ($type$msg$file$line$context = []) {
            if (
E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) {
                
// Cloner never dies
                
throw new ErrorException($msg0$type$file$line);
            }

            if (
$this->prevErrorHandler) {
                return (
$this->prevErrorHandler)($type$msg$file$line$context);
            }

            return 
false;
        });
        
$this->filter $filter;

        if (
$gc gc_enabled()) {
            
gc_disable();
        }
        try {
            return new 
Data($this->doClone($var));
        } finally {
            if (
$gc) {
                
gc_enable();
            }
            
restore_error_handler();
            
$this->prevErrorHandler null;
        }
    }

    
/**
     * Effectively clones the PHP variable.
     */
    
abstract protected function doClone(mixed $var): array;

    
/**
     * Casts an object to an array representation.
     *
     * @param bool $isNested True if the object is nested in the dumped structure
     */
    
protected function castObject(Stub $stubbool $isNested): array
    {
        
$obj $stub->value;
        
$class $stub->class;

        if (
str_contains($class"@anonymous")) {
            
$stub->class get_debug_type($obj);
        }
        if (isset(
$this->classInfo[$class])) {
            [
$i$parents$hasDebugInfo$fileInfo] = $this->classInfo[$class];
        } else {
            
$i 2;
            
$parents = [$class];
            
$hasDebugInfo method_exists($class'__debugInfo');

            foreach (
class_parents($class) as $p) {
                
$parents[] = $p;
                ++
$i;
            }
            foreach (
class_implements($class) as $p) {
                
$parents[] = $p;
                ++
$i;
            }
            
$parents[] = '*';

            
$r = new ReflectionClass($class);
            
$fileInfo $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [
                
'file' => $r->getFileName(),
                
'line' => $r->getStartLine(),
            ];

            
$this->classInfo[$class] = [$i$parents$hasDebugInfo$fileInfo];
        }

        
$stub->attr += $fileInfo;
        
$a Caster::castObject($obj$class$hasDebugInfo$stub->class);

        try {
            while (
$i--) {
                if (!empty(
$this->casters[$p $parents[$i]])) {
                    foreach (
$this->casters[$p] as $callback) {
                        
$a $callback($obj$a$stub$isNested$this->filter);
                    }
                }
            }
        } catch (
Exception $e) {
            
$a = [(Stub::TYPE_OBJECT === $stub->type Caster::PREFIX_VIRTUAL '').'⚠' => new ThrowingCasterException($e)] + $a;
        }

        return 
$a;
    }

    
/**
     * Casts a resource to an array representation.
     *
     * @param bool $isNested True if the object is nested in the dumped structure
     */
    
protected function castResource(Stub $stubbool $isNested): array
    {
        
$a = [];
        
$res $stub->value;
        
$type $stub->class;

        try {
            if (!empty(
$this->casters[':'.$type])) {
                foreach (
$this->casters[':'.$type] as $callback) {
                    
$a $callback($res$a$stub$isNested$this->filter);
                }
            }
        } catch (
Exception $e) {
            
$a = [(Stub::TYPE_OBJECT === $stub->type Caster::PREFIX_VIRTUAL '').'⚠' => new ThrowingCasterException($e)] + $a;
        }

        return 
$a;
    }
}
Онлайн: 1
Реклама