HtmlDumper example



        // In all other conditions that remove the web debug toolbar, dumps are written on the output.         if (!$this->requestStack
            || !$response->headers->has('X-Debug-Token')
            || $response->isRedirection()
            || ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type') ?? '', 'html'))
            || 'html' !== $request->getRequestFormat()
            || false === strripos($response->getContent(), '</body>')
        ) {
            if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type') ?? '', 'html')) {
                $dumper = new HtmlDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            } else {
                $dumper = new CliDumper('php://output', $this->charset);
                if (method_exists($dumper, 'setDisplayOptions')) {
                    $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
                }
            }

            foreach ($this->data as $dump) {
                $this->doDump($dumper$dump['data']$dump['name']$dump['file']$dump['line']$dump['label'] ?? '');
            }
        }
EODUMP;

        $this->assertDumpMatchesFormat($expectedDump$args);
    }

    public function testLinkStub()
    {
        $var = [new LinkStub(__CLASS__, 0, __FILE__)];

        $cloner = new VarCloner();
        $dumper = new HtmlDumper();
        $dumper->setDumpHeader('<foo></foo>');
        $dumper->setDumpBoundaries('<bar>', '</bar>');
        $dumper->setDisplayOptions(['fileLinkFormat' => '%f:%l']);
        $dump = $dumper->dump($cloner->cloneVar($var), true);

        $expectedDump = <<<'EODUMP' <foo></foo><bar><span class=sf-dump-note>array:1</span> [<samp data-depth=1 class=sf-dump-expanded> <span class=sf-dump-index>0</span> => "<a href="%sStubCasterTest.php:0" rel="noopener noreferrer"><span class=sf-dump-str title="55 characters">Symfony\Component\VarDumper\Tests\Caster\StubCasterTest</span></a>" </samp>] </bar> EODUMP;

        
public function testHtmlDump()
    {
        if (\ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {
            $this->markTestSkipped('A custom file_link_format is defined.');
        }

        $e = $this->getTestException(1);
        ExceptionCaster::$srcContext = -1;

        $cloner = new VarCloner();
        $cloner->setMaxItems(1);
        $dumper = new HtmlDumper();
        $dumper->setDumpHeader('<foo></foo>');
        $dumper->setDumpBoundaries('<bar>', '</bar>');
        $dump = $dumper->dump($cloner->cloneVar($e)->withRefHandles(false), true);

        $expectedDump = <<<'EODUMP' <foo></foo><bar><span class=sf-dump-note>Exception</span> {<samp data-depth=1 class=sf-dump-expanded> #<span class=sf-dump-protected title="Protected property">message</span>: "<span class=sf-dump-str>1</span>" #<span class=sf-dump-protected title="Protected property">code</span>: <span class=sf-dump-num>0</span> #<span class=sf-dump-protected title="Protected property">file</span>: "<span class=sf-dump-str title="%sExceptionCasterTest.php %d characters"><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%e</span>Tests%eCaster%eExceptionCasterTest.php</span>" #<span class=sf-dump-protected title="Protected property">line</span>: <span class=sf-dump-num>%d</span> <span class=sf-dump-meta>trace</span>: {<samp data-depth=2 class=sf-dump-compact> <span class=sf-dump-meta title="%sExceptionCasterTest.php Stack level %d."><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%s%eVarDumper</span><span class="sf-dump-ellipsis sf-dump-ellipsis-path">%e</span>Tests%eCaster%eExceptionCasterTest.php</span>:<span class=sf-dump-num>%d</span> &#8230;%d </samp>} </samp>} </bar>
'exception' => $exception,
            'exceptionMessage' => $exceptionMessage,
            'statusText' => $statusText,
            'statusCode' => $statusCode,
            'logger' => DebugLoggerConfigurator::getDebugLogger($this->logger),
            'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(),
        ]);
    }

    private function dumpValue(Data $value): string
    {
        $dumper = new HtmlDumper();
        $dumper->setTheme('light');

        return $dumper->dump($value, true);
    }

    private function formatArgs(array $args): string
    {
        $result = [];
        foreach ($args as $key => $item) {
            if ('object' === $item[0]) {
                $formattedValue = sprintf('<em>object</em>(%s)', $this->abbrClass($item[1]));
            }
return $prevHandler;
    }

    private static function register(): void
    {
        $cloner = new VarCloner();
        $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);

        $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;
        switch (true) {
            case 'html' === $format:
                $dumper = new HtmlDumper();
                break;
            case 'cli' === $format:
                $dumper = new CliDumper();
                break;
            case 'server' === $format:
            case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME):
                $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format;
                $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();
                $dumper = new ServerDumper($host$dumper, self::getDefaultContextProviders());
                break;
            default:
                

class HtmlDumperTest extends TestCase
{
    public function testGet()
    {
        if (\ini_get('xdebug.file_link_format') || get_cfg_var('xdebug.file_link_format')) {
            $this->markTestSkipped('A custom file_link_format is defined.');
        }

        require __DIR__.'/../Fixtures/dumb-var.php';

        $dumper = new HtmlDumper('php://output');
        $dumper->setDumpHeader('<foo></foo>');
        $dumper->setDumpBoundaries('<bar>', '</bar>');
        $cloner = new VarCloner();
        $cloner->addCasters([
            ':stream' => function D$res$a) {
                unset($a['uri']$a['wrapper_data']);

                return $a;
            },
        ]);
        $data = $cloner->cloneVar($var);

        
private HtmlDumper $dumper;

    /** * @var resource */
    private $output;

    private int $stackLevel = 0;

    public function __construct(HtmlDumper $dumper = null)
    {
        $this->dumper = $dumper ?? new HtmlDumper();
        $this->dumper->setOutput($this->output = fopen('php://memory', 'r+'));
    }

    public function enter(Profile $profile): void
    {
        ++$this->stackLevel;
    }

    public function leave(Profile $profile): void
    {
        if (0 === --$this->stackLevel) {
            
if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file']$context['line'])) {
            $context['file_link'] = $fileLink;
        }

        return $context;
    }

    private function htmlEncode(string $s): string
    {
        $html = '';

        $dumper = new HtmlDumper(function D$line) use (&$html) { $html .= $line}$this->charset);
        $dumper->setDumpHeader('');
        $dumper->setDumpBoundaries('', '');

        $cloner = new VarCloner();
        $dumper->dump($cloner->cloneVar($s));

        return substr(strip_tags($html), 1, -1);
    }
}

    private DumpServer $server;

    /** @var DumpDescriptorInterface[] */
    private array $descriptors;

    public function __construct(DumpServer $server, array $descriptors = [])
    {
        $this->server = $server;
        $this->descriptors = $descriptors + [
            'cli' => new CliDescriptor(new CliDumper()),
            'html' => new HtmlDescriptor(new HtmlDumper()),
        ];

        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli')
            ->setHelp(<<<'EOF' <info>%command.name%</info> starts a dump server that collects and displays dumps in a single place for debugging you application: <info>php %command.full_name%</info> You can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option and redirecting the output to a file: <info>php %command.full_name% --format="html" > dump.html</info>

    private DumpServer $server;

    /** @var DumpDescriptorInterface[] */
    private array $descriptors;

    public function __construct(DumpServer $server, array $descriptors = [])
    {
        $this->server = $server;
        $this->descriptors = $descriptors + [
            'cli' => new CliDescriptor(new CliDumper()),
            'html' => new HtmlDescriptor(new HtmlDumper()),
        ];

        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli')
            ->setHelp(<<<'EOF' <info>%command.name%</info> starts a dump server that collects and displays dumps in a single place for debugging you application: <info>php %command.full_name%</info> You can consult dumped data in HTML format in your browser by providing the <comment>--format=html</comment> option and redirecting the output to a file: <info>php %command.full_name% --format="html" > dump.html</info>
'exception' => $exception,
            'exceptionMessage' => $exceptionMessage,
            'statusText' => $statusText,
            'statusCode' => $statusCode,
            'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
            'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(),
        ]);
    }

    private function dumpValue(Data $value): string
    {
        $dumper = new HtmlDumper();
        $dumper->setTheme('light');

        return $dumper->dump($value, true);
    }

    private function formatArgs(array $args): string
    {
        $result = [];
        foreach ($args as $key => $item) {
            if ('object' === $item[0]) {
                $formattedValue = sprintf('<em>object</em>(%s)', $this->abbrClass($item[1]));
            }
return $prevHandler;
    }

    private static function register(): void
    {
        $cloner = new VarCloner();
        $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);

        $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null;
        switch (true) {
            case 'html' === $format:
                $dumper = new HtmlDumper();
                break;
            case 'cli' === $format:
                $dumper = new CliDumper();
                break;
            case 'server' === $format:
            case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME):
                $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format;
                $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper();
                $dumper = new ServerDumper($host$dumper, self::getDefaultContextProviders());
                break;
            default:
                
if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file']$context['line'])) {
            $context['file_link'] = $fileLink;
        }

        return $context;
    }

    private function htmlEncode(string $s): string
    {
        $html = '';

        $dumper = new HtmlDumper(function D$line) use (&$html) { $html .= $line}$this->charset);
        $dumper->setDumpHeader('');
        $dumper->setDumpBoundaries('', '');

        $cloner = new VarCloner();
        $dumper->dump($cloner->cloneVar($s));

        return substr(strip_tags($html), 1, -1);
    }
}


        // In all other conditions that remove the web debug toolbar, dumps are written on the output.         if (!$this->requestStack
            || !$response->headers->has('X-Debug-Token')
            || $response->isRedirection()
            || ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type') ?? '', 'html'))
            || 'html' !== $request->getRequestFormat()
            || false === strripos($response->getContent(), '</body>')
        ) {
            if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type') ?? '', 'html')) {
                $dumper = new HtmlDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            } else {
                $dumper = new CliDumper('php://output', $this->charset);
                $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
            }

            foreach ($this->data as $dump) {
                $this->doDump($dumper$dump['data']$dump['name']$dump['file']$dump['line']$dump['label'] ?? '');
            }
        }
    }

    

        return $this->getComputedData('block_count');
    }

    public function getMacroCount(): int
    {
        return $this->getComputedData('macro_count');
    }

    public function getHtmlCallGraph(): Markup
    {
        $dumper = new HtmlDumper();
        $dump = $dumper->dump($this->getProfile());

        // needed to remove the hardcoded CSS styles         $dump = str_replace([
            '<span style="background-color: #ffd">',
            '<span style="color: #d44">',
            '<span style="background-color: #dfd">',
            '<span style="background-color: #ddf">',
        ][
            '<span class="status-warning">',
            '<span class="status-error">',
            
Home | Imprint | This part of the site doesn't use cookies.