"Fossies" - the Fresh Open Source Software Archive

Member "Symfony/vendor/symfony/symfony/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php" (30 Mar 2020, 16394 Bytes) of package /linux/www/Symfony_Standard_Vendors_3.4.39.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AbstractCloner.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 
    3 /*
    4  * This file is part of the Symfony package.
    5  *
    6  * (c) Fabien Potencier <fabien@symfony.com>
    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 use Symfony\Component\VarDumper\Caster\Caster;
   15 use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
   16 
   17 /**
   18  * AbstractCloner implements a generic caster mechanism for objects and resources.
   19  *
   20  * @author Nicolas Grekas <p@tchwork.com>
   21  */
   22 abstract class AbstractCloner implements ClonerInterface
   23 {
   24     public static $defaultCasters = [
   25         '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'],
   26 
   27         'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
   28         'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'],
   29         'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'],
   30         'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'],
   31 
   32         'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'],
   33         'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'],
   34         'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'],
   35         'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'],
   36         'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'],
   37         'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'],
   38         'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'],
   39         'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'],
   40         'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'],
   41         'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'],
   42         'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'],
   43 
   44         'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   45         'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'],
   46         'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'],
   47         'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'],
   48         'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   49 
   50         'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'],
   51         'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
   52         'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
   53         'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'],
   54         'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
   55         'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'],
   56         'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'],
   57         'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'],
   58         'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
   59         'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
   60         'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'],
   61         'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'],
   62         'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'],
   63         'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'],
   64         'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'],
   65         'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'],
   66         'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'],
   67         'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'],
   68         'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'],
   69         'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'],
   70         'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'],
   71         'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'],
   72 
   73         'XmlReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'],
   74 
   75         'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'],
   76         'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'],
   77         'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'],
   78         'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   79         'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'],
   80         'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'],
   81         'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'],
   82         'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'],
   83         'Symfony\Component\Debug\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'],
   84 
   85         'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   86         'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   87         'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   88         'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   89         'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
   90 
   91         'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'],
   92         'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'],
   93 
   94         'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'],
   95         'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'],
   96         'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'],
   97         'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'],
   98         'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'],
   99 
  100         'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'],
  101         'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'],
  102         'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'],
  103         'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'],
  104         'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'],
  105         'SplFixedArray' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'],
  106         'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
  107         'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'],
  108         'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
  109         'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'],
  110 
  111         'MongoCursorInterface' => ['Symfony\Component\VarDumper\Caster\MongoCaster', 'castCursor'],
  112 
  113         'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'],
  114         'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'],
  115 
  116         'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'],
  117         'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'],
  118         'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'],
  119         'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'],
  120 
  121         ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'],
  122         ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'],
  123         ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'],
  124         ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'],
  125         ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'],
  126         ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'],
  127         ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'],
  128         ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'],
  129         ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'],
  130         ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'],
  131         ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'],
  132         ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'],
  133         ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'],
  134         ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'],
  135     ];
  136 
  137     protected $maxItems = 2500;
  138     protected $maxString = -1;
  139     protected $minDepth = 1;
  140     protected $useExt;
  141 
  142     private $casters = [];
  143     private $prevErrorHandler;
  144     private $classInfo = [];
  145     private $filter = 0;
  146 
  147     /**
  148      * @param callable[]|null $casters A map of casters
  149      *
  150      * @see addCasters
  151      */
  152     public function __construct(array $casters = null)
  153     {
  154         if (null === $casters) {
  155             $casters = static::$defaultCasters;
  156         }
  157         $this->addCasters($casters);
  158         $this->useExt = \extension_loaded('symfony_debug');
  159     }
  160 
  161     /**
  162      * Adds casters for resources and objects.
  163      *
  164      * Maps resources or objects types to a callback.
  165      * Types are in the key, with a callable caster for value.
  166      * Resource types are to be prefixed with a `:`,
  167      * see e.g. static::$defaultCasters.
  168      *
  169      * @param callable[] $casters A map of casters
  170      */
  171     public function addCasters(array $casters)
  172     {
  173         foreach ($casters as $type => $callback) {
  174             $this->casters[strtolower($type)][] = \is_string($callback) && false !== strpos($callback, '::') ? explode('::', $callback, 2) : $callback;
  175         }
  176     }
  177 
  178     /**
  179      * Sets the maximum number of items to clone past the minimum depth in nested structures.
  180      *
  181      * @param int $maxItems
  182      */
  183     public function setMaxItems($maxItems)
  184     {
  185         $this->maxItems = (int) $maxItems;
  186     }
  187 
  188     /**
  189      * Sets the maximum cloned length for strings.
  190      *
  191      * @param int $maxString
  192      */
  193     public function setMaxString($maxString)
  194     {
  195         $this->maxString = (int) $maxString;
  196     }
  197 
  198     /**
  199      * Sets the minimum tree depth where we are guaranteed to clone all the items.  After this
  200      * depth is reached, only setMaxItems items will be cloned.
  201      *
  202      * @param int $minDepth
  203      */
  204     public function setMinDepth($minDepth)
  205     {
  206         $this->minDepth = (int) $minDepth;
  207     }
  208 
  209     /**
  210      * Clones a PHP variable.
  211      *
  212      * @param mixed $var    Any PHP variable
  213      * @param int   $filter A bit field of Caster::EXCLUDE_* constants
  214      *
  215      * @return Data The cloned variable represented by a Data object
  216      */
  217     public function cloneVar($var, $filter = 0)
  218     {
  219         $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) {
  220             if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) {
  221                 // Cloner never dies
  222                 throw new \ErrorException($msg, 0, $type, $file, $line);
  223             }
  224 
  225             if ($this->prevErrorHandler) {
  226                 return \call_user_func($this->prevErrorHandler, $type, $msg, $file, $line, $context);
  227             }
  228 
  229             return false;
  230         });
  231         $this->filter = $filter;
  232 
  233         if ($gc = gc_enabled()) {
  234             gc_disable();
  235         }
  236         try {
  237             return new Data($this->doClone($var));
  238         } finally {
  239             if ($gc) {
  240                 gc_enable();
  241             }
  242             restore_error_handler();
  243             $this->prevErrorHandler = null;
  244         }
  245     }
  246 
  247     /**
  248      * Effectively clones the PHP variable.
  249      *
  250      * @param mixed $var Any PHP variable
  251      *
  252      * @return array The cloned variable represented in an array
  253      */
  254     abstract protected function doClone($var);
  255 
  256     /**
  257      * Casts an object to an array representation.
  258      *
  259      * @param Stub $stub     The Stub for the casted object
  260      * @param bool $isNested True if the object is nested in the dumped structure
  261      *
  262      * @return array The object casted as array
  263      */
  264     protected function castObject(Stub $stub, $isNested)
  265     {
  266         $obj = $stub->value;
  267         $class = $stub->class;
  268 
  269         if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) {
  270             $stub->class = get_parent_class($class).'@anonymous';
  271         }
  272         if (isset($this->classInfo[$class])) {
  273             list($i, $parents, $hasDebugInfo) = $this->classInfo[$class];
  274         } else {
  275             $i = 2;
  276             $parents = [strtolower($class)];
  277             $hasDebugInfo = method_exists($class, '__debugInfo');
  278 
  279             foreach (class_parents($class) as $p) {
  280                 $parents[] = strtolower($p);
  281                 ++$i;
  282             }
  283             foreach (class_implements($class) as $p) {
  284                 $parents[] = strtolower($p);
  285                 ++$i;
  286             }
  287             $parents[] = '*';
  288 
  289             $this->classInfo[$class] = [$i, $parents, $hasDebugInfo];
  290         }
  291 
  292         $a = Caster::castObject($obj, $class, $hasDebugInfo);
  293 
  294         try {
  295             while ($i--) {
  296                 if (!empty($this->casters[$p = $parents[$i]])) {
  297                     foreach ($this->casters[$p] as $callback) {
  298                         $a = $callback($obj, $a, $stub, $isNested, $this->filter);
  299                     }
  300                 }
  301             }
  302         } catch (\Exception $e) {
  303             $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;
  304         }
  305 
  306         return $a;
  307     }
  308 
  309     /**
  310      * Casts a resource to an array representation.
  311      *
  312      * @param Stub $stub     The Stub for the casted resource
  313      * @param bool $isNested True if the object is nested in the dumped structure
  314      *
  315      * @return array The resource casted as array
  316      */
  317     protected function castResource(Stub $stub, $isNested)
  318     {
  319         $a = [];
  320         $res = $stub->value;
  321         $type = $stub->class;
  322 
  323         try {
  324             if (!empty($this->casters[':'.$type])) {
  325                 foreach ($this->casters[':'.$type] as $callback) {
  326                     $a = $callback($res, $a, $stub, $isNested, $this->filter);
  327                 }
  328             }
  329         } catch (\Exception $e) {
  330             $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a;
  331         }
  332 
  333         return $a;
  334     }
  335 }