feature #32695 [WebProfilerBundle] Decoupling TwigBundle and using the new ErrorRenderer mechanism (yceruto)
This PR was merged into the 4.4 branch.
Discussion
----------
[WebProfilerBundle] Decoupling TwigBundle and using the new ErrorRenderer mechanism
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | yes
| Tests pass? | yes
| Fixed tickets | https://github.com/symfony/symfony/pull/31398#discussion_r303213713
| License | MIT
| Doc PR | -
Commits
-------
846d3e0e58
Decoupling TwigBundle and using the new ErrorRenderer mechanism
This commit is contained in:
commit
f492ba5dc0
@ -237,7 +237,7 @@ Validator
|
|||||||
WebProfilerBundle
|
WebProfilerBundle
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
* Deprecated the `ExceptionController::templateExists()` method
|
* Deprecated the `ExceptionController` class in favor of `ExceptionErrorController`
|
||||||
* Deprecated the `TemplateManager::templateExists()` method
|
* Deprecated the `TemplateManager::templateExists()` method
|
||||||
|
|
||||||
WebServerBundle
|
WebServerBundle
|
||||||
|
@ -579,6 +579,11 @@ Yaml
|
|||||||
* The parser is now stricter and will throw a `ParseException` when a
|
* The parser is now stricter and will throw a `ParseException` when a
|
||||||
mapping is found inside a multi-line string.
|
mapping is found inside a multi-line string.
|
||||||
|
|
||||||
|
WebProfilerBundle
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Removed the `ExceptionController` class, use `ExceptionErrorController` instead.
|
||||||
|
|
||||||
WebServerBundle
|
WebServerBundle
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ CHANGELOG
|
|||||||
* Added button to clear the ajax request tab
|
* Added button to clear the ajax request tab
|
||||||
* Deprecated the `ExceptionController::templateExists()` method
|
* Deprecated the `ExceptionController::templateExists()` method
|
||||||
* Deprecated the `TemplateManager::templateExists()` method
|
* Deprecated the `TemplateManager::templateExists()` method
|
||||||
|
* Deprecated the `ExceptionController` in favor of `ExceptionErrorController`
|
||||||
|
|
||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
@ -20,10 +20,14 @@ use Twig\Environment;
|
|||||||
use Twig\Error\LoaderError;
|
use Twig\Error\LoaderError;
|
||||||
use Twig\Loader\ExistsLoaderInterface;
|
use Twig\Loader\ExistsLoaderInterface;
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionController::class, ExceptionErrorController::class), E_USER_DEPRECATED);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExceptionController.
|
* ExceptionController.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.4, use the ExceptionErrorController instead.
|
||||||
*/
|
*/
|
||||||
class ExceptionController
|
class ExceptionController
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
<?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\WebProfilerBundle\Controller;
|
||||||
|
|
||||||
|
use Symfony\Component\ErrorRenderer\ErrorRenderer\HtmlErrorRenderer;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the exception panel.
|
||||||
|
*
|
||||||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||||
|
*/
|
||||||
|
class ExceptionErrorController
|
||||||
|
{
|
||||||
|
private $htmlErrorRenderer;
|
||||||
|
private $profiler;
|
||||||
|
|
||||||
|
public function __construct(HtmlErrorRenderer $htmlErrorRenderer, ?Profiler $profiler)
|
||||||
|
{
|
||||||
|
$this->htmlErrorRenderer = $htmlErrorRenderer;
|
||||||
|
$this->profiler = $profiler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the exception panel stacktrace for the given token.
|
||||||
|
*/
|
||||||
|
public function body(string $token): Response
|
||||||
|
{
|
||||||
|
if (null === $this->profiler) {
|
||||||
|
throw new NotFoundHttpException('The profiler must be enabled.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$exception = $this->profiler->loadProfile($token)
|
||||||
|
->getCollector('exception')
|
||||||
|
->getException()
|
||||||
|
;
|
||||||
|
|
||||||
|
return new Response($this->htmlErrorRenderer->getBody($exception));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the exception panel stylesheet.
|
||||||
|
*/
|
||||||
|
public function stylesheet(): Response
|
||||||
|
{
|
||||||
|
return new Response($this->htmlErrorRenderer->getStylesheet());
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,13 @@
|
|||||||
<argument type="service" id="twig" />
|
<argument type="service" id="twig" />
|
||||||
<argument>%kernel.debug%</argument>
|
<argument>%kernel.debug%</argument>
|
||||||
<argument type="service" id="debug.file_link_formatter" />
|
<argument type="service" id="debug.file_link_formatter" />
|
||||||
<argument type="service" id="error_renderer.renderer.html" on-invalid="null" />
|
<argument type="service" id="error_renderer.renderer.html" />
|
||||||
|
<deprecated>The "%service_id%" service is deprecated since Symfony 4.4, use the "web_profiler.controller.exception_error" service instead.</deprecated>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<service id="web_profiler.controller.exception_error" class="Symfony\Bundle\WebProfilerBundle\Controller\ExceptionErrorController" public="true">
|
||||||
|
<argument type="service" id="error_renderer.renderer.html" />
|
||||||
|
<argument type="service" id="profiler" on-invalid="null" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="web_profiler.csp.handler" class="Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler">
|
<service id="web_profiler.csp.handler" class="Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler">
|
||||||
|
@ -37,11 +37,11 @@
|
|||||||
</route>
|
</route>
|
||||||
|
|
||||||
<route id="_profiler_exception" path="/{token}/exception">
|
<route id="_profiler_exception" path="/{token}/exception">
|
||||||
<default key="_controller">web_profiler.controller.exception::showAction</default>
|
<default key="_controller">web_profiler.controller.exception_error::body</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
<route id="_profiler_exception_css" path="/{token}/exception.css">
|
<route id="_profiler_exception_css" path="/{token}/exception.css">
|
||||||
<default key="_controller">web_profiler.controller.exception::cssAction</default>
|
<default key="_controller">web_profiler.controller.exception_error::stylesheet</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
</routes>
|
</routes>
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
{{ include('@Twig/exception.css.twig') }}
|
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: auto;
|
max-width: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
{% if collector.hasexception %}
|
{% if collector.hasexception %}
|
||||||
<style>
|
<style>
|
||||||
{{ render(path('_profiler_exception_css', { token: token })) }}
|
{{ render(path('_profiler_exception_css', { token: token })) }}
|
||||||
|
{{ include('@WebProfiler/Collector/exception.css.twig') }}
|
||||||
</style>
|
</style>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
@ -119,8 +119,8 @@
|
|||||||
<span class="label status-error">exception</span>
|
<span class="label status-error">exception</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="toggle-button">
|
<a class="toggle-button">
|
||||||
<span class="icon icon-close">{{ include('@Twig/images/icon-minus-square.svg') }}</span>
|
<span class="icon icon-close">{{ include('@WebProfiler/images/icon-minus-square.svg') }}</span>
|
||||||
<span class="icon icon-open">{{ include('@Twig/images/icon-plus-square.svg') }}</span>
|
<span class="icon icon-open">{{ include('@WebProfiler/images/icon-plus-square.svg') }}</span>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta charset="{{ _charset }}" />
|
<meta charset="{{ _charset }}" />
|
||||||
<meta name="robots" content="noindex,nofollow" />
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Symfony Profiler</title>
|
<title>{% block title %}Symfony Profiler{% endblock %}</title>
|
||||||
<link rel="icon" type="image/x-icon" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFEUlEQVR4AZVXA4wm2RMf27bXDM/+3/+sYBGfrbVtezc6BWtzfPbYXtvDL9906t6v0vWl05me7q1JzXuvvu4yXnvZgJ9hH6bwZYXLFR739vauUGuDwhq1L1N4Uv/tRYUhFjwcg49hn6aYr1V4TiGp86CoP9Oh1tV414KnM6t9fHymKUZ3DAI0hW4b1AyK3lE8phh5OxWeoJgUGhi5mLm95YzBwcHuhIQEV1JSEoWGhoKWHxYWFmenhJ/B5W0GwZpDt5Ovry9lZWWRyWOu5ORk7JsUpogsq5gnmISTU+HKQoLFQv/qq6/os88+I+EVFRUlSsRZ5oRiVmwlXMWShQkahUdERJCfnx/vd+3aRTU1NXTixAmqrq6mK1eu0PTp05mnrmD+QK6XhLO0XP2O2FJAQICRjjMU4P1PP/1EfX19NGfOHM8Z0N7ezueQkBBXYGAgSWIaQ5Em2T5QzFNSUig9PV3OHOe4uDjZ87p//34C7Nm7x/NcRUUFAX799Vec8Y7m7+8Pz92SfBDXr7VwPYRbxn/MmDG8Tps2jQBd3V30/PPPe35/6qmnaPXq1TR69Gg+h4eHiwwosdLT4dBkQDSXWmJiIq/vv/8+/fvvv3ThwgWqr6+n/Px8oyCmAerq6jy03Nxc2Yv7ySSjQzrmi4i92fVpaWlYOZ79/f2MW7dtpSlTptDp06epo6ODPvroI850ASiGdyZOnEjXrl2jyspKT4XA9cgjkaPL/D8UWG62HokieyQQoKSkRGiMs2bNotraWmprayOBNWvWyO+scGdnp5zF/WYvLEb8TwpRykp1MV7feust6uzqJMD169fpueeeY/rDDz/MKzzgdrsJoGkaffvtt/TFF19wQsIDmzZtssojt+6Fo1CgzKiAvAB3DRs2jAULtLS0eErPGB5Ad3c3lZaWUnFxMfeAd955h5+JjY3FaqXAPwhBnRCNySK4b98+Aoilv/z6i/zGggSk1g0opWupAMvGP91yt96zadWqVdTc3Ezz58/31LOAy+US6zgHBP766y+mDR8+HBUgFWSnQI2EAFnqlpcaGxsJIFkMN8L9AnPnzmX6jRs3SACeAi0vL888JwYPgTEJpauhnADo6/LSgQMHCHD37l2Cp15//XXq7eslgKb+Fi1exM9lZmbaCDclIcpQQhATE4OVsrOzuamg+cyePZuzG64Hrlu3jp9ZuWolCdy+fZueeOIJpkdHR1sLHqgM0Yh0bTRz1m7fvp2KiopYkYKCApo8ebLZIwzlFeXSOXEnsLPe2Ij+p5DbYYdOdOtDQ0rNjFya5sTcsGGDcTDZoXTcNoVBMoxWyzDS2yXmOyeUtGSskmDjx4/nRgPAfBDmMpZtUIbRcsi2GsfSD2QYyd2OcdmyZSSwdu1apuXk5GB16v4bak0yX0imyIUEgwNovFTglhMZGcm0srIy43zAVUxuTLbW4xn17Fci23wly9dngUummrTaixcvMpOtW7fiiBwQpqKYU9efHuxDJE5hC9wvL9TW1RLg+PHjPGTQ8wsLC4WpDC5Y5UR4k5qKMSLT6lqeAiX0nuAaMmSI9sMPP9CZM2foyJEj9O677wpTVIuTjidNp0HibvttoH9E5OMqbWKkSaNSlojldoLF7TEP+nUEmKI62y1kOBINbVaNarcI0PuGGUlHyfYvLHg7/jhFSFYqZh0P8KHSptd5ksOPU3tvqAEUot/hFmOIYJLp87wGe9Dwm95eg5xa/R8G6d8U5EcFhwAAAABJRU5ErkJggg==">
|
<link rel="icon" type="image/x-icon" sizes="16x16" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFEUlEQVR4AZVXA4wm2RMf27bXDM/+3/+sYBGfrbVtezc6BWtzfPbYXtvDL9906t6v0vWl05me7q1JzXuvvu4yXnvZgJ9hH6bwZYXLFR739vauUGuDwhq1L1N4Uv/tRYUhFjwcg49hn6aYr1V4TiGp86CoP9Oh1tV414KnM6t9fHymKUZ3DAI0hW4b1AyK3lE8phh5OxWeoJgUGhi5mLm95YzBwcHuhIQEV1JSEoWGhoKWHxYWFmenhJ/B5W0GwZpDt5Ovry9lZWWRyWOu5ORk7JsUpogsq5gnmISTU+HKQoLFQv/qq6/os88+I+EVFRUlSsRZ5oRiVmwlXMWShQkahUdERJCfnx/vd+3aRTU1NXTixAmqrq6mK1eu0PTp05mnrmD+QK6XhLO0XP2O2FJAQICRjjMU4P1PP/1EfX19NGfOHM8Z0N7ezueQkBBXYGAgSWIaQ5Em2T5QzFNSUig9PV3OHOe4uDjZ87p//34C7Nm7x/NcRUUFAX799Vec8Y7m7+8Pz92SfBDXr7VwPYRbxn/MmDG8Tps2jQBd3V30/PPPe35/6qmnaPXq1TR69Gg+h4eHiwwosdLT4dBkQDSXWmJiIq/vv/8+/fvvv3ThwgWqr6+n/Px8oyCmAerq6jy03Nxc2Yv7ySSjQzrmi4i92fVpaWlYOZ79/f2MW7dtpSlTptDp06epo6ODPvroI850ASiGdyZOnEjXrl2jyspKT4XA9cgjkaPL/D8UWG62HokieyQQoKSkRGiMs2bNotraWmprayOBNWvWyO+scGdnp5zF/WYvLEb8TwpRykp1MV7feust6uzqJMD169fpueeeY/rDDz/MKzzgdrsJoGkaffvtt/TFF19wQsIDmzZtssojt+6Fo1CgzKiAvAB3DRs2jAULtLS0eErPGB5Ad3c3lZaWUnFxMfeAd955h5+JjY3FaqXAPwhBnRCNySK4b98+Aoilv/z6i/zGggSk1g0opWupAMvGP91yt96zadWqVdTc3Ezz58/31LOAy+US6zgHBP766y+mDR8+HBUgFWSnQI2EAFnqlpcaGxsJIFkMN8L9AnPnzmX6jRs3SACeAi0vL888JwYPgTEJpauhnADo6/LSgQMHCHD37l2Cp15//XXq7eslgKb+Fi1exM9lZmbaCDclIcpQQhATE4OVsrOzuamg+cyePZuzG64Hrlu3jp9ZuWolCdy+fZueeOIJpkdHR1sLHqgM0Yh0bTRz1m7fvp2KiopYkYKCApo8ebLZIwzlFeXSOXEnsLPe2Ij+p5DbYYdOdOtDQ0rNjFya5sTcsGGDcTDZoXTcNoVBMoxWyzDS2yXmOyeUtGSskmDjx4/nRgPAfBDmMpZtUIbRcsi2GsfSD2QYyd2OcdmyZSSwdu1apuXk5GB16v4bak0yX0imyIUEgwNovFTglhMZGcm0srIy43zAVUxuTLbW4xn17Fci23wly9dngUummrTaixcvMpOtW7fiiBwQpqKYU9efHuxDJE5hC9wvL9TW1RLg+PHjPGTQ8wsLC4WpDC5Y5UR4k5qKMSLT6lqeAiX0nuAaMmSI9sMPP9CZM2foyJEj9O677wpTVIuTjidNp0HibvttoH9E5OMqbWKkSaNSlojldoLF7TEP+nUEmKI62y1kOBINbVaNarcI0PuGGUlHyfYvLHg7/jhFSFYqZh0P8KHSptd5ksOPU3tvqAEUot/hFmOIYJLp87wGe9Dwm95eg5xa/R8G6d8U5EcFhwAAAABJRU5ErkJggg==">
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% extends '@Twig/layout.html.twig' %}
|
{% extends '@WebProfiler/Profiler/base.html.twig' %}
|
||||||
|
|
||||||
{% block title 'Redirection Intercepted' %}
|
{% block title 'Redirection Intercepted' %}
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg>
|
After Width: | Height: | Size: 337 B |
@ -0,0 +1 @@
|
|||||||
|
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1408 960V832q0-26-19-45t-45-19h-320V448q0-26-19-45t-45-19H832q-26 0-45 19t-19 45v320H448q-26 0-45 19t-19 45v128q0 26 19 45t45 19h320v320q0 26 19 45t45 19h128q26 0 45-19t19-45v-320h320q26 0 45-19t19-45zm256-544v960q0 119-84.5 203.5T1376 1664H416q-119 0-203.5-84.5T128 1376V416q0-119 84.5-203.5T416 128h960q119 0 203.5 84.5T1664 416z"/></svg>
|
After Width: | Height: | Size: 442 B |
@ -54,7 +54,7 @@ class WebProfilerExtensionTest extends TestCase
|
|||||||
$this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock();
|
$this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock();
|
||||||
|
|
||||||
$this->container = new ContainerBuilder();
|
$this->container = new ContainerBuilder();
|
||||||
$this->container->register('error_renderer.renderer.html', HtmlErrorRenderer::class);
|
$this->container->register('error_renderer.renderer.html', HtmlErrorRenderer::class)->setPublic(true);
|
||||||
$this->container->register('event_dispatcher', EventDispatcher::class)->setPublic(true);
|
$this->container->register('event_dispatcher', EventDispatcher::class)->setPublic(true);
|
||||||
$this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface'))->setPublic(true);
|
$this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface'))->setPublic(true);
|
||||||
$this->container->register('twig', 'Twig\Environment')->setPublic(true);
|
$this->container->register('twig', 'Twig\Environment')->setPublic(true);
|
||||||
@ -92,10 +92,11 @@ class WebProfilerExtensionTest extends TestCase
|
|||||||
|
|
||||||
$extension = new WebProfilerExtension();
|
$extension = new WebProfilerExtension();
|
||||||
$extension->load([[]], $this->container);
|
$extension->load([[]], $this->container);
|
||||||
|
$this->container->removeDefinition('web_profiler.controller.exception');
|
||||||
|
|
||||||
$this->assertFalse($this->container->has('web_profiler.debug_toolbar'));
|
$this->assertFalse($this->container->has('web_profiler.debug_toolbar'));
|
||||||
|
|
||||||
$this->assertSaneContainer($this->getCompiledContainer());
|
self::assertSaneContainer($this->getCompiledContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,10 +106,11 @@ class WebProfilerExtensionTest extends TestCase
|
|||||||
{
|
{
|
||||||
$extension = new WebProfilerExtension();
|
$extension = new WebProfilerExtension();
|
||||||
$extension->load([['toolbar' => $toolbarEnabled, 'intercept_redirects' => $interceptRedirects]], $this->container);
|
$extension->load([['toolbar' => $toolbarEnabled, 'intercept_redirects' => $interceptRedirects]], $this->container);
|
||||||
|
$this->container->removeDefinition('web_profiler.controller.exception');
|
||||||
|
|
||||||
$this->assertSame($listenerInjected, $this->container->has('web_profiler.debug_toolbar'));
|
$this->assertSame($listenerInjected, $this->container->has('web_profiler.debug_toolbar'));
|
||||||
|
|
||||||
$this->assertSaneContainer($this->getCompiledContainer(), '', ['web_profiler.csp.handler']);
|
self::assertSaneContainer($this->getCompiledContainer(), '', ['web_profiler.csp.handler']);
|
||||||
|
|
||||||
if ($listenerInjected) {
|
if ($listenerInjected) {
|
||||||
$this->assertSame($listenerEnabled, $this->container->get('web_profiler.debug_toolbar')->isEnabled());
|
$this->assertSame($listenerEnabled, $this->container->get('web_profiler.debug_toolbar')->isEnabled());
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.1.3",
|
||||||
"symfony/config": "^4.2|^5.0",
|
"symfony/config": "^4.2|^5.0",
|
||||||
|
"symfony/error-renderer": "^4.4|^5.0",
|
||||||
"symfony/http-kernel": "^4.4",
|
"symfony/http-kernel": "^4.4",
|
||||||
"symfony/routing": "^3.4|^4.0|^5.0",
|
"symfony/routing": "^3.4|^4.0|^5.0",
|
||||||
"symfony/twig-bundle": "^4.2|^5.0",
|
"symfony/twig-bundle": "^4.2|^5.0",
|
||||||
|
Reference in New Issue
Block a user