diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d2f8eb5..5e5e8db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,39 @@ CHANGELOG ========= +7.3 +--- + + * Add `profiler.php` and `wdt.php` routing configuration files (use them instead of their XML equivalent) + + Before: + + ```yaml + when@dev: + web_profiler_wdt: + resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' + prefix: /_wdt + + web_profiler_profiler: + resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' + prefix: /_profiler + ``` + + After: + + ```yaml + when@dev: + web_profiler_wdt: + resource: '@WebProfilerBundle/Resources/config/routing/wdt.php' + prefix: /_wdt + + web_profiler_profiler: + resource: '@WebProfilerBundle/Resources/config/routing/profiler.php + prefix: /_profiler + ``` + + * Add `ajax_replace` option for replacing toolbar on AJAX requests + 7.2 --- @@ -65,7 +98,7 @@ CHANGELOG ----- * added information about orphaned events - * made the toolbar auto-update with info from ajax reponses when they set the + * made the toolbar auto-update with info from ajax responses when they set the `Symfony-Debug-Toolbar-Replace header` to `1` 4.0.0 diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 51ddad76..649bf459 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -31,9 +31,20 @@ public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('web_profiler'); - $treeBuilder->getRootNode() + $treeBuilder + ->getRootNode() + ->docUrl('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/web_profiler.html', 'symfony/web-profiler-bundle') ->children() - ->booleanNode('toolbar')->defaultFalse()->end() + ->arrayNode('toolbar') + ->info('Profiler toolbar configuration') + ->canBeEnabled() + ->children() + ->booleanNode('ajax_replace') + ->defaultFalse() + ->info('Replace toolbar on AJAX requests') + ->end() + ->end() + ->end() ->booleanNode('intercept_redirects')->defaultFalse()->end() ->scalarNode('excluded_ajax_paths')->defaultValue('^/((index|app(_[\w]+)?)\.php/)?_wdt')->end() ->end() diff --git a/DependencyInjection/WebProfilerExtension.php b/DependencyInjection/WebProfilerExtension.php index 6ad6982c..d1867029 100644 --- a/DependencyInjection/WebProfilerExtension.php +++ b/DependencyInjection/WebProfilerExtension.php @@ -46,11 +46,12 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('profiler.php'); - if ($config['toolbar'] || $config['intercept_redirects']) { + if ($config['toolbar']['enabled'] || $config['intercept_redirects']) { $loader->load('toolbar.php'); $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(4, $config['excluded_ajax_paths']); + $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(7, $config['toolbar']['ajax_replace']); $container->setParameter('web_profiler.debug_toolbar.intercept_redirects', $config['intercept_redirects']); - $container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED); + $container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar']['enabled'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED); } $container->getDefinition('debug.file_link_formatter') diff --git a/EventListener/WebDebugToolbarListener.php b/EventListener/WebDebugToolbarListener.php index c51cf309..2ad19250 100644 --- a/EventListener/WebDebugToolbarListener.php +++ b/EventListener/WebDebugToolbarListener.php @@ -48,6 +48,7 @@ public function __construct( private string $excludedAjaxPaths = '^/bundles|^/_wdt', private ?ContentSecurityPolicyHandler $cspHandler = null, private ?DumpDataCollector $dumpDataCollector = null, + private bool $ajaxReplace = false, ) { } @@ -96,6 +97,10 @@ public function onKernelResponse(ResponseEvent $event): void // do not capture redirects or modify XML HTTP Requests if ($request->isXmlHttpRequest()) { + if (self::ENABLED === $this->mode && $this->ajaxReplace && !$response->headers->has('Symfony-Debug-Toolbar-Replace')) { + $response->headers->set('Symfony-Debug-Toolbar-Replace', '1'); + } + return; } diff --git a/Resources/config/routing/profiler.php b/Resources/config/routing/profiler.php new file mode 100644 index 00000000..46175d1d --- /dev/null +++ b/Resources/config/routing/profiler.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +use Symfony\Component\Routing\Loader\XmlFileLoader; + +return function (RoutingConfigurator $routes): void { + foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT) as $trace) { + if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { + if (__DIR__ === dirname(realpath($trace['args'][3]))) { + trigger_deprecation('symfony/routing', '7.3', 'The "profiler.xml" routing configuration file is deprecated, import "profile.php" instead.'); + + break; + } + } + } + + $routes->add('_profiler_home', '/') + ->controller('web_profiler.controller.profiler::homeAction') + ; + $routes->add('_profiler_search', '/search') + ->controller('web_profiler.controller.profiler::searchAction') + ; + $routes->add('_profiler_search_bar', '/search_bar') + ->controller('web_profiler.controller.profiler::searchBarAction') + ; + $routes->add('_profiler_phpinfo', '/phpinfo') + ->controller('web_profiler.controller.profiler::phpinfoAction') + ; + $routes->add('_profiler_xdebug', '/xdebug') + ->controller('web_profiler.controller.profiler::xdebugAction') + ; + $routes->add('_profiler_font', '/font/{fontName}.woff2') + ->controller('web_profiler.controller.profiler::fontAction') + ; + $routes->add('_profiler_search_results', '/{token}/search/results') + ->controller('web_profiler.controller.profiler::searchResultsAction') + ; + $routes->add('_profiler_open_file', '/open') + ->controller('web_profiler.controller.profiler::openAction') + ; + $routes->add('_profiler', '/{token}') + ->controller('web_profiler.controller.profiler::panelAction') + ; + $routes->add('_profiler_router', '/{token}/router') + ->controller('web_profiler.controller.router::panelAction') + ; + $routes->add('_profiler_exception', '/{token}/exception') + ->controller('web_profiler.controller.exception_panel::body') + ; + $routes->add('_profiler_exception_css', '/{token}/exception.css') + ->controller('web_profiler.controller.exception_panel::stylesheet') + ; +}; diff --git a/Resources/config/routing/profiler.xml b/Resources/config/routing/profiler.xml index 363b15d8..8712f387 100644 --- a/Resources/config/routing/profiler.xml +++ b/Resources/config/routing/profiler.xml @@ -4,52 +4,5 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - web_profiler.controller.profiler::homeAction - - - - web_profiler.controller.profiler::searchAction - - - - web_profiler.controller.profiler::searchBarAction - - - - web_profiler.controller.profiler::phpinfoAction - - - - web_profiler.controller.profiler::xdebugAction - - - - web_profiler.controller.profiler::fontAction - - - - web_profiler.controller.profiler::searchResultsAction - - - - web_profiler.controller.profiler::openAction - - - - web_profiler.controller.profiler::panelAction - - - - web_profiler.controller.router::panelAction - - - - web_profiler.controller.exception_panel::body - - - - web_profiler.controller.exception_panel::stylesheet - - + diff --git a/Resources/config/routing/wdt.php b/Resources/config/routing/wdt.php new file mode 100644 index 00000000..81b471d2 --- /dev/null +++ b/Resources/config/routing/wdt.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +use Symfony\Component\Routing\Loader\XmlFileLoader; + +return function (RoutingConfigurator $routes): void { + foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT) as $trace) { + if (isset($trace['object']) && $trace['object'] instanceof XmlFileLoader && 'doImport' === $trace['function']) { + if (__DIR__ === dirname(realpath($trace['args'][3]))) { + trigger_deprecation('symfony/routing', '7.3', 'The "xdt.xml" routing configuration file is deprecated, import "xdt.php" instead.'); + + break; + } + } + } + + $routes->add('_wdt_stylesheet', '/styles') + ->controller('web_profiler.controller.profiler::toolbarStylesheetAction') + ; + $routes->add('_wdt', '/{token}') + ->controller('web_profiler.controller.profiler::toolbarAction') + ; +}; diff --git a/Resources/config/routing/wdt.xml b/Resources/config/routing/wdt.xml index 9f45f1b7..04bddb4f 100644 --- a/Resources/config/routing/wdt.xml +++ b/Resources/config/routing/wdt.xml @@ -4,11 +4,5 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - web_profiler.controller.profiler::toolbarStylesheetAction - - - - web_profiler.controller.profiler::toolbarAction - + diff --git a/Resources/config/schema/webprofiler-1.0.xsd b/Resources/config/schema/webprofiler-1.0.xsd index e22105a1..0a3a0767 100644 --- a/Resources/config/schema/webprofiler-1.0.xsd +++ b/Resources/config/schema/webprofiler-1.0.xsd @@ -9,6 +9,14 @@ + + + + + + + + diff --git a/Resources/config/toolbar.php b/Resources/config/toolbar.php index 473b3630..c264b77d 100644 --- a/Resources/config/toolbar.php +++ b/Resources/config/toolbar.php @@ -25,6 +25,7 @@ abstract_arg('paths that should be excluded from the AJAX requests shown in the toolbar'), service('web_profiler.csp.handler'), service('data_collector.dump')->ignoreOnInvalid(), + abstract_arg('whether to replace toolbar on AJAX requests or not'), ]) ->tag('kernel.event_subscriber') ; diff --git a/Resources/views/Collector/cache.html.twig b/Resources/views/Collector/cache.html.twig index d0bc9686..217ad78f 100644 --- a/Resources/views/Collector/cache.html.twig +++ b/Resources/views/Collector/cache.html.twig @@ -93,7 +93,7 @@ {{ loop.index }} {{ '%0.2f'|format((call.end - call.start) * 1000) }} ms - {{ call.name }}() + {{ call.name }}({{ call.namespace|default('') }}) {{ profiler_dump(call.value.result, maxDepth=2) }} {% endfor %} diff --git a/Resources/views/Collector/translation.html.twig b/Resources/views/Collector/translation.html.twig index eeb8a06a..53560cf3 100644 --- a/Resources/views/Collector/translation.html.twig +++ b/Resources/views/Collector/translation.html.twig @@ -156,6 +156,27 @@ {% endblock messages %} {% endif %} + {% if collector.globalParameters|default([]) %} +

Global parameters

+ + + + + + + + + + {% for id, value in collector.globalParameters %} + + + + + {% endfor %} + +
Message IDValue
{{ id }}{{ profiler_dump(value) }}
+ {% endif %} + {% endblock %} {% macro render_table(messages, is_fallback) %} diff --git a/Resources/views/Collector/workflow.html.twig b/Resources/views/Collector/workflow.html.twig index 6f09b363..dfe7beac 100644 --- a/Resources/views/Collector/workflow.html.twig +++ b/Resources/views/Collector/workflow.html.twig @@ -137,20 +137,22 @@ {{ source('@WebProfiler/Script/Mermaid/mermaid-flowchart-v2.min.js') }} const isDarkMode = document.querySelector('body').classList.contains('theme-dark'); mermaid.initialize({ - flowchart: { useMaxWidth: false }, + flowchart: { + useMaxWidth: true, + }, securityLevel: 'loose', - 'theme': 'base', - 'themeVariables': { + theme: 'base', + themeVariables: { darkMode: isDarkMode, - 'fontFamily': 'var(--font-family-system)', - 'fontSize': 'var(--font-size-body)', + fontFamily: 'var(--font-family-system)', + fontSize: 'var(--font-size-body)', // the properties below don't support CSS variables - 'primaryColor': isDarkMode ? 'lightsteelblue' : 'aliceblue', - 'primaryTextColor': isDarkMode ? '#000' : '#000', - 'primaryBorderColor': isDarkMode ? 'steelblue' : 'lightsteelblue', - 'lineColor': isDarkMode ? '#939393' : '#d4d4d4', - 'secondaryColor': isDarkMode ? 'lightyellow' : 'lightyellow', - 'tertiaryColor': isDarkMode ? 'lightSalmon' : 'lightSalmon', + primaryColor: isDarkMode ? 'lightsteelblue' : 'aliceblue', + primaryTextColor: isDarkMode ? '#000' : '#000', + primaryBorderColor: isDarkMode ? 'steelblue' : 'lightsteelblue', + lineColor: isDarkMode ? '#939393' : '#d4d4d4', + secondaryColor: isDarkMode ? 'lightyellow' : 'lightyellow', + tertiaryColor: isDarkMode ? 'lightSalmon' : 'lightSalmon', } }); @@ -275,6 +277,7 @@ click {{ nodeId }} showNodeDetails{{ collector.hash(name) }} {% endfor %} + View on mermaid.live

Calls

diff --git a/Resources/views/Profiler/toolbar.css.twig b/Resources/views/Profiler/toolbar.css.twig index b61fa5e9..148b7638 100644 --- a/Resources/views/Profiler/toolbar.css.twig +++ b/Resources/views/Profiler/toolbar.css.twig @@ -46,45 +46,11 @@ --sf-toolbar-green-900: #030404; } -.sf-minitoolbar { - --sf-toolbar-gray-800: #262626; - - background-color: var(--sf-toolbar-gray-800); - border-top-left-radius: 4px; - bottom: 0; - box-sizing: border-box; - display: none; - height: 36px; - padding: 6px; - position: fixed; - right: 0; - z-index: 99999; -} - -.sf-minitoolbar button { - background-color: transparent; - padding: 0; - border: none; -} -.sf-minitoolbar svg, -.sf-minitoolbar img { - --sf-toolbar-gray-200: #e5e5e5; - - color: var(--sf-toolbar-gray-200); - max-height: 24px; - max-width: 24px; - display: inline; -} - .sf-toolbar-clearer { clear: both; height: 36px; } -.sf-display-none { - display: none; -} - .sf-toolbarreset *:not(svg rect) { box-sizing: content-box; vertical-align: baseline; @@ -127,27 +93,52 @@ color: var(--sf-toolbar-gray-700); } -.sf-toolbarreset .hide-button { +.sf-toolbarreset .sf-toolbar-toggle-button { background: var(--sf-toolbar-gray-800); color: var(--sf-toolbar-gray-300); display: block; position: absolute; - top: 2px; + top: 1px; right: 0; width: 36px; - height: 34px; + height: 35px; cursor: pointer; text-align: center; border: none; margin: 0; padding: 0; + outline: none; } -.sf-toolbarreset .hide-button:hover { +.sf-toolbarreset .sf-toolbar-toggle-button:hover { background: var(--sf-toolbar-gray-700); } -.sf-toolbarreset .hide-button svg { - max-height: 18px; - margin-top: 1px; + +.sf-toolbar.sf-toolbar-closed .sf-toolbarreset .sf-toolbar-block { + display: none; +} +.sf-toolbar.sf-toolbar-closed .sf-toolbarreset .sf-toolbar-toggle-button { + top: -37px; +} + +.sf-toolbar .sf-toolbar-toggle-button i { + display: block; + height: 35px; + place-content: center; +} +.sf-toolbar.sf-toolbar-opened .sf-toolbar-toggle-button .sf-toolbar-icon-closed { + display: none; +} +.sf-toolbar.sf-toolbar-opened .sf-toolbar-toggle-button .sf-toolbar-icon-opened { + display: block; +} +.sf-toolbar.sf-toolbar-closed .sf-toolbar-toggle-button .sf-toolbar-icon-closed { + display: block; +} +.sf-toolbar.sf-toolbar-closed .sf-toolbar-toggle-button .sf-toolbar-icon-opened { + display: none; +} +.sf-toolbar.sf-toolbar-closed .sf-toolbarreset .sf-toolbar-toggle-button { + border-top: 2px solid var(--sf-toolbar-gray-800); } .sf-toolbar-block { diff --git a/Resources/views/Profiler/toolbar.html.twig b/Resources/views/Profiler/toolbar.html.twig index 565ec39b..b82f911c 100644 --- a/Resources/views/Profiler/toolbar.html.twig +++ b/Resources/views/Profiler/toolbar.html.twig @@ -1,11 +1,4 @@ - -
- -
-
{% for name, template in templates %} {% if block('toolbar', template) is defined %} @@ -39,8 +32,8 @@
{% endif %} - - diff --git a/Resources/views/Profiler/toolbar_js.html.twig b/Resources/views/Profiler/toolbar_js.html.twig index eaf9329a..91e6dc05 100644 --- a/Resources/views/Profiler/toolbar_js.html.twig +++ b/Resources/views/Profiler/toolbar_js.html.twig @@ -1,4 +1,5 @@ -
+ +
{{ include('@WebProfiler/Profiler/toolbar.html.twig', { templates: { 'request': '@WebProfiler/Profiler/cancel.html.twig' @@ -453,60 +454,32 @@ showToolbar: function(token) { var sfwdt = this.getSfwdt(token); - removeClass(sfwdt, 'sf-display-none'); - if (getPreference('toolbar/displayState') == 'none') { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'none'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'block'; + if ('closed' === getPreference('toolbar/displayState')) { + addClass(sfwdt, 'sf-toolbar-closed'); + removeClass(sfwdt, 'sf-toolbar-opened'); } else { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'block'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'block'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'none'; + addClass(sfwdt, 'sf-toolbar-opened'); + removeClass(sfwdt, 'sf-toolbar-closed'); } }, hideToolbar: function(token) { var sfwdt = this.getSfwdt(token); - addClass(sfwdt, 'sf-display-none'); + addClass(sfwdt, 'sf-toolbar-closed'); + removeClass(sfwdt, 'sf-toolbar-opened'); }, initToolbar: function(token) { this.showToolbar(token); - var hideButton = document.getElementById('sfToolbarHideButton-' + token); - var hideButtonSvg = hideButton.querySelector('svg'); - hideButtonSvg.setAttribute('aria-hidden', 'true'); - hideButtonSvg.setAttribute('focusable', 'false'); - addEventListener(hideButton, 'click', function (event) { + var toggleButton = document.querySelector(`#sfToolbarToggleButton-${token}`); + addEventListener(toggleButton, 'click', function (event) { event.preventDefault(); - var p = this.parentNode; - p.style.display = 'none'; - (p.previousElementSibling || p.previousSibling).style.display = 'none'; - document.getElementById('sfMiniToolbar-' + token).style.display = 'block'; - setPreference('toolbar/displayState', 'none'); - }); - - var showButton = document.getElementById('sfToolbarMiniToggler-' + token); - var showButtonSvg = showButton.querySelector('svg'); - showButtonSvg.setAttribute('aria-hidden', 'true'); - showButtonSvg.setAttribute('focusable', 'false'); - addEventListener(showButton, 'click', function (event) { - event.preventDefault(); - - var elem = this.parentNode; - if (elem.style.display == 'none') { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'none'; - elem.style.display = 'block'; - } else { - document.getElementById('sfToolbarMainContent-' + token).style.display = 'block'; - document.getElementById('sfToolbarClearer-' + token).style.display = 'block'; - elem.style.display = 'none' - } - - setPreference('toolbar/displayState', 'block'); + const newState = 'opened' === getPreference('toolbar/displayState') ? 'closed' : 'opened'; + setPreference('toolbar/displayState', newState); + 'opened' === newState ? Sfjs.showToolbar(token) : Sfjs.hideToolbar(token); }); }, @@ -655,3 +628,4 @@ Sfjs.loadToolbar('{{ token }}'); /*]]>*/ + diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index d957cafc..6a9fc99f 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -36,7 +36,10 @@ public static function getDebugModes() 'options' => [], 'expectedResult' => [ 'intercept_redirects' => false, - 'toolbar' => false, + 'toolbar' => [ + 'enabled' => false, + 'ajax_replace' => false, + ], 'excluded_ajax_paths' => '^/((index|app(_[\w]+)?)\.php/)?_wdt', ], ], @@ -44,7 +47,10 @@ public static function getDebugModes() 'options' => ['toolbar' => true], 'expectedResult' => [ 'intercept_redirects' => false, - 'toolbar' => true, + 'toolbar' => [ + 'enabled' => true, + 'ajax_replace' => false, + ], 'excluded_ajax_paths' => '^/((index|app(_[\w]+)?)\.php/)?_wdt', ], ], @@ -52,10 +58,24 @@ public static function getDebugModes() 'options' => ['excluded_ajax_paths' => 'test'], 'expectedResult' => [ 'intercept_redirects' => false, - 'toolbar' => false, + 'toolbar' => [ + 'enabled' => false, + 'ajax_replace' => false, + ], 'excluded_ajax_paths' => 'test', ], ], + [ + 'options' => ['toolbar' => ['ajax_replace' => true]], + 'expectedResult' => [ + 'intercept_redirects' => false, + 'toolbar' => [ + 'enabled' => true, + 'ajax_replace' => true, + ], + 'excluded_ajax_paths' => '^/((index|app(_[\w]+)?)\.php/)?_wdt', + ], + ], ]; } @@ -78,7 +98,10 @@ public static function getInterceptRedirectsConfiguration() 'interceptRedirects' => true, 'expectedResult' => [ 'intercept_redirects' => true, - 'toolbar' => false, + 'toolbar' => [ + 'enabled' => false, + 'ajax_replace' => false, + ], 'excluded_ajax_paths' => '^/((index|app(_[\w]+)?)\.php/)?_wdt', ], ], @@ -86,7 +109,10 @@ public static function getInterceptRedirectsConfiguration() 'interceptRedirects' => false, 'expectedResult' => [ 'intercept_redirects' => false, - 'toolbar' => false, + 'toolbar' => [ + 'enabled' => false, + 'ajax_replace' => false, + ], 'excluded_ajax_paths' => '^/((index|app(_[\w]+)?)\.php/)?_wdt', ], ], diff --git a/Tests/EventListener/WebDebugToolbarListenerTest.php b/Tests/EventListener/WebDebugToolbarListenerTest.php index cf3c1892..981c85be 100644 --- a/Tests/EventListener/WebDebugToolbarListenerTest.php +++ b/Tests/EventListener/WebDebugToolbarListenerTest.php @@ -360,6 +360,66 @@ public function testNullContentTypeWithNoDebugEnv() $this->expectNotToPerformAssertions(); } + public function testAjaxReplaceHeaderOnDisabledToolbar() + { + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::DISABLED, null, '', null, null, true); + $listener->onKernelResponse($event); + + $this->assertFalse($response->headers->has('Symfony-Debug-Toolbar-Replace')); + } + + public function testAjaxReplaceHeaderOnDisabledReplace() + { + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, null, '', null, null); + $listener->onKernelResponse($event); + + $this->assertFalse($response->headers->has('Symfony-Debug-Toolbar-Replace')); + } + + public function testAjaxReplaceHeaderOnEnabledAndNonXHR() + { + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, null, '', null, null, true); + $listener->onKernelResponse($event); + + $this->assertFalse($response->headers->has('Symfony-Debug-Toolbar-Replace')); + } + + public function testAjaxReplaceHeaderOnEnabledAndXHR() + { + $request = new Request(); + $request->headers->set('X-Requested-With', 'XMLHttpRequest'); + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), $request, HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, null, '', null, null, true); + $listener->onKernelResponse($event); + + $this->assertSame('1', $response->headers->get('Symfony-Debug-Toolbar-Replace')); + } + + public function testAjaxReplaceHeaderOnEnabledAndXHRButPreviouslySet() + { + $request = new Request(); + $request->headers->set('X-Requested-With', 'XMLHttpRequest'); + $response = new Response(); + $response->headers->set('Symfony-Debug-Toolbar-Replace', '0'); + $event = new ResponseEvent($this->createMock(Kernel::class), $request, HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, null, '', null, null, true); + $listener->onKernelResponse($event); + + $this->assertSame('0', $response->headers->get('Symfony-Debug-Toolbar-Replace')); + } + protected function getTwigMock($render = 'WDT') { $templating = $this->createMock(Environment::class); diff --git a/Tests/Functional/WebProfilerBundleKernel.php b/Tests/Functional/WebProfilerBundleKernel.php index 64389602..0447e578 100644 --- a/Tests/Functional/WebProfilerBundleKernel.php +++ b/Tests/Functional/WebProfilerBundleKernel.php @@ -43,8 +43,8 @@ public function registerBundles(): iterable protected function configureRoutes(RoutingConfigurator $routes): void { - $routes->import(__DIR__.'/../../Resources/config/routing/profiler.xml')->prefix('/_profiler'); - $routes->import(__DIR__.'/../../Resources/config/routing/wdt.xml')->prefix('/_wdt'); + $routes->import(__DIR__.'/../../Resources/config/routing/profiler.php')->prefix('/_profiler'); + $routes->import(__DIR__.'/../../Resources/config/routing/wdt.php')->prefix('/_wdt'); $routes->add('_', '/')->controller('kernel::homepageController'); } @@ -55,7 +55,7 @@ protected function configureContainer(ContainerBuilder $container, LoaderInterfa 'http_method_override' => false, 'php_errors' => ['log' => true], 'secret' => 'foo-secret', - 'profiler' => ['only_exceptions' => false], + 'profiler' => ['only_exceptions' => false, 'collect_serializer_data' => true], 'session' => ['handler_id' => null, 'storage_factory_id' => 'session.storage.factory.mock_file', 'cookie-secure' => 'auto', 'cookie-samesite' => 'lax'], 'router' => ['utf8' => true], ]; diff --git a/composer.json b/composer.json index ce94b4b6..00269dd2 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,9 @@ ], "require": { "php": ">=8.2", - "symfony/config": "^6.4|^7.0", + "composer-runtime-api": ">=2.1", + "symfony/config": "^7.3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/framework-bundle": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/routing": "^6.4|^7.0", @@ -34,7 +36,8 @@ "symfony/form": "<6.4", "symfony/mailer": "<6.4", "symfony/messenger": "<6.4", - "symfony/serializer": "<7.2" + "symfony/serializer": "<7.2", + "symfony/workflow": "<7.3" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebProfilerBundle\\": "" },