mirror of
https://github.com/linuxserver/Heimdall.git
synced 2025-12-02 21:19:58 +09:00
Update to laravel 7
This commit is contained in:
5
vendor/symfony/http-kernel/.gitignore
vendored
5
vendor/symfony/http-kernel/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
vendor/
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
Tests/Fixtures/cache/
|
||||
Tests/Fixtures/logs/
|
||||
23
vendor/symfony/http-kernel/Attribute/ArgumentInterface.php
vendored
Normal file
23
vendor/symfony/http-kernel/Attribute/ArgumentInterface.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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\HttpKernel\Attribute;
|
||||
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" interface is deprecated.', ArgumentInterface::class);
|
||||
|
||||
/**
|
||||
* Marker interface for controller argument attributes.
|
||||
*
|
||||
* @deprecated since Symfony 5.3
|
||||
*/
|
||||
interface ArgumentInterface
|
||||
{
|
||||
}
|
||||
@@ -9,11 +9,15 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller;
|
||||
namespace Symfony\Component\HttpKernel\Attribute;
|
||||
|
||||
class NullableController
|
||||
/**
|
||||
* Service tag to autoconfigure controllers.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||
class AsController
|
||||
{
|
||||
public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory)
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
19
vendor/symfony/http-kernel/Bundle/Bundle.php
vendored
19
vendor/symfony/http-kernel/Bundle/Bundle.php
vendored
@@ -18,8 +18,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||
|
||||
/**
|
||||
* An implementation of BundleInterface that adds a few conventions
|
||||
* for DependencyInjection extensions and Console commands.
|
||||
* An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
@@ -59,7 +58,7 @@ abstract class Bundle implements BundleInterface
|
||||
/**
|
||||
* Returns the bundle's container extension.
|
||||
*
|
||||
* @return ExtensionInterface|null The container extension
|
||||
* @return ExtensionInterface|null
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
@@ -70,7 +69,7 @@ abstract class Bundle implements BundleInterface
|
||||
|
||||
if (null !== $extension) {
|
||||
if (!$extension instanceof ExtensionInterface) {
|
||||
throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension)));
|
||||
throw new \LogicException(sprintf('Extension "%s" must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_debug_type($extension)));
|
||||
}
|
||||
|
||||
// check naming convention
|
||||
@@ -87,9 +86,7 @@ abstract class Bundle implements BundleInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->extension) {
|
||||
return $this->extension;
|
||||
}
|
||||
return $this->extension ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,10 +116,8 @@ abstract class Bundle implements BundleInterface
|
||||
|
||||
/**
|
||||
* Returns the bundle name (the class short name).
|
||||
*
|
||||
* @return string The Bundle name
|
||||
*/
|
||||
final public function getName()
|
||||
final public function getName(): string
|
||||
{
|
||||
if (null === $this->name) {
|
||||
$this->parseClassName();
|
||||
@@ -154,9 +149,7 @@ abstract class Bundle implements BundleInterface
|
||||
*/
|
||||
protected function createContainerExtension()
|
||||
{
|
||||
if (class_exists($class = $this->getContainerExtensionClass())) {
|
||||
return new $class();
|
||||
}
|
||||
return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null;
|
||||
}
|
||||
|
||||
private function parseClassName()
|
||||
|
||||
@@ -42,21 +42,21 @@ interface BundleInterface extends ContainerAwareInterface
|
||||
/**
|
||||
* Returns the container extension that should be implicitly loaded.
|
||||
*
|
||||
* @return ExtensionInterface|null The default extension or null if there is none
|
||||
* @return ExtensionInterface|null
|
||||
*/
|
||||
public function getContainerExtension();
|
||||
|
||||
/**
|
||||
* Returns the bundle name (the class short name).
|
||||
*
|
||||
* @return string The Bundle name
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Gets the Bundle namespace.
|
||||
*
|
||||
* @return string The Bundle namespace
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace();
|
||||
|
||||
@@ -65,7 +65,7 @@ interface BundleInterface extends ContainerAwareInterface
|
||||
*
|
||||
* The path should always be returned as a Unix path (with /).
|
||||
*
|
||||
* @return string The Bundle absolute path
|
||||
* @return string
|
||||
*/
|
||||
public function getPath();
|
||||
}
|
||||
|
||||
103
vendor/symfony/http-kernel/CHANGELOG.md
vendored
103
vendor/symfony/http-kernel/CHANGELOG.md
vendored
@@ -1,6 +1,105 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Add the ability to enable the profiler using a request query parameter, body parameter or attribute
|
||||
* Deprecate `AbstractTestSessionListener::getSession` inject a session in the request instead
|
||||
* Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener`
|
||||
* Add support for configuring log level, and status code by exception class
|
||||
* Allow ignoring "kernel.reset" methods that don't exist with "on_invalid" attribute
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Deprecate `ArgumentInterface`
|
||||
* Add `ArgumentMetadata::getAttributes()`
|
||||
* Deprecate `ArgumentMetadata::getAttribute()`, use `getAttributes()` instead
|
||||
* Mark the class `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` as internal
|
||||
* Deprecate returning a `ContainerBuilder` from `KernelInterface::registerContainerConfiguration()`
|
||||
* Deprecate `HttpKernelInterface::MASTER_REQUEST` and add `HttpKernelInterface::MAIN_REQUEST` as replacement
|
||||
* Deprecate `KernelEvent::isMasterRequest()` and add `isMainRequest()` as replacement
|
||||
* Add `#[AsController]` attribute for declaring standalone controllers on PHP 8
|
||||
* Add `FragmentUriGeneratorInterface` and `FragmentUriGenerator` to generate the URI of a fragment
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
* added session usage
|
||||
* made the public `http_cache` service handle requests when available
|
||||
* allowed enabling trusted hosts and proxies using new `kernel.trusted_hosts`,
|
||||
`kernel.trusted_proxies` and `kernel.trusted_headers` parameters
|
||||
* content of request parameter `_password` is now also hidden
|
||||
in the request profiler raw content section
|
||||
* Allowed adding attributes on controller arguments that will be passed to argument resolvers.
|
||||
* kernels implementing the `ExtensionInterface` will now be auto-registered to the container
|
||||
* added parameter `kernel.runtime_environment`, defined as `%env(default:kernel.environment:APP_RUNTIME_ENV)%`
|
||||
* do not set a default `Accept` HTTP header when using `HttpKernelBrowser`
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
||||
* allowed to use a specific logger channel for deprecations
|
||||
* made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+;
|
||||
not returning an array is deprecated
|
||||
* made kernels implementing `WarmableInterface` be part of the cache warmup stage
|
||||
* deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead
|
||||
* allowed using public aliases to reference controllers
|
||||
* added session usage reporting when the `_stateless` attribute of the request is set to `true`
|
||||
* added `AbstractSessionListener::onSessionUsage()` to report when the session is used while a request is stateless
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* removed support for getting the container from a non-booted kernel
|
||||
* removed the first and second constructor argument of `ConfigDataCollector`
|
||||
* removed `ConfigDataCollector::getApplicationName()`
|
||||
* removed `ConfigDataCollector::getApplicationVersion()`
|
||||
* removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only
|
||||
* removed `TranslatorListener` in favor of `LocaleAwareListener`
|
||||
* removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface`
|
||||
* removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead
|
||||
* removed `FilterControllerEvent`, use `ControllerEvent` instead
|
||||
* removed `FilterResponseEvent`, use `ResponseEvent` instead
|
||||
* removed `GetResponseEvent`, use `RequestEvent` instead
|
||||
* removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead
|
||||
* removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead
|
||||
* removed `PostResponseEvent`, use `TerminateEvent` instead
|
||||
* removed `SaveSessionListener` in favor of `AbstractSessionListener`
|
||||
* removed `Client`, use `HttpKernelBrowser` instead
|
||||
* added method `getProjectDir()` to `KernelInterface`
|
||||
* removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead
|
||||
* made `ProfilerStorageInterface` internal
|
||||
* removed the second and third argument of `KernelInterface::locateResource`
|
||||
* removed the second and third argument of `FileLocator::__construct`
|
||||
* removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
|
||||
fallback directories.
|
||||
* removed class `ExceptionListener`, use `ErrorListener` instead
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* The `DebugHandlersListener` class has been marked as `final`
|
||||
* Added new Bundle directory convention consistent with standard skeletons
|
||||
* Deprecated the second and third argument of `KernelInterface::locateResource`
|
||||
* Deprecated the second and third argument of `FileLocator::__construct`
|
||||
* Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as
|
||||
fallback directories. Resources like service definitions are usually loaded relative to the
|
||||
current directory or with a glob pattern. The fallback directories have never been advocated
|
||||
so you likely do not use those in any app based on the SF Standard or Flex edition.
|
||||
* Marked all dispatched event classes as `@final`
|
||||
* Added `ErrorController` to enable the preview and error rendering mechanism
|
||||
* Getting the container from a non-booted kernel is deprecated.
|
||||
* Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`,
|
||||
`ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`,
|
||||
`RequestDataCollector` and `TimeDataCollector` classes as `@final`.
|
||||
* Marked the `RouterDataCollector::collect()` method as `@final`.
|
||||
* The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature
|
||||
will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0.
|
||||
* Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead
|
||||
* Deprecated class `ExceptionListener`, use `ErrorListener` instead
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
@@ -31,8 +130,8 @@ CHANGELOG
|
||||
|
||||
* deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter
|
||||
* deprecated `KernelInterface::getName()` and the `kernel.name` parameter
|
||||
* deprecated the first and second constructor argument of `ConfigDataCollector`
|
||||
* deprecated `ConfigDataCollector::getApplicationName()`
|
||||
* deprecated the first and second constructor argument of `ConfigDataCollector`
|
||||
* deprecated `ConfigDataCollector::getApplicationName()`
|
||||
* deprecated `ConfigDataCollector::getApplicationVersion()`
|
||||
|
||||
4.1.0
|
||||
|
||||
@@ -20,8 +20,6 @@ interface CacheClearerInterface
|
||||
{
|
||||
/**
|
||||
* Clears any caches necessary.
|
||||
*
|
||||
* @param string $cacheDir The cache directory
|
||||
*/
|
||||
public function clear($cacheDir);
|
||||
public function clear(string $cacheDir);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ class ChainCacheClearer implements CacheClearerInterface
|
||||
{
|
||||
private $clearers;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, CacheClearerInterface> $clearers
|
||||
*/
|
||||
public function __construct(iterable $clearers = [])
|
||||
{
|
||||
$this->clearers = $clearers;
|
||||
@@ -30,7 +33,7 @@ class ChainCacheClearer implements CacheClearerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clear($cacheDir)
|
||||
public function clear(string $cacheDir)
|
||||
{
|
||||
foreach ($this->clearers as $clearer) {
|
||||
$clearer->clear($cacheDir);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\CacheClearer;
|
||||
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
@@ -18,29 +20,45 @@ class Psr6CacheClearer implements CacheClearerInterface
|
||||
{
|
||||
private $pools = [];
|
||||
|
||||
/**
|
||||
* @param array<string, CacheItemPoolInterface> $pools
|
||||
*/
|
||||
public function __construct(array $pools = [])
|
||||
{
|
||||
$this->pools = $pools;
|
||||
}
|
||||
|
||||
public function hasPool($name)
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPool(string $name)
|
||||
{
|
||||
return isset($this->pools[$name]);
|
||||
}
|
||||
|
||||
public function getPool($name)
|
||||
/**
|
||||
* @return CacheItemPoolInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException If the cache pool with the given name does not exist
|
||||
*/
|
||||
public function getPool(string $name)
|
||||
{
|
||||
if (!$this->hasPool($name)) {
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name));
|
||||
}
|
||||
|
||||
return $this->pools[$name];
|
||||
}
|
||||
|
||||
public function clearPool($name)
|
||||
/**
|
||||
* @return bool
|
||||
*
|
||||
* @throws \InvalidArgumentException If the cache pool with the given name does not exist
|
||||
*/
|
||||
public function clearPool(string $name)
|
||||
{
|
||||
if (!isset($this->pools[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name));
|
||||
}
|
||||
|
||||
return $this->pools[$name]->clear();
|
||||
@@ -49,7 +67,7 @@ class Psr6CacheClearer implements CacheClearerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clear($cacheDir)
|
||||
public function clear(string $cacheDir)
|
||||
{
|
||||
foreach ($this->pools as $pool) {
|
||||
$pool->clear();
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Symfony\Component\HttpKernel\CacheWarmer;
|
||||
*/
|
||||
abstract class CacheWarmer implements CacheWarmerInterface
|
||||
{
|
||||
protected function writeCacheFile($file, $content)
|
||||
protected function writeCacheFile(string $file, $content)
|
||||
{
|
||||
$tmpFile = @tempnam(\dirname($file), basename($file));
|
||||
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
|
||||
|
||||
@@ -26,6 +26,9 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
private $optionalsEnabled = false;
|
||||
private $onlyOptionalsEnabled = false;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, CacheWarmerInterface> $warmers
|
||||
*/
|
||||
public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null)
|
||||
{
|
||||
$this->warmers = $warmers;
|
||||
@@ -44,27 +47,24 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Warms up the cache.
|
||||
*
|
||||
* @param string $cacheDir The cache directory
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function warmUp($cacheDir)
|
||||
public function warmUp(string $cacheDir): array
|
||||
{
|
||||
if ($this->debug) {
|
||||
if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
|
||||
$collectedLogs = [];
|
||||
$previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL');
|
||||
$previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
|
||||
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
|
||||
$previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
|
||||
if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) {
|
||||
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
|
||||
}
|
||||
|
||||
if (isset($collectedLogs[$message])) {
|
||||
++$collectedLogs[$message]['count'];
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
$backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
// Clean the trace by removing first frames added by the error handler itself.
|
||||
for ($i = 0; isset($backtrace[$i]); ++$i) {
|
||||
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
|
||||
@@ -81,9 +81,12 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
'trace' => $backtrace,
|
||||
'count' => 1,
|
||||
];
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
$preload = [];
|
||||
try {
|
||||
foreach ($this->warmers as $warmer) {
|
||||
if (!$this->optionalsEnabled && $warmer->isOptional()) {
|
||||
@@ -93,28 +96,30 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
$warmer->warmUp($cacheDir);
|
||||
$preload[] = array_values((array) $warmer->warmUp($cacheDir));
|
||||
}
|
||||
} finally {
|
||||
if ($this->debug && true !== $previousHandler) {
|
||||
if ($collectDeprecations) {
|
||||
restore_error_handler();
|
||||
|
||||
if (file_exists($this->deprecationLogsFilepath)) {
|
||||
if (is_file($this->deprecationLogsFilepath)) {
|
||||
$previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath));
|
||||
$collectedLogs = array_merge($previousLogs, $collectedLogs);
|
||||
if (\is_array($previousLogs)) {
|
||||
$collectedLogs = array_merge($previousLogs, $collectedLogs);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs)));
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique(array_merge([], ...$preload)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this warmer is optional or not.
|
||||
*
|
||||
* @return bool always false
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isOptional()
|
||||
public function isOptional(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ interface CacheWarmerInterface extends WarmableInterface
|
||||
* A warmer should return true if the cache can be
|
||||
* generated incrementally and on-demand.
|
||||
*
|
||||
* @return bool true if the warmer is optional, false otherwise
|
||||
* @return bool
|
||||
*/
|
||||
public function isOptional();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ interface WarmableInterface
|
||||
/**
|
||||
* Warms up the cache.
|
||||
*
|
||||
* @param string $cacheDir The cache directory
|
||||
* @return string[] A list of classes or files to preload on PHP 7.4+
|
||||
*/
|
||||
public function warmUp($cacheDir);
|
||||
public function warmUp(string $cacheDir);
|
||||
}
|
||||
|
||||
201
vendor/symfony/http-kernel/Client.php
vendored
201
vendor/symfony/http-kernel/Client.php
vendored
@@ -1,201 +0,0 @@
|
||||
<?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\HttpKernel;
|
||||
|
||||
use Symfony\Component\BrowserKit\AbstractBrowser;
|
||||
use Symfony\Component\BrowserKit\CookieJar;
|
||||
use Symfony\Component\BrowserKit\History;
|
||||
use Symfony\Component\BrowserKit\Request as DomRequest;
|
||||
use Symfony\Component\BrowserKit\Response as DomResponse;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Client simulates a browser and makes requests to an HttpKernel instance.
|
||||
*
|
||||
* @deprecated since Symfony 4.3, use HttpKernelBrowser instead.
|
||||
*/
|
||||
class Client extends AbstractBrowser
|
||||
{
|
||||
protected $kernel;
|
||||
private $catchExceptions = true;
|
||||
|
||||
/**
|
||||
* @param HttpKernelInterface $kernel An HttpKernel instance
|
||||
* @param array $server The server parameters (equivalent of $_SERVER)
|
||||
* @param History $history A History instance to store the browser history
|
||||
* @param CookieJar $cookieJar A CookieJar instance to store the cookies
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null)
|
||||
{
|
||||
// These class properties must be set before calling the parent constructor, as it may depend on it.
|
||||
$this->kernel = $kernel;
|
||||
$this->followRedirects = false;
|
||||
|
||||
parent::__construct($server, $history, $cookieJar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to catch exceptions when the kernel is handling a request.
|
||||
*
|
||||
* @param bool $catchExceptions Whether to catch exceptions
|
||||
*/
|
||||
public function catchExceptions($catchExceptions)
|
||||
{
|
||||
$this->catchExceptions = $catchExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a request.
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*/
|
||||
protected function doRequest($request)
|
||||
{
|
||||
$response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions);
|
||||
|
||||
if ($this->kernel instanceof TerminableInterface) {
|
||||
$this->kernel->terminate($request, $response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script to execute when the request must be insulated.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getScript($request)
|
||||
{
|
||||
$kernel = var_export(serialize($this->kernel), true);
|
||||
$request = var_export(serialize($request), true);
|
||||
|
||||
$errorReporting = error_reporting();
|
||||
|
||||
$requires = '';
|
||||
foreach (get_declared_classes() as $class) {
|
||||
if (0 === strpos($class, 'ComposerAutoloaderInit')) {
|
||||
$r = new \ReflectionClass($class);
|
||||
$file = \dirname(\dirname($r->getFileName())).'/autoload.php';
|
||||
if (file_exists($file)) {
|
||||
$requires .= 'require_once '.var_export($file, true).";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$requires) {
|
||||
throw new \RuntimeException('Composer autoloader not found.');
|
||||
}
|
||||
|
||||
$code = <<<EOF
|
||||
<?php
|
||||
|
||||
error_reporting($errorReporting);
|
||||
|
||||
$requires
|
||||
|
||||
\$kernel = unserialize($kernel);
|
||||
\$request = unserialize($request);
|
||||
EOF;
|
||||
|
||||
return $code.$this->getHandleScript();
|
||||
}
|
||||
|
||||
protected function getHandleScript()
|
||||
{
|
||||
return <<<'EOF'
|
||||
$response = $kernel->handle($request);
|
||||
|
||||
if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) {
|
||||
$kernel->terminate($request, $response);
|
||||
}
|
||||
|
||||
echo serialize($response);
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the BrowserKit request to a HttpKernel request.
|
||||
*
|
||||
* @return Request A Request instance
|
||||
*/
|
||||
protected function filterRequest(DomRequest $request)
|
||||
{
|
||||
$httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());
|
||||
|
||||
foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) {
|
||||
$httpRequest->files->set($key, $value);
|
||||
}
|
||||
|
||||
return $httpRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an array of files.
|
||||
*
|
||||
* This method created test instances of UploadedFile so that the move()
|
||||
* method can be called on those instances.
|
||||
*
|
||||
* If the size of a file is greater than the allowed size (from php.ini) then
|
||||
* an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
|
||||
*
|
||||
* @see UploadedFile
|
||||
*
|
||||
* @return array An array with all uploaded files marked as already moved
|
||||
*/
|
||||
protected function filterFiles(array $files)
|
||||
{
|
||||
$filtered = [];
|
||||
foreach ($files as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
$filtered[$key] = $this->filterFiles($value);
|
||||
} elseif ($value instanceof UploadedFile) {
|
||||
if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
|
||||
$filtered[$key] = new UploadedFile(
|
||||
'',
|
||||
$value->getClientOriginalName(),
|
||||
$value->getClientMimeType(),
|
||||
UPLOAD_ERR_INI_SIZE,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
$filtered[$key] = new UploadedFile(
|
||||
$value->getPathname(),
|
||||
$value->getClientOriginalName(),
|
||||
$value->getClientMimeType(),
|
||||
$value->getError(),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the HttpKernel response to a BrowserKit response.
|
||||
*
|
||||
* @return DomResponse A DomResponse instance
|
||||
*/
|
||||
protected function filterResponse($response)
|
||||
{
|
||||
// this is needed to support StreamedResponse
|
||||
ob_start();
|
||||
$response->sendContent();
|
||||
$content = ob_get_clean();
|
||||
|
||||
return new DomResponse($content, $response->getStatusCode(), $response->headers->all());
|
||||
}
|
||||
}
|
||||
@@ -22,31 +22,23 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
class FileLocator extends BaseFileLocator
|
||||
{
|
||||
private $kernel;
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* @param KernelInterface $kernel A KernelInterface instance
|
||||
* @param string|null $path The path the global resource directory
|
||||
* @param array $paths An array of paths where to look for resources
|
||||
*/
|
||||
public function __construct(KernelInterface $kernel, string $path = null, array $paths = [])
|
||||
public function __construct(KernelInterface $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
if (null !== $path) {
|
||||
$this->path = $path;
|
||||
$paths[] = $path;
|
||||
}
|
||||
|
||||
parent::__construct($paths);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function locate($file, $currentPath = null, $first = true)
|
||||
public function locate(string $file, string $currentPath = null, bool $first = true)
|
||||
{
|
||||
if (isset($file[0]) && '@' === $file[0]) {
|
||||
return $this->kernel->locateResource($file, $this->path, $first);
|
||||
$resource = $this->kernel->locateResource($file);
|
||||
|
||||
return $first ? $resource : [$resource];
|
||||
}
|
||||
|
||||
return parent::locate($file, $currentPath, $first);
|
||||
|
||||
@@ -28,22 +28,21 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInter
|
||||
final class ArgumentResolver implements ArgumentResolverInterface
|
||||
{
|
||||
private $argumentMetadataFactory;
|
||||
|
||||
/**
|
||||
* @var iterable|ArgumentValueResolverInterface[]
|
||||
*/
|
||||
private $argumentValueResolvers;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, ArgumentValueResolverInterface> $argumentValueResolvers
|
||||
*/
|
||||
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [])
|
||||
{
|
||||
$this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
|
||||
$this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory();
|
||||
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
public function getArguments(Request $request, callable $controller): array
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
@@ -55,12 +54,14 @@ final class ArgumentResolver implements ArgumentResolverInterface
|
||||
|
||||
$resolved = $resolver->resolve($request, $metadata);
|
||||
|
||||
if (!$resolved instanceof \Generator) {
|
||||
throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver)));
|
||||
$atLeastOne = false;
|
||||
foreach ($resolved as $append) {
|
||||
$atLeastOne = true;
|
||||
$arguments[] = $append;
|
||||
}
|
||||
|
||||
foreach ($resolved as $append) {
|
||||
$arguments[] = $append;
|
||||
if (!$atLeastOne) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', get_debug_type($resolver)));
|
||||
}
|
||||
|
||||
// continue to the next controller argument
|
||||
@@ -81,6 +82,9 @@ final class ArgumentResolver implements ArgumentResolverInterface
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<int, ArgumentValueResolverInterface>
|
||||
*/
|
||||
public static function getDefaultArgumentValueResolvers(): iterable
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -25,7 +25,7 @@ final class DefaultValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic());
|
||||
}
|
||||
@@ -33,7 +33,7 @@ final class DefaultValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
$controller = $request->attributes->get('_controller');
|
||||
|
||||
@@ -58,7 +58,7 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
if (\is_array($controller = $request->attributes->get('_controller'))) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
|
||||
@@ -25,7 +25,7 @@ final class RequestAttributeValueResolver implements ArgumentValueResolverInterf
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
return !$argument->isVariadic() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
@@ -33,7 +33,7 @@ final class RequestAttributeValueResolver implements ArgumentValueResolverInterf
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
yield $request->attributes->get($argument->getName());
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ final class RequestValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ final class RequestValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
yield $request;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
$controller = $request->attributes->get('_controller');
|
||||
|
||||
@@ -58,7 +58,7 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
if (\is_array($controller = $request->attributes->get('_controller'))) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
|
||||
@@ -26,7 +26,7 @@ final class SessionValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
if (!$request->hasSession()) {
|
||||
return false;
|
||||
@@ -43,7 +43,7 @@ final class SessionValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
yield $request->getSession();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ final class VariadicValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
return $argument->isVariadic() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
@@ -33,16 +33,14 @@ final class VariadicValueResolver implements ArgumentValueResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
$values = $request->attributes->get($argument->getName());
|
||||
|
||||
if (!\is_array($values)) {
|
||||
throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), \gettype($values)));
|
||||
throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), get_debug_type($values)));
|
||||
}
|
||||
|
||||
foreach ($values as $value) {
|
||||
yield $value;
|
||||
}
|
||||
yield from $values;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,9 @@ interface ArgumentResolverInterface
|
||||
/**
|
||||
* Returns the arguments to pass to the controller.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param callable $controller
|
||||
*
|
||||
* @return array An array of arguments to pass to the controller
|
||||
* @return array
|
||||
*
|
||||
* @throws \RuntimeException When no value could be provided for a required argument
|
||||
*/
|
||||
public function getArguments(Request $request, $controller);
|
||||
public function getArguments(Request $request, callable $controller);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,6 @@ interface ArgumentValueResolverInterface
|
||||
/**
|
||||
* Whether this resolver can resolve the value for the given ArgumentMetadata.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ArgumentMetadata $argument
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument);
|
||||
@@ -34,10 +31,7 @@ interface ArgumentValueResolverInterface
|
||||
/**
|
||||
* Returns the possible value(s).
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ArgumentMetadata $argument
|
||||
*
|
||||
* @return \Generator
|
||||
* @return iterable
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
|
||||
/**
|
||||
* A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation.
|
||||
* A controller resolver searching for a controller in a psr-11 container when using the "service::method" notation.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
@@ -32,11 +32,11 @@ class ContainerControllerResolver extends ControllerResolver
|
||||
parent::__construct($logger);
|
||||
}
|
||||
|
||||
protected function createController($controller)
|
||||
protected function createController(string $controller)
|
||||
{
|
||||
if (1 === substr_count($controller, ':')) {
|
||||
$controller = str_replace(':', '::', $controller);
|
||||
// TODO deprecate this in 5.1
|
||||
trigger_deprecation('symfony/http-kernel', '5.1', 'Referencing controllers with a single colon is deprecated. Use "%s" instead.', $controller);
|
||||
}
|
||||
|
||||
return parent::createController($controller);
|
||||
@@ -45,8 +45,10 @@ class ContainerControllerResolver extends ControllerResolver
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function instantiateController($class)
|
||||
protected function instantiateController(string $class)
|
||||
{
|
||||
$class = ltrim($class, '\\');
|
||||
|
||||
if ($this->container->has($class)) {
|
||||
return $this->container->get($class);
|
||||
}
|
||||
@@ -59,10 +61,10 @@ class ContainerControllerResolver extends ControllerResolver
|
||||
$this->throwExceptionIfControllerWasRemoved($class, $e);
|
||||
|
||||
if ($e instanceof \ArgumentCountError) {
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', $class), 0, $e);
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e);
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e);
|
||||
}
|
||||
|
||||
private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous)
|
||||
|
||||
@@ -47,7 +47,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) {
|
||||
try {
|
||||
$controller[0] = $this->instantiateController($controller[0]);
|
||||
} catch (\Error | \LogicException $e) {
|
||||
} catch (\Error|\LogicException $e) {
|
||||
try {
|
||||
// We cannot just check is_callable but have to use reflection because a non-static method
|
||||
// can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we
|
||||
@@ -64,7 +64,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
}
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller)));
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
@@ -72,7 +72,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
|
||||
if (\is_object($controller)) {
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller)));
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
@@ -82,10 +82,14 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
return $controller;
|
||||
}
|
||||
|
||||
$callable = $this->createController($controller);
|
||||
try {
|
||||
$callable = $this->createController($controller);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if (!\is_callable($callable)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable)));
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($callable));
|
||||
}
|
||||
|
||||
return $callable;
|
||||
@@ -94,21 +98,27 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
/**
|
||||
* Returns a callable for the given controller.
|
||||
*
|
||||
* @param string $controller A Controller string
|
||||
* @return callable
|
||||
*
|
||||
* @return callable A PHP callable
|
||||
* @throws \InvalidArgumentException When the controller cannot be created
|
||||
*/
|
||||
protected function createController($controller)
|
||||
protected function createController(string $controller)
|
||||
{
|
||||
if (false === strpos($controller, '::')) {
|
||||
return $this->instantiateController($controller);
|
||||
if (!str_contains($controller, '::')) {
|
||||
$controller = $this->instantiateController($controller);
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException($this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
list($class, $method) = explode('::', $controller, 2);
|
||||
[$class, $method] = explode('::', $controller, 2);
|
||||
|
||||
try {
|
||||
return [$this->instantiateController($class), $method];
|
||||
} catch (\Error | \LogicException $e) {
|
||||
$controller = [$this->instantiateController($class), $method];
|
||||
} catch (\Error|\LogicException $e) {
|
||||
try {
|
||||
if ((new \ReflectionMethod($class, $method))->isStatic()) {
|
||||
return $class.'::'.$method;
|
||||
@@ -119,24 +129,28 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException($this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instantiated controller.
|
||||
*
|
||||
* @param string $class A class name
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function instantiateController($class)
|
||||
protected function instantiateController(string $class)
|
||||
{
|
||||
return new $class();
|
||||
}
|
||||
|
||||
private function getControllerError($callable)
|
||||
private function getControllerError($callable): string
|
||||
{
|
||||
if (\is_string($callable)) {
|
||||
if (false !== strpos($callable, '::')) {
|
||||
if (str_contains($callable, '::')) {
|
||||
$callable = explode('::', $callable, 2);
|
||||
} else {
|
||||
return sprintf('Function "%s" does not exist.', $callable);
|
||||
@@ -147,24 +161,24 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
$availableMethods = $this->getClassMethodsWithoutMagicMethods($callable);
|
||||
$alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : '';
|
||||
|
||||
return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', \get_class($callable), $alternativeMsg);
|
||||
return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', get_debug_type($callable), $alternativeMsg);
|
||||
}
|
||||
|
||||
if (!\is_array($callable)) {
|
||||
return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', \gettype($callable));
|
||||
return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', get_debug_type($callable));
|
||||
}
|
||||
|
||||
if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) {
|
||||
return 'Invalid array callable, expected [controller, method].';
|
||||
}
|
||||
|
||||
list($controller, $method) = $callable;
|
||||
[$controller, $method] = $callable;
|
||||
|
||||
if (\is_string($controller) && !class_exists($controller)) {
|
||||
return sprintf('Class "%s" does not exist.', $controller);
|
||||
}
|
||||
|
||||
$className = \is_object($controller) ? \get_class($controller) : $controller;
|
||||
$className = \is_object($controller) ? get_debug_type($controller) : $controller;
|
||||
|
||||
if (method_exists($controller, $method)) {
|
||||
return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className);
|
||||
@@ -177,7 +191,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($method, $item);
|
||||
|
||||
if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) {
|
||||
if ($lev <= \strlen($method) / 3 || str_contains($item, $method)) {
|
||||
$alternatives[] = $item;
|
||||
}
|
||||
}
|
||||
@@ -195,7 +209,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
return $message;
|
||||
}
|
||||
|
||||
private function getClassMethodsWithoutMagicMethods($classOrObject)
|
||||
private function getClassMethodsWithoutMagicMethods($classOrObject): array
|
||||
{
|
||||
$methods = get_class_methods($classOrObject);
|
||||
|
||||
|
||||
62
vendor/symfony/http-kernel/Controller/ErrorController.php
vendored
Normal file
62
vendor/symfony/http-kernel/Controller/ErrorController.php
vendored
Normal 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\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Renders error or exception pages from a given FlattenException.
|
||||
*
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
* @author Matthias Pigulla <mp@webfactory.de>
|
||||
*/
|
||||
class ErrorController
|
||||
{
|
||||
private $kernel;
|
||||
private $controller;
|
||||
private $errorRenderer;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->controller = $controller;
|
||||
$this->errorRenderer = $errorRenderer;
|
||||
}
|
||||
|
||||
public function __invoke(\Throwable $exception): Response
|
||||
{
|
||||
$exception = $this->errorRenderer->render($exception);
|
||||
|
||||
return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders());
|
||||
}
|
||||
|
||||
public function preview(Request $request, int $code): Response
|
||||
{
|
||||
/*
|
||||
* This Request mimics the parameters set by
|
||||
* \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with
|
||||
* the additional "showException" flag.
|
||||
*/
|
||||
$subRequest = $request->duplicate(null, null, [
|
||||
'_controller' => $this->controller,
|
||||
'exception' => new HttpException($code, 'This is a sample exception.'),
|
||||
'logger' => null,
|
||||
'showException' => false,
|
||||
]);
|
||||
|
||||
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class TraceableArgumentResolver implements ArgumentResolverInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
public function getArguments(Request $request, callable $controller)
|
||||
{
|
||||
$e = $this->stopwatch->start('controller.get_arguments');
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\ControllerMetadata;
|
||||
|
||||
use Symfony\Component\HttpKernel\Attribute\ArgumentInterface;
|
||||
|
||||
/**
|
||||
* Responsible for storing metadata of an argument.
|
||||
*
|
||||
@@ -18,14 +20,20 @@ namespace Symfony\Component\HttpKernel\ControllerMetadata;
|
||||
*/
|
||||
class ArgumentMetadata
|
||||
{
|
||||
public const IS_INSTANCEOF = 2;
|
||||
|
||||
private $name;
|
||||
private $type;
|
||||
private $isVariadic;
|
||||
private $hasDefaultValue;
|
||||
private $defaultValue;
|
||||
private $isNullable;
|
||||
private $attributes;
|
||||
|
||||
public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false)
|
||||
/**
|
||||
* @param object[] $attributes
|
||||
*/
|
||||
public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false, $attributes = [])
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
@@ -33,6 +41,13 @@ class ArgumentMetadata
|
||||
$this->hasDefaultValue = $hasDefaultValue;
|
||||
$this->defaultValue = $defaultValue;
|
||||
$this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
|
||||
|
||||
if (null === $attributes || $attributes instanceof ArgumentInterface) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" constructor expects an array of PHP attributes as last argument, %s given.', __CLASS__, get_debug_type($attributes));
|
||||
$attributes = $attributes ? [$attributes] : [];
|
||||
}
|
||||
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +65,7 @@ class ArgumentMetadata
|
||||
*
|
||||
* The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
@@ -99,9 +114,50 @@ class ArgumentMetadata
|
||||
public function getDefaultValue()
|
||||
{
|
||||
if (!$this->hasDefaultValue) {
|
||||
throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.', $this->name, __CLASS__));
|
||||
throw new \LogicException(sprintf('Argument $%s does not have a default value. Use "%s::hasDefaultValue()" to avoid this exception.', $this->name, __CLASS__));
|
||||
}
|
||||
|
||||
return $this->defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute (if any) that was set on the argument.
|
||||
*/
|
||||
public function getAttribute(): ?ArgumentInterface
|
||||
{
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Method "%s()" is deprecated, use "getAttributes()" instead.', __METHOD__);
|
||||
|
||||
if (!$this->attributes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->attributes[0] instanceof ArgumentInterface ? $this->attributes[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object[]
|
||||
*/
|
||||
public function getAttributes(string $name = null, int $flags = 0): array
|
||||
{
|
||||
if (!$name) {
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
$attributes = [];
|
||||
if ($flags & self::IS_INSTANCEOF) {
|
||||
foreach ($this->attributes as $attribute) {
|
||||
if ($attribute instanceof $name) {
|
||||
$attributes[] = $attribute;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($this->attributes as $attribute) {
|
||||
if (\get_class($attribute) === $name) {
|
||||
$attributes[] = $attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,20 +21,34 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createArgumentMetadata($controller)
|
||||
public function createArgumentMetadata($controller): array
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
if (\is_array($controller)) {
|
||||
$reflection = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
$class = $reflection->class;
|
||||
} elseif (\is_object($controller) && !$controller instanceof \Closure) {
|
||||
$reflection = (new \ReflectionObject($controller))->getMethod('__invoke');
|
||||
$reflection = new \ReflectionMethod($controller, '__invoke');
|
||||
$class = $reflection->class;
|
||||
} else {
|
||||
$reflection = new \ReflectionFunction($controller);
|
||||
if ($class = str_contains($reflection->name, '{closure}') ? null : $reflection->getClosureScopeClass()) {
|
||||
$class = $class->name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($reflection->getParameters() as $param) {
|
||||
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull());
|
||||
$attributes = [];
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
foreach ($param->getAttributes() as $reflectionAttribute) {
|
||||
if (class_exists($reflectionAttribute->getName())) {
|
||||
$attributes[] = $reflectionAttribute->newInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $class), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
@@ -42,30 +56,23 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
|
||||
|
||||
/**
|
||||
* Returns an associated type to the given parameter if available.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
|
||||
private function getType(\ReflectionParameter $parameter, ?string $class): ?string
|
||||
{
|
||||
if (!$type = $parameter->getType()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
$name = $type->getName();
|
||||
$lcName = strtolower($name);
|
||||
$name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
|
||||
|
||||
if ('self' !== $lcName && 'parent' !== $lcName) {
|
||||
return $name;
|
||||
}
|
||||
if (!$function instanceof \ReflectionMethod) {
|
||||
return;
|
||||
}
|
||||
if ('self' === $lcName) {
|
||||
return $function->getDeclaringClass()->name;
|
||||
}
|
||||
if ($parent = $function->getDeclaringClass()->getParentClass()) {
|
||||
return $parent->name;
|
||||
if (null !== $class) {
|
||||
switch (strtolower($name)) {
|
||||
case 'self':
|
||||
return $class;
|
||||
case 'parent':
|
||||
return get_parent_class($class) ?: null;
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Symfony\Component\HttpKernel\ControllerMetadata;
|
||||
interface ArgumentMetadataFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $controller The controller to resolve the arguments for
|
||||
* @param string|object|array $controller The controller to resolve the arguments for
|
||||
*
|
||||
* @return ArgumentMetadata[]
|
||||
*/
|
||||
|
||||
@@ -15,13 +15,13 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* AjaxDataCollector.
|
||||
*
|
||||
* @author Bart van den Burg <bart@burgov.nl>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class AjaxDataCollector extends DataCollector
|
||||
{
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
// all collecting is done client side
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class AjaxDataCollector extends DataCollector
|
||||
// all collecting is done client side
|
||||
}
|
||||
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'ajax';
|
||||
}
|
||||
|
||||
@@ -15,10 +15,12 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\VarDumper\Caster\LinkStub;
|
||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
@@ -26,23 +28,6 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
* @var KernelInterface
|
||||
*/
|
||||
private $kernel;
|
||||
private $name;
|
||||
private $version;
|
||||
private $hasVarDumper;
|
||||
|
||||
public function __construct(string $name = null, string $version = null)
|
||||
{
|
||||
if (1 <= \func_num_args()) {
|
||||
@trigger_error(sprintf('The "$name" argument in method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
if (2 <= \func_num_args()) {
|
||||
@trigger_error(sprintf('The "$version" argument in method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->hasVarDumper = class_exists(LinkStub::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Kernel associated with this Request.
|
||||
@@ -55,38 +40,36 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
$eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE);
|
||||
$eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE);
|
||||
|
||||
$this->data = [
|
||||
'app_name' => $this->name,
|
||||
'app_version' => $this->version,
|
||||
'token' => $response->headers->get('X-Debug-Token'),
|
||||
'symfony_version' => Kernel::VERSION,
|
||||
'symfony_state' => 'unknown',
|
||||
'symfony_minor_version' => sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION),
|
||||
'symfony_lts' => 4 === Kernel::MINOR_VERSION,
|
||||
'symfony_state' => $this->determineSymfonyState(),
|
||||
'symfony_eom' => $eom->format('F Y'),
|
||||
'symfony_eol' => $eol->format('F Y'),
|
||||
'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a',
|
||||
'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a',
|
||||
'php_version' => PHP_VERSION,
|
||||
'php_architecture' => PHP_INT_SIZE * 8,
|
||||
'php_intl_locale' => class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a',
|
||||
'php_version' => \PHP_VERSION,
|
||||
'php_architecture' => \PHP_INT_SIZE * 8,
|
||||
'php_intl_locale' => class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a',
|
||||
'php_timezone' => date_default_timezone_get(),
|
||||
'xdebug_enabled' => \extension_loaded('xdebug'),
|
||||
'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN),
|
||||
'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN),
|
||||
'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN),
|
||||
'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN),
|
||||
'bundles' => [],
|
||||
'sapi_name' => \PHP_SAPI,
|
||||
];
|
||||
|
||||
if (isset($this->kernel)) {
|
||||
foreach ($this->kernel->getBundles() as $name => $bundle) {
|
||||
$this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath();
|
||||
$this->data['bundles'][$name] = new ClassStub(\get_class($bundle));
|
||||
}
|
||||
|
||||
$this->data['symfony_state'] = $this->determineSymfonyState();
|
||||
$this->data['symfony_minor_version'] = sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION);
|
||||
$eom = \DateTime::createFromFormat('m/Y', Kernel::END_OF_MAINTENANCE);
|
||||
$eol = \DateTime::createFromFormat('m/Y', Kernel::END_OF_LIFE);
|
||||
$this->data['symfony_eom'] = $eom->format('F Y');
|
||||
$this->data['symfony_eol'] = $eol->format('F Y');
|
||||
}
|
||||
|
||||
if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) {
|
||||
@@ -108,42 +91,18 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
public function getApplicationName()
|
||||
{
|
||||
@trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->data['app_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
public function getApplicationVersion()
|
||||
{
|
||||
@trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->data['app_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the token.
|
||||
*
|
||||
* @return string The token
|
||||
*/
|
||||
public function getToken()
|
||||
public function getToken(): ?string
|
||||
{
|
||||
return $this->data['token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Symfony version.
|
||||
*
|
||||
* @return string The Symfony version
|
||||
*/
|
||||
public function getSymfonyVersion()
|
||||
public function getSymfonyVersion(): string
|
||||
{
|
||||
return $this->data['symfony_version'];
|
||||
}
|
||||
@@ -153,7 +112,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
*
|
||||
* @return string One of: unknown, dev, stable, eom, eol
|
||||
*/
|
||||
public function getSymfonyState()
|
||||
public function getSymfonyState(): string
|
||||
{
|
||||
return $this->data['symfony_state'];
|
||||
}
|
||||
@@ -161,100 +120,76 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* Returns the minor Symfony version used (without patch numbers of extra
|
||||
* suffix like "RC", "beta", etc.).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymfonyMinorVersion()
|
||||
public function getSymfonyMinorVersion(): string
|
||||
{
|
||||
return $this->data['symfony_minor_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human redable date when this Symfony version ends its
|
||||
* maintenance period.
|
||||
*
|
||||
* @return string
|
||||
* Returns if the current Symfony version is a Long-Term Support one.
|
||||
*/
|
||||
public function getSymfonyEom()
|
||||
public function isSymfonyLts(): bool
|
||||
{
|
||||
return $this->data['symfony_lts'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human readable date when this Symfony version ends its
|
||||
* maintenance period.
|
||||
*/
|
||||
public function getSymfonyEom(): string
|
||||
{
|
||||
return $this->data['symfony_eom'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human redable date when this Symfony version reaches its
|
||||
* Returns the human readable date when this Symfony version reaches its
|
||||
* "end of life" and won't receive bugs or security fixes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymfonyEol()
|
||||
public function getSymfonyEol(): string
|
||||
{
|
||||
return $this->data['symfony_eol'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP version.
|
||||
*
|
||||
* @return string The PHP version
|
||||
*/
|
||||
public function getPhpVersion()
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return $this->data['php_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP version extra part.
|
||||
*
|
||||
* @return string|null The extra part
|
||||
*/
|
||||
public function getPhpVersionExtra()
|
||||
public function getPhpVersionExtra(): ?string
|
||||
{
|
||||
return isset($this->data['php_version_extra']) ? $this->data['php_version_extra'] : null;
|
||||
return $this->data['php_version_extra'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The PHP architecture as number of bits (e.g. 32 or 64)
|
||||
*/
|
||||
public function getPhpArchitecture()
|
||||
public function getPhpArchitecture(): int
|
||||
{
|
||||
return $this->data['php_architecture'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPhpIntlLocale()
|
||||
public function getPhpIntlLocale(): string
|
||||
{
|
||||
return $this->data['php_intl_locale'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPhpTimezone()
|
||||
public function getPhpTimezone(): string
|
||||
{
|
||||
return $this->data['php_timezone'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the application name.
|
||||
*
|
||||
* @return string The application name
|
||||
*
|
||||
* @deprecated since Symfony 4.2
|
||||
*/
|
||||
public function getAppName()
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return 'n/a';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the environment.
|
||||
*
|
||||
* @return string The environment
|
||||
*/
|
||||
public function getEnv()
|
||||
public function getEnv(): string
|
||||
{
|
||||
return $this->data['env'];
|
||||
}
|
||||
@@ -262,7 +197,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* Returns true if the debug is enabled.
|
||||
*
|
||||
* @return bool true if debug is enabled, false otherwise
|
||||
* @return bool|string true if debug is enabled, false otherwise or a string if no kernel was set
|
||||
*/
|
||||
public function isDebug()
|
||||
{
|
||||
@@ -271,30 +206,24 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
|
||||
/**
|
||||
* Returns true if the XDebug is enabled.
|
||||
*
|
||||
* @return bool true if XDebug is enabled, false otherwise
|
||||
*/
|
||||
public function hasXDebug()
|
||||
public function hasXDebug(): bool
|
||||
{
|
||||
return $this->data['xdebug_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if APCu is enabled.
|
||||
*
|
||||
* @return bool true if APCu is enabled, false otherwise
|
||||
*/
|
||||
public function hasApcu()
|
||||
public function hasApcu(): bool
|
||||
{
|
||||
return $this->data['apcu_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Zend OPcache is enabled.
|
||||
*
|
||||
* @return bool true if Zend OPcache is enabled, false otherwise
|
||||
*/
|
||||
public function hasZendOpcache()
|
||||
public function hasZendOpcache(): bool
|
||||
{
|
||||
return $this->data['zend_opcache_enabled'];
|
||||
}
|
||||
@@ -306,10 +235,8 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
|
||||
/**
|
||||
* Gets the PHP SAPI name.
|
||||
*
|
||||
* @return string The environment
|
||||
*/
|
||||
public function getSapiName()
|
||||
public function getSapiName(): string
|
||||
{
|
||||
return $this->data['sapi_name'];
|
||||
}
|
||||
@@ -317,7 +244,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'config';
|
||||
}
|
||||
@@ -327,11 +254,11 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
*
|
||||
* @return string One of: dev, stable, eom, eol
|
||||
*/
|
||||
private function determineSymfonyState()
|
||||
private function determineSymfonyState(): string
|
||||
{
|
||||
$now = new \DateTime();
|
||||
$eom = \DateTime::createFromFormat('m/Y', Kernel::END_OF_MAINTENANCE)->modify('last day of this month');
|
||||
$eol = \DateTime::createFromFormat('m/Y', Kernel::END_OF_LIFE)->modify('last day of this month');
|
||||
$eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE)->modify('last day of this month');
|
||||
$eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE)->modify('last day of this month');
|
||||
|
||||
if ($now > $eol) {
|
||||
$versionState = 'eol';
|
||||
|
||||
@@ -28,6 +28,9 @@ use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
*/
|
||||
abstract class DataCollector implements DataCollectorInterface
|
||||
{
|
||||
/**
|
||||
* @var array|Data
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
@@ -35,29 +38,6 @@ abstract class DataCollector implements DataCollectorInterface
|
||||
*/
|
||||
private $cloner;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, store all the serialized state in the data property instead
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3, store all the serialized state in the data property instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
|
||||
$isCalledFromOverridingMethod = isset($trace[1]['function'], $trace[1]['object']) && 'serialize' === $trace[1]['function'] && $this === $trace[1]['object'];
|
||||
|
||||
return $isCalledFromOverridingMethod ? $this->data : serialize($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, store all the serialized state in the data property instead
|
||||
*/
|
||||
public function unserialize($data)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3, store all the serialized state in the data property instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->data = \is_array($data) ? $data : unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the variable into a serializable Data instance.
|
||||
*
|
||||
@@ -74,9 +54,6 @@ abstract class DataCollector implements DataCollectorInterface
|
||||
return $var;
|
||||
}
|
||||
if (null === $this->cloner) {
|
||||
if (!class_exists(CutStub::class)) {
|
||||
throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.4 or above.', __METHOD__));
|
||||
}
|
||||
$this->cloner = new VarCloner();
|
||||
$this->cloner->setMaxItems(-1);
|
||||
$this->cloner->addCasters($this->getCasters());
|
||||
@@ -102,30 +79,34 @@ abstract class DataCollector implements DataCollectorInterface
|
||||
|
||||
return $a;
|
||||
},
|
||||
];
|
||||
|
||||
if (method_exists(ReflectionCaster::class, 'unsetClosureFileInfo')) {
|
||||
$casters += ReflectionCaster::UNSET_CLOSURE_FILE_INFO;
|
||||
}
|
||||
] + ReflectionCaster::UNSET_CLOSURE_FILE_INFO;
|
||||
|
||||
return $casters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'serialize'))->getDeclaringClass()->name) {
|
||||
@trigger_error(sprintf('Implementing the "%s::serialize()" method is deprecated since Symfony 4.3, store all the serialized state in the "data" property instead.', $c), E_USER_DEPRECATED);
|
||||
$this->data = $this->serialize();
|
||||
}
|
||||
|
||||
return ['data'];
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'unserialize'))->getDeclaringClass()->name) {
|
||||
@trigger_error(sprintf('Implementing the "%s::unserialize()" method is deprecated since Symfony 4.3, store all the serialized state in the "data" property instead.', $c), E_USER_DEPRECATED);
|
||||
$this->unserialize($this->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal to prevent implementing \Serializable
|
||||
*/
|
||||
final protected function serialize()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal to prevent implementing \Serializable
|
||||
*/
|
||||
final protected function unserialize($data)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ interface DataCollectorInterface extends ResetInterface
|
||||
/**
|
||||
* Collects data for the given Request and Response.
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null);
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null);
|
||||
|
||||
/**
|
||||
* Returns the name of the collector.
|
||||
*
|
||||
* @return string The collector name
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
@@ -26,7 +27,7 @@ use Symfony\Component\VarDumper\Server\Connection;
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
{
|
||||
@@ -43,6 +44,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
private $sourceContextProvider;
|
||||
|
||||
/**
|
||||
* @param string|FileLinkFormatter|null $fileLinkFormat
|
||||
* @param DataDumperInterface|Connection|null $dumper
|
||||
*/
|
||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null)
|
||||
@@ -75,7 +77,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->stopwatch->start('dump');
|
||||
}
|
||||
|
||||
list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext();
|
||||
['name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt] = $this->sourceContextProvider->getContext();
|
||||
|
||||
if ($this->dumper instanceof Connection) {
|
||||
if (!$this->dumper->write($data)) {
|
||||
@@ -98,14 +100,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
if (!$this->dataCount) {
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
// Sub-requests and programmatic calls stay in the collected profile.
|
||||
if ($this->dumper || ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) {
|
||||
if ($this->dumper || ($this->requestStack && $this->requestStack->getMainRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,11 +115,11 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
if (!$this->requestStack
|
||||
|| !$response->headers->has('X-Debug-Token')
|
||||
|| $response->isRedirection()
|
||||
|| ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html'))
|
||||
|| ($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') && false !== strpos($response->headers->get('Content-Type'), 'html')) {
|
||||
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 {
|
||||
@@ -148,7 +150,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __sleep()
|
||||
public function __sleep(): array
|
||||
{
|
||||
if (!$this->dataCount) {
|
||||
$this->data = [];
|
||||
@@ -176,24 +178,29 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$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, $fileLinkFormat, $charset);
|
||||
self::__construct($this->stopwatch, \is_string($fileLinkFormat) || $fileLinkFormat instanceof FileLinkFormatter ? $fileLinkFormat : null, \is_string($charset) ? $charset : null);
|
||||
}
|
||||
|
||||
public function getDumpsCount()
|
||||
public function getDumpsCount(): int
|
||||
{
|
||||
return $this->dataCount;
|
||||
}
|
||||
|
||||
public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1)
|
||||
public function getDumps(string $format, int $maxDepthLimit = -1, int $maxItemsPerDepth = -1): array
|
||||
{
|
||||
$data = fopen('php://memory', 'r+b');
|
||||
$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));
|
||||
throw new \InvalidArgumentException(sprintf('Invalid dump format: "%s".', $format));
|
||||
}
|
||||
$dumps = [];
|
||||
|
||||
@@ -212,7 +219,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
return $dumps;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'dump';
|
||||
}
|
||||
@@ -230,13 +237,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
--$i;
|
||||
}
|
||||
|
||||
if (isset($_SERVER['VAR_DUMPER_FORMAT'])) {
|
||||
$html = 'html' === $_SERVER['VAR_DUMPER_FORMAT'];
|
||||
} else {
|
||||
$html = !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html');
|
||||
}
|
||||
|
||||
if ($html) {
|
||||
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html')) {
|
||||
$dumper = new HtmlDumper('php://output', $this->charset);
|
||||
$dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
|
||||
} else {
|
||||
@@ -256,7 +257,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function doDump(DataDumperInterface $dumper, $data, $name, $file, $line)
|
||||
private function doDump(DataDumperInterface $dumper, Data $data, string $name, string $file, int $line)
|
||||
{
|
||||
if ($dumper instanceof CliDumper) {
|
||||
$contextDumper = function ($name, $file, $line, $fmt) {
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Contracts\Service\ResetInterface;
|
||||
|
||||
/**
|
||||
* EventDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class EventDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
@@ -39,9 +39,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
$this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null;
|
||||
$this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
|
||||
$this->data = [
|
||||
'called_listeners' => [],
|
||||
'not_called_listeners' => [],
|
||||
@@ -60,12 +60,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
|
||||
public function lateCollect()
|
||||
{
|
||||
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
|
||||
if ($this->dispatcher instanceof TraceableEventDispatcher) {
|
||||
$this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest));
|
||||
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest));
|
||||
}
|
||||
|
||||
if ($this->dispatcher instanceof TraceableEventDispatcher) {
|
||||
$this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest));
|
||||
}
|
||||
|
||||
@@ -73,8 +70,6 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the called listeners.
|
||||
*
|
||||
* @param array $listeners An array of called listeners
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
@@ -85,11 +80,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the called listeners.
|
||||
*
|
||||
* @return array An array of called listeners
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
*
|
||||
* @return array|Data
|
||||
*/
|
||||
public function getCalledListeners()
|
||||
{
|
||||
@@ -97,10 +90,6 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the not called listeners.
|
||||
*
|
||||
* @param array $listeners
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
*/
|
||||
public function setNotCalledListeners(array $listeners)
|
||||
@@ -109,11 +98,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the not called listeners.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
*
|
||||
* @return array|Data
|
||||
*/
|
||||
public function getNotCalledListeners()
|
||||
{
|
||||
@@ -121,8 +108,6 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orphaned events.
|
||||
*
|
||||
* @param array $events An array of orphaned events
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
@@ -133,11 +118,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the orphaned events.
|
||||
*
|
||||
* @return array An array of orphaned events
|
||||
*
|
||||
* @see TraceableEventDispatcher
|
||||
*
|
||||
* @return array|Data
|
||||
*/
|
||||
public function getOrphanedEvents()
|
||||
{
|
||||
@@ -147,7 +130,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'events';
|
||||
}
|
||||
|
||||
@@ -11,25 +11,25 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\Debug\Exception\FlattenException;
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* ExceptionDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class ExceptionDataCollector extends DataCollector
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
if (null !== $exception) {
|
||||
$this->data = [
|
||||
'exception' => FlattenException::create($exception),
|
||||
'exception' => FlattenException::createFromThrowable($exception),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -42,62 +42,35 @@ class ExceptionDataCollector extends DataCollector
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the exception is not null.
|
||||
*
|
||||
* @return bool true if the exception is not null, false otherwise
|
||||
*/
|
||||
public function hasException()
|
||||
public function hasException(): bool
|
||||
{
|
||||
return isset($this->data['exception']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception.
|
||||
*
|
||||
* @return \Exception The exception
|
||||
* @return \Exception|FlattenException
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->data['exception'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception message.
|
||||
*
|
||||
* @return string The exception message
|
||||
*/
|
||||
public function getMessage()
|
||||
public function getMessage(): string
|
||||
{
|
||||
return $this->data['exception']->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception code.
|
||||
*
|
||||
* @return int The exception code
|
||||
*/
|
||||
public function getCode()
|
||||
public function getCode(): int
|
||||
{
|
||||
return $this->data['exception']->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status code.
|
||||
*
|
||||
* @return int The status code
|
||||
*/
|
||||
public function getStatusCode()
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->data['exception']->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception trace.
|
||||
*
|
||||
* @return array The exception trace
|
||||
*/
|
||||
public function getTrace()
|
||||
public function getTrace(): array
|
||||
{
|
||||
return $this->data['exception']->getTrace();
|
||||
}
|
||||
@@ -105,7 +78,7 @@ class ExceptionDataCollector extends DataCollector
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'exception';
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\Debug\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
|
||||
/**
|
||||
* LogDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
@@ -28,8 +28,9 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
private $containerPathPrefix;
|
||||
private $currentRequest;
|
||||
private $requestStack;
|
||||
private $processedLogs;
|
||||
|
||||
public function __construct($logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null)
|
||||
public function __construct(object $logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null)
|
||||
{
|
||||
if (null !== $logger && $logger instanceof DebugLoggerInterface) {
|
||||
$this->logger = $logger;
|
||||
@@ -42,9 +43,9 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
$this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null;
|
||||
$this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,39 +76,110 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
$this->currentRequest = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logs.
|
||||
*
|
||||
* @return array An array of logs
|
||||
*/
|
||||
public function getLogs()
|
||||
{
|
||||
return isset($this->data['logs']) ? $this->data['logs'] : [];
|
||||
return $this->data['logs'] ?? [];
|
||||
}
|
||||
|
||||
public function getProcessedLogs()
|
||||
{
|
||||
if (null !== $this->processedLogs) {
|
||||
return $this->processedLogs;
|
||||
}
|
||||
|
||||
$rawLogs = $this->getLogs();
|
||||
if ([] === $rawLogs) {
|
||||
return $this->processedLogs = $rawLogs;
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
foreach ($this->getLogs()->getValue() as $rawLog) {
|
||||
$rawLogData = $rawLog->getValue();
|
||||
|
||||
if ($rawLogData['priority']->getValue() > 300) {
|
||||
$logType = 'error';
|
||||
} elseif (isset($rawLogData['scream']) && false === $rawLogData['scream']->getValue()) {
|
||||
$logType = 'deprecation';
|
||||
} elseif (isset($rawLogData['scream']) && true === $rawLogData['scream']->getValue()) {
|
||||
$logType = 'silenced';
|
||||
} else {
|
||||
$logType = 'regular';
|
||||
}
|
||||
|
||||
$logs[] = [
|
||||
'type' => $logType,
|
||||
'errorCount' => $rawLog['errorCount'] ?? 1,
|
||||
'timestamp' => $rawLogData['timestamp_rfc3339']->getValue(),
|
||||
'priority' => $rawLogData['priority']->getValue(),
|
||||
'priorityName' => $rawLogData['priorityName']->getValue(),
|
||||
'channel' => $rawLogData['channel']->getValue(),
|
||||
'message' => $rawLogData['message'],
|
||||
'context' => $rawLogData['context'],
|
||||
];
|
||||
}
|
||||
|
||||
// sort logs from oldest to newest
|
||||
usort($logs, static function ($logA, $logB) {
|
||||
return $logA['timestamp'] <=> $logB['timestamp'];
|
||||
});
|
||||
|
||||
return $this->processedLogs = $logs;
|
||||
}
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
$filters = [
|
||||
'channel' => [],
|
||||
'priority' => [
|
||||
'Debug' => 100,
|
||||
'Info' => 200,
|
||||
'Notice' => 250,
|
||||
'Warning' => 300,
|
||||
'Error' => 400,
|
||||
'Critical' => 500,
|
||||
'Alert' => 550,
|
||||
'Emergency' => 600,
|
||||
],
|
||||
];
|
||||
|
||||
$allChannels = [];
|
||||
foreach ($this->getProcessedLogs() as $log) {
|
||||
if ('' === trim($log['channel'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$allChannels[] = $log['channel'];
|
||||
}
|
||||
$channels = array_unique($allChannels);
|
||||
sort($channels);
|
||||
$filters['channel'] = $channels;
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function getPriorities()
|
||||
{
|
||||
return isset($this->data['priorities']) ? $this->data['priorities'] : [];
|
||||
return $this->data['priorities'] ?? [];
|
||||
}
|
||||
|
||||
public function countErrors()
|
||||
{
|
||||
return isset($this->data['error_count']) ? $this->data['error_count'] : 0;
|
||||
return $this->data['error_count'] ?? 0;
|
||||
}
|
||||
|
||||
public function countDeprecations()
|
||||
{
|
||||
return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0;
|
||||
return $this->data['deprecation_count'] ?? 0;
|
||||
}
|
||||
|
||||
public function countWarnings()
|
||||
{
|
||||
return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0;
|
||||
return $this->data['warning_count'] ?? 0;
|
||||
}
|
||||
|
||||
public function countScreams()
|
||||
{
|
||||
return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0;
|
||||
return $this->data['scream_count'] ?? 0;
|
||||
}
|
||||
|
||||
public function getCompilerLogs()
|
||||
@@ -118,14 +190,14 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'logger';
|
||||
}
|
||||
|
||||
private function getContainerDeprecationLogs()
|
||||
private function getContainerDeprecationLogs(): array
|
||||
{
|
||||
if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) {
|
||||
if (null === $this->containerPathPrefix || !is_file($file = $this->containerPathPrefix.'Deprecations.log')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -138,6 +210,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
foreach (unserialize($logContent) as $log) {
|
||||
$log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])];
|
||||
$log['timestamp'] = $bootTime;
|
||||
$log['timestamp_rfc3339'] = (new \DateTimeImmutable())->setTimestamp($bootTime)->format(\DateTimeInterface::RFC3339_EXTENDED);
|
||||
$log['priority'] = 100;
|
||||
$log['priorityName'] = 'DEBUG';
|
||||
$log['channel'] = null;
|
||||
@@ -149,14 +222,14 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function getContainerCompilerLogs(?string $compilerLogsFilepath = null): array
|
||||
private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array
|
||||
{
|
||||
if (!file_exists($compilerLogsFilepath)) {
|
||||
if (!is_file($compilerLogsFilepath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
foreach (file($compilerLogsFilepath, FILE_IGNORE_NEW_LINES) as $log) {
|
||||
foreach (file($compilerLogsFilepath, \FILE_IGNORE_NEW_LINES) as $log) {
|
||||
$log = explode(': ', $log, 2);
|
||||
if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) {
|
||||
$log = ['Unknown Compiler Pass', implode(': ', $log)];
|
||||
@@ -168,7 +241,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function sanitizeLogs($logs)
|
||||
private function sanitizeLogs(array $logs)
|
||||
{
|
||||
$sanitizedLogs = [];
|
||||
$silencedLogs = [];
|
||||
@@ -180,7 +253,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
continue;
|
||||
}
|
||||
|
||||
$message = $log['message'];
|
||||
$message = '_'.$log['message'];
|
||||
$exception = $log['context']['exception'];
|
||||
|
||||
if ($exception instanceof SilencedErrorContext) {
|
||||
@@ -217,7 +290,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return array_values($sanitizedLogs);
|
||||
}
|
||||
|
||||
private function isSilencedOrDeprecationErrorLog(array $log)
|
||||
private function isSilencedOrDeprecationErrorLog(array $log): bool
|
||||
{
|
||||
if (!isset($log['context']['exception'])) {
|
||||
return false;
|
||||
@@ -229,14 +302,14 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) {
|
||||
if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [\E_DEPRECATED, \E_USER_DEPRECATED], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function computeErrorsCount(array $containerDeprecationLogs)
|
||||
private function computeErrorsCount(array $containerDeprecationLogs): array
|
||||
{
|
||||
$silencedLogs = [];
|
||||
$count = [
|
||||
|
||||
@@ -15,9 +15,9 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* MemoryDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
@@ -29,7 +29,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
$this->updateMemoryUsage();
|
||||
}
|
||||
@@ -53,29 +53,19 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
$this->updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the memory.
|
||||
*
|
||||
* @return int The memory
|
||||
*/
|
||||
public function getMemory()
|
||||
public function getMemory(): int
|
||||
{
|
||||
return $this->data['memory'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP memory limit.
|
||||
*
|
||||
* @return int The memory limit
|
||||
* @return int|float
|
||||
*/
|
||||
public function getMemoryLimit()
|
||||
{
|
||||
return $this->data['memory_limit'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the memory usage data.
|
||||
*/
|
||||
public function updateMemoryUsage()
|
||||
{
|
||||
$this->data['memory'] = memory_get_peak_usage(true);
|
||||
@@ -84,12 +74,15 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'memory';
|
||||
}
|
||||
|
||||
private function convertToBytes($memoryLimit)
|
||||
/**
|
||||
* @return int|float
|
||||
*/
|
||||
private function convertToBytes(string $memoryLimit)
|
||||
{
|
||||
if ('-1' === $memoryLimit) {
|
||||
return -1;
|
||||
@@ -97,9 +90,9 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
|
||||
$memoryLimit = strtolower($memoryLimit);
|
||||
$max = strtolower(ltrim($memoryLimit, '+'));
|
||||
if (0 === strpos($max, '0x')) {
|
||||
if (str_starts_with($max, '0x')) {
|
||||
$max = \intval($max, 16);
|
||||
} elseif (0 === strpos($max, '0')) {
|
||||
} elseif (str_starts_with($max, '0')) {
|
||||
$max = \intval($max, 8);
|
||||
} else {
|
||||
$max = (int) $max;
|
||||
|
||||
@@ -15,27 +15,39 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
|
||||
{
|
||||
protected $controllers;
|
||||
/**
|
||||
* @var \SplObjectStorage<Request, callable>
|
||||
*/
|
||||
private $controllers;
|
||||
private $sessionUsages = [];
|
||||
private $requestStack;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(RequestStack $requestStack = null)
|
||||
{
|
||||
$this->controllers = new \SplObjectStorage();
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
// attributes are serialized and as they can be anything, they need to be converted to strings.
|
||||
$attributes = [];
|
||||
@@ -49,23 +61,16 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
}
|
||||
}
|
||||
|
||||
$content = null;
|
||||
try {
|
||||
$content = $request->getContent();
|
||||
} catch (\LogicException $e) {
|
||||
// the user already got the request content as a resource
|
||||
$content = false;
|
||||
}
|
||||
$content = $request->getContent();
|
||||
|
||||
$sessionMetadata = [];
|
||||
$sessionAttributes = [];
|
||||
$session = null;
|
||||
$flashes = [];
|
||||
if ($request->hasSession()) {
|
||||
$session = $request->getSession();
|
||||
if ($session->isStarted()) {
|
||||
$sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated());
|
||||
$sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed());
|
||||
$sessionMetadata['Created'] = date(\DATE_RFC822, $session->getMetadataBag()->getCreated());
|
||||
$sessionMetadata['Last used'] = date(\DATE_RFC822, $session->getMetadataBag()->getLastUsed());
|
||||
$sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime();
|
||||
$sessionAttributes = $session->all();
|
||||
$flashes = $session->getFlashBag()->peekAll();
|
||||
@@ -80,18 +85,17 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
}
|
||||
|
||||
$dotenvVars = [];
|
||||
foreach (explode(',', getenv('SYMFONY_DOTENV_VARS')) as $name) {
|
||||
if ('' !== $name && false !== $value = getenv($name)) {
|
||||
$dotenvVars[$name] = $value;
|
||||
foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) {
|
||||
if ('' !== $name && isset($_ENV[$name])) {
|
||||
$dotenvVars[$name] = $_ENV[$name];
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = [
|
||||
'method' => $request->getMethod(),
|
||||
'format' => $request->getRequestFormat(),
|
||||
'content' => $content,
|
||||
'content_type' => $response->headers->get('Content-Type', 'text/html'),
|
||||
'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
|
||||
'status_text' => Response::$statusTexts[$statusCode] ?? '',
|
||||
'status_code' => $statusCode,
|
||||
'request_query' => $request->query->all(),
|
||||
'request_request' => $request->request->all(),
|
||||
@@ -105,6 +109,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
'response_cookies' => $responseCookies,
|
||||
'session_metadata' => $sessionMetadata,
|
||||
'session_attributes' => $sessionAttributes,
|
||||
'session_usages' => array_values($this->sessionUsages),
|
||||
'stateless_check' => $this->requestStack && $this->requestStack->getMainRequest()->attributes->get('_stateless', false),
|
||||
'flashes' => $flashes,
|
||||
'path_info' => $request->getPathInfo(),
|
||||
'controller' => 'n/a',
|
||||
@@ -121,9 +127,13 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
}
|
||||
|
||||
if (isset($this->data['request_request']['_password'])) {
|
||||
$encodedPassword = rawurlencode($this->data['request_request']['_password']);
|
||||
$content = str_replace('_password='.$encodedPassword, '_password=******', $content);
|
||||
$this->data['request_request']['_password'] = '******';
|
||||
}
|
||||
|
||||
$this->data['content'] = $content;
|
||||
|
||||
foreach ($this->data as $key => $value) {
|
||||
if (!\is_array($value)) {
|
||||
continue;
|
||||
@@ -153,7 +163,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
'method' => $request->getMethod(),
|
||||
'controller' => $this->parseController($request->attributes->get('_controller')),
|
||||
'status_code' => $statusCode,
|
||||
'status_text' => Response::$statusTexts[(int) $statusCode],
|
||||
'status_text' => Response::$statusTexts[$statusCode],
|
||||
]),
|
||||
0, '/', null, $request->isSecure(), true, false, 'lax'
|
||||
));
|
||||
@@ -175,6 +185,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
{
|
||||
$this->data = [];
|
||||
$this->controllers = new \SplObjectStorage();
|
||||
$this->sessionUsages = [];
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
@@ -207,12 +218,12 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
return new ParameterBag($this->data['request_headers']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestServer($raw = false)
|
||||
public function getRequestServer(bool $raw = false)
|
||||
{
|
||||
return new ParameterBag($this->data['request_server']->getValue($raw));
|
||||
}
|
||||
|
||||
public function getRequestCookies($raw = false)
|
||||
public function getRequestCookies(bool $raw = false)
|
||||
{
|
||||
return new ParameterBag($this->data['request_cookies']->getValue($raw));
|
||||
}
|
||||
@@ -242,6 +253,16 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
return $this->data['session_attributes']->getValue();
|
||||
}
|
||||
|
||||
public function getStatelessCheck()
|
||||
{
|
||||
return $this->data['stateless_check'];
|
||||
}
|
||||
|
||||
public function getSessionUsages()
|
||||
{
|
||||
return $this->data['session_usages'];
|
||||
}
|
||||
|
||||
public function getFlashes()
|
||||
{
|
||||
return $this->data['flashes']->getValue();
|
||||
@@ -261,7 +282,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
{
|
||||
$decoded = json_decode($this->getContent());
|
||||
|
||||
return JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, JSON_PRETTY_PRINT) : null;
|
||||
return \JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, \JSON_PRETTY_PRINT) : null;
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
@@ -298,10 +319,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
* Gets the route name.
|
||||
*
|
||||
* The _route request attributes is automatically set by the Router Matcher.
|
||||
*
|
||||
* @return string The route
|
||||
*/
|
||||
public function getRoute()
|
||||
public function getRoute(): string
|
||||
{
|
||||
return $this->data['route'];
|
||||
}
|
||||
@@ -315,10 +334,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
* Gets the route parameters.
|
||||
*
|
||||
* The _route_params request attributes is automatically set by the RouterListener.
|
||||
*
|
||||
* @return array The parameters
|
||||
*/
|
||||
public function getRouteParams()
|
||||
public function getRouteParams(): array
|
||||
{
|
||||
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : [];
|
||||
}
|
||||
@@ -326,8 +343,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
/**
|
||||
* Gets the parsed controller.
|
||||
*
|
||||
* @return array|string The controller as a string or array of data
|
||||
* with keys 'class', 'method', 'file' and 'line'
|
||||
* @return array|string|Data The controller as a string or array of data
|
||||
* with keys 'class', 'method', 'file' and 'line'
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
@@ -337,33 +354,27 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
/**
|
||||
* Gets the previous request attributes.
|
||||
*
|
||||
* @return array|bool A legacy array of data from the previous redirection response
|
||||
* or false otherwise
|
||||
* @return array|Data|false A legacy array of data from the previous redirection response
|
||||
* or false otherwise
|
||||
*/
|
||||
public function getRedirect()
|
||||
{
|
||||
return isset($this->data['redirect']) ? $this->data['redirect'] : false;
|
||||
return $this->data['redirect'] ?? false;
|
||||
}
|
||||
|
||||
public function getForwardToken()
|
||||
{
|
||||
return isset($this->data['forward_token']) ? $this->data['forward_token'] : null;
|
||||
return $this->data['forward_token'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @final since Symfony 4.3
|
||||
*/
|
||||
public function onKernelController(FilterControllerEvent $event)
|
||||
public function onKernelController(ControllerEvent $event)
|
||||
{
|
||||
$this->controllers[$event->getRequest()] = $event->getController();
|
||||
}
|
||||
|
||||
/**
|
||||
* @final since Symfony 4.3
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -372,7 +383,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::CONTROLLER => 'onKernelController',
|
||||
@@ -383,21 +394,50 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'request';
|
||||
}
|
||||
|
||||
public function collectSessionUsage(): void
|
||||
{
|
||||
$trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
|
||||
$traceEndIndex = \count($trace) - 1;
|
||||
for ($i = $traceEndIndex; $i > 0; --$i) {
|
||||
if (null !== ($class = $trace[$i]['class'] ?? null) && (is_subclass_of($class, SessionInterface::class) || is_subclass_of($class, SessionBagInterface::class))) {
|
||||
$traceEndIndex = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((\count($trace) - 1) === $traceEndIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove part of the backtrace that belongs to session only
|
||||
array_splice($trace, 0, $traceEndIndex);
|
||||
|
||||
// Merge identical backtraces generated by internal call reports
|
||||
$name = sprintf('%s:%s', $trace[1]['class'] ?? $trace[0]['file'], $trace[0]['line']);
|
||||
if (!\array_key_exists($name, $this->sessionUsages)) {
|
||||
$this->sessionUsages[$name] = [
|
||||
'name' => $name,
|
||||
'file' => $trace[0]['file'],
|
||||
'line' => $trace[0]['line'],
|
||||
'trace' => $trace,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a controller.
|
||||
*
|
||||
* @param mixed $controller The controller to parse
|
||||
* @param string|object|array|null $controller The controller to parse
|
||||
*
|
||||
* @return array|string An array of controller data or a simple string
|
||||
*/
|
||||
protected function parseController($controller)
|
||||
private function parseController($controller)
|
||||
{
|
||||
if (\is_string($controller) && false !== strpos($controller, '::')) {
|
||||
if (\is_string($controller) && str_contains($controller, '::')) {
|
||||
$controller = explode('::', $controller);
|
||||
}
|
||||
|
||||
@@ -406,7 +446,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
$r = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
|
||||
return [
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
@@ -415,7 +455,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
if (\is_callable($controller)) {
|
||||
// using __call or __callStatic
|
||||
return [
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'class' => \is_object($controller[0]) ? get_debug_type($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => 'n/a',
|
||||
'line' => 'n/a',
|
||||
@@ -434,7 +474,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
'line' => $r->getStartLine(),
|
||||
];
|
||||
|
||||
if (false !== strpos($r->name, '{closure}')) {
|
||||
if (str_contains($r->name, '{closure}')) {
|
||||
return $controller;
|
||||
}
|
||||
$controller['method'] = $r->name;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerEvent;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
class RouterDataCollector extends DataCollector
|
||||
{
|
||||
/**
|
||||
* @var \SplObjectStorage
|
||||
* @var \SplObjectStorage<Request, callable>
|
||||
*/
|
||||
protected $controllers;
|
||||
|
||||
@@ -33,8 +33,10 @@ class RouterDataCollector extends DataCollector
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
if ($response instanceof RedirectResponse) {
|
||||
$this->data['redirect'] = true;
|
||||
@@ -66,10 +68,8 @@ class RouterDataCollector extends DataCollector
|
||||
|
||||
/**
|
||||
* Remembers the controller associated to each request.
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
*/
|
||||
public function onKernelController(FilterControllerEvent $event)
|
||||
public function onKernelController(ControllerEvent $event)
|
||||
{
|
||||
$this->controllers[$event->getRequest()] = $event->getController();
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class RouterDataCollector extends DataCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null The target URL
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTargetUrl()
|
||||
{
|
||||
@@ -91,7 +91,7 @@ class RouterDataCollector extends DataCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null The target route
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTargetRoute()
|
||||
{
|
||||
|
||||
@@ -15,16 +15,17 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\Stopwatch\StopwatchEvent;
|
||||
|
||||
/**
|
||||
* TimeDataCollector.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
protected $kernel;
|
||||
protected $stopwatch;
|
||||
private $kernel;
|
||||
private $stopwatch;
|
||||
|
||||
public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null)
|
||||
{
|
||||
@@ -35,7 +36,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
if (null !== $this->kernel) {
|
||||
$startTime = $this->kernel->getStartTime();
|
||||
@@ -44,10 +45,10 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
}
|
||||
|
||||
$this->data = [
|
||||
'token' => $response->headers->get('X-Debug-Token'),
|
||||
'token' => $request->attributes->get('_stopwatch_token'),
|
||||
'start_time' => $startTime * 1000,
|
||||
'events' => [],
|
||||
'stopwatch_installed' => \class_exists(Stopwatch::class, false),
|
||||
'stopwatch_installed' => class_exists(Stopwatch::class, false),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -75,9 +76,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request events.
|
||||
*
|
||||
* @param array $events The request events
|
||||
* @param StopwatchEvent[] $events The request events
|
||||
*/
|
||||
public function setEvents(array $events)
|
||||
{
|
||||
@@ -89,21 +88,17 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request events.
|
||||
*
|
||||
* @return array The request events
|
||||
* @return StopwatchEvent[]
|
||||
*/
|
||||
public function getEvents()
|
||||
public function getEvents(): array
|
||||
{
|
||||
return $this->data['events'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request elapsed time.
|
||||
*
|
||||
* @return float The elapsed time
|
||||
*/
|
||||
public function getDuration()
|
||||
public function getDuration(): float
|
||||
{
|
||||
if (!isset($this->data['events']['__section__'])) {
|
||||
return 0;
|
||||
@@ -118,10 +113,8 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
* Gets the initialization time.
|
||||
*
|
||||
* This is the time spent until the beginning of the request handling.
|
||||
*
|
||||
* @return float The elapsed time
|
||||
*/
|
||||
public function getInitTime()
|
||||
public function getInitTime(): float
|
||||
{
|
||||
if (!isset($this->data['events']['__section__'])) {
|
||||
return 0;
|
||||
@@ -130,20 +123,12 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
return $this->data['events']['__section__']->getOrigin() - $this->getStartTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request time.
|
||||
*
|
||||
* @return int The time
|
||||
*/
|
||||
public function getStartTime()
|
||||
public function getStartTime(): float
|
||||
{
|
||||
return $this->data['start_time'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether or not the stopwatch component is installed
|
||||
*/
|
||||
public function isStopwatchInstalled()
|
||||
public function isStopwatchInstalled(): bool
|
||||
{
|
||||
return $this->data['stopwatch_installed'];
|
||||
}
|
||||
@@ -151,7 +136,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return 'time';
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace Symfony\Component\HttpKernel\Debug;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
/**
|
||||
@@ -21,10 +20,20 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
*
|
||||
* @author Jérémy Romey <jeremy@free-agent.fr>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class FileLinkFormatter
|
||||
{
|
||||
private const FORMATS = [
|
||||
'textmate' => 'txmt://open?url=file://%f&line=%l',
|
||||
'macvim' => 'mvim://open?url=file://%f&line=%l',
|
||||
'emacs' => 'emacs://open?url=file://%f&line=%l',
|
||||
'sublime' => 'subl://open?url=file://%f&line=%l',
|
||||
'phpstorm' => 'phpstorm://open?file=%f&line=%l',
|
||||
'atom' => 'atom://core/open/file?filename=%f&line=%l',
|
||||
'vscode' => 'vscode://file/%f:%l',
|
||||
];
|
||||
|
||||
private $fileLinkFormat;
|
||||
private $requestStack;
|
||||
private $baseDir;
|
||||
@@ -33,12 +42,12 @@ class FileLinkFormatter
|
||||
/**
|
||||
* @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand
|
||||
*/
|
||||
public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null)
|
||||
public function __construct(string $fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null)
|
||||
{
|
||||
$fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
$fileLinkFormat = (self::FORMATS[$fileLinkFormat] ?? $fileLinkFormat) ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
if ($fileLinkFormat && !\is_array($fileLinkFormat)) {
|
||||
$i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f);
|
||||
$fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, \PREG_SPLIT_DELIM_CAPTURE);
|
||||
}
|
||||
|
||||
$this->fileLinkFormat = $fileLinkFormat;
|
||||
@@ -47,11 +56,11 @@ class FileLinkFormatter
|
||||
$this->urlFormat = $urlFormat;
|
||||
}
|
||||
|
||||
public function format($file, $line)
|
||||
public function format(string $file, int $line)
|
||||
{
|
||||
if ($fmt = $this->getFileLinkFormat()) {
|
||||
for ($i = 1; isset($fmt[$i]); ++$i) {
|
||||
if (0 === strpos($file, $k = $fmt[$i++])) {
|
||||
if (str_starts_with($file, $k = $fmt[$i++])) {
|
||||
$file = substr_replace($file, $fmt[$i], 0, \strlen($k));
|
||||
break;
|
||||
}
|
||||
@@ -76,11 +85,11 @@ class FileLinkFormatter
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function generateUrlFormat(UrlGeneratorInterface $router, $routeName, $queryString)
|
||||
public static function generateUrlFormat(UrlGeneratorInterface $router, string $routeName, string $queryString): ?string
|
||||
{
|
||||
try {
|
||||
return $router->generate($routeName).$queryString;
|
||||
} catch (ExceptionInterface $e) {
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -92,14 +101,16 @@ class FileLinkFormatter
|
||||
}
|
||||
|
||||
if ($this->requestStack && $this->baseDir && $this->urlFormat) {
|
||||
$request = $this->requestStack->getMasterRequest();
|
||||
$request = $this->requestStack->getMainRequest();
|
||||
|
||||
if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) {
|
||||
return [
|
||||
$request->getSchemeAndHttpHost().$request->getBasePath().$this->urlFormat,
|
||||
$request->getSchemeAndHttpHost().$this->urlFormat,
|
||||
$this->baseDir.\DIRECTORY_SEPARATOR, '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function beforeDispatch(string $eventName, $event)
|
||||
protected function beforeDispatch(string $eventName, object $event)
|
||||
{
|
||||
switch ($eventName) {
|
||||
case KernelEvents::REQUEST:
|
||||
$event->getRequest()->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6));
|
||||
$this->stopwatch->openSection();
|
||||
break;
|
||||
case KernelEvents::VIEW:
|
||||
@@ -40,14 +41,17 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
}
|
||||
break;
|
||||
case KernelEvents::TERMINATE:
|
||||
$token = $event->getResponse()->headers->get('X-Debug-Token');
|
||||
$sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
|
||||
if (null === $sectionId) {
|
||||
break;
|
||||
}
|
||||
// There is a very special case when using built-in AppCache class as kernel wrapper, in the case
|
||||
// of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A].
|
||||
// In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID
|
||||
// is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception
|
||||
// which must be caught.
|
||||
try {
|
||||
$this->stopwatch->openSection($token);
|
||||
$this->stopwatch->openSection($sectionId);
|
||||
} catch (\LogicException $e) {
|
||||
}
|
||||
break;
|
||||
@@ -57,22 +61,28 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function afterDispatch(string $eventName, $event)
|
||||
protected function afterDispatch(string $eventName, object $event)
|
||||
{
|
||||
switch ($eventName) {
|
||||
case KernelEvents::CONTROLLER_ARGUMENTS:
|
||||
$this->stopwatch->start('controller', 'section');
|
||||
break;
|
||||
case KernelEvents::RESPONSE:
|
||||
$token = $event->getResponse()->headers->get('X-Debug-Token');
|
||||
$this->stopwatch->stopSection($token);
|
||||
$sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
|
||||
if (null === $sectionId) {
|
||||
break;
|
||||
}
|
||||
$this->stopwatch->stopSection($sectionId);
|
||||
break;
|
||||
case KernelEvents::TERMINATE:
|
||||
// In the special case described in the `preDispatch` method above, the `$token` section
|
||||
// does not exist, then closing it throws an exception which must be caught.
|
||||
$token = $event->getResponse()->headers->get('X-Debug-Token');
|
||||
$sectionId = $event->getRequest()->attributes->get('_stopwatch_token');
|
||||
if (null === $sectionId) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
$this->stopwatch->stopSection($token);
|
||||
$this->stopwatch->stopSection($sectionId);
|
||||
} catch (\LogicException $e) {
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
namespace Symfony\Component\HttpKernel\DependencyInjection;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\ErrorHandler\DebugClassLoader;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
|
||||
/**
|
||||
@@ -36,13 +37,15 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$annotatedClasses = $this->kernel->getAnnotatedClassesToCompile();
|
||||
$annotatedClasses = [];
|
||||
foreach ($container->getExtensions() as $extension) {
|
||||
if ($extension instanceof Extension) {
|
||||
$annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile());
|
||||
$annotatedClasses[] = $extension->getAnnotatedClassesToCompile();
|
||||
}
|
||||
}
|
||||
|
||||
$annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses);
|
||||
|
||||
$existingClasses = $this->getClassesInComposerClassMaps();
|
||||
|
||||
$annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses);
|
||||
@@ -54,16 +57,14 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
*
|
||||
* @param array $patterns The class patterns to expand
|
||||
* @param array $classes The existing classes to match against the patterns
|
||||
*
|
||||
* @return array A list of classes derived from the patterns
|
||||
*/
|
||||
private function expandClasses(array $patterns, array $classes)
|
||||
private function expandClasses(array $patterns, array $classes): array
|
||||
{
|
||||
$expanded = [];
|
||||
|
||||
// Explicit classes declared in the patterns are returned directly
|
||||
foreach ($patterns as $key => $pattern) {
|
||||
if ('\\' !== substr($pattern, -1) && false === strpos($pattern, '*')) {
|
||||
if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) {
|
||||
unset($patterns[$key]);
|
||||
$expanded[] = ltrim($pattern, '\\');
|
||||
}
|
||||
@@ -83,7 +84,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
return array_unique($expanded);
|
||||
}
|
||||
|
||||
private function getClassesInComposerClassMaps()
|
||||
private function getClassesInComposerClassMaps(): array
|
||||
{
|
||||
$classes = [];
|
||||
|
||||
@@ -92,7 +93,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($function[0] instanceof DebugClassLoader) {
|
||||
if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) {
|
||||
$function = $function[0]->getClassLoader();
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
return array_keys($classes);
|
||||
}
|
||||
|
||||
private function patternsToRegexps($patterns)
|
||||
private function patternsToRegexps(array $patterns): array
|
||||
{
|
||||
$regexps = [];
|
||||
|
||||
@@ -126,12 +127,12 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
return $regexps;
|
||||
}
|
||||
|
||||
private function matchAnyRegexps($class, $regexps)
|
||||
private function matchAnyRegexps(string $class, array $regexps): bool
|
||||
{
|
||||
$blacklisted = false !== strpos($class, 'Test');
|
||||
$isTest = str_contains($class, 'Test');
|
||||
|
||||
foreach ($regexps as $regex) {
|
||||
if ($blacklisted && false === strpos($regex, 'Test')) {
|
||||
if ($isTest && !str_contains($regex, 'Test')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ class ControllerArgumentValueResolverPass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->argumentResolverService = $argumentResolverService;
|
||||
$this->argumentValueResolverTag = $argumentValueResolverTag;
|
||||
$this->traceableResolverStopwatch = $traceableResolverStopwatch;
|
||||
|
||||
@@ -25,7 +25,7 @@ abstract class Extension extends BaseExtension
|
||||
/**
|
||||
* Gets the annotated classes to cache.
|
||||
*
|
||||
* @return array An array of classes
|
||||
* @return array
|
||||
*/
|
||||
public function getAnnotatedClassesToCompile()
|
||||
{
|
||||
|
||||
@@ -30,6 +30,10 @@ class FragmentRendererPass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->handlerService = $handlerService;
|
||||
$this->rendererTag = $rendererTag;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
|
||||
class LazyLoadingFragmentHandler extends FragmentHandler
|
||||
{
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $initialized = [];
|
||||
|
||||
public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false)
|
||||
@@ -35,7 +39,7 @@ class LazyLoadingFragmentHandler extends FragmentHandler
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($uri, $renderer = 'inline', array $options = [])
|
||||
public function render($uri, string $renderer = 'inline', array $options = [])
|
||||
{
|
||||
if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) {
|
||||
$this->addRenderer($this->container->get($renderer));
|
||||
|
||||
@@ -23,6 +23,9 @@ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPas
|
||||
{
|
||||
private $extensions;
|
||||
|
||||
/**
|
||||
* @param string[] $extensions
|
||||
*/
|
||||
public function __construct(array $extensions)
|
||||
{
|
||||
$this->extensions = $extensions;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Target;
|
||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
@@ -23,6 +24,7 @@ use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
/**
|
||||
* Creates the service-locators required by ServiceValueResolver.
|
||||
@@ -38,6 +40,10 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->resolverServiceId = $resolverServiceId;
|
||||
$this->controllerTag = $controllerTag;
|
||||
$this->controllerLocator = $controllerLocator;
|
||||
@@ -53,6 +59,13 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
$parameterBag = $container->getParameterBag();
|
||||
$controllers = [];
|
||||
|
||||
$publicAliases = [];
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($alias->isPublic() && !$alias->isPrivate()) {
|
||||
$publicAliases[(string) $alias][] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) {
|
||||
$def = $container->getDefinition($id);
|
||||
$def->setPublic(true);
|
||||
@@ -93,13 +106,13 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
}
|
||||
foreach (['action', 'argument', 'id'] as $k) {
|
||||
if (!isset($attributes[$k][0])) {
|
||||
throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, JSON_UNESCAPED_UNICODE), $id));
|
||||
throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id));
|
||||
}
|
||||
}
|
||||
if (!isset($methods[$action = strtolower($attributes['action'])])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class));
|
||||
}
|
||||
list($r, $parameters) = $methods[$action];
|
||||
[$r, $parameters] = $methods[$action];
|
||||
$found = false;
|
||||
|
||||
foreach ($parameters as $p) {
|
||||
@@ -117,14 +130,14 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($methods as list($r, $parameters)) {
|
||||
foreach ($methods as [$r, $parameters]) {
|
||||
/** @var \ReflectionMethod $r */
|
||||
|
||||
// create a per-method map of argument-names to service/type-references
|
||||
$args = [];
|
||||
foreach ($parameters as $p) {
|
||||
/** @var \ReflectionParameter $p */
|
||||
$type = ltrim($target = ProxyHelper::getTypeHint($r, $p), '\\');
|
||||
$type = ltrim($target = (string) ProxyHelper::getTypeHint($r, $p), '\\');
|
||||
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
|
||||
|
||||
if (isset($arguments[$r->name][$p->name])) {
|
||||
@@ -136,10 +149,10 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
} elseif ($p->allowsNull() && !$p->isOptional()) {
|
||||
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
|
||||
}
|
||||
} elseif (isset($bindings[$bindingName = $type.' $'.$p->name]) || isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) {
|
||||
} elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) {
|
||||
$binding = $bindings[$bindingName];
|
||||
|
||||
list($bindingValue, $bindingId, , $bindingType, $bindingFile) = $binding->getValues();
|
||||
[$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues();
|
||||
$binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]);
|
||||
|
||||
if (!$bindingValue instanceof Reference) {
|
||||
@@ -154,11 +167,14 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
continue;
|
||||
} elseif (!$type || !$autowire || '\\' !== $target[0]) {
|
||||
continue;
|
||||
} elseif (is_subclass_of($type, \UnitEnum::class)) {
|
||||
// do not attempt to register enum typed arguments if not already present in bindings
|
||||
continue;
|
||||
} elseif (!$p->allowsNull()) {
|
||||
$invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
|
||||
}
|
||||
|
||||
if (Request::class === $type) {
|
||||
if (Request::class === $type || SessionInterface::class === $type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -170,15 +186,22 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
$message .= ' Did you forget to add a use statement?';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
$container->register($erroredId = '.errored.'.$container->hash($message), $type)
|
||||
->addError($message);
|
||||
|
||||
$target = ltrim($target, '\\');
|
||||
$args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior);
|
||||
$args[$p->name] = new Reference($erroredId, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE);
|
||||
} else {
|
||||
$target = ltrim($target, '\\');
|
||||
$args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior);
|
||||
}
|
||||
}
|
||||
// register the maps as a per-method service-locators
|
||||
if ($args) {
|
||||
$controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args);
|
||||
|
||||
foreach ($publicAliases[$id] ?? [] as $alias) {
|
||||
$controllers[$alias.'::'.$r->name] = clone $controllers[$id.'::'.$r->name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ class RegisterLocaleAwareServicesPass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->listenerServiceId = $listenerServiceId;
|
||||
$this->localeAwareTag = $localeAwareTag;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $controllerLocator = 'argument_resolver.controller_locator')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->controllerLocator = $controllerLocator;
|
||||
}
|
||||
|
||||
@@ -42,16 +46,21 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
} else {
|
||||
// any methods listed for call-at-instantiation cannot be actions
|
||||
$reason = false;
|
||||
list($id, $action) = explode('::', $controller);
|
||||
[$id, $action] = explode('::', $controller);
|
||||
|
||||
if ($container->hasAlias($id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$controllerDef = $container->getDefinition($id);
|
||||
foreach ($controllerDef->getMethodCalls() as list($method)) {
|
||||
foreach ($controllerDef->getMethodCalls() as [$method]) {
|
||||
if (0 === strcasecmp($action, $method)) {
|
||||
$reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$reason) {
|
||||
// Deprecated since Symfony 4.1. See Symfony\Component\HttpKernel\Controller\ContainerControllerResolver
|
||||
// see Symfony\Component\HttpKernel\Controller\ContainerControllerResolver
|
||||
$controllers[$id.':'.$action] = $argumentRef;
|
||||
|
||||
if ('__invoke' === $action) {
|
||||
|
||||
@@ -27,6 +27,10 @@ class ResettableServicePass implements CompilerPassInterface
|
||||
|
||||
public function __construct(string $tagName = 'kernel.reset')
|
||||
{
|
||||
if (0 < \func_num_args()) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
|
||||
}
|
||||
|
||||
$this->tagName = $tagName;
|
||||
}
|
||||
|
||||
@@ -43,16 +47,25 @@ class ResettableServicePass implements CompilerPassInterface
|
||||
|
||||
foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) {
|
||||
$services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
$attributes = $tags[0];
|
||||
|
||||
if (!isset($attributes['method'])) {
|
||||
throw new RuntimeException(sprintf('Tag %s requires the "method" attribute to be set.', $this->tagName));
|
||||
foreach ($tags as $attributes) {
|
||||
if (!isset($attributes['method'])) {
|
||||
throw new RuntimeException(sprintf('Tag "%s" requires the "method" attribute to be set.', $this->tagName));
|
||||
}
|
||||
|
||||
if (!isset($methods[$id])) {
|
||||
$methods[$id] = [];
|
||||
}
|
||||
|
||||
if ('ignore' === ($attributes['on_invalid'] ?? null)) {
|
||||
$attributes['method'] = '?'.$attributes['method'];
|
||||
}
|
||||
|
||||
$methods[$id][] = $attributes['method'];
|
||||
}
|
||||
|
||||
$methods[$id] = $attributes['method'];
|
||||
}
|
||||
|
||||
if (empty($services)) {
|
||||
if (!$services) {
|
||||
$container->removeAlias('services_resetter');
|
||||
$container->removeDefinition('services_resetter');
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ class ServicesResetter implements ResetInterface
|
||||
private $resettableServices;
|
||||
private $resetMethods;
|
||||
|
||||
/**
|
||||
* @param \Traversable<string, object> $resettableServices
|
||||
* @param array<string, string|string[]> $resetMethods
|
||||
*/
|
||||
public function __construct(\Traversable $resettableServices, array $resetMethods)
|
||||
{
|
||||
$this->resettableServices = $resettableServices;
|
||||
@@ -35,7 +39,13 @@ class ServicesResetter implements ResetInterface
|
||||
public function reset()
|
||||
{
|
||||
foreach ($this->resettableServices as $id => $service) {
|
||||
$service->{$this->resetMethods[$id]}();
|
||||
foreach ((array) $this->resetMethods[$id] as $resetMethod) {
|
||||
if ('?' === $resetMethod[0] && !method_exists($service, $resetMethod = substr($resetMethod, 1))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$service->$resetMethod();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows filtering of controller arguments.
|
||||
*
|
||||
@@ -23,6 +26,36 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*/
|
||||
class ControllerArgumentsEvent extends FilterControllerArgumentsEvent
|
||||
final class ControllerArgumentsEvent extends KernelEvent
|
||||
{
|
||||
private $controller;
|
||||
private $arguments;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->controller = $controller;
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
public function getController(): callable
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
public function setController(callable $controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
}
|
||||
|
||||
public function getArguments(): array
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows filtering of a controller callable.
|
||||
*
|
||||
@@ -22,6 +25,24 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ControllerEvent extends FilterControllerEvent
|
||||
final class ControllerEvent extends KernelEvent
|
||||
{
|
||||
private $controller;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setController($controller);
|
||||
}
|
||||
|
||||
public function getController(): callable
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
public function setController(callable $controller): void
|
||||
{
|
||||
$this->controller = $controller;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows to create a response for a thrown exception.
|
||||
*
|
||||
@@ -18,12 +21,56 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
* current request. The propagation of this event is stopped as soon as a
|
||||
* response is set.
|
||||
*
|
||||
* You can also call setException() to replace the thrown exception. This
|
||||
* You can also call setThrowable() to replace the thrown exception. This
|
||||
* exception will be thrown if no response is set during processing of this
|
||||
* event.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ExceptionEvent extends GetResponseForExceptionEvent
|
||||
final class ExceptionEvent extends RequestEvent
|
||||
{
|
||||
private $throwable;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $allowCustomResponseCode = false;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setThrowable($e);
|
||||
}
|
||||
|
||||
public function getThrowable(): \Throwable
|
||||
{
|
||||
return $this->throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the thrown exception.
|
||||
*
|
||||
* This exception will be thrown if no response is set in the event.
|
||||
*/
|
||||
public function setThrowable(\Throwable $exception): void
|
||||
{
|
||||
$this->throwable = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the event as allowing a custom response code.
|
||||
*/
|
||||
public function allowCustomResponseCode(): void
|
||||
{
|
||||
$this->allowCustomResponseCode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the event allows a custom response code.
|
||||
*/
|
||||
public function isAllowingCustomResponseCode(): bool
|
||||
{
|
||||
return $this->allowCustomResponseCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use ControllerArgumentsEvent instead
|
||||
*/
|
||||
class FilterControllerArgumentsEvent extends ControllerEvent
|
||||
{
|
||||
private $arguments;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType)
|
||||
{
|
||||
parent::__construct($kernel, $controller, $request, $requestType);
|
||||
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use ControllerEvent instead
|
||||
*/
|
||||
class FilterControllerEvent extends KernelEvent
|
||||
{
|
||||
private $controller;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setController($controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current controller.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
public function setController(callable $controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use ResponseEvent instead
|
||||
*/
|
||||
class FilterResponseEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current response object.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new response object.
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,6 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class FinishRequestEvent extends KernelEvent
|
||||
final class FinishRequestEvent extends KernelEvent
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use RequestEvent instead
|
||||
*/
|
||||
class GetResponseEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* Returns the response object.
|
||||
*
|
||||
* @return Response|null
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a response and stops event propagation.
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
|
||||
$this->stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a response was set.
|
||||
*
|
||||
* @return bool Whether a response was set
|
||||
*/
|
||||
public function hasResponse()
|
||||
{
|
||||
return null !== $this->response;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use ViewEvent instead
|
||||
*/
|
||||
class GetResponseForControllerResultEvent extends RequestEvent
|
||||
{
|
||||
/**
|
||||
* The return value of the controller.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $controllerResult;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->controllerResult = $controllerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the return value of the controller.
|
||||
*
|
||||
* @return mixed The controller return value
|
||||
*/
|
||||
public function getControllerResult()
|
||||
{
|
||||
return $this->controllerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the return value of the controller.
|
||||
*
|
||||
* @param mixed $controllerResult The controller return value
|
||||
*/
|
||||
public function setControllerResult($controllerResult)
|
||||
{
|
||||
$this->controllerResult = $controllerResult;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use ExceptionEvent instead
|
||||
*/
|
||||
class GetResponseForExceptionEvent extends RequestEvent
|
||||
{
|
||||
/**
|
||||
* The exception object.
|
||||
*
|
||||
* @var \Exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $allowCustomResponseCode = false;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Exception $e)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setException($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thrown exception.
|
||||
*
|
||||
* @return \Exception The thrown exception
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the thrown exception.
|
||||
*
|
||||
* This exception will be thrown if no response is set in the event.
|
||||
*
|
||||
* @param \Exception $exception The thrown exception
|
||||
*/
|
||||
public function setException(\Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the event as allowing a custom response code.
|
||||
*/
|
||||
public function allowCustomResponseCode()
|
||||
{
|
||||
$this->allowCustomResponseCode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the event allows a custom response code.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowingCustomResponseCode()
|
||||
{
|
||||
return $this->allowCustomResponseCode;
|
||||
}
|
||||
}
|
||||
26
vendor/symfony/http-kernel/Event/KernelEvent.php
vendored
26
vendor/symfony/http-kernel/Event/KernelEvent.php
vendored
@@ -11,9 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Base class for events thrown in the HttpKernel component.
|
||||
@@ -27,10 +27,8 @@ class KernelEvent extends Event
|
||||
private $requestType;
|
||||
|
||||
/**
|
||||
* @param HttpKernelInterface $kernel The kernel in which this event was thrown
|
||||
* @param Request $request The request the kernel is currently processing
|
||||
* @param int $requestType The request type the kernel is currently processing; one of
|
||||
* HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST
|
||||
* @param int $requestType The request type the kernel is currently processing; one of
|
||||
* HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType)
|
||||
{
|
||||
@@ -62,7 +60,7 @@ class KernelEvent extends Event
|
||||
/**
|
||||
* Returns the request type the kernel is currently processing.
|
||||
*
|
||||
* @return int One of HttpKernelInterface::MASTER_REQUEST and
|
||||
* @return int One of HttpKernelInterface::MAIN_REQUEST and
|
||||
* HttpKernelInterface::SUB_REQUEST
|
||||
*/
|
||||
public function getRequestType()
|
||||
@@ -70,13 +68,25 @@ class KernelEvent extends Event
|
||||
return $this->requestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is the main request.
|
||||
*/
|
||||
public function isMainRequest(): bool
|
||||
{
|
||||
return HttpKernelInterface::MAIN_REQUEST === $this->requestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a master request.
|
||||
*
|
||||
* @return bool True if the request is a master request
|
||||
* @return bool
|
||||
*
|
||||
* @deprecated since symfony/http-kernel 5.3, use isMainRequest() instead
|
||||
*/
|
||||
public function isMasterRequest()
|
||||
{
|
||||
return HttpKernelInterface::MASTER_REQUEST === $this->requestType;
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', '"%s()" is deprecated, use "isMainRequest()" instead.', __METHOD__);
|
||||
|
||||
return $this->isMainRequest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?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\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 4.3, use TerminateEvent instead
|
||||
*/
|
||||
class PostResponseEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, Response $response)
|
||||
{
|
||||
parent::__construct($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
|
||||
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response for which this event was thrown.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Allows to create a response for a request.
|
||||
*
|
||||
@@ -20,6 +22,37 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class RequestEvent extends GetResponseEvent
|
||||
class RequestEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* Returns the response object.
|
||||
*
|
||||
* @return Response|null
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a response and stops event propagation.
|
||||
*/
|
||||
public function setResponse(Response $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
|
||||
$this->stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a response was set.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResponse()
|
||||
{
|
||||
return null !== $this->response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows to filter a Response object.
|
||||
*
|
||||
@@ -20,6 +24,24 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ResponseEvent extends FilterResponseEvent
|
||||
final class ResponseEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->setResponse($response);
|
||||
}
|
||||
|
||||
public function getResponse(): Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function setResponse(Response $response): void
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,31 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows to execute logic after a response was sent.
|
||||
*
|
||||
* Since it's only triggered on master requests, the `getRequestType()` method
|
||||
* will always return the value of `HttpKernelInterface::MASTER_REQUEST`.
|
||||
* Since it's only triggered on main requests, the `getRequestType()` method
|
||||
* will always return the value of `HttpKernelInterface::MAIN_REQUEST`.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class TerminateEvent extends PostResponseEvent
|
||||
final class TerminateEvent extends KernelEvent
|
||||
{
|
||||
private $response;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, Response $response)
|
||||
{
|
||||
parent::__construct($kernel, $request, HttpKernelInterface::MAIN_REQUEST);
|
||||
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getResponse(): Response
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
|
||||
38
vendor/symfony/http-kernel/Event/ViewEvent.php
vendored
38
vendor/symfony/http-kernel/Event/ViewEvent.php
vendored
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Event;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Allows to create a response for the return value of a controller.
|
||||
*
|
||||
@@ -20,6 +23,39 @@ namespace Symfony\Component\HttpKernel\Event;
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ViewEvent extends GetResponseForControllerResultEvent
|
||||
final class ViewEvent extends RequestEvent
|
||||
{
|
||||
/**
|
||||
* The return value of the controller.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $controllerResult;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
$this->controllerResult = $controllerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the return value of the controller.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getControllerResult()
|
||||
{
|
||||
return $this->controllerResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the return value of the controller.
|
||||
*
|
||||
* @param mixed $controllerResult The controller return value
|
||||
*/
|
||||
public function setControllerResult($controllerResult): void
|
||||
{
|
||||
$this->controllerResult = $controllerResult;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@ namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionUtils;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Contracts\Service\ResetInterface;
|
||||
|
||||
/**
|
||||
* Sets the session onto the request on the "kernel.request" event and saves
|
||||
@@ -33,43 +37,65 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @internal since Symfony 4.3
|
||||
* @internal
|
||||
*/
|
||||
abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface
|
||||
{
|
||||
const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
|
||||
public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
|
||||
|
||||
protected $container;
|
||||
private $sessionUsageStack = [];
|
||||
private $debug;
|
||||
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
private $sessionOptions;
|
||||
|
||||
public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = [])
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->debug = $debug;
|
||||
$this->sessionOptions = $sessionOptions;
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$session = null;
|
||||
$request = $event->getRequest();
|
||||
if ($request->hasSession()) {
|
||||
// no-op
|
||||
} elseif (method_exists($request, 'setSessionFactory')) {
|
||||
$request->setSessionFactory(function () { return $this->getSession(); });
|
||||
} elseif ($session = $this->getSession()) {
|
||||
$request->setSession($session);
|
||||
if (!$request->hasSession()) {
|
||||
// This variable prevents calling `$this->getSession()` twice in case the Request (and the below factory) is cloned
|
||||
$sess = null;
|
||||
$request->setSessionFactory(function () use (&$sess, $request) {
|
||||
if (!$sess) {
|
||||
$sess = $this->getSession();
|
||||
}
|
||||
|
||||
/*
|
||||
* For supporting sessions in php runtime with runners like roadrunner or swoole, the session
|
||||
* cookie needs to be read from the cookie bag and set on the session storage.
|
||||
*
|
||||
* Do not set it when a native php session is active.
|
||||
*/
|
||||
if ($sess && !$sess->isStarted() && \PHP_SESSION_ACTIVE !== session_status()) {
|
||||
$sessionId = $request->cookies->get($sess->getName(), '');
|
||||
$sess->setId($sessionId);
|
||||
}
|
||||
|
||||
return $sess;
|
||||
});
|
||||
}
|
||||
|
||||
$session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null);
|
||||
$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null;
|
||||
$this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0;
|
||||
}
|
||||
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest() || (!$this->container->has('initialized_session') && !$event->getRequest()->hasSession())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,15 +108,6 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) {
|
||||
if ($autoCacheControl) {
|
||||
$response
|
||||
->setPrivate()
|
||||
->setMaxAge(0)
|
||||
->headers->addCacheControlDirective('must-revalidate');
|
||||
}
|
||||
}
|
||||
|
||||
if ($session->isStarted()) {
|
||||
/*
|
||||
* Saves the session, in case it is still open, before sending the response/headers.
|
||||
@@ -106,7 +123,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
* the one above. But by saving the session before long-running things in the terminate event,
|
||||
* we ensure the session is not blocked longer than needed.
|
||||
* * When regenerating the session ID no locking is involved in PHPs session design. See
|
||||
* https://bugs.php.net/bug.php?id=61470 for a discussion. So in this case, the session must
|
||||
* https://bugs.php.net/61470 for a discussion. So in this case, the session must
|
||||
* be saved anyway before sending the headers with the new session ID. Otherwise session
|
||||
* data could get lost again for concurrent requests with the new ID. One result could be
|
||||
* that you get logged out after just logging in.
|
||||
@@ -118,20 +135,126 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
* it is saved will just restart it.
|
||||
*/
|
||||
$session->save();
|
||||
|
||||
/*
|
||||
* For supporting sessions in php runtime with runners like roadrunner or swoole the session
|
||||
* cookie need to be written on the response object and should not be written by PHP itself.
|
||||
*/
|
||||
$sessionName = $session->getName();
|
||||
$sessionId = $session->getId();
|
||||
$sessionOptions = $this->getSessionOptions($this->sessionOptions);
|
||||
$sessionCookiePath = $sessionOptions['cookie_path'] ?? '/';
|
||||
$sessionCookieDomain = $sessionOptions['cookie_domain'] ?? null;
|
||||
$sessionCookieSecure = $sessionOptions['cookie_secure'] ?? false;
|
||||
$sessionCookieHttpOnly = $sessionOptions['cookie_httponly'] ?? true;
|
||||
$sessionCookieSameSite = $sessionOptions['cookie_samesite'] ?? Cookie::SAMESITE_LAX;
|
||||
|
||||
SessionUtils::popSessionCookie($sessionName, $sessionId);
|
||||
|
||||
$request = $event->getRequest();
|
||||
$requestSessionCookieId = $request->cookies->get($sessionName);
|
||||
|
||||
$isSessionEmpty = $session->isEmpty() && empty($_SESSION); // checking $_SESSION to keep compatibility with native sessions
|
||||
if ($requestSessionCookieId && $isSessionEmpty) {
|
||||
$response->headers->clearCookie(
|
||||
$sessionName,
|
||||
$sessionCookiePath,
|
||||
$sessionCookieDomain,
|
||||
$sessionCookieSecure,
|
||||
$sessionCookieHttpOnly,
|
||||
$sessionCookieSameSite
|
||||
);
|
||||
} elseif ($sessionId !== $requestSessionCookieId && !$isSessionEmpty) {
|
||||
$expire = 0;
|
||||
$lifetime = $sessionOptions['cookie_lifetime'] ?? null;
|
||||
if ($lifetime) {
|
||||
$expire = time() + $lifetime;
|
||||
}
|
||||
|
||||
$response->headers->setCookie(
|
||||
Cookie::create(
|
||||
$sessionName,
|
||||
$sessionId,
|
||||
$expire,
|
||||
$sessionCookiePath,
|
||||
$sessionCookieDomain,
|
||||
$sessionCookieSecure,
|
||||
$sessionCookieHttpOnly,
|
||||
false,
|
||||
$sessionCookieSameSite
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($session instanceof Session ? $session->getUsageIndex() === end($this->sessionUsageStack) : !$session->isStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($autoCacheControl) {
|
||||
$response
|
||||
->setExpires(new \DateTime())
|
||||
->setPrivate()
|
||||
->setMaxAge(0)
|
||||
->headers->addCacheControlDirective('must-revalidate');
|
||||
}
|
||||
|
||||
if (!$event->getRequest()->attributes->get('_stateless', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->debug) {
|
||||
throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
|
||||
}
|
||||
|
||||
if ($this->container->has('logger')) {
|
||||
$this->container->get('logger')->warning('Session was used while the request was declared stateless.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function onFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if ($event->isMasterRequest()) {
|
||||
if ($event->isMainRequest()) {
|
||||
array_pop($this->sessionUsageStack);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public function onSessionUsage(): void
|
||||
{
|
||||
if (!$this->debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->container && $this->container->has('session_collector')) {
|
||||
$this->container->get('session_collector')();
|
||||
}
|
||||
|
||||
if (!$requestStack = $this->container && $this->container->has('request_stack') ? $this->container->get('request_stack') : null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stateless = false;
|
||||
$clonedRequestStack = clone $requestStack;
|
||||
while (null !== ($request = $clonedRequestStack->pop()) && !$stateless) {
|
||||
$stateless = $request->attributes->get('_stateless');
|
||||
}
|
||||
|
||||
if (!$stateless) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $requestStack->getCurrentRequest()->getSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($session->isStarted()) {
|
||||
$session->save();
|
||||
}
|
||||
|
||||
throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 128],
|
||||
@@ -141,10 +264,43 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
];
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
if (\PHP_SESSION_ACTIVE === session_status()) {
|
||||
session_abort();
|
||||
}
|
||||
|
||||
session_unset();
|
||||
$_SESSION = [];
|
||||
|
||||
if (!headers_sent()) { // session id can only be reset when no headers were so we check for headers_sent first
|
||||
session_id('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
* @return SessionInterface|null
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
|
||||
private function getSessionOptions(array $sessionOptions): array
|
||||
{
|
||||
$mergedSessionOptions = [];
|
||||
|
||||
foreach (session_get_cookie_params() as $key => $value) {
|
||||
$mergedSessionOptions['cookie_'.$key] = $value;
|
||||
}
|
||||
|
||||
foreach ($sessionOptions as $key => $value) {
|
||||
// do the same logic as in the NativeSessionStorage
|
||||
if ('cookie_secure' === $key && 'auto' === $value) {
|
||||
continue;
|
||||
}
|
||||
$mergedSessionOptions[$key] = $value;
|
||||
}
|
||||
|
||||
return $mergedSessionOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,9 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal since Symfony 4.3
|
||||
* @internal
|
||||
*
|
||||
* @deprecated the TestSessionListener use the default SessionListener instead
|
||||
*/
|
||||
abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
{
|
||||
@@ -37,17 +39,20 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
public function __construct(array $sessionOptions = [])
|
||||
{
|
||||
$this->sessionOptions = $sessionOptions;
|
||||
|
||||
trigger_deprecation('symfony/http-kernel', '5.4', 'The %s is deprecated use the %s instead.', __CLASS__, AbstractSessionListener::class);
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// bootstrap the session
|
||||
$session = $this->getSession();
|
||||
if (!$session) {
|
||||
if ($event->getRequest()->hasSession()) {
|
||||
$session = $event->getRequest()->getSession();
|
||||
} elseif (!$session = $this->getSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,12 +65,12 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if session was initialized and saves if current request is master
|
||||
* Checks if session was initialized and saves if current request is the main request
|
||||
* Runs on 'kernel.response' in test environment.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,7 +87,7 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) {
|
||||
$params = session_get_cookie_params() + ['samesite' => null];
|
||||
foreach ($this->sessionOptions as $k => $v) {
|
||||
if (0 === strpos($k, 'cookie_')) {
|
||||
if (str_starts_with($k, 'cookie_')) {
|
||||
$params[substr($k, 7)] = $v;
|
||||
}
|
||||
}
|
||||
@@ -98,10 +103,10 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 192],
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 127], // AFTER SessionListener
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -128],
|
||||
];
|
||||
}
|
||||
@@ -109,7 +114,9 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
* @deprecated since Symfony 5.4, will be removed in 6.0.
|
||||
*
|
||||
* @return SessionInterface|null
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
@@ -20,7 +20,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
*
|
||||
* @author Gildas Quemener <gildas.quemener@gmail.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class AddRequestFormatsListener implements EventSubscriberInterface
|
||||
{
|
||||
@@ -34,7 +34,7 @@ class AddRequestFormatsListener implements EventSubscriberInterface
|
||||
/**
|
||||
* Adds request formats.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
foreach ($this->formats as $format => $mimeTypes) {
|
||||
@@ -45,7 +45,7 @@ class AddRequestFormatsListener implements EventSubscriberInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [KernelEvents::REQUEST => ['onKernelRequest', 100]];
|
||||
}
|
||||
|
||||
@@ -15,14 +15,8 @@ use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleEvent;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\ErrorHandler\ErrorHandler;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\KernelEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
@@ -30,47 +24,61 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
* Configures errors and exceptions handlers.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @internal since Symfony 5.3
|
||||
*/
|
||||
class DebugHandlersListener implements EventSubscriberInterface
|
||||
{
|
||||
private $earlyHandler;
|
||||
private $exceptionHandler;
|
||||
private $logger;
|
||||
private $deprecationLogger;
|
||||
private $levels;
|
||||
private $throwAt;
|
||||
private $scream;
|
||||
private $fileLinkFormat;
|
||||
private $scope;
|
||||
private $charset;
|
||||
private $firstCall = true;
|
||||
private $hasTerminatedWithException;
|
||||
|
||||
/**
|
||||
* @param callable|null $exceptionHandler A handler that will be called on Exception
|
||||
* @param LoggerInterface|null $logger A PSR-3 logger
|
||||
* @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
|
||||
* @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
|
||||
* @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
|
||||
* @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files
|
||||
* @param bool $scope Enables/disables scoping mode
|
||||
* @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception
|
||||
* @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
|
||||
* @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
|
||||
* @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
|
||||
* @param bool $scope Enables/disables scoping mode
|
||||
*/
|
||||
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true, string $charset = null)
|
||||
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $scope = true, $deprecationLogger = null, $fileLinkFormat = null)
|
||||
{
|
||||
if (!\is_bool($scope)) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.4', 'Passing a $fileLinkFormat is deprecated.');
|
||||
$scope = $deprecationLogger;
|
||||
$deprecationLogger = $fileLinkFormat;
|
||||
}
|
||||
|
||||
$handler = set_exception_handler('var_dump');
|
||||
$this->earlyHandler = \is_array($handler) ? $handler[0] : null;
|
||||
restore_exception_handler();
|
||||
|
||||
$this->exceptionHandler = $exceptionHandler;
|
||||
$this->logger = $logger;
|
||||
$this->levels = null === $levels ? E_ALL : $levels;
|
||||
$this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null));
|
||||
$this->levels = $levels ?? \E_ALL;
|
||||
$this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null));
|
||||
$this->scream = $scream;
|
||||
$this->fileLinkFormat = $fileLinkFormat;
|
||||
$this->scope = $scope;
|
||||
$this->charset = $charset;
|
||||
$this->deprecationLogger = $deprecationLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the error handler.
|
||||
*/
|
||||
public function configure(Event $event = null)
|
||||
public function configure(object $event = null)
|
||||
{
|
||||
if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) {
|
||||
if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
|
||||
return;
|
||||
}
|
||||
if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
$this->firstCall = $this->hasTerminatedWithException = false;
|
||||
@@ -79,31 +87,34 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
$handler = \is_array($handler) ? $handler[0] : null;
|
||||
restore_exception_handler();
|
||||
|
||||
if ($this->logger || null !== $this->throwAt) {
|
||||
if ($handler instanceof ErrorHandler) {
|
||||
if ($this->logger) {
|
||||
$handler->setDefaultLogger($this->logger, $this->levels);
|
||||
if (\is_array($this->levels)) {
|
||||
$levels = 0;
|
||||
foreach ($this->levels as $type => $log) {
|
||||
$levels |= $type;
|
||||
}
|
||||
} else {
|
||||
$levels = $this->levels;
|
||||
if (!$handler instanceof ErrorHandler) {
|
||||
$handler = $this->earlyHandler;
|
||||
}
|
||||
|
||||
if ($handler instanceof ErrorHandler) {
|
||||
if ($this->logger || $this->deprecationLogger) {
|
||||
$this->setDefaultLoggers($handler);
|
||||
if (\is_array($this->levels)) {
|
||||
$levels = 0;
|
||||
foreach ($this->levels as $type => $log) {
|
||||
$levels |= $type;
|
||||
}
|
||||
if ($this->scream) {
|
||||
$handler->screamAt($levels);
|
||||
}
|
||||
if ($this->scope) {
|
||||
$handler->scopeAt($levels & ~E_USER_DEPRECATED & ~E_DEPRECATED);
|
||||
} else {
|
||||
$handler->scopeAt(0, true);
|
||||
}
|
||||
$this->logger = $this->levels = null;
|
||||
} else {
|
||||
$levels = $this->levels;
|
||||
}
|
||||
if (null !== $this->throwAt) {
|
||||
$handler->throwAt($this->throwAt, true);
|
||||
|
||||
if ($this->scream) {
|
||||
$handler->screamAt($levels);
|
||||
}
|
||||
if ($this->scope) {
|
||||
$handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED);
|
||||
} else {
|
||||
$handler->scopeAt(0, true);
|
||||
}
|
||||
$this->logger = $this->deprecationLogger = $this->levels = null;
|
||||
}
|
||||
if (null !== $this->throwAt) {
|
||||
$handler->throwAt($this->throwAt, true);
|
||||
}
|
||||
}
|
||||
if (!$this->exceptionHandler) {
|
||||
@@ -111,10 +122,11 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
|
||||
$request = $event->getRequest();
|
||||
$hasRun = &$this->hasTerminatedWithException;
|
||||
$this->exceptionHandler = static function (\Exception $e) use ($kernel, $request, &$hasRun) {
|
||||
$this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) {
|
||||
if ($hasRun) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$hasRun = true;
|
||||
$kernel->terminateWithException($e, $request);
|
||||
};
|
||||
@@ -124,61 +136,55 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
$this->exceptionHandler = function ($e) use ($app, $output) {
|
||||
$app->renderException($e, $output);
|
||||
$this->exceptionHandler = static function (\Throwable $e) use ($app, $output) {
|
||||
$app->renderThrowable($e, $output);
|
||||
};
|
||||
}
|
||||
}
|
||||
if ($this->exceptionHandler) {
|
||||
if ($handler instanceof ErrorHandler) {
|
||||
$h = $handler->setExceptionHandler('var_dump');
|
||||
if (\is_array($h) && $h[0] instanceof ExceptionHandler) {
|
||||
$handler->setExceptionHandler($h);
|
||||
$handler = $h[0];
|
||||
} else {
|
||||
$handler->setExceptionHandler($this->exceptionHandler);
|
||||
}
|
||||
}
|
||||
if ($handler instanceof ExceptionHandler) {
|
||||
$handler->setHandler($this->exceptionHandler);
|
||||
if (null !== $this->fileLinkFormat) {
|
||||
$handler->setFileLinkFormat($this->fileLinkFormat);
|
||||
}
|
||||
$handler->setExceptionHandler($this->exceptionHandler);
|
||||
}
|
||||
$this->exceptionHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function onKernelException(GetResponseForExceptionEvent $event)
|
||||
private function setDefaultLoggers(ErrorHandler $handler): void
|
||||
{
|
||||
if (!$this->hasTerminatedWithException || !$event->isMasterRequest()) {
|
||||
return;
|
||||
if (\is_array($this->levels)) {
|
||||
$levelsDeprecatedOnly = [];
|
||||
$levelsWithoutDeprecated = [];
|
||||
foreach ($this->levels as $type => $log) {
|
||||
if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) {
|
||||
$levelsDeprecatedOnly[$type] = $log;
|
||||
} else {
|
||||
$levelsWithoutDeprecated[$type] = $log;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED);
|
||||
$levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED;
|
||||
}
|
||||
|
||||
$debug = $this->scream && $this->scope;
|
||||
$controller = function (Request $request) use ($debug) {
|
||||
$e = $request->attributes->get('exception');
|
||||
$handler = new ExceptionHandler($debug, $this->charset, $this->fileLinkFormat);
|
||||
$defaultLoggerLevels = $this->levels;
|
||||
if ($this->deprecationLogger && $levelsDeprecatedOnly) {
|
||||
$handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly);
|
||||
$defaultLoggerLevels = $levelsWithoutDeprecated;
|
||||
}
|
||||
|
||||
return new Response($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders());
|
||||
};
|
||||
|
||||
(new ExceptionListener($controller, $this->logger, $debug))->onKernelException($event);
|
||||
if ($this->logger && $defaultLoggerLevels) {
|
||||
$handler->setDefaultLogger($this->logger, $defaultLoggerLevels);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
$events = [KernelEvents::REQUEST => ['configure', 2048]];
|
||||
|
||||
if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
|
||||
if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
|
||||
$events[ConsoleEvents::COMMAND] = ['configure', 2048];
|
||||
}
|
||||
|
||||
$events[KernelEvents::EXCEPTION] = ['onKernelException', -2048];
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
|
||||
180
vendor/symfony/http-kernel/EventListener/ErrorListener.php
vendored
Normal file
180
vendor/symfony/http-kernel/EventListener/ErrorListener.php
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
<?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\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException;
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ErrorListener implements EventSubscriberInterface
|
||||
{
|
||||
protected $controller;
|
||||
protected $logger;
|
||||
protected $debug;
|
||||
protected $exceptionsMapping;
|
||||
|
||||
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = [])
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->logger = $logger;
|
||||
$this->debug = $debug;
|
||||
$this->exceptionsMapping = $exceptionsMapping;
|
||||
}
|
||||
|
||||
public function logKernelException(ExceptionEvent $event)
|
||||
{
|
||||
$throwable = $event->getThrowable();
|
||||
$logLevel = null;
|
||||
|
||||
foreach ($this->exceptionsMapping as $class => $config) {
|
||||
if ($throwable instanceof $class && $config['log_level']) {
|
||||
$logLevel = $config['log_level'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->exceptionsMapping as $class => $config) {
|
||||
if (!$throwable instanceof $class || !$config['status_code']) {
|
||||
continue;
|
||||
}
|
||||
if (!$throwable instanceof HttpExceptionInterface || $throwable->getStatusCode() !== $config['status_code']) {
|
||||
$headers = $throwable instanceof HttpExceptionInterface ? $throwable->getHeaders() : [];
|
||||
$throwable = new HttpException($config['status_code'], $throwable->getMessage(), $throwable, $headers);
|
||||
$event->setThrowable($throwable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$e = FlattenException::createFromThrowable($throwable);
|
||||
|
||||
$this->logException($throwable, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()), $logLevel);
|
||||
}
|
||||
|
||||
public function onKernelException(ExceptionEvent $event)
|
||||
{
|
||||
if (null === $this->controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
$throwable = $event->getThrowable();
|
||||
$request = $this->duplicateRequest($throwable, $event->getRequest());
|
||||
|
||||
try {
|
||||
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false);
|
||||
} catch (\Exception $e) {
|
||||
$f = FlattenException::createFromThrowable($e);
|
||||
|
||||
$this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine()));
|
||||
|
||||
$prev = $e;
|
||||
do {
|
||||
if ($throwable === $wrapper = $prev) {
|
||||
throw $e;
|
||||
}
|
||||
} while ($prev = $wrapper->getPrevious());
|
||||
|
||||
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
|
||||
$prev->setAccessible(true);
|
||||
$prev->setValue($wrapper, $throwable);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$event->setResponse($response);
|
||||
|
||||
if ($this->debug) {
|
||||
$event->getRequest()->attributes->set('_remove_csp_headers', true);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeCspHeader(ResponseEvent $event): void
|
||||
{
|
||||
if ($this->debug && $event->getRequest()->attributes->get('_remove_csp_headers', false)) {
|
||||
$event->getResponse()->headers->remove('Content-Security-Policy');
|
||||
}
|
||||
}
|
||||
|
||||
public function onControllerArguments(ControllerArgumentsEvent $event)
|
||||
{
|
||||
$e = $event->getRequest()->attributes->get('exception');
|
||||
|
||||
if (!$e instanceof \Throwable || false === $k = array_search($e, $event->getArguments(), true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = new \ReflectionFunction(\Closure::fromCallable($event->getController()));
|
||||
$r = $r->getParameters()[$k] ?? null;
|
||||
|
||||
if ($r && (!($r = $r->getType()) instanceof \ReflectionNamedType || \in_array($r->getName(), [FlattenException::class, LegacyFlattenException::class], true))) {
|
||||
$arguments = $event->getArguments();
|
||||
$arguments[$k] = FlattenException::createFromThrowable($e);
|
||||
$event->setArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments',
|
||||
KernelEvents::EXCEPTION => [
|
||||
['logKernelException', 0],
|
||||
['onKernelException', -128],
|
||||
],
|
||||
KernelEvents::RESPONSE => ['removeCspHeader', -128],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an exception.
|
||||
*/
|
||||
protected function logException(\Throwable $exception, string $message, string $logLevel = null): void
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
if (null !== $logLevel) {
|
||||
$this->logger->log($logLevel, $message, ['exception' => $exception]);
|
||||
} elseif (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
|
||||
$this->logger->critical($message, ['exception' => $exception]);
|
||||
} else {
|
||||
$this->logger->error($message, ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the request for the exception.
|
||||
*/
|
||||
protected function duplicateRequest(\Throwable $exception, Request $request): Request
|
||||
{
|
||||
$attributes = [
|
||||
'_controller' => $this->controller,
|
||||
'exception' => $exception,
|
||||
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
|
||||
];
|
||||
$request = $request->duplicate(null, null, $attributes);
|
||||
$request->setMethod('GET');
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
<?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\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Debug\Exception\FlattenException;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
*/
|
||||
class ExceptionListener implements EventSubscriberInterface
|
||||
{
|
||||
protected $controller;
|
||||
protected $logger;
|
||||
protected $debug;
|
||||
|
||||
public function __construct($controller, LoggerInterface $logger = null, $debug = false)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->logger = $logger;
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
public function logKernelException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
$e = FlattenException::create($event->getException());
|
||||
|
||||
$this->logException($event->getException(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $eventName
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function onKernelException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
if (null === $this->controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
$exception = $event->getException();
|
||||
$request = $this->duplicateRequest($exception, $event->getRequest());
|
||||
$eventDispatcher = \func_num_args() > 2 ? func_get_arg(2) : null;
|
||||
|
||||
try {
|
||||
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false);
|
||||
} catch (\Exception $e) {
|
||||
$f = FlattenException::create($e);
|
||||
|
||||
$this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine()));
|
||||
|
||||
$prev = $e;
|
||||
do {
|
||||
if ($exception === $wrapper = $prev) {
|
||||
throw $e;
|
||||
}
|
||||
} while ($prev = $wrapper->getPrevious());
|
||||
|
||||
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
|
||||
$prev->setAccessible(true);
|
||||
$prev->setValue($wrapper, $exception);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$event->setResponse($response);
|
||||
|
||||
if ($this->debug && $eventDispatcher instanceof EventDispatcherInterface) {
|
||||
$cspRemovalListener = function ($event) use (&$cspRemovalListener, $eventDispatcher) {
|
||||
$event->getResponse()->headers->remove('Content-Security-Policy');
|
||||
$eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener);
|
||||
};
|
||||
$eventDispatcher->addListener(KernelEvents::RESPONSE, $cspRemovalListener, -128);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::EXCEPTION => [
|
||||
['logKernelException', 0],
|
||||
['onKernelException', -128],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an exception.
|
||||
*
|
||||
* @param \Exception $exception The \Exception instance
|
||||
* @param string $message The error message to log
|
||||
*/
|
||||
protected function logException(\Exception $exception, $message)
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
|
||||
$this->logger->critical($message, ['exception' => $exception]);
|
||||
} else {
|
||||
$this->logger->error($message, ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the request for the exception.
|
||||
*
|
||||
* @param \Exception $exception The thrown exception
|
||||
* @param Request $request The original request
|
||||
*
|
||||
* @return Request The cloned request
|
||||
*/
|
||||
protected function duplicateRequest(\Exception $exception, Request $request)
|
||||
{
|
||||
$attributes = [
|
||||
'_controller' => $this->controller,
|
||||
'exception' => FlattenException::create($exception),
|
||||
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
|
||||
];
|
||||
$request = $request->duplicate(null, null, $attributes);
|
||||
$request->setMethod('GET');
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\UriSigner;
|
||||
@@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\UriSigner;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class FragmentListener implements EventSubscriberInterface
|
||||
{
|
||||
@@ -37,8 +37,7 @@ class FragmentListener implements EventSubscriberInterface
|
||||
private $fragmentPath;
|
||||
|
||||
/**
|
||||
* @param UriSigner $signer A UriSigner instance
|
||||
* @param string $fragmentPath The path that triggers this listener
|
||||
* @param string $fragmentPath The path that triggers this listener
|
||||
*/
|
||||
public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment')
|
||||
{
|
||||
@@ -51,7 +50,7 @@ class FragmentListener implements EventSubscriberInterface
|
||||
*
|
||||
* @throws AccessDeniedHttpException if the request does not come from a trusted IP
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
@@ -66,7 +65,7 @@ class FragmentListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->isMasterRequest()) {
|
||||
if ($event->isMainRequest()) {
|
||||
$this->validateRequest($request);
|
||||
}
|
||||
|
||||
@@ -79,20 +78,19 @@ class FragmentListener implements EventSubscriberInterface
|
||||
protected function validateRequest(Request $request)
|
||||
{
|
||||
// is the Request safe?
|
||||
if (!$request->isMethodSafe(false)) {
|
||||
if (!$request->isMethodSafe()) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
// is the Request signed?
|
||||
// we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
|
||||
if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) {
|
||||
if ($this->signer->checkRequest($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 48]],
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
@@ -30,7 +29,7 @@ class LocaleAwareListener implements EventSubscriberInterface
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
* @param LocaleAwareInterface[] $localeAwareServices
|
||||
* @param iterable<mixed, LocaleAwareInterface> $localeAwareServices
|
||||
*/
|
||||
public function __construct(iterable $localeAwareServices, RequestStack $requestStack)
|
||||
{
|
||||
@@ -46,7 +45,9 @@ class LocaleAwareListener implements EventSubscriberInterface
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event): void
|
||||
{
|
||||
if (null === $parentRequest = $this->requestStack->getParentRequest()) {
|
||||
$this->setLocale($event->getRequest()->getDefaultLocale());
|
||||
foreach ($this->localeAwareServices as $service) {
|
||||
$service->setLocale($event->getRequest()->getDefaultLocale());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -63,7 +64,7 @@ class LocaleAwareListener implements EventSubscriberInterface
|
||||
];
|
||||
}
|
||||
|
||||
private function setLocale(string $locale, ?string $defaultLocale = null): void
|
||||
private function setLocale(string $locale, string $defaultLocale): void
|
||||
{
|
||||
foreach ($this->localeAwareServices as $service) {
|
||||
try {
|
||||
|
||||
@@ -15,8 +15,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\KernelEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
|
||||
@@ -25,24 +25,23 @@ use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class LocaleListener implements EventSubscriberInterface
|
||||
{
|
||||
private $router;
|
||||
private $defaultLocale;
|
||||
private $requestStack;
|
||||
private $useAcceptLanguageHeader;
|
||||
private $enabledLocales;
|
||||
|
||||
/**
|
||||
* @param RequestStack $requestStack A RequestStack instance
|
||||
* @param string $defaultLocale The default locale
|
||||
* @param RequestContextAwareInterface|null $router The router
|
||||
*/
|
||||
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null)
|
||||
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = [])
|
||||
{
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
$this->requestStack = $requestStack;
|
||||
$this->router = $router;
|
||||
$this->useAcceptLanguageHeader = $useAcceptLanguageHeader;
|
||||
$this->enabledLocales = $enabledLocales;
|
||||
}
|
||||
|
||||
public function setDefaultLocale(KernelEvent $event)
|
||||
@@ -50,7 +49,7 @@ class LocaleListener implements EventSubscriberInterface
|
||||
$event->getRequest()->setDefaultLocale($this->defaultLocale);
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
@@ -69,6 +68,9 @@ class LocaleListener implements EventSubscriberInterface
|
||||
{
|
||||
if ($locale = $request->attributes->get('_locale')) {
|
||||
$request->setLocale($locale);
|
||||
} elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) {
|
||||
$request->setLocale($preferredLanguage);
|
||||
$request->attributes->set('_vary_by_language', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +81,7 @@ class LocaleListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\TerminateEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profile;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
|
||||
/**
|
||||
@@ -25,56 +27,56 @@ use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class ProfilerListener implements EventSubscriberInterface
|
||||
{
|
||||
protected $profiler;
|
||||
protected $matcher;
|
||||
protected $onlyException;
|
||||
protected $onlyMasterRequests;
|
||||
protected $onlyMainRequests;
|
||||
protected $exception;
|
||||
/** @var \SplObjectStorage<Request, Profile> */
|
||||
protected $profiles;
|
||||
protected $requestStack;
|
||||
protected $collectParameter;
|
||||
/** @var \SplObjectStorage<Request, Request|null> */
|
||||
protected $parents;
|
||||
|
||||
/**
|
||||
* @param Profiler $profiler A Profiler instance
|
||||
* @param RequestStack $requestStack A RequestStack instance
|
||||
* @param RequestMatcherInterface|null $matcher A RequestMatcher instance
|
||||
* @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise
|
||||
* @param bool $onlyMasterRequests True if the profiler only collects data when the request is a master request, false otherwise
|
||||
* @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise
|
||||
* @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise
|
||||
*/
|
||||
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMasterRequests = false)
|
||||
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null)
|
||||
{
|
||||
$this->profiler = $profiler;
|
||||
$this->matcher = $matcher;
|
||||
$this->onlyException = $onlyException;
|
||||
$this->onlyMasterRequests = $onlyMasterRequests;
|
||||
$this->onlyMainRequests = $onlyMainRequests;
|
||||
$this->profiles = new \SplObjectStorage();
|
||||
$this->parents = new \SplObjectStorage();
|
||||
$this->requestStack = $requestStack;
|
||||
$this->collectParameter = $collectParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the onKernelException event.
|
||||
*/
|
||||
public function onKernelException(GetResponseForExceptionEvent $event)
|
||||
public function onKernelException(ExceptionEvent $event)
|
||||
{
|
||||
if ($this->onlyMasterRequests && !$event->isMasterRequest()) {
|
||||
if ($this->onlyMainRequests && !$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->exception = $event->getException();
|
||||
$this->exception = $event->getThrowable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the onKernelResponse event.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
$master = $event->isMasterRequest();
|
||||
if ($this->onlyMasterRequests && !$master) {
|
||||
if ($this->onlyMainRequests && !$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,6 +85,10 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
if (null !== $this->collectParameter && null !== $collectParameterValue = $request->get($this->collectParameter)) {
|
||||
true === $collectParameterValue || filter_var($collectParameterValue, \FILTER_VALIDATE_BOOLEAN) ? $this->profiler->enable() : $this->profiler->disable();
|
||||
}
|
||||
|
||||
$exception = $this->exception;
|
||||
$this->exception = null;
|
||||
|
||||
@@ -99,7 +105,7 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
$this->parents[$request] = $this->requestStack->getParentRequest();
|
||||
}
|
||||
|
||||
public function onKernelTerminate(PostResponseEvent $event)
|
||||
public function onKernelTerminate(TerminateEvent $event)
|
||||
{
|
||||
// attach children to parents
|
||||
foreach ($this->profiles as $request) {
|
||||
@@ -119,7 +125,7 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
$this->parents = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -100],
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
@@ -20,23 +20,25 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class ResponseListener implements EventSubscriberInterface
|
||||
{
|
||||
private $charset;
|
||||
private $addContentLanguageHeader;
|
||||
|
||||
public function __construct(string $charset)
|
||||
public function __construct(string $charset, bool $addContentLanguageHeader = false)
|
||||
{
|
||||
$this->charset = $charset;
|
||||
$this->addContentLanguageHeader = $addContentLanguageHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the Response.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,10 +48,18 @@ class ResponseListener implements EventSubscriberInterface
|
||||
$response->setCharset($this->charset);
|
||||
}
|
||||
|
||||
if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) {
|
||||
$response->headers->set('Content-Language', $event->getRequest()->getLocale());
|
||||
}
|
||||
|
||||
if ($event->getRequest()->attributes->get('_vary_by_language')) {
|
||||
$response->setVary('Accept-Language', false);
|
||||
}
|
||||
|
||||
$response->prepare($event->getRequest());
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::RESPONSE => 'onKernelResponse',
|
||||
|
||||
@@ -16,9 +16,9 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@@ -38,7 +38,7 @@ use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class RouterListener implements EventSubscriberInterface
|
||||
{
|
||||
@@ -50,12 +50,8 @@ class RouterListener implements EventSubscriberInterface
|
||||
private $debug;
|
||||
|
||||
/**
|
||||
* @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
|
||||
* @param RequestStack $requestStack A RequestStack instance
|
||||
* @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
|
||||
* @param LoggerInterface|null $logger The logger
|
||||
* @param string $projectDir
|
||||
* @param bool $debug
|
||||
* @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
|
||||
* @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
@@ -70,7 +66,7 @@ class RouterListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
$this->matcher = $matcher;
|
||||
$this->context = $context ?: $matcher->getContext();
|
||||
$this->context = $context ?? $matcher->getContext();
|
||||
$this->requestStack = $requestStack;
|
||||
$this->logger = $logger;
|
||||
$this->projectDir = $projectDir;
|
||||
@@ -91,15 +87,13 @@ class RouterListener implements EventSubscriberInterface
|
||||
/**
|
||||
* After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator
|
||||
* operates on the correct context again.
|
||||
*
|
||||
* @param FinishRequestEvent $event
|
||||
*/
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
$this->setCurrentRequest($this->requestStack->getParentRequest());
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
@@ -121,7 +115,7 @@ class RouterListener implements EventSubscriberInterface
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Matched route "{route}".', [
|
||||
'route' => isset($parameters['_route']) ? $parameters['_route'] : 'n/a',
|
||||
'route' => $parameters['_route'] ?? 'n/a',
|
||||
'route_parameters' => $parameters,
|
||||
'request_uri' => $request->getUri(),
|
||||
'method' => $request->getMethod(),
|
||||
@@ -132,7 +126,7 @@ class RouterListener implements EventSubscriberInterface
|
||||
unset($parameters['_route'], $parameters['_controller']);
|
||||
$request->attributes->set('_route_params', $parameters);
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
$message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
|
||||
$message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getUriForPath($request->getPathInfo()));
|
||||
|
||||
if ($referer = $request->headers->get('referer')) {
|
||||
$message .= sprintf(' (from "%s")', $referer);
|
||||
@@ -140,15 +134,15 @@ class RouterListener implements EventSubscriberInterface
|
||||
|
||||
throw new NotFoundHttpException($message, $e);
|
||||
} catch (MethodNotAllowedException $e) {
|
||||
$message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods()));
|
||||
$message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getUriForPath($request->getPathInfo()), implode(', ', $e->getAllowedMethods()));
|
||||
|
||||
throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
|
||||
}
|
||||
}
|
||||
|
||||
public function onKernelException(GetResponseForExceptionEvent $event)
|
||||
public function onKernelException(ExceptionEvent $event)
|
||||
{
|
||||
if (!$this->debug || !($e = $event->getException()) instanceof NotFoundHttpException) {
|
||||
if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,7 +151,7 @@ class RouterListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 32]],
|
||||
@@ -166,14 +160,14 @@ class RouterListener implements EventSubscriberInterface
|
||||
];
|
||||
}
|
||||
|
||||
private function createWelcomeResponse()
|
||||
private function createWelcomeResponse(): Response
|
||||
{
|
||||
$version = Kernel::VERSION;
|
||||
$baseDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR;
|
||||
$projectDir = realpath((string) $this->projectDir).\DIRECTORY_SEPARATOR;
|
||||
$docVersion = substr(Kernel::VERSION, 0, 3);
|
||||
|
||||
ob_start();
|
||||
include __DIR__.'/../Resources/welcome.html.php';
|
||||
include \dirname(__DIR__).'/Resources/welcome.html.php';
|
||||
|
||||
return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?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\HttpKernel\EventListener;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1, use AbstractSessionListener instead.', SaveSessionListener::class), E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @deprecated since Symfony 4.1, use AbstractSessionListener instead
|
||||
*/
|
||||
class SaveSessionListener implements EventSubscriberInterface
|
||||
{
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$session = $event->getRequest()->getSession();
|
||||
if ($session && $session->isStarted()) {
|
||||
$session->save();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
// low priority but higher than StreamedResponseListener
|
||||
KernelEvents::RESPONSE => [['onKernelResponse', -1000]],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -11,15 +11,16 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
|
||||
/**
|
||||
* Sets the session in the request.
|
||||
*
|
||||
* When the passed container contains a "session_storage" entry which
|
||||
* holds a NativeSessionStorage instance, the "cookie_secure" option
|
||||
* will be set to true whenever the current master request is secure.
|
||||
* will be set to true whenever the current main request is secure.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
@@ -27,25 +28,33 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
*/
|
||||
class SessionListener extends AbstractSessionListener
|
||||
{
|
||||
public function __construct(ContainerInterface $container)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
parent::onKernelRequest($event);
|
||||
|
||||
protected function getSession()
|
||||
{
|
||||
if (!$this->container->has('session')) {
|
||||
if (!$event->isMainRequest() || (!$this->container->has('session') && !$this->container->has('session_factory'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->container->has('session_storage')
|
||||
&& ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage
|
||||
&& ($masterRequest = $this->container->get('request_stack')->getMasterRequest())
|
||||
&& $masterRequest->isSecure()
|
||||
&& ($mainRequest = $this->container->get('request_stack')->getMainRequest())
|
||||
&& $mainRequest->isSecure()
|
||||
) {
|
||||
$storage->setOptions(['cookie_secure' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->container->get('session');
|
||||
protected function getSession(): ?SessionInterface
|
||||
{
|
||||
if ($this->container->has('session')) {
|
||||
return $this->container->get('session');
|
||||
}
|
||||
|
||||
if ($this->container->has('session_factory')) {
|
||||
return $this->container->get('session_factory')->createSession();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
@@ -22,16 +22,16 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class StreamedResponseListener implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Filters the Response.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class StreamedResponseListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -1024],
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
|
||||
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
@@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class SurrogateListener implements EventSubscriberInterface
|
||||
{
|
||||
@@ -36,9 +36,9 @@ class SurrogateListener implements EventSubscriberInterface
|
||||
/**
|
||||
* Filters the Response.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
public function onKernelResponse(ResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class SurrogateListener implements EventSubscriberInterface
|
||||
$surrogate->addSurrogateControl($event->getResponse());
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::RESPONSE => 'onKernelResponse',
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
/**
|
||||
* Sets the session in the request.
|
||||
@@ -19,6 +20,8 @@ use Psr\Container\ContainerInterface;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*
|
||||
* @deprecated the TestSessionListener use the default SessionListener instead
|
||||
*/
|
||||
class TestSessionListener extends AbstractTestSessionListener
|
||||
{
|
||||
@@ -30,12 +33,17 @@ class TestSessionListener extends AbstractTestSessionListener
|
||||
parent::__construct($sessionOptions);
|
||||
}
|
||||
|
||||
protected function getSession()
|
||||
/**
|
||||
* @deprecated since Symfony 5.4, will be removed in 6.0.
|
||||
*/
|
||||
protected function getSession(): ?SessionInterface
|
||||
{
|
||||
if (!$this->container->has('session')) {
|
||||
return;
|
||||
trigger_deprecation('symfony/http-kernel', '5.4', '"%s" is deprecated and will be removed in 6.0, inject a session in the request instead.', __METHOD__);
|
||||
|
||||
if ($this->container->has('session')) {
|
||||
return $this->container->get('session');
|
||||
}
|
||||
|
||||
return $this->container->get('session');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
<?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\HttpKernel\EventListener;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3 and will be removed in 5.0, use LocaleAwareListener instead.', TranslatorListener::class), E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Contracts\Translation\LocaleAwareInterface;
|
||||
|
||||
/**
|
||||
* Synchronizes the locale between the request and the translator.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.3, use LocaleAwareListener instead
|
||||
*/
|
||||
class TranslatorListener implements EventSubscriberInterface
|
||||
{
|
||||
private $translator;
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
* @param LocaleAwareInterface $translator
|
||||
*/
|
||||
public function __construct($translator, RequestStack $requestStack)
|
||||
{
|
||||
if (!$translator instanceof TranslatorInterface && !$translator instanceof LocaleAwareInterface) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, LocaleAwareInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||
}
|
||||
$this->translator = $translator;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
$this->setLocale($event->getRequest());
|
||||
}
|
||||
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if (null === $parentRequest = $this->requestStack->getParentRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setLocale($parentRequest);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
// must be registered after the Locale listener
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 10]],
|
||||
KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]],
|
||||
];
|
||||
}
|
||||
|
||||
private function setLocale(Request $request)
|
||||
{
|
||||
try {
|
||||
$this->translator->setLocale($request->getLocale());
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->translator->setLocale($request->getDefaultLocale());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
@@ -20,16 +20,16 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
*
|
||||
* @author Magnus Nordlander <magnus@fervo.se>
|
||||
*
|
||||
* @final since Symfony 4.3
|
||||
* @final
|
||||
*/
|
||||
class ValidateRequestListener implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Performs the validation.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
public function onKernelRequest(RequestEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
if (!$event->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
$request = $event->getRequest();
|
||||
@@ -44,7 +44,7 @@ class ValidateRequestListener implements EventSubscriberInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [
|
||||
|
||||
@@ -18,13 +18,18 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
class AccessDeniedHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* @param string $message The internal exception message
|
||||
* @param \Throwable $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
* @param array $headers
|
||||
* @param string|null $message The internal exception message
|
||||
* @param \Throwable|null $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
*/
|
||||
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
{
|
||||
if (null === $message) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);
|
||||
|
||||
$message = '';
|
||||
}
|
||||
|
||||
parent::__construct(403, $message, $previous, $headers, $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
class BadRequestHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* @param string $message The internal exception message
|
||||
* @param \Throwable $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
* @param array $headers
|
||||
* @param string|null $message The internal exception message
|
||||
* @param \Throwable|null $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
*/
|
||||
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
{
|
||||
if (null === $message) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);
|
||||
|
||||
$message = '';
|
||||
}
|
||||
|
||||
parent::__construct(400, $message, $previous, $headers, $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
class ConflictHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* @param string $message The internal exception message
|
||||
* @param \Throwable $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
* @param array $headers
|
||||
* @param string|null $message The internal exception message
|
||||
* @param \Throwable|null $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
*/
|
||||
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
{
|
||||
if (null === $message) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);
|
||||
|
||||
$message = '';
|
||||
}
|
||||
|
||||
parent::__construct(409, $message, $previous, $headers, $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class ControllerDoesNotReturnResponseException extends \LogicException
|
||||
|
||||
private function parseControllerDefinition(callable $controller): ?array
|
||||
{
|
||||
if (\is_string($controller) && false !== strpos($controller, '::')) {
|
||||
if (\is_string($controller) && str_contains($controller, '::')) {
|
||||
$controller = explode('::', $controller);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,18 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
class GoneHttpException extends HttpException
|
||||
{
|
||||
/**
|
||||
* @param string $message The internal exception message
|
||||
* @param \Throwable $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
* @param array $headers
|
||||
* @param string|null $message The internal exception message
|
||||
* @param \Throwable|null $previous The previous exception
|
||||
* @param int $code The internal exception code
|
||||
*/
|
||||
public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
|
||||
{
|
||||
if (null === $message) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);
|
||||
|
||||
$message = '';
|
||||
}
|
||||
|
||||
parent::__construct(410, $message, $previous, $headers, $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,19 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface
|
||||
private $statusCode;
|
||||
private $headers;
|
||||
|
||||
public function __construct(int $statusCode, string $message = null, \Throwable $previous = null, array $headers = [], ?int $code = 0)
|
||||
public function __construct(int $statusCode, ?string $message = '', \Throwable $previous = null, array $headers = [], ?int $code = 0)
|
||||
{
|
||||
if (null === $message) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);
|
||||
|
||||
$message = '';
|
||||
}
|
||||
if (null === $code) {
|
||||
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $code to "%s()" is deprecated, pass 0 instead.', __METHOD__);
|
||||
|
||||
$code = 0;
|
||||
}
|
||||
|
||||
$this->statusCode = $statusCode;
|
||||
$this->headers = $headers;
|
||||
|
||||
|
||||
@@ -16,19 +16,19 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
*
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
*/
|
||||
interface HttpExceptionInterface
|
||||
interface HttpExceptionInterface extends \Throwable
|
||||
{
|
||||
/**
|
||||
* Returns the status code.
|
||||
*
|
||||
* @return int An HTTP response status code
|
||||
* @return int
|
||||
*/
|
||||
public function getStatusCode();
|
||||
|
||||
/**
|
||||
* Returns response headers.
|
||||
*
|
||||
* @return array Response headers
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders();
|
||||
}
|
||||
|
||||
@@ -9,11 +9,8 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller;
|
||||
namespace Symfony\Component\HttpKernel\Exception;
|
||||
|
||||
class VariadicController
|
||||
class InvalidMetadataException extends \LogicException
|
||||
{
|
||||
public function action($foo, ...$bar)
|
||||
{
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user