"Fossies" - the Fresh Open Source Software Archive

Member "grav/vendor/symfony/var-dumper/Cloner/AbstractCloner.php" (19 Mar 2020, 16749 Bytes) of package /linux/www/grav-v1.6.23.zip:


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