initial commit

This commit is contained in:
boris
2025-09-30 09:24:25 +01:00
committed by boris
parent a783a12c97
commit c7770ea03b
4695 changed files with 525784 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
CHANGELOG
=========
4.1.0
-----
* Added the `server:dump` command to run a server collecting and displaying
dumps on a single place with multiple formats support

View File

@@ -0,0 +1,54 @@
<?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\Bundle\DebugBundle\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\VarDumper\Command\ServerDumpCommand;
use Symfony\Component\VarDumper\Server\DumpServer;
/**
* A placeholder command easing VarDumper server discovery.
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*
* @internal
*/
#[AsCommand(name: 'server:dump', description: 'Start a dump server that collects and displays dumps in a single place')]
class ServerDumpPlaceholderCommand extends Command
{
private ServerDumpCommand $replacedCommand;
public function __construct(?DumpServer $server = null, array $descriptors = [])
{
$this->replacedCommand = new ServerDumpCommand((new \ReflectionClass(DumpServer::class))->newInstanceWithoutConstructor(), $descriptors);
parent::__construct();
}
protected function configure(): void
{
$this->setDefinition($this->replacedCommand->getDefinition());
$this->setHelp($this->replacedCommand->getHelp());
$this->setDescription($this->replacedCommand->getDescription());
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
(new SymfonyStyle($input, $output))->getErrorStyle()->warning('In order to use the VarDumper server, set the "debug.dump_destination" config option to "tcp://%env(VAR_DUMPER_SERVER)%"');
return 8;
}
}

View File

@@ -0,0 +1,63 @@
<?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\Bundle\DebugBundle;
use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass;
use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\VarDumper\VarDumper;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class DebugBundle extends Bundle
{
public function boot(): void
{
if ($this->container->getParameter('kernel.debug')) {
$container = $this->container;
// This code is here to lazy load the dump stack. This default
// configuration is overridden in CLI mode on 'console.command' event.
// The dump data collector is used by default, so dump output is sent to
// the WDT. In a CLI context, if dump is used too soon, the data collector
// will buffer it, and release it at the end of the script.
VarDumper::setHandler(function ($var, ?string $label = null) use ($container) {
$dumper = $container->get('data_collector.dump');
$cloner = $container->get('var_dumper.cloner');
$handler = function ($var, ?string $label = null) use ($dumper, $cloner) {
$var = $cloner->cloneVar($var);
if (null !== $label) {
$var = $var->withContext(['label' => $label]);
}
$dumper->dump($var);
};
VarDumper::setHandler($handler);
$handler($var, $label);
});
}
}
public function build(ContainerBuilder $container): void
{
parent::build($container);
$container->addCompilerPass(new DumpDataCollectorPass());
}
public function registerCommands(Application $application): void
{
// noop
}
}

View File

@@ -0,0 +1,42 @@
<?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\Bundle\DebugBundle\DependencyInjection\Compiler;
use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers the file link format for the {@link \Symfony\Component\HttpKernel\DataCollector\DumpDataCollector}.
*
* @author Christian Flothmann <christian.flothmann@xabbuh.de>
*/
class DumpDataCollectorPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->hasDefinition('data_collector.dump')) {
return;
}
$definition = $container->getDefinition('data_collector.dump');
if (!$container->has('.virtual_request_stack')) {
$definition->replaceArgument(3, new Reference('request_stack'));
}
if (!$container->hasParameter('web_profiler.debug_toolbar.mode') || WebDebugToolbarListener::DISABLED === $container->getParameter('web_profiler.debug_toolbar.mode')) {
$definition->replaceArgument(3, null);
}
}
}

View File

@@ -0,0 +1,62 @@
<?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\Bundle\DebugBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* DebugExtension configuration structure.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('debug');
$rootNode = $treeBuilder->getRootNode();
$rootNode
->docUrl('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/debug.html', 'symfony/debug-bundle')
->children()
->integerNode('max_items')
->info('Max number of displayed items past the first level, -1 means no limit.')
->min(-1)
->defaultValue(2500)
->end()
->integerNode('min_depth')
->info('Minimum tree depth to clone all the items, 1 is default.')
->min(0)
->defaultValue(1)
->end()
->integerNode('max_string_length')
->info('Max length of displayed strings, -1 means no limit.')
->min(-1)
->defaultValue(-1)
->end()
->scalarNode('dump_destination')
->info('A stream URL where dumps should be written to.')
->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command')
->defaultNull()
->end()
->enumNode('theme')
->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light".')
->example('dark')
->values(['dark', 'light'])
->defaultValue('dark')
->end()
;
return $treeBuilder;
}
}

View File

@@ -0,0 +1,97 @@
<?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\Bundle\DebugBundle\DependencyInjection;
use Symfony\Bridge\Monolog\Command\ServerLogCommand;
use Symfony\Bundle\DebugBundle\Command\ServerDumpPlaceholderCommand;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class DebugExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.php');
$container->getDefinition('var_dumper.cloner')
->addMethodCall('setMaxItems', [$config['max_items']])
->addMethodCall('setMinDepth', [$config['min_depth']])
->addMethodCall('setMaxString', [$config['max_string_length']])
->addMethodCall('addCasters', [ReflectionCaster::UNSET_CLOSURE_FILE_INFO]);
if ('dark' !== $config['theme']) {
$container->getDefinition('var_dumper.html_dumper')
->addMethodCall('setTheme', [$config['theme']]);
}
if (null === $config['dump_destination']) {
$container->getDefinition('var_dumper.command.server_dump')
->setClass(ServerDumpPlaceholderCommand::class)
;
} elseif (str_starts_with($config['dump_destination'], 'tcp://')) {
$container->getDefinition('debug.dump_listener')
->replaceArgument(2, new Reference('var_dumper.server_connection'))
;
$container->getDefinition('data_collector.dump')
->replaceArgument(4, new Reference('var_dumper.server_connection'))
;
$container->getDefinition('var_dumper.dump_server')
->replaceArgument(0, $config['dump_destination'])
;
$container->getDefinition('var_dumper.server_connection')
->replaceArgument(0, $config['dump_destination'])
;
} else {
$container->getDefinition('var_dumper.cli_dumper')
->replaceArgument(0, $config['dump_destination'])
;
$container->getDefinition('data_collector.dump')
->replaceArgument(4, new Reference('var_dumper.cli_dumper'))
;
$container->getDefinition('var_dumper.command.server_dump')
->setClass(ServerDumpPlaceholderCommand::class)
;
}
$container->getDefinition('var_dumper.cli_dumper')
->addMethodCall('setDisplayOptions', [[
'fileLinkFormat' => new Reference('debug.file_link_formatter', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE),
]])
;
if (!class_exists(Command::class) || !class_exists(ServerLogCommand::class)) {
$container->removeDefinition('monolog.command.server_log');
}
}
public function getXsdValidationBasePath(): string|false
{
return __DIR__.'/../Resources/config/schema';
}
public function getNamespace(): string
{
return 'http://symfony.com/schema/dic/debug';
}
}

19
vendor/symfony/debug-bundle/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2014-present Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

13
vendor/symfony/debug-bundle/README.md vendored Normal file
View File

@@ -0,0 +1,13 @@
DebugBundle
===========
DebugBundle provides a tight integration of the Symfony VarDumper component and
the ServerLogCommand from MonologBridge into the Symfony full-stack framework.
Resources
---------
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://symfony.com/schema/dic/debug"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://symfony.com/schema/dic/debug"
elementFormDefault="qualified">
<xsd:element name="config" type="config" />
<xsd:complexType name="config">
<xsd:attribute name="max-items" type="xsd:integer" />
<xsd:attribute name="min-depth" type="xsd:integer" />
<xsd:attribute name="max-string-length" type="xsd:integer" />
<xsd:attribute name="dump-destination" type="xsd:string" />
</xsd:complexType>
</xsd:schema>

View File

@@ -0,0 +1,140 @@
<?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\DependencyInjection\Loader\Configurator;
use Monolog\Formatter\FormatterInterface;
use Symfony\Bridge\Monolog\Command\ServerLogCommand;
use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter;
use Symfony\Bridge\Twig\Extension\DumpExtension;
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
use Symfony\Component\HttpKernel\EventListener\DumpListener;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor;
use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor;
use Symfony\Component\VarDumper\Command\ServerDumpCommand;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider;
use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider;
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Server\Connection;
use Symfony\Component\VarDumper\Server\DumpServer;
return static function (ContainerConfigurator $container) {
$container->parameters()
->set('env(VAR_DUMPER_SERVER)', '127.0.0.1:9912')
;
$container->services()
->set('twig.extension.dump', DumpExtension::class)
->args([
service('var_dumper.cloner'),
service('var_dumper.html_dumper'),
])
->tag('twig.extension')
->set('data_collector.dump', DumpDataCollector::class)
->public()
->args([
service('debug.stopwatch')->ignoreOnInvalid(),
service('debug.file_link_formatter')->ignoreOnInvalid(),
param('kernel.charset'),
service('.virtual_request_stack'),
null, // var_dumper.cli_dumper or var_dumper.server_connection when debug.dump_destination is set
])
->tag('data_collector', [
'id' => 'dump',
'template' => '@Debug/Profiler/dump.html.twig',
'priority' => 240,
])
->set('debug.dump_listener', DumpListener::class)
->args([
service('var_dumper.cloner'),
service('var_dumper.cli_dumper'),
null,
])
->tag('kernel.event_subscriber')
->set('var_dumper.cloner', VarCloner::class)
->public()
->set('var_dumper.cli_dumper', CliDumper::class)
->args([
null, // debug.dump_destination,
param('kernel.charset'),
0, // flags
])
->set('var_dumper.contextualized_cli_dumper', ContextualizedDumper::class)
->decorate('var_dumper.cli_dumper')
->args([
service('var_dumper.contextualized_cli_dumper.inner'),
[
'source' => inline_service(SourceContextProvider::class)->args([
param('kernel.charset'),
param('kernel.project_dir'),
service('debug.file_link_formatter')->nullOnInvalid(),
]),
],
])
->set('var_dumper.html_dumper', HtmlDumper::class)
->args([
null,
param('kernel.charset'),
0, // flags
])
->call('setDisplayOptions', [
['fileLinkFormat' => service('debug.file_link_formatter')->ignoreOnInvalid()],
])
->set('var_dumper.server_connection', Connection::class)
->args([
'', // server host
[
'source' => inline_service(SourceContextProvider::class)->args([
param('kernel.charset'),
param('kernel.project_dir'),
service('debug.file_link_formatter')->nullOnInvalid(),
]),
'request' => inline_service(RequestContextProvider::class)->args([service('request_stack')]),
'cli' => inline_service(CliContextProvider::class),
],
])
->set('var_dumper.dump_server', DumpServer::class)
->args([
'', // server host
service('logger')->nullOnInvalid(),
])
->tag('monolog.logger', ['channel' => 'debug'])
->set('var_dumper.command.server_dump', ServerDumpCommand::class)
->args([
service('var_dumper.dump_server'),
[
'cli' => inline_service(CliDescriptor::class)->args([service('var_dumper.contextualized_cli_dumper.inner')]),
'html' => inline_service(HtmlDescriptor::class)->args([service('var_dumper.html_dumper')]),
],
])
->tag('console.command')
->set('monolog.command.server_log', ServerLogCommand::class)
;
if (class_exists(ConsoleFormatter::class) && interface_exists(FormatterInterface::class)) {
$container->services()->get('monolog.command.server_log')->tag('console.command');
}
};

View File

@@ -0,0 +1,83 @@
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% block toolbar %}
{% if collector.dumpsCount %}
{% set icon %}
{{ source('@Debug/Profiler/icon.svg') }}
<span class="sf-toolbar-value">{{ collector.dumpsCount }}</span>
{% endset %}
{% set text %}
{% for dump in collector.getDumps('html') %}
<div class="sf-toolbar-info-piece">
<span>
{% if dump.label is defined and '' != dump.label %}
<span class="sf-toolbar-file-line"><strong>{{ dump.label }}</strong> in </span>
{% endif %}
{% if dump.file %}
{% set link = dump.file|file_link(dump.line) %}
{% if link %}
<a href="{{ link }}" title="{{ dump.file }}">{{ dump.name }}</a>
{% else %}
<abbr title="{{ dump.file }}">{{ dump.name }}</abbr>
{% endif %}
{% else %}
{{ dump.name }}
{% endif %}
</span>
<span class="sf-toolbar-file-line">line {{ dump.line }}</span>
{{ dump.data|raw }}
</div>
{% endfor %}
{% endset %}
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
{% endif %}
{% endblock %}
{% block menu %}
<span class="label {{ collector.dumpsCount == 0 ? 'disabled' }}">
<span class="icon">{{ source('@Debug/Profiler/icon.svg') }}</span>
<strong>Debug</strong>
</span>
{% endblock %}
{% block panel %}
<h2>Dumped Contents</h2>
{% for dump in collector.getDumps('html') %}
<div class="sf-dump sf-reset">
<span class="metadata">
{% if dump.label is defined and '' != dump.label %}
<strong>{{ dump.label }}</strong> in
{% else %}
In
{% endif %}
{% if dump.line %}
{% set link = dump.file|file_link(dump.line) %}
{% if link %}
<a href="{{ link }}" title="{{ dump.file }}">{{ dump.name }}</a>
{% else %}
<abbr title="{{ dump.file }}">{{ dump.name }}</abbr>
{% endif %}
{% else %}
{{ dump.name }}
{% endif %}
line <a class="text-small sf-toggle" data-toggle-selector="#sf-trace-{{ loop.index0 }}">{{ dump.line }}</a>:
</span>
<div class="sf-dump-compact hidden" id="sf-trace-{{ loop.index0 }}">
<div class="trace">
{{ dump.fileExcerpt ? dump.fileExcerpt|raw : dump.file|file_excerpt(dump.line) }}
</div>
</div>
{{ dump.data|raw }}
</div>
{% else %}
<div class="empty empty-panel">
<p>No content was dumped.</p>
</div>
{% endfor %}
{% endblock %}

View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" data-icon-name="icon-tabler-viewfinder" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<circle cx="12" cy="12" r="9"></circle>
<line x1="12" y1="3" x2="12" y2="7"></line>
<line x1="12" y1="21" x2="12" y2="18"></line>
<line x1="3" y1="12" x2="7" y2="12"></line>
<line x1="21" y1="12" x2="18" y2="12"></line>
<line x1="12" y1="12" x2="12" y2="12.01"></line>
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@@ -0,0 +1,38 @@
{
"name": "symfony/debug-bundle",
"type": "symfony-bundle",
"description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=8.2",
"ext-xml": "*",
"composer-runtime-api": ">=2.1",
"symfony/config": "^7.3",
"symfony/dependency-injection": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/twig-bridge": "^6.4|^7.0",
"symfony/var-dumper": "^6.4|^7.0"
},
"require-dev": {
"symfony/web-profiler-bundle": "^6.4|^7.0"
},
"autoload": {
"psr-4": { "Symfony\\Bundle\\DebugBundle\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev"
}