Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. DumpDataCollector.php

class DumpDataCollector

@author Nicolas Grekas <p@tchwork.com>

@final

Hierarchy

  • class \Symfony\Component\HttpKernel\DataCollector\DataCollector implements \Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface
    • class \Symfony\Component\HttpKernel\DataCollector\DumpDataCollector extends \Symfony\Component\HttpKernel\DataCollector\DataCollector implements \Symfony\Component\VarDumper\Dumper\DataDumperInterface

Expanded class hierarchy of DumpDataCollector

File

vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php, line 32

Namespace

Symfony\Component\HttpKernel\DataCollector
View source
class DumpDataCollector extends DataCollector implements DataDumperInterface {
    private string|FileLinkFormatter|false $fileLinkFormat;
    private int $dataCount = 0;
    private bool $isCollected = true;
    private int $clonesCount = 0;
    private int $clonesIndex = 0;
    private array $rootRefs;
    private string $charset;
    private mixed $sourceContextProvider;
    private bool $webMode;
    public function __construct(?Stopwatch $stopwatch = null, string|FileLinkFormatter|null $fileLinkFormat = null, ?string $charset = null, ?RequestStack $requestStack = null, DataDumperInterface|Connection|null $dumper = null, ?bool $webMode = null) {
        $fileLinkFormat = ($fileLinkFormat ?: \ini_get('xdebug.file_link_format')) ?: get_cfg_var('xdebug.file_link_format');
        $this->fileLinkFormat = $fileLinkFormat instanceof FileLinkFormatter && false === $fileLinkFormat->format('', 0) ? false : $fileLinkFormat;
        $this->charset = (($charset ?: \ini_get('php.output_encoding')) ?: \ini_get('default_charset')) ?: 'UTF-8';
        $this->webMode = $webMode ?? !\in_array(\PHP_SAPI, [
            'cli',
            'phpdbg',
            'embed',
        ], true);
        // All clones share these properties by reference:
        $this->rootRefs = [
            &$this->data,
            &$this->dataCount,
            &$this->isCollected,
            &$this->clonesCount,
        ];
        $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
    }
    public function __clone() {
        $this->clonesIndex = ++$this->clonesCount;
    }
    public function dump(Data $data) : ?string {
        $this->stopwatch?->start('dump');
        [
            'name' => $name,
            'file' => $file,
            'line' => $line,
            'file_excerpt' => $fileExcerpt,
        ] = $this->sourceContextProvider
            ->getContext();
        if (!$this->dumper || $this->dumper instanceof Connection && !$this->dumper
            ->write($data)) {
            $this->isCollected = false;
        }
        $context = $data->getContext();
        $label = $context['label'] ?? '';
        unset($context['label']);
        $data = $data->withContext($context);
        if ($this->dumper && !$this->dumper instanceof Connection) {
            $this->doDump($this->dumper, $data, $name, $file, $line, $label);
        }
        if (!$this->dataCount) {
            $this->data = [];
        }
        $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt', 'label');
        ++$this->dataCount;
        $this->stopwatch?->stop('dump');
        return null;
    }
    public function collect(Request $request, Response $response, ?\Throwable $exception = null) : void {
        if (!$this->dataCount) {
            $this->data = [];
        }
        // Sub-requests and programmatic calls stay in the collected profile.
        if ($this->dumper || $this->requestStack && $this->requestStack
            ->getMainRequest() !== $request || $request->isXmlHttpRequest() || $request->headers
            ->has('Origin')) {
            return;
        }
        // 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);
            }
            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'] ?? '');
            }
        }
    }
    public function reset() : void {
        $this->stopwatch?->reset();
        parent::reset();
        $this->dataCount = 0;
        $this->isCollected = true;
        $this->clonesCount = 0;
        $this->clonesIndex = 0;
    }
    
    /**
     * @internal
     */
    public function __sleep() : array {
        if (!$this->dataCount) {
            $this->data = [];
        }
        if ($this->clonesCount !== $this->clonesIndex) {
            return [];
        }
        $this->data[] = $this->fileLinkFormat;
        $this->data[] = $this->charset;
        $this->dataCount = 0;
        $this->isCollected = true;
        return parent::__sleep();
    }
    
    /**
     * @internal
     */
    public function __wakeup() : void {
        parent::__wakeup();
        $charset = array_pop($this->data);
        $fileLinkFormat = array_pop($this->data);
        $this->dataCount = \count($this->data);
        foreach ($this->data as $dump) {
            if (!\is_string($dump['name']) || !\is_string($dump['file']) || !\is_int($dump['line'])) {
                throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
            }
        }
        self::__construct($this->stopwatch ?? null, \is_string($fileLinkFormat) || $fileLinkFormat instanceof FileLinkFormatter ? $fileLinkFormat : null, \is_string($charset) ? $charset : null);
    }
    public function getDumpsCount() : int {
        return $this->dataCount;
    }
    public function getDumps(string $format, int $maxDepthLimit = -1, int $maxItemsPerDepth = -1) : array {
        $data = fopen('php://memory', 'r+');
        if ('html' === $format) {
            $dumper = new HtmlDumper($data, $this->charset);
            $dumper->setDisplayOptions([
                'fileLinkFormat' => $this->fileLinkFormat,
            ]);
        }
        else {
            throw new \InvalidArgumentException(\sprintf('Invalid dump format: "%s".', $format));
        }
        $dumps = [];
        if (!$this->dataCount) {
            return $this->data = [];
        }
        foreach ($this->data as $dump) {
            $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)
                ->withMaxItemsPerDepth($maxItemsPerDepth));
            $dump['data'] = stream_get_contents($data, -1, 0);
            ftruncate($data, 0);
            rewind($data);
            $dumps[] = $dump;
        }
        return $dumps;
    }
    public function getName() : string {
        return 'dump';
    }
    public function __destruct() {
        if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) {
            $this->clonesCount = 0;
            $this->isCollected = true;
            $h = headers_list();
            $i = \count($h);
            array_unshift($h, 'Content-Type: ' . \ini_get('default_mimetype'));
            while (0 !== stripos($h[$i], 'Content-Type:')) {
                --$i;
            }
            if ($this->webMode) {
                $dumper = new HtmlDumper('php://output', $this->charset);
            }
            else {
                $dumper = new CliDumper('php://output', $this->charset);
            }
            $dumper->setDisplayOptions([
                'fileLinkFormat' => $this->fileLinkFormat,
            ]);
            foreach ($this->data as $i => $dump) {
                $this->data[$i] = null;
                $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line'], $dump['label'] ?? '');
            }
            $this->data = [];
            $this->dataCount = 0;
        }
    }
    private function doDump(DataDumperInterface $dumper, Data $data, string $name, string $file, int $line, string $label) : void {
        if ($dumper instanceof CliDumper) {
            $contextDumper = function ($name, $file, $line, $fmt, $label) {
                $this->line = '' !== $label ? $this->style('meta', $label) . ' in ' : '';
                if ($this instanceof HtmlDumper) {
                    if ($file) {
                        $s = $this->style('meta', '%s');
                        $f = strip_tags($this->style('', $file));
                        $name = strip_tags($this->style('', $name));
                        if ($fmt && ($link = \is_string($fmt) ? strtr($fmt, [
                            '%f' => $file,
                            '%l' => $line,
                        ]) : $fmt->format($file, $line))) {
                            $name = \sprintf('<a href="%s" title="%s">' . $s . '</a>', strip_tags($this->style('', $link)), $f, $name);
                        }
                        else {
                            $name = \sprintf('<abbr title="%s">' . $s . '</abbr>', $f, $name);
                        }
                    }
                    else {
                        $name = $this->style('meta', $name);
                    }
                    $this->line .= $name . ' on line ' . $this->style('meta', $line) . ':';
                }
                else {
                    $this->line .= $this->style('meta', $name) . ' on line ' . $this->style('meta', $line) . ':';
                }
                $this->dumpLine(0);
            };
            $contextDumper = $contextDumper->bindTo($dumper, $dumper);
            $contextDumper($name, $file, $line, $this->fileLinkFormat, $label);
        }
        else {
            $cloner = new VarCloner();
            $dumper->dump($cloner->cloneVar(('' !== $label ? $label . ' in ' : '') . $name . ' on line ' . $line . ':'));
        }
        $dumper->dump($data);
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
DataCollector::$cloner private property
DataCollector::$data protected property
DataCollector::cloneVar protected function Converts the variable into a serializable Data instance.
DataCollector::getCasters protected function 1
DataCollector::serialize final protected function @internal to prevent implementing \Serializable
DataCollector::unserialize final protected function @internal to prevent implementing \Serializable
DumpDataCollector::$charset private property
DumpDataCollector::$clonesCount private property
DumpDataCollector::$clonesIndex private property
DumpDataCollector::$dataCount private property
DumpDataCollector::$fileLinkFormat private property
DumpDataCollector::$isCollected private property
DumpDataCollector::$rootRefs private property
DumpDataCollector::$sourceContextProvider private property
DumpDataCollector::$webMode private property
DumpDataCollector::collect public function Collects data for the given Request and Response. Overrides DataCollectorInterface::collect
DumpDataCollector::doDump private function
DumpDataCollector::dump public function Overrides DataDumperInterface::dump
DumpDataCollector::getDumps public function
DumpDataCollector::getDumpsCount public function
DumpDataCollector::getName public function Returns the name of the collector. Overrides DataCollectorInterface::getName
DumpDataCollector::reset public function Overrides DataCollector::reset
DumpDataCollector::__clone public function
DumpDataCollector::__construct public function
DumpDataCollector::__destruct public function
DumpDataCollector::__sleep public function @internal Overrides DataCollector::__sleep
DumpDataCollector::__wakeup public function @internal Overrides DataCollector::__wakeup

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal