Вход Регистрация
Файл: symfony-2.7/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
Строк: 415
<?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 
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 = array(
        
'SymfonyComponentVarDumperCasterCutStub' => 'SymfonyComponentVarDumperCasterStubCaster::castStub',
        
'SymfonyComponentVarDumperCasterConstStub' => 'SymfonyComponentVarDumperCasterStubCaster::castStub',

        
'Closure' => 'SymfonyComponentVarDumperCasterReflectionCaster::castClosure',
        
'Reflector' => 'SymfonyComponentVarDumperCasterReflectionCaster::castReflector',

        
'DoctrineCommonPersistenceObjectManager' => 'SymfonyComponentVarDumperCasterStubCaster::cutInternals',
        
'DoctrineCommonProxyProxy' => 'SymfonyComponentVarDumperCasterDoctrineCaster::castCommonProxy',
        
'DoctrineORMProxyProxy' => 'SymfonyComponentVarDumperCasterDoctrineCaster::castOrmProxy',
        
'DoctrineORMPersistentCollection' => 'SymfonyComponentVarDumperCasterDoctrineCaster::castPersistentCollection',

        
'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',
        
'DOMTypeinfo' => 'SymfonyComponentVarDumperCasterDOMCaster::castTypeinfo',
        
'DOMDomError' => 'SymfonyComponentVarDumperCasterDOMCaster::castDomError',
        
'DOMLocator' => 'SymfonyComponentVarDumperCasterDOMCaster::castLocator',
        
'DOMDocumentType' => 'SymfonyComponentVarDumperCasterDOMCaster::castDocumentType',
        
'DOMNotation' => 'SymfonyComponentVarDumperCasterDOMCaster::castNotation',
        
'DOMEntity' => 'SymfonyComponentVarDumperCasterDOMCaster::castEntity',
        
'DOMProcessingInstruction' => 'SymfonyComponentVarDumperCasterDOMCaster::castProcessingInstruction',
        
'DOMXPath' => 'SymfonyComponentVarDumperCasterDOMCaster::castXPath',

        
'ErrorException' => 'SymfonyComponentVarDumperCasterExceptionCaster::castErrorException',
        
'Exception' => 'SymfonyComponentVarDumperCasterExceptionCaster::castException',
        
'SymfonyComponentDependencyInjectionContainerInterface' => 'SymfonyComponentVarDumperCasterStubCaster::cutInternals',
        
'SymfonyComponentVarDumperExceptionThrowingCasterException' => 'SymfonyComponentVarDumperCasterExceptionCaster::castThrowingCasterException',

        
'PDO' => 'SymfonyComponentVarDumperCasterPdoCaster::castPdo',
        
'PDOStatement' => 'SymfonyComponentVarDumperCasterPdoCaster::castPdoStatement',

        
'ArrayObject' => 'SymfonyComponentVarDumperCasterSplCaster::castArrayObject',
        
'SplDoublyLinkedList' => 'SymfonyComponentVarDumperCasterSplCaster::castDoublyLinkedList',
        
'SplFixedArray' => 'SymfonyComponentVarDumperCasterSplCaster::castFixedArray',
        
'SplHeap' => 'SymfonyComponentVarDumperCasterSplCaster::castHeap',
        
'SplObjectStorage' => 'SymfonyComponentVarDumperCasterSplCaster::castObjectStorage',
        
'SplPriorityQueue' => 'SymfonyComponentVarDumperCasterSplCaster::castHeap',

        
':curl' => 'SymfonyComponentVarDumperCasterResourceCaster::castCurl',
        
':dba' => 'SymfonyComponentVarDumperCasterResourceCaster::castDba',
        
':dba persistent' => 'SymfonyComponentVarDumperCasterResourceCaster::castDba',
        
':gd' => 'SymfonyComponentVarDumperCasterResourceCaster::castGd',
        
':mysql link' => 'SymfonyComponentVarDumperCasterResourceCaster::castMysqlLink',
        
':process' => 'SymfonyComponentVarDumperCasterResourceCaster::castProcess',
        
':stream' => 'SymfonyComponentVarDumperCasterResourceCaster::castStream',
        
':stream-context' => 'SymfonyComponentVarDumperCasterResourceCaster::castStreamContext',
    );

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

    private 
$casters = array();
    private 
$prevErrorHandler;
    private 
$classInfo = array();

    
/**
     * @param callable[]|null $casters A map of casters.
     *
     * @see addCasters
     */
    
public function __construct(array $casters null)
    {
        if (
null === $casters) {
            
$casters = static::$defaultCasters;
        }
        
$this->addCasters($casters);
        
$this->useExt extension_loaded('symfony_debug');
    }

    
/**
     * 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.
     */
    
public function addCasters(array $casters)
    {
        foreach (
$casters as $type => $callback) {
            
$this->casters[strtolower($type)][] = $callback;
        }
    }

    
/**
     * Sets the maximum number of items to clone past the first level in nested structures.
     *
     * @param int $maxItems
     */
    
public function setMaxItems($maxItems)
    {
        
$this->maxItems = (int) $maxItems;
    }

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

    
/**
     * {@inheritdoc}
     */
    
public function cloneVar($var)
    {
        
$this->prevErrorHandler set_error_handler(array($this'handleError'));
        try {
            if (!
function_exists('iconv')) {
                
$this->maxString = -1;
            }
            
$data $this->doClone($var);
        } catch (
Exception $e) {
        }
        
restore_error_handler();
        
$this->prevErrorHandler null;

        if (isset(
$e)) {
            throw 
$e;
        }

        return new 
Data($data);
    }

    
/**
     * Effectively clones the PHP variable.
     *
     * @param mixed $var Any PHP variable.
     *
     * @return array The cloned variable represented in an array.
     */
    
abstract protected function doClone($var);

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

        if (isset(
$this->classInfo[$class])) {
            
$classInfo $this->classInfo[$class];
            
$stub->class $classInfo[0];
        } else {
            
$classInfo = array(
                
$class,
                
method_exists($class'__debugInfo'),
                new 
ReflectionClass($class),
                
array_reverse(array($class => $class) + class_parents($class) + class_implements($class)),
            );

            
$this->classInfo[$class] = $classInfo;
        }

        if (
$classInfo[1]) {
            
$a $this->callCaster(function ($obj) {return $obj->__debugInfo();}, $obj, array(), null$isNested);
        } else {
            
$a = (array) $obj;
        }

        foreach (
$a as $k => $p) {
            if (!isset(
$k[0]) || ("" !== $k[0] && !$classInfo[2]->hasProperty($k))) {
                unset(
$a[$k]);
                
$a["+".$k] = $p;
            }
        }

        foreach (
$classInfo[3] as $p) {
            if (!empty(
$this->casters[$p strtolower($p)])) {
                foreach (
$this->casters[$p] as $p) {
                    
$a $this->callCaster($p$obj$a$stub$isNested);
                }
            }
        }

        return 
$a;
    }

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

        if (!empty(
$this->casters[':'.$type])) {
            foreach (
$this->casters[':'.$type] as $c) {
                
$a $this->callCaster($c$res$a$stub$isNested);
            }
        }

        return 
$a;
    }

    
/**
     * Calls a custom caster.
     *
     * @param callable        $callback The caster.
     * @param object|resource $obj      The object/resource being casted.
     * @param array           $a        The result of the previous cast for chained casters.
     * @param Stub            $stub     The Stub for the casted object/resource.
     * @param bool            $isNested True if $obj is nested in the dumped structure.
     *
     * @return array The casted object/resource.
     */
    
private function callCaster($callback$obj$a$stub$isNested)
    {
        try {
            
$cast call_user_func($callback$obj$a$stub$isNested);

            if (
is_array($cast)) {
                
$a $cast;
            }
        } catch (
Exception $e) {
            
$a["~⚠"] = new ThrowingCasterException($callback$e);
        }

        return 
$a;
    }

    
/**
     * Special handling for errors: cloning must be fail-safe.
     *
     * @internal
     */
    
public function handleError($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 
call_user_func($this->prevErrorHandler$type$msg$file$line$context);
        }

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