This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/VarDumper/Cloner/Data.php

202 lines
6.7 KiB
PHP
Raw Normal View History

<?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 Symfony\Component\VarDumper\Cloner;
use Symfony\Component\VarDumper\Dumper\DumperInternalsInterface;
use Symfony\Component\VarDumper\Dumper\Cursor;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class Data
{
private $data;
/**
* @param array $data A array as returned by ClonerInterface::cloneVar().
*/
public function __construct(array $data)
{
$this->data = $data;
}
public function getRawData()
{
return $this->data;
}
/**
* Dumps data with a DumperInternalsInterface dumper.
*/
public function dump(DumperInternalsInterface $dumper)
{
$refs = array(0);
$this->dumpItem($dumper, new Cursor, $refs, $this->data[0][0]);
}
/**
* Breadth-first dumping of items.
*
* @param DumperInternalsInterface $dumper The dumper being used for dumping.
* @param Cursor $cursor A cursor used for tracking dumper state position.
* @param array &$refs A map of all references discovered while dumping.
* @param mixed $item A stub stdClass or the original value being dumped.
*/
private function dumpItem($dumper, $cursor, &$refs, $item)
{
$cursor->refIndex = $cursor->refTo = $cursor->refIsHard = false;
if ($item instanceof \stdClass) {
if (property_exists($item, 'val')) {
if (isset($item->ref)) {
if (isset($refs[$r = $item->ref])) {
$cursor->refTo = $refs[$r];
$cursor->refIsHard = true;
} else {
$cursor->refIndex = $refs[$r] = ++$refs[0];
}
}
$item = $item->val;
}
if (isset($item->ref)) {
if (isset($refs[$r = $item->ref])) {
if (false === $cursor->refTo) {
$cursor->refTo = $refs[$r];
$cursor->refIsHard = isset($item->count);
}
} elseif (false !== $cursor->refIndex) {
$refs[$r] = $cursor->refIndex;
} else {
$cursor->refIndex = $refs[$r] = ++$refs[0];
}
}
$cut = isset($item->cut) ? $item->cut : 0;
if (isset($item->pos) && false === $cursor->refTo) {
$children = $this->data[$item->pos];
if ($cursor->stop) {
if ($cut >= 0) {
$cut += count($children);
}
$children = array();
}
} else {
$children = array();
}
switch (true) {
case isset($item->bin):
$dumper->dumpString($cursor, $item->bin, true, $cut);
return;
case isset($item->str):
$dumper->dumpString($cursor, $item->str, false, $cut);
return;
case isset($item->count):
$dumper->enterArray($cursor, $item->count, !empty($item->indexed), (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, empty($item->indexed) ? $cursor::HASH_ASSOC : $cursor::HASH_INDEXED);
$dumper->leaveArray($cursor, $item->count, !empty($item->indexed), (bool) $children, $cut);
return;
case isset($item->class):
$dumper->enterObject($cursor, $item->class, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_OBJECT);
$dumper->leaveObject($cursor, $item->class, (bool) $children, $cut);
return;
case isset($item->res):
$dumper->enterResource($cursor, $item->res, (bool) $children);
$cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $cursor::HASH_RESOURCE);
$dumper->leaveResource($cursor, $item->res, (bool) $children, $cut);
return;
}
}
if ('array' === $type = gettype($item)) {
$dumper->enterArray($cursor, 0, true, 0, 0);
$dumper->leaveArray($cursor, 0, true, 0, 0);
} else {
$dumper->dumpScalar($cursor, $type, $item);
}
}
/**
* Dumps children of hash structures.
*
* @param DumperInternalsInterface $dumper
* @param Cursor $parentCursor The cursor of the parent hash.
* @param array &$refs A map of all references discovered while dumping.
* @param array $children The children to dump.
* @param int $hashCut The number of items removed from the original hash.
* @param int $hashType A Cursor::HASH_* const.
*
* @return int The final number of removed items.
*/
private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCut, $hashType)
{
if ($children) {
$cursor = clone $parentCursor;
++$cursor->depth;
$cursor->hashType = $hashType;
$cursor->hashIndex = 0;
$cursor->hashLength = count($children);
$cursor->hashCut = $hashCut;
foreach ($children as $cursor->hashKey => $child) {
$this->dumpItem($dumper, $cursor, $refs, $child);
++$cursor->hashIndex;
if ($cursor->stop) {
$parentCursor->stop = true;
return $hashCut >= 0 ? $hashCut + $children - $cursor->hashIndex : $hashCut;
}
}
}
return $hashCut;
}
/**
* Portable variant of utf8_encode()
*
* @param string $s
*
* @return string
*
* @internal
*/
public static function utf8Encode($s)
{
if (function_exists('iconv')) {
return iconv('CP1252', 'UTF-8', $s);
2014-08-27 16:29:38 +01:00
}
2014-08-27 16:29:38 +01:00
$s .= $s;
$len = strlen($s);
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
switch (true) {
case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
default: $s[$j] = "\xC3"; $s[++$j] = chr(ord($s[$i]) - 64); break;
}
}
2014-08-27 16:29:38 +01:00
return substr($s, 0, $j);
}
}