Augmentation vers version 3.3.0
This commit is contained in:
59
vendor/symfony/http-kernel/Bundle/Bundle.php
vendored
59
vendor/symfony/http-kernel/Bundle/Bundle.php
vendored
@@ -13,26 +13,24 @@ namespace Symfony\Component\HttpKernel\Bundle;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
abstract class Bundle implements BundleInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
use ContainerAwareTrait;
|
||||
|
||||
protected $name;
|
||||
protected $extension;
|
||||
protected $path;
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -59,15 +57,9 @@ abstract class Bundle implements BundleInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Returns the bundle's container extension.
|
||||
*
|
||||
* @return ExtensionInterface|null The container extension
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
@@ -95,9 +87,7 @@ abstract class Bundle implements BundleInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->extension) {
|
||||
return $this->extension;
|
||||
}
|
||||
return $this->extension ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,9 +95,11 @@ abstract class Bundle implements BundleInterface
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
$class = \get_class($this);
|
||||
if (null === $this->namespace) {
|
||||
$this->parseClassName();
|
||||
}
|
||||
|
||||
return substr($class, 0, strrpos($class, '\\'));
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,14 +127,11 @@ abstract class Bundle implements BundleInterface
|
||||
*/
|
||||
final public function getName()
|
||||
{
|
||||
if (null !== $this->name) {
|
||||
return $this->name;
|
||||
if (null === $this->name) {
|
||||
$this->parseClassName();
|
||||
}
|
||||
|
||||
$name = \get_class($this);
|
||||
$pos = strrpos($name, '\\');
|
||||
|
||||
return $this->name = false === $pos ? $name : substr($name, $pos + 1);
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,13 +163,16 @@ abstract class Bundle implements BundleInterface
|
||||
}
|
||||
$class = $ns.'\\'.$file->getBasename('.php');
|
||||
if ($this->container) {
|
||||
$commandIds = $this->container->hasParameter('console.command.ids') ? $this->container->getParameter('console.command.ids') : [];
|
||||
$alias = 'console.command.'.strtolower(str_replace('\\', '_', $class));
|
||||
if ($this->container->has($alias)) {
|
||||
if (isset($commandIds[$alias]) || $this->container->has($alias)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$r = new \ReflectionClass($class);
|
||||
if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) {
|
||||
@trigger_error(sprintf('Auto-registration of the command "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Use PSR-4 based service discovery instead.', $class), E_USER_DEPRECATED);
|
||||
|
||||
$application->add($r->newInstance());
|
||||
}
|
||||
}
|
||||
@@ -205,8 +197,15 @@ 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()
|
||||
{
|
||||
$pos = strrpos(static::class, '\\');
|
||||
$this->namespace = false === $pos ? '' : substr(static::class, 0, $pos);
|
||||
if (null === $this->name) {
|
||||
$this->name = false === $pos ? static::class : substr(static::class, $pos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ interface BundleInterface extends ContainerAwareInterface
|
||||
* bundle.
|
||||
*
|
||||
* @return string The Bundle name it overrides or null if no parent
|
||||
*
|
||||
* @deprecated This method is deprecated as of 3.4 and will be removed in 4.0.
|
||||
*/
|
||||
public function getParent();
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace Symfony\Component\HttpKernel\CacheClearer;
|
||||
* ChainCacheClearer.
|
||||
*
|
||||
* @author Dustin Dobervich <ddobervich@gmail.com>
|
||||
*
|
||||
* @final since version 3.4
|
||||
*/
|
||||
class ChainCacheClearer implements CacheClearerInterface
|
||||
{
|
||||
@@ -25,7 +27,7 @@ class ChainCacheClearer implements CacheClearerInterface
|
||||
*
|
||||
* @param array $clearers The initial clearers
|
||||
*/
|
||||
public function __construct(array $clearers = array())
|
||||
public function __construct($clearers = [])
|
||||
{
|
||||
$this->clearers = $clearers;
|
||||
}
|
||||
@@ -42,9 +44,13 @@ class ChainCacheClearer implements CacheClearerInterface
|
||||
|
||||
/**
|
||||
* Adds a cache clearer to the aggregate.
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead.
|
||||
*/
|
||||
public function add(CacheClearerInterface $clearer)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->clearers[] = $clearer;
|
||||
}
|
||||
}
|
||||
|
||||
58
vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php
vendored
Normal file
58
vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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\CacheClearer;
|
||||
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class Psr6CacheClearer implements CacheClearerInterface
|
||||
{
|
||||
private $pools = [];
|
||||
|
||||
public function __construct(array $pools = [])
|
||||
{
|
||||
$this->pools = $pools;
|
||||
}
|
||||
|
||||
public function addPool(CacheItemPoolInterface $pool)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->pools[] = $pool;
|
||||
}
|
||||
|
||||
public function hasPool($name)
|
||||
{
|
||||
return isset($this->pools[$name]);
|
||||
}
|
||||
|
||||
public function clearPool($name)
|
||||
{
|
||||
if (!isset($this->pools[$name])) {
|
||||
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
|
||||
}
|
||||
|
||||
return $this->pools[$name]->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clear($cacheDir)
|
||||
{
|
||||
foreach ($this->pools as $pool) {
|
||||
$pool->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,21 @@ namespace Symfony\Component\HttpKernel\CacheWarmer;
|
||||
* Aggregates several cache warmers into a single one.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since version 3.4
|
||||
*/
|
||||
class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
{
|
||||
protected $warmers = array();
|
||||
protected $warmers = [];
|
||||
protected $optionalsEnabled = false;
|
||||
private $triggerDeprecation = false;
|
||||
|
||||
public function __construct(array $warmers = array())
|
||||
public function __construct($warmers = [])
|
||||
{
|
||||
foreach ($warmers as $warmer) {
|
||||
$this->add($warmer);
|
||||
}
|
||||
$this->triggerDeprecation = true;
|
||||
}
|
||||
|
||||
public function enableOptionalWarmers()
|
||||
@@ -59,16 +63,28 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead.
|
||||
*/
|
||||
public function setWarmers(array $warmers)
|
||||
{
|
||||
$this->warmers = array();
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->warmers = [];
|
||||
foreach ($warmers as $warmer) {
|
||||
$this->add($warmer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead.
|
||||
*/
|
||||
public function add(CacheWarmerInterface $warmer)
|
||||
{
|
||||
if ($this->triggerDeprecation) {
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->warmers[] = $warmer;
|
||||
}
|
||||
}
|
||||
|
||||
53
vendor/symfony/http-kernel/Client.php
vendored
53
vendor/symfony/http-kernel/Client.php
vendored
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\HttpKernel;
|
||||
|
||||
use Symfony\Component\BrowserKit\Client as BaseClient;
|
||||
use Symfony\Component\BrowserKit\Cookie as DomCookie;
|
||||
use Symfony\Component\BrowserKit\CookieJar;
|
||||
use Symfony\Component\BrowserKit\History;
|
||||
use Symfony\Component\BrowserKit\Request as DomRequest;
|
||||
@@ -32,6 +31,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
class Client extends BaseClient
|
||||
{
|
||||
protected $kernel;
|
||||
private $catchExceptions = true;
|
||||
|
||||
/**
|
||||
* @param HttpKernelInterface $kernel An HttpKernel instance
|
||||
@@ -39,7 +39,7 @@ class Client extends BaseClient
|
||||
* @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 = array(), History $history = null, CookieJar $cookieJar = null)
|
||||
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;
|
||||
@@ -48,6 +48,16 @@ class Client extends BaseClient
|
||||
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.
|
||||
*
|
||||
@@ -55,7 +65,7 @@ class Client extends BaseClient
|
||||
*/
|
||||
protected function doRequest($request)
|
||||
{
|
||||
$response = $this->kernel->handle($request);
|
||||
$response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions);
|
||||
|
||||
if ($this->kernel instanceof TerminableInterface) {
|
||||
$this->kernel->terminate($request, $response);
|
||||
@@ -74,21 +84,29 @@ class Client extends BaseClient
|
||||
$kernel = var_export(serialize($this->kernel), true);
|
||||
$request = var_export(serialize($request), true);
|
||||
|
||||
$r = new \ReflectionClass('\\Symfony\\Component\\ClassLoader\\ClassLoader');
|
||||
$requirePath = var_export($r->getFileName(), true);
|
||||
$symfonyPath = var_export(\dirname(\dirname(\dirname(__DIR__))), 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);
|
||||
|
||||
require_once $requirePath;
|
||||
|
||||
\$loader = new Symfony\Component\ClassLoader\ClassLoader();
|
||||
\$loader->addPrefix('Symfony', $symfonyPath);
|
||||
\$loader->register();
|
||||
$requires
|
||||
|
||||
\$kernel = unserialize($kernel);
|
||||
\$request = unserialize($request);
|
||||
@@ -141,7 +159,7 @@ EOF;
|
||||
*/
|
||||
protected function filterFiles(array $files)
|
||||
{
|
||||
$filtered = array();
|
||||
$filtered = [];
|
||||
foreach ($files as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
$filtered[$key] = $this->filterFiles($value);
|
||||
@@ -178,20 +196,11 @@ EOF;
|
||||
*/
|
||||
protected function filterResponse($response)
|
||||
{
|
||||
$headers = $response->headers->all();
|
||||
if ($response->headers->getCookies()) {
|
||||
$cookies = array();
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
$cookies[] = new DomCookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
|
||||
}
|
||||
$headers['Set-Cookie'] = $cookies;
|
||||
}
|
||||
|
||||
// this is needed to support StreamedResponse
|
||||
ob_start();
|
||||
$response->sendContent();
|
||||
$content = ob_get_clean();
|
||||
|
||||
return new DomResponse($content, $response->getStatusCode(), $headers);
|
||||
return new DomResponse($content, $response->getStatusCode(), $response->headers->all());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
|
||||
* EnvParametersResource represents resources stored in prefixed environment variables.
|
||||
*
|
||||
* @author Chris Wilkinson <chriswilkinson84@gmail.com>
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable
|
||||
{
|
||||
@@ -48,11 +50,11 @@ class EnvParametersResource implements SelfCheckingResourceInterface, \Serializa
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return array An array with two keys: 'prefix' for the prefix used and 'variables' containing all the variables watched by this resource
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return array('prefix' => $this->prefix, 'variables' => $this->variables);
|
||||
return ['prefix' => $this->prefix, 'variables' => $this->variables];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,14 +65,24 @@ class EnvParametersResource implements SelfCheckingResourceInterface, \Serializa
|
||||
return $this->findVariables() === $this->variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize(array('prefix' => $this->prefix, 'variables' => $this->variables));
|
||||
return serialize(['prefix' => $this->prefix, 'variables' => $this->variables]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$unserialized = unserialize($serialized);
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
$unserialized = unserialize($serialized, ['allowed_classes' => false]);
|
||||
} else {
|
||||
$unserialized = unserialize($serialized);
|
||||
}
|
||||
|
||||
$this->prefix = $unserialized['prefix'];
|
||||
$this->variables = $unserialized['variables'];
|
||||
@@ -78,7 +90,7 @@ class EnvParametersResource implements SelfCheckingResourceInterface, \Serializa
|
||||
|
||||
private function findVariables()
|
||||
{
|
||||
$variables = array();
|
||||
$variables = [];
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (0 === strpos($key, $this->prefix)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ class FileLocator extends BaseFileLocator
|
||||
* @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, $path = null, array $paths = array())
|
||||
public function __construct(KernelInterface $kernel, $path = null, array $paths = [])
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
if (null !== $path) {
|
||||
|
||||
94
vendor/symfony/http-kernel/Controller/ArgumentResolver.php
vendored
Normal file
94
vendor/symfony/http-kernel/Controller/ArgumentResolver.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?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\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
|
||||
|
||||
/**
|
||||
* Responsible for resolving the arguments passed to an action.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class ArgumentResolver implements ArgumentResolverInterface
|
||||
{
|
||||
private $argumentMetadataFactory;
|
||||
|
||||
/**
|
||||
* @var iterable|ArgumentValueResolverInterface[]
|
||||
*/
|
||||
private $argumentValueResolvers;
|
||||
|
||||
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = [])
|
||||
{
|
||||
$this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
|
||||
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
|
||||
foreach ($this->argumentValueResolvers as $resolver) {
|
||||
if (!$resolver->supports($request, $metadata)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$resolved = $resolver->resolve($request, $metadata);
|
||||
|
||||
if (!$resolved instanceof \Generator) {
|
||||
throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver)));
|
||||
}
|
||||
|
||||
foreach ($resolved as $append) {
|
||||
$arguments[] = $append;
|
||||
}
|
||||
|
||||
// continue to the next controller argument
|
||||
continue 2;
|
||||
}
|
||||
|
||||
$representative = $controller;
|
||||
|
||||
if (\is_array($representative)) {
|
||||
$representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]);
|
||||
} elseif (\is_object($representative)) {
|
||||
$representative = \get_class($representative);
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName()));
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
public static function getDefaultArgumentValueResolvers()
|
||||
{
|
||||
return [
|
||||
new RequestAttributeValueResolver(),
|
||||
new RequestValueResolver(),
|
||||
new SessionValueResolver(),
|
||||
new DefaultValueResolver(),
|
||||
new VariadicValueResolver(),
|
||||
];
|
||||
}
|
||||
}
|
||||
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields the default value defined in the action signature when no value has been given.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class DefaultValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null;
|
||||
}
|
||||
}
|
||||
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields a non-variadic argument's value from the request attributes.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class RequestAttributeValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
return !$argument->isVariadic() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
yield $request->attributes->get($argument->getName());
|
||||
}
|
||||
}
|
||||
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields the same instance as the request object passed along.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class RequestValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
yield $request;
|
||||
}
|
||||
}
|
||||
77
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
77
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields a service keyed by _controller and argument name.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class ServiceValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
$controller = $request->attributes->get('_controller');
|
||||
|
||||
if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
} elseif (!\is_string($controller) || '' === $controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('\\' === $controller[0]) {
|
||||
$controller = ltrim($controller, '\\');
|
||||
}
|
||||
|
||||
if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) {
|
||||
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
|
||||
}
|
||||
|
||||
return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
if (\is_array($controller = $request->attributes->get('_controller'))) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
}
|
||||
|
||||
if ('\\' === $controller[0]) {
|
||||
$controller = ltrim($controller, '\\');
|
||||
}
|
||||
|
||||
if (!$this->container->has($controller)) {
|
||||
$i = strrpos($controller, ':');
|
||||
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
|
||||
}
|
||||
|
||||
yield $this->container->get($controller)->get($argument->getName());
|
||||
}
|
||||
}
|
||||
46
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
46
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields the Session.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class SessionValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
$type = $argument->getType();
|
||||
if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $request->getSession() instanceof $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
yield $request->getSession();
|
||||
}
|
||||
}
|
||||
48
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
48
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields a variadic argument's values from the request attributes.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class VariadicValueResolver implements ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
return $argument->isVariadic() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument)
|
||||
{
|
||||
$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)));
|
||||
}
|
||||
|
||||
foreach ($values as $value) {
|
||||
yield $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php
vendored
Normal file
34
vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* An ArgumentResolverInterface instance knows how to determine the
|
||||
* arguments for a specific action.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ArgumentResolverInterface
|
||||
{
|
||||
/**
|
||||
* Returns the arguments to pass to the controller.
|
||||
*
|
||||
* @param callable $controller
|
||||
*
|
||||
* @return array An array of arguments to pass to the controller
|
||||
*
|
||||
* @throws \RuntimeException When no value could be provided for a required argument
|
||||
*/
|
||||
public function getArguments(Request $request, $controller);
|
||||
}
|
||||
37
vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php
vendored
Normal file
37
vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Responsible for resolving the value of an argument based on its metadata.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
interface ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* Whether this resolver can resolve the value for the given ArgumentMetadata.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument);
|
||||
|
||||
/**
|
||||
* Returns the possible value(s).
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument);
|
||||
}
|
||||
121
vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php
vendored
Normal file
121
vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?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 Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
class ContainerControllerResolver extends ControllerResolver
|
||||
{
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
parent::__construct($logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getController(Request $request)
|
||||
{
|
||||
$controller = parent::getController($request);
|
||||
|
||||
if (\is_array($controller) && isset($controller[0]) && \is_string($controller[0]) && $this->container->has($controller[0])) {
|
||||
$controller[0] = $this->instantiateController($controller[0]);
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callable for the given controller.
|
||||
*
|
||||
* @param string $controller A Controller string
|
||||
*
|
||||
* @return mixed A PHP callable
|
||||
*
|
||||
* @throws \LogicException When the name could not be parsed
|
||||
* @throws \InvalidArgumentException When the controller class does not exist
|
||||
*/
|
||||
protected function createController($controller)
|
||||
{
|
||||
if (false !== strpos($controller, '::')) {
|
||||
return parent::createController($controller);
|
||||
}
|
||||
|
||||
$method = null;
|
||||
if (1 == substr_count($controller, ':')) {
|
||||
// controller in the "service:method" notation
|
||||
list($controller, $method) = explode(':', $controller, 2);
|
||||
}
|
||||
|
||||
if (!$this->container->has($controller)) {
|
||||
$this->throwExceptionIfControllerWasRemoved($controller);
|
||||
|
||||
throw new \LogicException(sprintf('Controller not found: service "%s" does not exist.', $controller));
|
||||
}
|
||||
|
||||
$service = $this->container->get($controller);
|
||||
if (null !== $method) {
|
||||
return [$service, $method];
|
||||
}
|
||||
|
||||
if (!method_exists($service, '__invoke')) {
|
||||
throw new \LogicException(sprintf('Controller "%s" cannot be called without a method name. Did you forget an "__invoke" method?', $controller));
|
||||
}
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function instantiateController($class)
|
||||
{
|
||||
if ($this->container->has($class)) {
|
||||
return $this->container->get($class);
|
||||
}
|
||||
|
||||
try {
|
||||
return parent::instantiateController($class);
|
||||
} catch (\ArgumentCountError $e) {
|
||||
} catch (\ErrorException $e) {
|
||||
} catch (\TypeError $e) {
|
||||
}
|
||||
|
||||
$this->throwExceptionIfControllerWasRemoved($class, $e);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $controller
|
||||
* @param \Exception|\Throwable|null $previous
|
||||
*/
|
||||
private function throwExceptionIfControllerWasRemoved($controller, $previous = null)
|
||||
{
|
||||
if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) {
|
||||
throw new \LogicException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,15 +27,15 @@ use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
|
||||
class ControllerReference
|
||||
{
|
||||
public $controller;
|
||||
public $attributes = array();
|
||||
public $query = array();
|
||||
public $attributes = [];
|
||||
public $query = [];
|
||||
|
||||
/**
|
||||
* @param string $controller The controller name
|
||||
* @param array $attributes An array of parameters to add to the Request attributes
|
||||
* @param array $query An array of parameters to add to the Request query string
|
||||
*/
|
||||
public function __construct($controller, array $attributes = array(), array $query = array())
|
||||
public function __construct($controller, array $attributes = [], array $query = [])
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->attributes = $attributes;
|
||||
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ControllerResolver implements ControllerResolverInterface
|
||||
class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface
|
||||
{
|
||||
private $logger;
|
||||
|
||||
@@ -85,10 +85,10 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
}
|
||||
}
|
||||
|
||||
$callable = $this->createController($controller);
|
||||
|
||||
if (!\is_callable($callable)) {
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', $controller, $request->getPathInfo()));
|
||||
try {
|
||||
$callable = $this->createController($controller);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage()));
|
||||
}
|
||||
|
||||
return $callable;
|
||||
@@ -96,9 +96,13 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead.
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
if (\is_array($controller)) {
|
||||
$r = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
} elseif (\is_object($controller) && !$controller instanceof \Closure) {
|
||||
@@ -112,18 +116,21 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param callable $controller
|
||||
* @param \ReflectionParameter[] $parameters
|
||||
*
|
||||
* @return array The arguments to use when calling the action
|
||||
*
|
||||
* @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead.
|
||||
*/
|
||||
protected function doGetArguments(Request $request, $controller, array $parameters)
|
||||
{
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
$attributes = $request->attributes->all();
|
||||
$arguments = array();
|
||||
$arguments = [];
|
||||
foreach ($parameters as $param) {
|
||||
if (array_key_exists($param->name, $attributes)) {
|
||||
if (\array_key_exists($param->name, $attributes)) {
|
||||
if ($this->supportsVariadic && $param->isVariadic() && \is_array($attributes[$param->name])) {
|
||||
$arguments = array_merge($arguments, array_values($attributes[$param->name]));
|
||||
} else {
|
||||
@@ -158,7 +165,7 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
*
|
||||
* @return callable A PHP callable
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \InvalidArgumentException When the controller cannot be created
|
||||
*/
|
||||
protected function createController($controller)
|
||||
{
|
||||
@@ -172,7 +179,13 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
|
||||
}
|
||||
|
||||
return array($this->instantiateController($class), $method);
|
||||
$controller = [$this->instantiateController($class), $method];
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException($this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,4 +199,65 @@ class ControllerResolver implements ControllerResolverInterface
|
||||
{
|
||||
return new $class();
|
||||
}
|
||||
|
||||
private function getControllerError($callable)
|
||||
{
|
||||
if (\is_string($callable)) {
|
||||
if (false !== strpos($callable, '::')) {
|
||||
$callable = explode('::', $callable);
|
||||
}
|
||||
|
||||
if (class_exists($callable) && !method_exists($callable, '__invoke')) {
|
||||
return sprintf('Class "%s" does not have a method "__invoke".', $callable);
|
||||
}
|
||||
|
||||
if (!\function_exists($callable)) {
|
||||
return sprintf('Function "%s" does not exist.', $callable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!\is_array($callable)) {
|
||||
return sprintf('Invalid type for controller given, expected string or array, got "%s".', \gettype($callable));
|
||||
}
|
||||
|
||||
if (2 !== \count($callable)) {
|
||||
return 'Invalid format for controller, expected [controller, method] or controller::method.';
|
||||
}
|
||||
|
||||
list($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;
|
||||
|
||||
if (method_exists($controller, $method)) {
|
||||
return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className);
|
||||
}
|
||||
|
||||
$collection = get_class_methods($controller);
|
||||
|
||||
$alternatives = [];
|
||||
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($method, $item);
|
||||
|
||||
if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) {
|
||||
$alternatives[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
asort($alternatives);
|
||||
|
||||
$message = sprintf('Expected method "%s" on class "%s"', $method, $className);
|
||||
|
||||
if (\count($alternatives) > 0) {
|
||||
$message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives));
|
||||
} else {
|
||||
$message .= sprintf('. Available methods: "%s".', implode('", "', $collection));
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ interface ControllerResolverInterface
|
||||
* As several resolvers can exist for a single application, a resolver must
|
||||
* return false when it is not able to determine the controller.
|
||||
*
|
||||
* The resolver must only throw an exception when it should be able to load
|
||||
* The resolver must only throw an exception when it should be able to load a
|
||||
* controller but cannot because of some errors made by the developer.
|
||||
*
|
||||
* @return callable|false A PHP callable representing the Controller,
|
||||
@@ -50,6 +50,8 @@ interface ControllerResolverInterface
|
||||
* @return array An array of arguments to pass to the controller
|
||||
*
|
||||
* @throws \RuntimeException When value for argument given is not provided
|
||||
*
|
||||
* @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Please use the {@see ArgumentResolverInterface} instead.
|
||||
*/
|
||||
public function getArguments(Request $request, $controller);
|
||||
}
|
||||
|
||||
44
vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php
vendored
Normal file
44
vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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\HttpFoundation\Request;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TraceableArgumentResolver implements ArgumentResolverInterface
|
||||
{
|
||||
private $resolver;
|
||||
private $stopwatch;
|
||||
|
||||
public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch)
|
||||
{
|
||||
$this->resolver = $resolver;
|
||||
$this->stopwatch = $stopwatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
{
|
||||
$e = $this->stopwatch->start('controller.get_arguments');
|
||||
|
||||
$ret = $this->resolver->getArguments($request, $controller);
|
||||
|
||||
$e->stop();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,26 @@ use Symfony\Component\Stopwatch\Stopwatch;
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TraceableControllerResolver implements ControllerResolverInterface
|
||||
class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface
|
||||
{
|
||||
private $resolver;
|
||||
private $stopwatch;
|
||||
private $argumentResolver;
|
||||
|
||||
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
|
||||
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null)
|
||||
{
|
||||
$this->resolver = $resolver;
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->argumentResolver = $argumentResolver;
|
||||
|
||||
// BC
|
||||
if (null === $this->argumentResolver) {
|
||||
$this->argumentResolver = $resolver;
|
||||
}
|
||||
|
||||
if (!$this->argumentResolver instanceof TraceableArgumentResolver) {
|
||||
$this->argumentResolver = new TraceableArgumentResolver($this->argumentResolver, $this->stopwatch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,14 +55,14 @@ class TraceableControllerResolver implements ControllerResolverInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated This method is deprecated as of 3.1 and will be removed in 4.0.
|
||||
*/
|
||||
public function getArguments(Request $request, $controller)
|
||||
{
|
||||
$e = $this->stopwatch->start('controller.get_arguments');
|
||||
@trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Please use the %s instead.', __METHOD__, TraceableArgumentResolver::class), E_USER_DEPRECATED);
|
||||
|
||||
$ret = $this->resolver->getArguments($request, $controller);
|
||||
|
||||
$e->stop();
|
||||
$ret = $this->argumentResolver->getArguments($request, $controller);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
115
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php
vendored
Normal file
115
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?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\ControllerMetadata;
|
||||
|
||||
/**
|
||||
* Responsible for storing metadata of an argument.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
class ArgumentMetadata
|
||||
{
|
||||
private $name;
|
||||
private $type;
|
||||
private $isVariadic;
|
||||
private $hasDefaultValue;
|
||||
private $defaultValue;
|
||||
private $isNullable;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param bool $isVariadic
|
||||
* @param bool $hasDefaultValue
|
||||
* @param mixed $defaultValue
|
||||
* @param bool $isNullable
|
||||
*/
|
||||
public function __construct($name, $type, $isVariadic, $hasDefaultValue, $defaultValue, $isNullable = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
$this->isVariadic = $isVariadic;
|
||||
$this->hasDefaultValue = $hasDefaultValue;
|
||||
$this->defaultValue = $defaultValue;
|
||||
$this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name as given in PHP, $foo would yield "foo".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the argument.
|
||||
*
|
||||
* The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the argument is defined as "...$variadic".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVariadic()
|
||||
{
|
||||
return $this->isVariadic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the argument has a default value.
|
||||
*
|
||||
* Implies whether an argument is optional.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDefaultValue()
|
||||
{
|
||||
return $this->hasDefaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the argument accepts null values.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNullable()
|
||||
{
|
||||
return $this->isNullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value of the argument.
|
||||
*
|
||||
* @throws \LogicException if no default value is present; {@see self::hasDefaultValue()}
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
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__));
|
||||
}
|
||||
|
||||
return $this->defaultValue;
|
||||
}
|
||||
}
|
||||
135
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php
vendored
Normal file
135
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
<?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\ControllerMetadata;
|
||||
|
||||
/**
|
||||
* Builds {@see ArgumentMetadata} objects based on the given Controller.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
|
||||
{
|
||||
/**
|
||||
* If the ...$arg functionality is available.
|
||||
*
|
||||
* Requires at least PHP 5.6.0 or HHVM 3.9.1
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $supportsVariadic;
|
||||
|
||||
/**
|
||||
* If the reflection supports the getType() method to resolve types.
|
||||
*
|
||||
* Requires at least PHP 7.0.0 or HHVM 3.11.0
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $supportsParameterType;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic');
|
||||
$this->supportsParameterType = method_exists('ReflectionParameter', 'getType');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createArgumentMetadata($controller)
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
if (\is_array($controller)) {
|
||||
$reflection = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
} elseif (\is_object($controller) && !$controller instanceof \Closure) {
|
||||
$reflection = (new \ReflectionObject($controller))->getMethod('__invoke');
|
||||
} else {
|
||||
$reflection = new \ReflectionFunction($controller);
|
||||
}
|
||||
|
||||
foreach ($reflection->getParameters() as $param) {
|
||||
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull());
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an argument is variadic.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isVariadic(\ReflectionParameter $parameter)
|
||||
{
|
||||
return $this->supportsVariadic && $parameter->isVariadic();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an argument has a default value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasDefaultValue(\ReflectionParameter $parameter)
|
||||
{
|
||||
return $parameter->isDefaultValueAvailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default value if available.
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
private function getDefaultValue(\ReflectionParameter $parameter)
|
||||
{
|
||||
return $this->hasDefaultValue($parameter) ? $parameter->getDefaultValue() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associated type to the given parameter if available.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
|
||||
{
|
||||
if ($this->supportsParameterType) {
|
||||
if (!$type = $parameter->getType()) {
|
||||
return null;
|
||||
}
|
||||
$name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString();
|
||||
if ('array' === $name && !$type->isBuiltin()) {
|
||||
// Special case for HHVM with variadics
|
||||
return null;
|
||||
}
|
||||
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $name)) {
|
||||
$name = $name[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
$lcName = strtolower($name);
|
||||
|
||||
if ('self' !== $lcName && 'parent' !== $lcName) {
|
||||
return $name;
|
||||
}
|
||||
if (!$function instanceof \ReflectionMethod) {
|
||||
return null;
|
||||
}
|
||||
if ('self' === $lcName) {
|
||||
return $function->getDeclaringClass()->name;
|
||||
}
|
||||
if ($parent = $function->getDeclaringClass()->getParentClass()) {
|
||||
return $parent->name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
27
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php
vendored
Normal file
27
vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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\ControllerMetadata;
|
||||
|
||||
/**
|
||||
* Builds method argument data.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
interface ArgumentMetadataFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $controller The controller to resolve the arguments for
|
||||
*
|
||||
* @return ArgumentMetadata[]
|
||||
*/
|
||||
public function createArgumentMetadata($controller);
|
||||
}
|
||||
@@ -26,6 +26,11 @@ class AjaxDataCollector extends DataCollector
|
||||
// all collecting is done client side
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
// all collecting is done client side
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'ajax';
|
||||
|
||||
@@ -15,11 +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;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ConfigDataCollector extends DataCollector
|
||||
class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
/**
|
||||
* @var KernelInterface
|
||||
@@ -27,6 +28,7 @@ class ConfigDataCollector extends DataCollector
|
||||
private $kernel;
|
||||
private $name;
|
||||
private $version;
|
||||
private $hasVarDumper;
|
||||
|
||||
/**
|
||||
* @param string $name The name of the application using the web profiler
|
||||
@@ -36,6 +38,7 @@ class ConfigDataCollector extends DataCollector
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->hasVarDumper = class_exists(LinkStub::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +54,7 @@ class ConfigDataCollector extends DataCollector
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
$this->data = array(
|
||||
$this->data = [
|
||||
'app_name' => $this->name,
|
||||
'app_version' => $this->version,
|
||||
'token' => $response->headers->get('X-Debug-Token'),
|
||||
@@ -61,23 +64,46 @@ class ConfigDataCollector extends DataCollector
|
||||
'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_timezone' => date_default_timezone_get(),
|
||||
'xdebug_enabled' => \extension_loaded('xdebug'),
|
||||
'eaccel_enabled' => \extension_loaded('eaccelerator') && ini_get('eaccelerator.enable'),
|
||||
'apc_enabled' => \extension_loaded('apc') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN),
|
||||
'xcache_enabled' => \extension_loaded('xcache') && filter_var(ini_get('xcache.cacher'), FILTER_VALIDATE_BOOLEAN),
|
||||
'wincache_enabled' => \extension_loaded('wincache') && filter_var(ini_get('wincache.ocenabled'), 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' => array(),
|
||||
'bundles' => [],
|
||||
'sapi_name' => \PHP_SAPI,
|
||||
);
|
||||
];
|
||||
|
||||
if (isset($this->kernel)) {
|
||||
foreach ($this->kernel->getBundles() as $name => $bundle) {
|
||||
$this->data['bundles'][$name] = $bundle->getPath();
|
||||
$this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath();
|
||||
}
|
||||
|
||||
$this->data['symfony_state'] = $this->determineSymfonyState();
|
||||
$this->data['symfony_minor_version'] = sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION);
|
||||
$eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE);
|
||||
$eol = \DateTime::createFromFormat('d/m/Y', '01/'.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])) {
|
||||
$this->data['php_version'] = $matches[1];
|
||||
$this->data['php_version_extra'] = $matches[2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
public function lateCollect()
|
||||
{
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
public function getApplicationName()
|
||||
@@ -93,7 +119,7 @@ class ConfigDataCollector extends DataCollector
|
||||
/**
|
||||
* Gets the token.
|
||||
*
|
||||
* @return string The token
|
||||
* @return string|null The token
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
@@ -120,9 +146,37 @@ class ConfigDataCollector extends DataCollector
|
||||
return $this->data['symfony_state'];
|
||||
}
|
||||
|
||||
public function setCacheVersionInfo($cacheVersionInfo)
|
||||
/**
|
||||
* Returns the minor Symfony version used (without patch numbers of extra
|
||||
* suffix like "RC", "beta", etc.).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymfonyMinorVersion()
|
||||
{
|
||||
// no-op for BC
|
||||
return $this->data['symfony_minor_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human redable date when this Symfony version ends its
|
||||
* maintenance period.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymfonyEom()
|
||||
{
|
||||
return $this->data['symfony_eom'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human redable date when this Symfony version reaches its
|
||||
* "end of life" and won't receive bugs or security fixes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymfonyEol()
|
||||
{
|
||||
return $this->data['symfony_eol'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +189,40 @@ class ConfigDataCollector extends DataCollector
|
||||
return $this->data['php_version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP version extra part.
|
||||
*
|
||||
* @return string|null The extra part
|
||||
*/
|
||||
public function getPhpVersionExtra()
|
||||
{
|
||||
return isset($this->data['php_version_extra']) ? $this->data['php_version_extra'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int The PHP architecture as number of bits (e.g. 32 or 64)
|
||||
*/
|
||||
public function getPhpArchitecture()
|
||||
{
|
||||
return $this->data['php_architecture'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPhpIntlLocale()
|
||||
{
|
||||
return $this->data['php_intl_locale'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPhpTimezone()
|
||||
{
|
||||
return $this->data['php_timezone'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the application name.
|
||||
*
|
||||
@@ -176,23 +264,13 @@ class ConfigDataCollector extends DataCollector
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if EAccelerator is enabled.
|
||||
* Returns true if APCu is enabled.
|
||||
*
|
||||
* @return bool true if EAccelerator is enabled, false otherwise
|
||||
* @return bool true if APCu is enabled, false otherwise
|
||||
*/
|
||||
public function hasEAccelerator()
|
||||
public function hasApcu()
|
||||
{
|
||||
return $this->data['eaccel_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if APC is enabled.
|
||||
*
|
||||
* @return bool true if APC is enabled, false otherwise
|
||||
*/
|
||||
public function hasApc()
|
||||
{
|
||||
return $this->data['apc_enabled'];
|
||||
return $this->data['apcu_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,36 +283,6 @@ class ConfigDataCollector extends DataCollector
|
||||
return $this->data['zend_opcache_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if XCache is enabled.
|
||||
*
|
||||
* @return bool true if XCache is enabled, false otherwise
|
||||
*/
|
||||
public function hasXCache()
|
||||
{
|
||||
return $this->data['xcache_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if WinCache is enabled.
|
||||
*
|
||||
* @return bool true if WinCache is enabled, false otherwise
|
||||
*/
|
||||
public function hasWinCache()
|
||||
{
|
||||
return $this->data['wincache_enabled'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any accelerator is enabled.
|
||||
*
|
||||
* @return bool true if any accelerator is enabled, false otherwise
|
||||
*/
|
||||
public function hasAccelerator()
|
||||
{
|
||||
return $this->hasApc() || $this->hasZendOpcache() || $this->hasEAccelerator() || $this->hasXCache() || $this->hasWinCache();
|
||||
}
|
||||
|
||||
public function getBundles()
|
||||
{
|
||||
return $this->data['bundles'];
|
||||
@@ -266,8 +314,8 @@ class ConfigDataCollector extends DataCollector
|
||||
private function determineSymfonyState()
|
||||
{
|
||||
$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';
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
|
||||
use Symfony\Component\VarDumper\Caster\CutStub;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
/**
|
||||
* DataCollector.
|
||||
@@ -23,21 +28,68 @@ use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
|
||||
*/
|
||||
abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
{
|
||||
protected $data = array();
|
||||
/**
|
||||
* @var array|Data
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* @var ValueExporter
|
||||
*/
|
||||
private $valueExporter;
|
||||
|
||||
/**
|
||||
* @var ClonerInterface
|
||||
*/
|
||||
private $cloner;
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->data);
|
||||
$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);
|
||||
}
|
||||
|
||||
public function unserialize($data)
|
||||
{
|
||||
$this->data = unserialize($data);
|
||||
$this->data = \is_array($data) ? $data : unserialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the variable into a serializable Data instance.
|
||||
*
|
||||
* This array can be displayed in the template using
|
||||
* the VarDumper component.
|
||||
*
|
||||
* @param mixed $var
|
||||
*
|
||||
* @return Data
|
||||
*/
|
||||
protected function cloneVar($var)
|
||||
{
|
||||
if ($var instanceof Data) {
|
||||
return $var;
|
||||
}
|
||||
if (null === $this->cloner) {
|
||||
if (class_exists(CutStub::class)) {
|
||||
$this->cloner = new VarCloner();
|
||||
$this->cloner->setMaxItems(-1);
|
||||
$this->cloner->addCasters($this->getCasters());
|
||||
} else {
|
||||
@trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since Symfony 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED);
|
||||
$this->cloner = false;
|
||||
}
|
||||
}
|
||||
if (false === $this->cloner) {
|
||||
if (null === $this->valueExporter) {
|
||||
$this->valueExporter = new ValueExporter();
|
||||
}
|
||||
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
|
||||
return $this->cloner->cloneVar($var);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,13 +98,37 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
|
||||
* @param mixed $var A PHP variable
|
||||
*
|
||||
* @return string The string representation of the variable
|
||||
*
|
||||
* @deprecated since version 3.2, to be removed in 4.0. Use cloneVar() instead.
|
||||
*/
|
||||
protected function varToString($var)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use cloneVar() instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if (null === $this->valueExporter) {
|
||||
$this->valueExporter = new ValueExporter();
|
||||
}
|
||||
|
||||
return $this->valueExporter->exportValue($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable[] The casters to add to the cloner
|
||||
*/
|
||||
protected function getCasters()
|
||||
{
|
||||
return [
|
||||
'*' => function ($v, array $a, Stub $s, $isNested) {
|
||||
if (!$v instanceof Stub) {
|
||||
foreach ($a as $k => $v) {
|
||||
if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
|
||||
$a[$k] = new CutStub($v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $a;
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
* DataCollectorInterface.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @method reset() Resets this data collector to its initial state.
|
||||
*/
|
||||
interface DataCollectorInterface
|
||||
{
|
||||
|
||||
@@ -49,12 +49,12 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->dumperIsInjected = null !== $dumper;
|
||||
|
||||
// All clones share these properties by reference:
|
||||
$this->rootRefs = array(
|
||||
$this->rootRefs = [
|
||||
&$this->data,
|
||||
&$this->dataCount,
|
||||
&$this->isCollected,
|
||||
&$this->clonesCount,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
@@ -71,12 +71,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->isCollected = false;
|
||||
}
|
||||
|
||||
$trace = DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS;
|
||||
if (\PHP_VERSION_ID >= 50400) {
|
||||
$trace = debug_backtrace($trace, 7);
|
||||
} else {
|
||||
$trace = debug_backtrace($trace);
|
||||
}
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 7);
|
||||
|
||||
$file = $trace[0]['file'];
|
||||
$line = $trace[0]['line'];
|
||||
@@ -108,7 +103,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
|
||||
if ($src) {
|
||||
$src = explode("\n", $src);
|
||||
$fileExcerpt = array();
|
||||
$fileExcerpt = [];
|
||||
|
||||
for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) {
|
||||
$fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';
|
||||
@@ -158,6 +153,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
) {
|
||||
if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) {
|
||||
$this->dumper = new HtmlDumper('php://output', $this->charset);
|
||||
$this->dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
|
||||
} else {
|
||||
$this->dumper = new CliDumper('php://output', $this->charset);
|
||||
}
|
||||
@@ -168,6 +164,18 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
if ($this->stopwatch) {
|
||||
$this->stopwatch->reset();
|
||||
}
|
||||
$this->data = [];
|
||||
$this->dataCount = 0;
|
||||
$this->isCollected = true;
|
||||
$this->clonesCount = 0;
|
||||
$this->clonesIndex = 0;
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
if ($this->clonesCount !== $this->clonesIndex) {
|
||||
@@ -177,7 +185,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->data[] = $this->fileLinkFormat;
|
||||
$this->data[] = $this->charset;
|
||||
$ser = serialize($this->data);
|
||||
$this->data = array();
|
||||
$this->data = [];
|
||||
$this->dataCount = 0;
|
||||
$this->isCollected = true;
|
||||
if (!$this->dumperIsInjected) {
|
||||
@@ -189,7 +197,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
|
||||
public function unserialize($data)
|
||||
{
|
||||
parent::unserialize($data);
|
||||
$this->data = unserialize($data);
|
||||
$charset = array_pop($this->data);
|
||||
$fileLinkFormat = array_pop($this->data);
|
||||
$this->dataCount = \count($this->data);
|
||||
@@ -207,18 +215,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
|
||||
if ('html' === $format) {
|
||||
$dumper = new HtmlDumper($data, $this->charset);
|
||||
$dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format));
|
||||
}
|
||||
$dumps = array();
|
||||
$dumps = [];
|
||||
|
||||
foreach ($this->data as $dump) {
|
||||
if (method_exists($dump['data'], 'withMaxDepth')) {
|
||||
$dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth));
|
||||
} else {
|
||||
// getLimitedClone is @deprecated, to be removed in 3.0
|
||||
$dumper->dump($dump['data']->getLimitedClone($maxDepthLimit, $maxItemsPerDepth));
|
||||
}
|
||||
$dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth));
|
||||
$dump['data'] = stream_get_contents($data, -1, 0);
|
||||
ftruncate($data, 0);
|
||||
rewind($data);
|
||||
@@ -246,8 +250,9 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
--$i;
|
||||
}
|
||||
|
||||
if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true) && stripos($h[$i], 'html')) {
|
||||
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html')) {
|
||||
$this->dumper = new HtmlDumper('php://output', $this->charset);
|
||||
$this->dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
|
||||
} else {
|
||||
$this->dumper = new CliDumper('php://output', $this->charset);
|
||||
}
|
||||
@@ -257,25 +262,24 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
|
||||
}
|
||||
|
||||
$this->data = array();
|
||||
$this->data = [];
|
||||
$this->dataCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private function doDump($data, $name, $file, $line)
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 50400 && $this->dumper instanceof CliDumper) {
|
||||
$contextDumper = function ($name, $file, $line, $fileLinkFormat) {
|
||||
if ($this->dumper instanceof CliDumper) {
|
||||
$contextDumper = function ($name, $file, $line, $fmt) {
|
||||
if ($this instanceof HtmlDumper) {
|
||||
if ($file) {
|
||||
$s = $this->style('meta', '%s');
|
||||
$f = strip_tags($this->style('', $file));
|
||||
$name = strip_tags($this->style('', $name));
|
||||
$file = strip_tags($this->style('', $file));
|
||||
if ($fileLinkFormat) {
|
||||
$link = strtr(strip_tags($this->style('', $fileLinkFormat)), array('%f' => $file, '%l' => (int) $line));
|
||||
$name = sprintf('<a href="%s" title="%s">'.$s.'</a>', $link, $file, $name);
|
||||
if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) {
|
||||
$name = sprintf('<a href="%s" title="%s">'.$s.'</a>', strip_tags($this->style('', $link)), $f, $name);
|
||||
} else {
|
||||
$name = sprintf('<abbr title="%s">'.$s.'</abbr>', $file, $name);
|
||||
$name = sprintf('<abbr title="%s">'.$s.'</abbr>', $f, $name);
|
||||
}
|
||||
} else {
|
||||
$name = $this->style('meta', $name);
|
||||
|
||||
@@ -27,6 +27,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
if ($dispatcher instanceof TraceableEventDispatcherInterface && !method_exists($dispatcher, 'reset')) {
|
||||
@trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', TraceableEventDispatcherInterface::class, \get_class($dispatcher)), E_USER_DEPRECATED);
|
||||
}
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
@@ -35,10 +38,23 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
$this->data = array(
|
||||
'called_listeners' => array(),
|
||||
'not_called_listeners' => array(),
|
||||
);
|
||||
$this->data = [
|
||||
'called_listeners' => [],
|
||||
'not_called_listeners' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [];
|
||||
|
||||
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
|
||||
if (!method_exists($this->dispatcher, 'reset')) {
|
||||
return; // @deprecated
|
||||
}
|
||||
|
||||
$this->dispatcher->reset();
|
||||
}
|
||||
}
|
||||
|
||||
public function lateCollect()
|
||||
@@ -47,6 +63,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
|
||||
$this->setCalledListeners($this->dispatcher->getCalledListeners());
|
||||
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
|
||||
}
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,12 +28,20 @@ class ExceptionDataCollector extends DataCollector
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
if (null !== $exception) {
|
||||
$this->data = array(
|
||||
$this->data = [
|
||||
'exception' => FlattenException::create($exception),
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the exception is not null.
|
||||
*
|
||||
@@ -47,7 +55,7 @@ class ExceptionDataCollector extends DataCollector
|
||||
/**
|
||||
* Gets the exception.
|
||||
*
|
||||
* @return \Exception The exception
|
||||
* @return \Exception|FlattenException
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\Debug\Exception\SilencedErrorContext;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
@@ -22,31 +23,20 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
*/
|
||||
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
private $errorNames = array(
|
||||
E_DEPRECATED => 'E_DEPRECATED',
|
||||
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
|
||||
E_NOTICE => 'E_NOTICE',
|
||||
E_USER_NOTICE => 'E_USER_NOTICE',
|
||||
E_STRICT => 'E_STRICT',
|
||||
E_WARNING => 'E_WARNING',
|
||||
E_USER_WARNING => 'E_USER_WARNING',
|
||||
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
|
||||
E_CORE_WARNING => 'E_CORE_WARNING',
|
||||
E_USER_ERROR => 'E_USER_ERROR',
|
||||
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
|
||||
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
|
||||
E_PARSE => 'E_PARSE',
|
||||
E_ERROR => 'E_ERROR',
|
||||
E_CORE_ERROR => 'E_CORE_ERROR',
|
||||
);
|
||||
|
||||
private $logger;
|
||||
private $containerPathPrefix;
|
||||
|
||||
public function __construct($logger = null)
|
||||
public function __construct($logger = null, $containerPathPrefix = null)
|
||||
{
|
||||
if (null !== $logger && $logger instanceof DebugLoggerInterface) {
|
||||
if (!method_exists($logger, 'clear')) {
|
||||
@trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
$this->containerPathPrefix = $containerPathPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,27 +50,36 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lateCollect()
|
||||
public function reset()
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->data = $this->computeErrorsCount();
|
||||
$this->data['logs'] = $this->sanitizeLogs($this->logger->getLogs());
|
||||
if ($this->logger && method_exists($this->logger, 'clear')) {
|
||||
$this->logger->clear();
|
||||
}
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the logs.
|
||||
*
|
||||
* @return array An array of logs
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lateCollect()
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$containerDeprecationLogs = $this->getContainerDeprecationLogs();
|
||||
$this->data = $this->computeErrorsCount($containerDeprecationLogs);
|
||||
$this->data['compiler_logs'] = $this->getContainerCompilerLogs();
|
||||
$this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs));
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
}
|
||||
|
||||
public function getLogs()
|
||||
{
|
||||
return isset($this->data['logs']) ? $this->data['logs'] : array();
|
||||
return isset($this->data['logs']) ? $this->data['logs'] : [];
|
||||
}
|
||||
|
||||
public function getPriorities()
|
||||
{
|
||||
return isset($this->data['priorities']) ? $this->data['priorities'] : array();
|
||||
return isset($this->data['priorities']) ? $this->data['priorities'] : [];
|
||||
}
|
||||
|
||||
public function countErrors()
|
||||
@@ -93,11 +92,21 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0;
|
||||
}
|
||||
|
||||
public function countWarnings()
|
||||
{
|
||||
return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0;
|
||||
}
|
||||
|
||||
public function countScreams()
|
||||
{
|
||||
return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0;
|
||||
}
|
||||
|
||||
public function getCompilerLogs()
|
||||
{
|
||||
return isset($this->data['compiler_logs']) ? $this->data['compiler_logs'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -106,106 +115,161 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
return 'logger';
|
||||
}
|
||||
|
||||
private function getContainerDeprecationLogs()
|
||||
{
|
||||
if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ('' === $logContent = trim(file_get_contents($file))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$bootTime = filemtime($file);
|
||||
$logs = [];
|
||||
foreach (unserialize($logContent) as $log) {
|
||||
$log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])];
|
||||
$log['timestamp'] = $bootTime;
|
||||
$log['priority'] = 100;
|
||||
$log['priorityName'] = 'DEBUG';
|
||||
$log['channel'] = '-';
|
||||
$log['scream'] = false;
|
||||
unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']);
|
||||
$logs[] = $log;
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function getContainerCompilerLogs()
|
||||
{
|
||||
if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Compiler.log')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
foreach (file($file, 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)];
|
||||
}
|
||||
|
||||
$logs[$log[0]][] = ['message' => $log[1]];
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function sanitizeLogs($logs)
|
||||
{
|
||||
$errorContextById = array();
|
||||
$sanitizedLogs = array();
|
||||
$sanitizedLogs = [];
|
||||
$silencedLogs = [];
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$context = $this->sanitizeContext($log['context']);
|
||||
if (!$this->isSilencedOrDeprecationErrorLog($log)) {
|
||||
$sanitizedLogs[] = $log;
|
||||
|
||||
if (isset($context['type'], $context['file'], $context['line'], $context['level'])) {
|
||||
$errorId = md5("{$context['type']}/{$context['line']}/{$context['file']}\x00{$log['message']}", true);
|
||||
$silenced = !($context['type'] & $context['level']);
|
||||
if (isset($this->errorNames[$context['type']])) {
|
||||
$context = array_merge(array('name' => $this->errorNames[$context['type']]), $context);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($errorContextById[$errorId])) {
|
||||
if (isset($errorContextById[$errorId]['errorCount'])) {
|
||||
++$errorContextById[$errorId]['errorCount'];
|
||||
} else {
|
||||
$errorContextById[$errorId]['errorCount'] = 2;
|
||||
}
|
||||
|
||||
if (!$silenced && isset($errorContextById[$errorId]['scream'])) {
|
||||
unset($errorContextById[$errorId]['scream']);
|
||||
$errorContextById[$errorId]['level'] = $context['level'];
|
||||
}
|
||||
$message = $log['message'];
|
||||
$exception = $log['context']['exception'];
|
||||
|
||||
if ($exception instanceof SilencedErrorContext) {
|
||||
if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
|
||||
continue;
|
||||
}
|
||||
$silencedLogs[$h] = true;
|
||||
|
||||
$errorContextById[$errorId] = &$context;
|
||||
if ($silenced) {
|
||||
$context['scream'] = true;
|
||||
if (!isset($sanitizedLogs[$message])) {
|
||||
$sanitizedLogs[$message] = $log + [
|
||||
'errorCount' => 0,
|
||||
'scream' => true,
|
||||
];
|
||||
}
|
||||
$sanitizedLogs[$message]['errorCount'] += $exception->count;
|
||||
|
||||
$log['context'] = &$context;
|
||||
unset($context);
|
||||
continue;
|
||||
}
|
||||
|
||||
$errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true);
|
||||
|
||||
if (isset($sanitizedLogs[$errorId])) {
|
||||
++$sanitizedLogs[$errorId]['errorCount'];
|
||||
} else {
|
||||
$log['context'] = $context;
|
||||
}
|
||||
$log += [
|
||||
'errorCount' => 1,
|
||||
'scream' => false,
|
||||
];
|
||||
|
||||
$sanitizedLogs[] = $log;
|
||||
$sanitizedLogs[$errorId] = $log;
|
||||
}
|
||||
}
|
||||
|
||||
return $sanitizedLogs;
|
||||
return array_values($sanitizedLogs);
|
||||
}
|
||||
|
||||
private function sanitizeContext($context)
|
||||
private function isSilencedOrDeprecationErrorLog(array $log)
|
||||
{
|
||||
if (\is_array($context)) {
|
||||
foreach ($context as $key => $value) {
|
||||
$context[$key] = $this->sanitizeContext($value);
|
||||
}
|
||||
|
||||
return $context;
|
||||
if (!isset($log['context']['exception'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\is_resource($context)) {
|
||||
return sprintf('Resource(%s)', get_resource_type($context));
|
||||
$exception = $log['context']['exception'];
|
||||
|
||||
if ($exception instanceof SilencedErrorContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\is_object($context)) {
|
||||
if ($context instanceof \Exception) {
|
||||
return sprintf('Exception(%s): %s', \get_class($context), $context->getMessage());
|
||||
}
|
||||
|
||||
return sprintf('Object(%s)', \get_class($context));
|
||||
if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $context;
|
||||
return false;
|
||||
}
|
||||
|
||||
private function computeErrorsCount()
|
||||
private function computeErrorsCount(array $containerDeprecationLogs)
|
||||
{
|
||||
$count = array(
|
||||
$silencedLogs = [];
|
||||
$count = [
|
||||
'error_count' => $this->logger->countErrors(),
|
||||
'deprecation_count' => 0,
|
||||
'warning_count' => 0,
|
||||
'scream_count' => 0,
|
||||
'priorities' => array(),
|
||||
);
|
||||
'priorities' => [],
|
||||
];
|
||||
|
||||
foreach ($this->logger->getLogs() as $log) {
|
||||
if (isset($count['priorities'][$log['priority']])) {
|
||||
++$count['priorities'][$log['priority']]['count'];
|
||||
} else {
|
||||
$count['priorities'][$log['priority']] = array(
|
||||
$count['priorities'][$log['priority']] = [
|
||||
'count' => 1,
|
||||
'name' => $log['priorityName'],
|
||||
);
|
||||
];
|
||||
}
|
||||
if ('WARNING' === $log['priorityName']) {
|
||||
++$count['warning_count'];
|
||||
}
|
||||
|
||||
if (isset($log['context']['type'], $log['context']['level'])) {
|
||||
if (E_DEPRECATED === $log['context']['type'] || E_USER_DEPRECATED === $log['context']['type']) {
|
||||
if ($this->isSilencedOrDeprecationErrorLog($log)) {
|
||||
$exception = $log['context']['exception'];
|
||||
if ($exception instanceof SilencedErrorContext) {
|
||||
if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
|
||||
continue;
|
||||
}
|
||||
$silencedLogs[$h] = true;
|
||||
$count['scream_count'] += $exception->count;
|
||||
} else {
|
||||
++$count['deprecation_count'];
|
||||
} elseif (!($log['context']['type'] & $log['context']['level'])) {
|
||||
++$count['scream_count'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($containerDeprecationLogs as $deprecationLog) {
|
||||
$count['deprecation_count'] += $deprecationLog['context']['exception']->count;
|
||||
}
|
||||
|
||||
ksort($count['priorities']);
|
||||
|
||||
return $count;
|
||||
|
||||
@@ -23,10 +23,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->data = array(
|
||||
'memory' => 0,
|
||||
'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
|
||||
);
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +34,17 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
||||
$this->updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [
|
||||
'memory' => 0,
|
||||
'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -12,16 +12,18 @@
|
||||
namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class RequestDataCollector extends DataCollector implements EventSubscriberInterface
|
||||
class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
|
||||
{
|
||||
protected $controllers;
|
||||
|
||||
@@ -35,28 +37,18 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Exception $exception = null)
|
||||
{
|
||||
$responseHeaders = $response->headers->all();
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
$responseHeaders['set-cookie'][] = (string) $cookie;
|
||||
}
|
||||
|
||||
// attributes are serialized and as they can be anything, they need to be converted to strings.
|
||||
$attributes = array();
|
||||
$attributes = [];
|
||||
$route = '';
|
||||
foreach ($request->attributes->all() as $key => $value) {
|
||||
if ('_route' === $key && \is_object($value)) {
|
||||
$attributes[$key] = $this->varToString($value->getPath());
|
||||
} elseif ('_route_params' === $key) {
|
||||
// we need to keep route params as an array (see getRouteParams())
|
||||
foreach ($value as $k => $v) {
|
||||
$value[$k] = $this->varToString($v);
|
||||
}
|
||||
$attributes[$key] = $value;
|
||||
if ('_route' === $key) {
|
||||
$route = \is_object($value) ? $value->getPath() : $value;
|
||||
$attributes[$key] = $route;
|
||||
} else {
|
||||
$attributes[$key] = $this->varToString($value);
|
||||
$attributes[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$content = null;
|
||||
try {
|
||||
$content = $request->getContent();
|
||||
} catch (\LogicException $e) {
|
||||
@@ -64,9 +56,9 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
$content = false;
|
||||
}
|
||||
|
||||
$sessionMetadata = array();
|
||||
$sessionAttributes = array();
|
||||
$flashes = array();
|
||||
$sessionMetadata = [];
|
||||
$sessionAttributes = [];
|
||||
$flashes = [];
|
||||
if ($request->hasSession()) {
|
||||
$session = $request->getSession();
|
||||
if ($session->isStarted()) {
|
||||
@@ -80,7 +72,13 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
|
||||
$statusCode = $response->getStatusCode();
|
||||
|
||||
$this->data = array(
|
||||
$responseCookies = [];
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
$responseCookies[$cookie->getName()] = $cookie;
|
||||
}
|
||||
|
||||
$this->data = [
|
||||
'method' => $request->getMethod(),
|
||||
'format' => $request->getRequestFormat(),
|
||||
'content' => $content,
|
||||
'content_type' => $response->headers->get('Content-Type', 'text/html'),
|
||||
@@ -92,14 +90,16 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
'request_server' => $request->server->all(),
|
||||
'request_cookies' => $request->cookies->all(),
|
||||
'request_attributes' => $attributes,
|
||||
'response_headers' => $responseHeaders,
|
||||
'route' => $route,
|
||||
'response_headers' => $response->headers->all(),
|
||||
'response_cookies' => $responseCookies,
|
||||
'session_metadata' => $sessionMetadata,
|
||||
'session_attributes' => $sessionAttributes,
|
||||
'flashes' => $flashes,
|
||||
'path_info' => $request->getPathInfo(),
|
||||
'controller' => 'n/a',
|
||||
'locale' => $request->getLocale(),
|
||||
);
|
||||
];
|
||||
|
||||
if (isset($this->data['request_headers']['php-auth-pw'])) {
|
||||
$this->data['request_headers']['php-auth-pw'] = '******';
|
||||
@@ -118,56 +118,52 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
continue;
|
||||
}
|
||||
if ('request_headers' === $key || 'response_headers' === $key) {
|
||||
$value = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
|
||||
}
|
||||
if ('request_server' !== $key && 'request_cookies' !== $key) {
|
||||
$this->data[$key] = $value;
|
||||
$this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->controllers[$request])) {
|
||||
$controller = $this->controllers[$request];
|
||||
if (\is_array($controller)) {
|
||||
try {
|
||||
$r = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
$this->data['controller'] = array(
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
);
|
||||
} catch (\ReflectionException $e) {
|
||||
if (\is_callable($controller)) {
|
||||
// using __call or __callStatic
|
||||
$this->data['controller'] = array(
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => 'n/a',
|
||||
'line' => 'n/a',
|
||||
);
|
||||
}
|
||||
}
|
||||
} elseif ($controller instanceof \Closure) {
|
||||
$r = new \ReflectionFunction($controller);
|
||||
$this->data['controller'] = array(
|
||||
'class' => $r->getName(),
|
||||
'method' => null,
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
);
|
||||
} elseif (\is_object($controller)) {
|
||||
$r = new \ReflectionClass($controller);
|
||||
$this->data['controller'] = array(
|
||||
'class' => $r->getName(),
|
||||
'method' => null,
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
);
|
||||
} else {
|
||||
$this->data['controller'] = (string) $controller ?: 'n/a';
|
||||
}
|
||||
$this->data['controller'] = $this->parseController($this->controllers[$request]);
|
||||
unset($this->controllers[$request]);
|
||||
}
|
||||
|
||||
if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) {
|
||||
$this->data['redirect'] = json_decode($redirectCookie, true);
|
||||
|
||||
$response->headers->clearCookie('sf_redirect');
|
||||
}
|
||||
|
||||
if ($response->isRedirect()) {
|
||||
$response->headers->setCookie(new Cookie(
|
||||
'sf_redirect',
|
||||
json_encode([
|
||||
'token' => $response->headers->get('x-debug-token'),
|
||||
'route' => $request->attributes->get('_route', 'n/a'),
|
||||
'method' => $request->getMethod(),
|
||||
'controller' => $this->parseController($request->attributes->get('_controller')),
|
||||
'status_code' => $statusCode,
|
||||
'status_text' => Response::$statusTexts[(int) $statusCode],
|
||||
])
|
||||
));
|
||||
}
|
||||
|
||||
$this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
|
||||
}
|
||||
|
||||
public function lateCollect()
|
||||
{
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [];
|
||||
$this->controllers = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->data['method'];
|
||||
}
|
||||
|
||||
public function getPathInfo()
|
||||
@@ -177,52 +173,57 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
|
||||
public function getRequestRequest()
|
||||
{
|
||||
return new ParameterBag($this->data['request_request']);
|
||||
return new ParameterBag($this->data['request_request']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestQuery()
|
||||
{
|
||||
return new ParameterBag($this->data['request_query']);
|
||||
return new ParameterBag($this->data['request_query']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestHeaders()
|
||||
{
|
||||
return new ParameterBag($this->data['request_headers']);
|
||||
return new ParameterBag($this->data['request_headers']->getValue());
|
||||
}
|
||||
|
||||
public function getRequestServer()
|
||||
public function getRequestServer($raw = false)
|
||||
{
|
||||
return new ParameterBag($this->data['request_server']);
|
||||
return new ParameterBag($this->data['request_server']->getValue($raw));
|
||||
}
|
||||
|
||||
public function getRequestCookies()
|
||||
public function getRequestCookies($raw = false)
|
||||
{
|
||||
return new ParameterBag($this->data['request_cookies']);
|
||||
return new ParameterBag($this->data['request_cookies']->getValue($raw));
|
||||
}
|
||||
|
||||
public function getRequestAttributes()
|
||||
{
|
||||
return new ParameterBag($this->data['request_attributes']);
|
||||
return new ParameterBag($this->data['request_attributes']->getValue());
|
||||
}
|
||||
|
||||
public function getResponseHeaders()
|
||||
{
|
||||
return new ParameterBag($this->data['response_headers']);
|
||||
return new ParameterBag($this->data['response_headers']->getValue());
|
||||
}
|
||||
|
||||
public function getResponseCookies()
|
||||
{
|
||||
return new ParameterBag($this->data['response_cookies']->getValue());
|
||||
}
|
||||
|
||||
public function getSessionMetadata()
|
||||
{
|
||||
return $this->data['session_metadata'];
|
||||
return $this->data['session_metadata']->getValue();
|
||||
}
|
||||
|
||||
public function getSessionAttributes()
|
||||
{
|
||||
return $this->data['session_attributes'];
|
||||
return $this->data['session_attributes']->getValue();
|
||||
}
|
||||
|
||||
public function getFlashes()
|
||||
{
|
||||
return $this->data['flashes'];
|
||||
return $this->data['flashes']->getValue();
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
@@ -264,7 +265,12 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return isset($this->data['request_attributes']['_route']) ? $this->data['request_attributes']['_route'] : '';
|
||||
return $this->data['route'];
|
||||
}
|
||||
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->data['identifier'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,27 +282,53 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
*/
|
||||
public function getRouteParams()
|
||||
{
|
||||
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params'] : array();
|
||||
return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the controller.
|
||||
* Gets the parsed controller.
|
||||
*
|
||||
* @return string The controller as a string
|
||||
* @return array|string The controller as a string or array of data
|
||||
* with keys 'class', 'method', 'file' and 'line'
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
return $this->data['controller'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the previous request attributes.
|
||||
*
|
||||
* @return array|bool 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;
|
||||
}
|
||||
|
||||
public function onKernelController(FilterControllerEvent $event)
|
||||
{
|
||||
$this->controllers[$event->getRequest()] = $event->getController();
|
||||
}
|
||||
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->getRequest()->cookies->has('sf_redirect')) {
|
||||
$event->getRequest()->attributes->set('_redirected', true);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(KernelEvents::CONTROLLER => 'onKernelController');
|
||||
return [
|
||||
KernelEvents::CONTROLLER => 'onKernelController',
|
||||
KernelEvents::RESPONSE => 'onKernelResponse',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,4 +338,78 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
|
||||
{
|
||||
return 'request';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a controller.
|
||||
*
|
||||
* @param mixed $controller The controller to parse
|
||||
*
|
||||
* @return array|string An array of controller data or a simple string
|
||||
*/
|
||||
protected function parseController($controller)
|
||||
{
|
||||
if (\is_string($controller) && false !== strpos($controller, '::')) {
|
||||
$controller = explode('::', $controller);
|
||||
}
|
||||
|
||||
if (\is_array($controller)) {
|
||||
try {
|
||||
$r = new \ReflectionMethod($controller[0], $controller[1]);
|
||||
|
||||
return [
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
];
|
||||
} catch (\ReflectionException $e) {
|
||||
if (\is_callable($controller)) {
|
||||
// using __call or __callStatic
|
||||
return [
|
||||
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
|
||||
'method' => $controller[1],
|
||||
'file' => 'n/a',
|
||||
'line' => 'n/a',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($controller instanceof \Closure) {
|
||||
$r = new \ReflectionFunction($controller);
|
||||
|
||||
$controller = [
|
||||
'class' => $r->getName(),
|
||||
'method' => null,
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
];
|
||||
|
||||
if (false !== strpos($r->name, '{closure}')) {
|
||||
return $controller;
|
||||
}
|
||||
$controller['method'] = $r->name;
|
||||
|
||||
if ($class = $r->getClosureScopeClass()) {
|
||||
$controller['class'] = $class->name;
|
||||
} else {
|
||||
return $r->name;
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
if (\is_object($controller)) {
|
||||
$r = new \ReflectionClass($controller);
|
||||
|
||||
return [
|
||||
'class' => $r->getName(),
|
||||
'method' => null,
|
||||
'file' => $r->getFileName(),
|
||||
'line' => $r->getStartLine(),
|
||||
];
|
||||
}
|
||||
|
||||
return \is_string($controller) ? $controller : 'n/a';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,17 +23,14 @@ use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
|
||||
*/
|
||||
class RouterDataCollector extends DataCollector
|
||||
{
|
||||
/**
|
||||
* @var \SplObjectStorage
|
||||
*/
|
||||
protected $controllers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->controllers = new \SplObjectStorage();
|
||||
|
||||
$this->data = array(
|
||||
'redirect' => false,
|
||||
'url' => null,
|
||||
'route' => null,
|
||||
);
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,6 +50,17 @@ class RouterDataCollector extends DataCollector
|
||||
unset($this->controllers[$request]);
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->controllers = new \SplObjectStorage();
|
||||
|
||||
$this->data = [
|
||||
'redirect' => false,
|
||||
'url' => null,
|
||||
'route' => null,
|
||||
];
|
||||
}
|
||||
|
||||
protected function guessRoute(Request $request, $controller)
|
||||
{
|
||||
return 'n/a';
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace Symfony\Component\HttpKernel\DataCollector;
|
||||
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>
|
||||
*/
|
||||
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
@@ -25,7 +25,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
protected $kernel;
|
||||
protected $stopwatch;
|
||||
|
||||
public function __construct(KernelInterface $kernel = null, $stopwatch = null)
|
||||
public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->stopwatch = $stopwatch;
|
||||
@@ -39,14 +39,27 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
if (null !== $this->kernel) {
|
||||
$startTime = $this->kernel->getStartTime();
|
||||
} else {
|
||||
$startTime = $request->server->get('REQUEST_TIME_FLOAT', $request->server->get('REQUEST_TIME'));
|
||||
$startTime = $request->server->get('REQUEST_TIME_FLOAT');
|
||||
}
|
||||
|
||||
$this->data = array(
|
||||
$this->data = [
|
||||
'token' => $response->headers->get('X-Debug-Token'),
|
||||
'start_time' => $startTime * 1000,
|
||||
'events' => array(),
|
||||
);
|
||||
'events' => [],
|
||||
'stopwatch_installed' => class_exists(Stopwatch::class, false),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->data = [];
|
||||
|
||||
if (null !== $this->stopwatch) {
|
||||
$this->stopwatch->reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +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)
|
||||
{
|
||||
@@ -77,7 +90,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
/**
|
||||
* Gets the request events.
|
||||
*
|
||||
* @return array The request events
|
||||
* @return StopwatchEvent[] The request events
|
||||
*/
|
||||
public function getEvents()
|
||||
{
|
||||
@@ -119,13 +132,21 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
|
||||
/**
|
||||
* Gets the request time.
|
||||
*
|
||||
* @return int The time
|
||||
* @return float
|
||||
*/
|
||||
public function getStartTime()
|
||||
{
|
||||
return $this->data['start_time'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether or not the stopwatch component is installed
|
||||
*/
|
||||
public function isStopwatchInstalled()
|
||||
{
|
||||
return $this->data['stopwatch_installed'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -11,8 +11,12 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DataCollector\Util;
|
||||
|
||||
@trigger_error('The '.__NAMESPACE__.'\ValueExporter class is deprecated since Symfony 3.2 and will be removed in 4.0. Use the VarDumper component instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*
|
||||
* @deprecated since version 3.2, to be removed in 4.0. Use the VarDumper component instead.
|
||||
*/
|
||||
class ValueExporter
|
||||
{
|
||||
@@ -32,7 +36,7 @@ class ValueExporter
|
||||
}
|
||||
|
||||
if (\is_object($value)) {
|
||||
if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) {
|
||||
if ($value instanceof \DateTimeInterface) {
|
||||
return sprintf('Object(%s) - %s', \get_class($value), $value->format(\DateTime::ATOM));
|
||||
}
|
||||
|
||||
@@ -46,7 +50,7 @@ class ValueExporter
|
||||
|
||||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
$a = array();
|
||||
$a = [];
|
||||
foreach ($value as $k => $v) {
|
||||
if (\is_array($v)) {
|
||||
$deep = true;
|
||||
@@ -58,7 +62,13 @@ class ValueExporter
|
||||
return sprintf("[\n%s%s\n%s]", $indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1));
|
||||
}
|
||||
|
||||
return sprintf('[%s]', implode(', ', $a));
|
||||
$s = sprintf('[%s]', implode(', ', $a));
|
||||
|
||||
if (80 > \strlen($s)) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return sprintf("[\n%s%s\n]", $indent, implode(sprintf(",\n%s", $indent), $a));
|
||||
}
|
||||
|
||||
if (\is_resource($value)) {
|
||||
|
||||
117
vendor/symfony/http-kernel/Debug/FileLinkFormatter.php
vendored
Normal file
117
vendor/symfony/http-kernel/Debug/FileLinkFormatter.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?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\Debug;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
/**
|
||||
* Formats debug file links.
|
||||
*
|
||||
* @author Jérémy Romey <jeremy@free-agent.fr>
|
||||
*/
|
||||
class FileLinkFormatter implements \Serializable
|
||||
{
|
||||
private $fileLinkFormat;
|
||||
private $requestStack;
|
||||
private $baseDir;
|
||||
private $urlFormat;
|
||||
|
||||
/**
|
||||
* @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand
|
||||
*/
|
||||
public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, $baseDir = null, $urlFormat = null)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
$this->fileLinkFormat = $fileLinkFormat;
|
||||
$this->requestStack = $requestStack;
|
||||
$this->baseDir = $baseDir;
|
||||
$this->urlFormat = $urlFormat;
|
||||
}
|
||||
|
||||
public function format($file, $line)
|
||||
{
|
||||
if ($fmt = $this->getFileLinkFormat()) {
|
||||
for ($i = 1; isset($fmt[$i]); ++$i) {
|
||||
if (0 === strpos($file, $k = $fmt[$i++])) {
|
||||
$file = substr_replace($file, $fmt[$i], 0, \strlen($k));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return strtr($fmt[0], ['%f' => $file, '%l' => $line]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->getFileLinkFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
$this->fileLinkFormat = unserialize($serialized, ['allowed_classes' => false]);
|
||||
} else {
|
||||
$this->fileLinkFormat = unserialize($serialized);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function generateUrlFormat(UrlGeneratorInterface $router, $routeName, $queryString)
|
||||
{
|
||||
try {
|
||||
return $router->generate($routeName).$queryString;
|
||||
} catch (ExceptionInterface $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function getFileLinkFormat()
|
||||
{
|
||||
if ($this->fileLinkFormat) {
|
||||
return $this->fileLinkFormat;
|
||||
}
|
||||
if ($this->requestStack && $this->baseDir && $this->urlFormat) {
|
||||
$request = $this->requestStack->getMasterRequest();
|
||||
if ($request instanceof Request) {
|
||||
if ($this->urlFormat instanceof \Closure && !$this->urlFormat = \call_user_func($this->urlFormat)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
$request->getSchemeAndHttpHost().$this->urlFormat,
|
||||
$this->baseDir.\DIRECTORY_SEPARATOR, '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ namespace Symfony\Component\HttpKernel\Debug;
|
||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
|
||||
/**
|
||||
* Collects some data about event listeners.
|
||||
@@ -25,22 +24,6 @@ use Symfony\Component\HttpKernel\Profiler\Profiler;
|
||||
*/
|
||||
class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
{
|
||||
/**
|
||||
* Sets the profiler.
|
||||
*
|
||||
* The traceable event dispatcher does not use the profiler anymore.
|
||||
* The job is now done directly by the Profiler listener and the
|
||||
* data collectors themselves.
|
||||
*
|
||||
* @param Profiler|null $profiler A Profiler instance
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0.
|
||||
*/
|
||||
public function setProfiler(Profiler $profiler = null)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -59,6 +42,9 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
break;
|
||||
case KernelEvents::TERMINATE:
|
||||
$token = $event->getResponse()->headers->get('X-Debug-Token');
|
||||
if (null === $token) {
|
||||
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
|
||||
@@ -78,17 +64,23 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
|
||||
protected function postDispatch($eventName, Event $event)
|
||||
{
|
||||
switch ($eventName) {
|
||||
case KernelEvents::CONTROLLER:
|
||||
case KernelEvents::CONTROLLER_ARGUMENTS:
|
||||
$this->stopwatch->start('controller', 'section');
|
||||
break;
|
||||
case KernelEvents::RESPONSE:
|
||||
$token = $event->getResponse()->headers->get('X-Debug-Token');
|
||||
if (null === $token) {
|
||||
break;
|
||||
}
|
||||
$this->stopwatch->stopSection($token);
|
||||
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');
|
||||
if (null === $token) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
$this->stopwatch->stopSection($token);
|
||||
} catch (\LogicException $e) {
|
||||
|
||||
153
vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php
vendored
Normal file
153
vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Symfony\Component\Debug\DebugClassLoader;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
|
||||
/**
|
||||
* Sets the classes to compile in the cache for the container.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
||||
{
|
||||
private $kernel;
|
||||
|
||||
public function __construct(Kernel $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$classes = [];
|
||||
$annotatedClasses = [];
|
||||
foreach ($container->getExtensions() as $extension) {
|
||||
if ($extension instanceof Extension) {
|
||||
if (\PHP_VERSION_ID < 70000) {
|
||||
$classes = array_merge($classes, $extension->getClassesToCompile());
|
||||
}
|
||||
$annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile());
|
||||
}
|
||||
}
|
||||
|
||||
$existingClasses = $this->getClassesInComposerClassMaps();
|
||||
|
||||
if (\PHP_VERSION_ID < 70000) {
|
||||
$classes = $container->getParameterBag()->resolveValue($classes);
|
||||
$this->kernel->setClassCache($this->expandClasses($classes, $existingClasses));
|
||||
}
|
||||
$annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses);
|
||||
$this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands the given class patterns using a list of existing classes.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
$expanded = [];
|
||||
|
||||
// Explicit classes declared in the patterns are returned directly
|
||||
foreach ($patterns as $key => $pattern) {
|
||||
if ('\\' !== substr($pattern, -1) && false === strpos($pattern, '*')) {
|
||||
unset($patterns[$key]);
|
||||
$expanded[] = ltrim($pattern, '\\');
|
||||
}
|
||||
}
|
||||
|
||||
// Match patterns with the classes list
|
||||
$regexps = $this->patternsToRegexps($patterns);
|
||||
|
||||
foreach ($classes as $class) {
|
||||
$class = ltrim($class, '\\');
|
||||
|
||||
if ($this->matchAnyRegexps($class, $regexps)) {
|
||||
$expanded[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($expanded);
|
||||
}
|
||||
|
||||
private function getClassesInComposerClassMaps()
|
||||
{
|
||||
$classes = [];
|
||||
|
||||
foreach (spl_autoload_functions() as $function) {
|
||||
if (!\is_array($function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($function[0] instanceof DebugClassLoader) {
|
||||
$function = $function[0]->getClassLoader();
|
||||
}
|
||||
|
||||
if (\is_array($function) && $function[0] instanceof ClassLoader) {
|
||||
$classes += array_filter($function[0]->getClassMap());
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($classes);
|
||||
}
|
||||
|
||||
private function patternsToRegexps($patterns)
|
||||
{
|
||||
$regexps = [];
|
||||
|
||||
foreach ($patterns as $pattern) {
|
||||
// Escape user input
|
||||
$regex = preg_quote(ltrim($pattern, '\\'));
|
||||
|
||||
// Wildcards * and **
|
||||
$regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']);
|
||||
|
||||
// If this class does not end by a slash, anchor the end
|
||||
if ('\\' !== substr($regex, -1)) {
|
||||
$regex .= '$';
|
||||
}
|
||||
|
||||
$regexps[] = '{^\\\\'.$regex.'}';
|
||||
}
|
||||
|
||||
return $regexps;
|
||||
}
|
||||
|
||||
private function matchAnyRegexps($class, $regexps)
|
||||
{
|
||||
$blacklisted = false !== strpos($class, 'Test');
|
||||
|
||||
foreach ($regexps as $regex) {
|
||||
if ($blacklisted && false === strpos($regex, 'Test')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match($regex, '\\'.$class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -11,36 +11,15 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
@trigger_error('The '.__NAMESPACE__.'\AddClassesToCachePass class is deprecated since Symfony 3.3 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Sets the classes to compile in the cache for the container.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0.
|
||||
*/
|
||||
class AddClassesToCachePass implements CompilerPassInterface
|
||||
class AddClassesToCachePass extends AddAnnotatedClassesToCachePass
|
||||
{
|
||||
private $kernel;
|
||||
|
||||
public function __construct(Kernel $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$classes = array();
|
||||
foreach ($container->getExtensions() as $extension) {
|
||||
if ($extension instanceof Extension) {
|
||||
$classes = array_merge($classes, $extension->getClassesToCompile());
|
||||
}
|
||||
}
|
||||
|
||||
$this->kernel->setClassCache(array_unique($container->getParameterBag()->resolveValue($classes)));
|
||||
}
|
||||
}
|
||||
|
||||
48
vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php
vendored
Normal file
48
vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Gathers and configures the argument value resolvers.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
class ControllerArgumentValueResolverPass implements CompilerPassInterface
|
||||
{
|
||||
use PriorityTaggedServiceTrait;
|
||||
|
||||
private $argumentResolverService;
|
||||
private $argumentValueResolverTag;
|
||||
|
||||
public function __construct($argumentResolverService = 'argument_resolver', $argumentValueResolverTag = 'controller.argument_value_resolver')
|
||||
{
|
||||
$this->argumentResolverService = $argumentResolverService;
|
||||
$this->argumentValueResolverTag = $argumentValueResolverTag;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition($this->argumentResolverService)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$container
|
||||
->getDefinition($this->argumentResolverService)
|
||||
->replaceArgument(1, new IteratorArgument($this->findAndSortTaggedServices($this->argumentValueResolverTag, $container)))
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -20,25 +20,58 @@ use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;
|
||||
*/
|
||||
abstract class Extension extends BaseExtension
|
||||
{
|
||||
private $classes = array();
|
||||
private $classes = [];
|
||||
private $annotatedClasses = [];
|
||||
|
||||
/**
|
||||
* Gets the classes to cache.
|
||||
*
|
||||
* @return array An array of classes
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0.
|
||||
*/
|
||||
public function getClassesToCompile()
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
@trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the annotated classes to cache.
|
||||
*
|
||||
* @return array An array of classes
|
||||
*/
|
||||
public function getAnnotatedClassesToCompile()
|
||||
{
|
||||
return $this->annotatedClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds classes to the class cache.
|
||||
*
|
||||
* @param array $classes An array of classes
|
||||
* @param array $classes An array of class patterns
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0.
|
||||
*/
|
||||
public function addClassesToCompile(array $classes)
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
@trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->classes = array_merge($this->classes, $classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds annotated classes to the class cache.
|
||||
*
|
||||
* @param array $annotatedClasses An array of class patterns
|
||||
*/
|
||||
public function addAnnotatedClassesToCompile(array $annotatedClasses)
|
||||
{
|
||||
$this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
namespace Symfony\Component\HttpKernel\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
|
||||
|
||||
/**
|
||||
* Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies.
|
||||
@@ -42,37 +45,23 @@ class FragmentRendererPass implements CompilerPassInterface
|
||||
}
|
||||
|
||||
$definition = $container->getDefinition($this->handlerService);
|
||||
foreach ($container->findTaggedServiceIds($this->rendererTag) as $id => $tags) {
|
||||
$renderers = [];
|
||||
foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) {
|
||||
$def = $container->getDefinition($id);
|
||||
if (!$def->isPublic()) {
|
||||
throw new \InvalidArgumentException(sprintf('The service "%s" must be public as fragment renderer are lazy-loaded.', $id));
|
||||
}
|
||||
|
||||
if ($def->isAbstract()) {
|
||||
throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as fragment renderer are lazy-loaded.', $id));
|
||||
}
|
||||
|
||||
$class = $container->getParameterBag()->resolveValue($def->getClass());
|
||||
$interface = 'Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface';
|
||||
|
||||
if (!is_subclass_of($class, $interface)) {
|
||||
if (!class_exists($class, false)) {
|
||||
throw new \InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
if (!$r->isSubclassOf(FragmentRendererInterface::class)) {
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class));
|
||||
}
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (!isset($tag['alias'])) {
|
||||
@trigger_error(sprintf('Service "%s" will have to define the "alias" attribute on the "%s" tag as of Symfony 3.0.', $id, $this->rendererTag), E_USER_DEPRECATED);
|
||||
|
||||
// register the handler as a non-lazy-loaded one
|
||||
$definition->addMethodCall('addRenderer', array(new Reference($id)));
|
||||
} else {
|
||||
$definition->addMethodCall('addRendererService', array($tag['alias'], $id));
|
||||
}
|
||||
$renderers[$tag['alias']] = new Reference($id);
|
||||
}
|
||||
}
|
||||
|
||||
$definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
|
||||
|
||||
@@ -23,30 +23,22 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
|
||||
class LazyLoadingFragmentHandler extends FragmentHandler
|
||||
{
|
||||
private $container;
|
||||
private $rendererIds = array();
|
||||
/**
|
||||
* @deprecated since version 3.3, to be removed in 4.0
|
||||
*/
|
||||
private $rendererIds = [];
|
||||
private $initialized = [];
|
||||
|
||||
/**
|
||||
* RequestStack will become required in 3.0.
|
||||
*
|
||||
* @param ContainerInterface $container A container
|
||||
* @param RequestStack $requestStack The Request stack that controls the lifecycle of requests
|
||||
* @param bool $debug Whether the debug mode is enabled or not
|
||||
*/
|
||||
public function __construct(ContainerInterface $container, $requestStack = null, $debug = false)
|
||||
public function __construct(ContainerInterface $container, RequestStack $requestStack, $debug = false)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
if ((null !== $requestStack && !$requestStack instanceof RequestStack) || $debug instanceof RequestStack) {
|
||||
$tmp = $debug;
|
||||
$debug = $requestStack;
|
||||
$requestStack = \func_num_args() < 3 ? null : $tmp;
|
||||
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as second argument as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
} elseif (!$requestStack instanceof RequestStack) {
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
parent::__construct($requestStack, array(), $debug);
|
||||
parent::__construct($requestStack, [], $debug);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,21 +46,32 @@ class LazyLoadingFragmentHandler extends FragmentHandler
|
||||
*
|
||||
* @param string $name The service name
|
||||
* @param string $renderer The render service id
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0
|
||||
*/
|
||||
public function addRendererService($name, $renderer)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->rendererIds[$name] = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($uri, $renderer = 'inline', array $options = array())
|
||||
public function render($uri, $renderer = 'inline', array $options = [])
|
||||
{
|
||||
// BC 3.x, to be removed in 4.0
|
||||
if (isset($this->rendererIds[$renderer])) {
|
||||
$this->addRenderer($this->container->get($this->rendererIds[$renderer]));
|
||||
|
||||
unset($this->rendererIds[$renderer]);
|
||||
|
||||
return parent::render($uri, $renderer, $options);
|
||||
}
|
||||
|
||||
if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) {
|
||||
$this->addRenderer($this->container->get($renderer));
|
||||
$this->initialized[$renderer] = true;
|
||||
}
|
||||
|
||||
return parent::render($uri, $renderer, $options);
|
||||
|
||||
41
vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php
vendored
Normal file
41
vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Log\Logger;
|
||||
|
||||
/**
|
||||
* Registers the default logger if necessary.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class LoggerPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$container->setAlias(LoggerInterface::class, 'logger')
|
||||
->setPublic(false);
|
||||
|
||||
if ($container->has('logger')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$container->register('logger', Logger::class)
|
||||
->setPublic(false);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPas
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (!\count($container->getExtensionConfig($extension))) {
|
||||
$container->loadFromExtension($extension, array());
|
||||
$container->loadFromExtension($extension, []);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
179
vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
vendored
Normal file
179
vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Creates the service-locators required by ServiceValueResolver.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
{
|
||||
private $resolverServiceId;
|
||||
private $controllerTag;
|
||||
|
||||
public function __construct($resolverServiceId = 'argument_resolver.service', $controllerTag = 'controller.service_arguments')
|
||||
{
|
||||
$this->resolverServiceId = $resolverServiceId;
|
||||
$this->controllerTag = $controllerTag;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (false === $container->hasDefinition($this->resolverServiceId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$parameterBag = $container->getParameterBag();
|
||||
$controllers = [];
|
||||
|
||||
foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) {
|
||||
$def = $container->getDefinition($id);
|
||||
$def->setPublic(true);
|
||||
$class = $def->getClass();
|
||||
$autowire = $def->isAutowired();
|
||||
$bindings = $def->getBindings();
|
||||
|
||||
// resolve service class, taking parent definitions into account
|
||||
while ($def instanceof ChildDefinition) {
|
||||
$def = $container->findDefinition($def->getParent());
|
||||
$class = $class ?: $def->getClass();
|
||||
$bindings += $def->getBindings();
|
||||
}
|
||||
$class = $parameterBag->resolveValue($class);
|
||||
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
}
|
||||
$isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class);
|
||||
|
||||
// get regular public methods
|
||||
$methods = [];
|
||||
$arguments = [];
|
||||
foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) {
|
||||
if ('setContainer' === $r->name && $isContainerAware) {
|
||||
continue;
|
||||
}
|
||||
if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) {
|
||||
$methods[strtolower($r->name)] = [$r, $r->getParameters()];
|
||||
}
|
||||
}
|
||||
|
||||
// validate and collect explicit per-actions and per-arguments service references
|
||||
foreach ($tags as $attributes) {
|
||||
if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) {
|
||||
$autowire = true;
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
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];
|
||||
$found = false;
|
||||
|
||||
foreach ($parameters as $p) {
|
||||
if ($attributes['argument'] === $p->name) {
|
||||
if (!isset($arguments[$r->name][$p->name])) {
|
||||
$arguments[$r->name][$p->name] = $attributes['id'];
|
||||
}
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($methods as list($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 = $target = ProxyHelper::getTypeHint($r, $p, true);
|
||||
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
|
||||
|
||||
if (isset($arguments[$r->name][$p->name])) {
|
||||
$target = $arguments[$r->name][$p->name];
|
||||
if ('?' !== $target[0]) {
|
||||
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
|
||||
} elseif ('' === $target = (string) substr($target, 1)) {
|
||||
throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id));
|
||||
} elseif ($p->allowsNull() && !$p->isOptional()) {
|
||||
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
|
||||
}
|
||||
} elseif (isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) {
|
||||
$binding = $bindings[$bindingName];
|
||||
|
||||
list($bindingValue, $bindingId) = $binding->getValues();
|
||||
|
||||
if (!$bindingValue instanceof Reference) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$binding->setValues([$bindingValue, $bindingId, true]);
|
||||
$args[$p->name] = $bindingValue;
|
||||
|
||||
continue;
|
||||
} elseif (!$type || !$autowire) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Request::class === $type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) {
|
||||
$message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type);
|
||||
|
||||
// see if the type-hint lives in the same namespace as the controller
|
||||
if (0 === strncmp($type, $class, strrpos($class, '\\'))) {
|
||||
$message .= ' Did you forget to add a use statement?';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
$args[$p->name] = $type ? new TypedReference($target, $type, $r->class, $invalidBehavior) : new Reference($target, $invalidBehavior);
|
||||
}
|
||||
// register the maps as a per-method service-locators
|
||||
if ($args) {
|
||||
$controllers[$id.':'.$r->name] = ServiceLocatorTagPass::register($container, $args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$container->getDefinition($this->resolverServiceId)
|
||||
->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers));
|
||||
}
|
||||
}
|
||||
76
vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php
vendored
Normal file
76
vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Removes empty service-locators registered for ServiceValueResolver.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
{
|
||||
private $resolverServiceId;
|
||||
|
||||
public function __construct($resolverServiceId = 'argument_resolver.service')
|
||||
{
|
||||
$this->resolverServiceId = $resolverServiceId;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (false === $container->hasDefinition($this->resolverServiceId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$serviceResolver = $container->getDefinition($this->resolverServiceId);
|
||||
$controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0));
|
||||
$controllers = $controllerLocator->getArgument(0);
|
||||
|
||||
foreach ($controllers as $controller => $argumentRef) {
|
||||
$argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]);
|
||||
|
||||
if (!$argumentLocator->getArgument(0)) {
|
||||
// remove empty argument locators
|
||||
$reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller);
|
||||
} else {
|
||||
// any methods listed for call-at-instantiation cannot be actions
|
||||
$reason = false;
|
||||
$action = substr(strrchr($controller, ':'), 1);
|
||||
$id = substr($controller, 0, -1 - \strlen($action));
|
||||
$controllerDef = $container->getDefinition($id);
|
||||
foreach ($controllerDef->getMethodCalls() as list($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) {
|
||||
if ($controllerDef->getClass() === $id) {
|
||||
$controllers[$id.'::'.$action] = $argumentRef;
|
||||
}
|
||||
if ('__invoke' === $action) {
|
||||
$controllers[$id] = $argumentRef;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unset($controllers[$controller]);
|
||||
$container->log($this, $reason);
|
||||
}
|
||||
|
||||
$controllerLocator->replaceArgument(0, $controllers);
|
||||
}
|
||||
}
|
||||
66
vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php
vendored
Normal file
66
vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Alexander M. Turek <me@derrabus.de>
|
||||
*/
|
||||
class ResettableServicePass implements CompilerPassInterface
|
||||
{
|
||||
private $tagName;
|
||||
|
||||
public function __construct($tagName = 'kernel.reset')
|
||||
{
|
||||
$this->tagName = $tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->has('services_resetter')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$services = $methods = [];
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
$methods[$id] = $attributes['method'];
|
||||
}
|
||||
|
||||
if (empty($services)) {
|
||||
$container->removeAlias('services_resetter');
|
||||
$container->removeDefinition('services_resetter');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$container->findDefinition('services_resetter')
|
||||
->setArgument(0, new IteratorArgument($services))
|
||||
->setArgument(1, $methods);
|
||||
}
|
||||
}
|
||||
39
vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php
vendored
Normal file
39
vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?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\DependencyInjection;
|
||||
|
||||
/**
|
||||
* Resets provided services.
|
||||
*
|
||||
* @author Alexander M. Turek <me@derrabus.de>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ServicesResetter
|
||||
{
|
||||
private $resettableServices;
|
||||
private $resetMethods;
|
||||
|
||||
public function __construct(\Traversable $resettableServices, array $resetMethods)
|
||||
{
|
||||
$this->resettableServices = $resettableServices;
|
||||
$this->resetMethods = $resetMethods;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
foreach ($this->resettableServices as $id => $service) {
|
||||
$service->{$this->resetMethods[$id]}();
|
||||
}
|
||||
}
|
||||
}
|
||||
52
vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php
vendored
Normal file
52
vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Allows filtering of controller arguments.
|
||||
*
|
||||
* You can call getController() to retrieve the controller and getArguments
|
||||
* to retrieve the current arguments. With setArguments() you can replace
|
||||
* arguments that are used to call the controller.
|
||||
*
|
||||
* Arguments set in the event must be compatible with the signature of the
|
||||
* controller.
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*/
|
||||
class FilterControllerArgumentsEvent extends FilterControllerEvent
|
||||
{
|
||||
private $arguments;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, $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;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class FilterControllerEvent extends KernelEvent
|
||||
{
|
||||
private $controller;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType)
|
||||
public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, $requestType)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
|
||||
@@ -46,54 +46,8 @@ class FilterControllerEvent extends KernelEvent
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new controller.
|
||||
*
|
||||
* @param callable $controller
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function setController($controller)
|
||||
public function setController(callable $controller)
|
||||
{
|
||||
// controller must be a callable
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
|
||||
}
|
||||
|
||||
$this->controller = $controller;
|
||||
}
|
||||
|
||||
private function varToString($var)
|
||||
{
|
||||
if (\is_object($var)) {
|
||||
return sprintf('Object(%s)', \get_class($var));
|
||||
}
|
||||
|
||||
if (\is_array($var)) {
|
||||
$a = array();
|
||||
foreach ($var as $k => $v) {
|
||||
$a[] = sprintf('%s => %s', $k, $this->varToString($v));
|
||||
}
|
||||
|
||||
return sprintf('Array(%s)', implode(', ', $a));
|
||||
}
|
||||
|
||||
if (\is_resource($var)) {
|
||||
return sprintf('Resource(%s)', get_resource_type($var));
|
||||
}
|
||||
|
||||
if (null === $var) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (false === $var) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
if (true === $var) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
return (string) $var;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ class GetResponseForExceptionEvent extends GetResponseEvent
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $allowCustomResponseCode = false;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
|
||||
{
|
||||
parent::__construct($kernel, $request, $requestType);
|
||||
@@ -64,4 +69,22 @@ class GetResponseForExceptionEvent extends GetResponseEvent
|
||||
{
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
92
vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php
vendored
Normal file
92
vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?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 Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* Sets the session in the request.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
{
|
||||
private $sessionUsageStack = [];
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
$session = $this->getSession();
|
||||
$this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : null;
|
||||
if (null === $session || $request->hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request->setSession($session);
|
||||
}
|
||||
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$session = $event->getRequest()->getSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) {
|
||||
$event->getResponse()
|
||||
->setExpires(new \DateTime())
|
||||
->setPrivate()
|
||||
->setMaxAge(0)
|
||||
->headers->addCacheControlDirective('must-revalidate');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function onFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if ($event->isMasterRequest()) {
|
||||
array_pop($this->sessionUsageStack);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 128],
|
||||
// low priority to come after regular response listeners, same as SaveSessionListener
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -1000],
|
||||
KernelEvents::FINISH_REQUEST => ['onFinishRequest'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
}
|
||||
100
vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php
vendored
Normal file
100
vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?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 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\KernelEvents;
|
||||
|
||||
/**
|
||||
* TestSessionListener.
|
||||
*
|
||||
* Saves session in test environment.
|
||||
*
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class AbstractTestSessionListener implements EventSubscriberInterface
|
||||
{
|
||||
private $sessionId;
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// bootstrap the session
|
||||
$session = $this->getSession();
|
||||
if (!$session) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cookies = $event->getRequest()->cookies;
|
||||
|
||||
if ($cookies->has($session->getName())) {
|
||||
$this->sessionId = $cookies->get($session->getName());
|
||||
$session->setId($this->sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if session was initialized and saves if current request is master
|
||||
* Runs on 'kernel.response' in test environment.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$session = $event->getRequest()->getSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($wasStarted = $session->isStarted()) {
|
||||
$session->save();
|
||||
}
|
||||
|
||||
if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) {
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
foreach ($event->getResponse()->headers->getCookies() as $cookie) {
|
||||
if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
|
||||
$this->sessionId = $session->getId();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => ['onKernelRequest', 192],
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -128],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
}
|
||||
@@ -45,6 +45,6 @@ class AddRequestFormatsListener implements EventSubscriberInterface
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(KernelEvents::REQUEST => array('onKernelRequest', 1));
|
||||
return [KernelEvents::REQUEST => ['onKernelRequest', 1]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
|
||||
use Symfony\Component\HttpKernel\Event\KernelEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
@@ -35,25 +36,28 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
private $throwAt;
|
||||
private $scream;
|
||||
private $fileLinkFormat;
|
||||
private $scope;
|
||||
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 $fileLinkFormat The format for links to source files
|
||||
* @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
|
||||
*/
|
||||
public function __construct($exceptionHandler, LoggerInterface $logger = null, $levels = null, $throwAt = -1, $scream = true, $fileLinkFormat = null)
|
||||
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true)
|
||||
{
|
||||
$this->exceptionHandler = $exceptionHandler;
|
||||
$this->logger = $logger;
|
||||
$this->levels = $levels;
|
||||
$this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? -1 : null));
|
||||
$this->levels = null === $levels ? E_ALL : $levels;
|
||||
$this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null));
|
||||
$this->scream = (bool) $scream;
|
||||
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
$this->fileLinkFormat = $fileLinkFormat;
|
||||
$this->scope = (bool) $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,15 +79,20 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
if ($this->logger) {
|
||||
$handler->setDefaultLogger($this->logger, $this->levels);
|
||||
if (\is_array($this->levels)) {
|
||||
$scream = 0;
|
||||
$levels = 0;
|
||||
foreach ($this->levels as $type => $log) {
|
||||
$scream |= $type;
|
||||
$levels |= $type;
|
||||
}
|
||||
} else {
|
||||
$scream = null === $this->levels ? E_ALL | E_STRICT : $this->levels;
|
||||
$levels = $this->levels;
|
||||
}
|
||||
if ($this->scream) {
|
||||
$handler->screamAt($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;
|
||||
}
|
||||
@@ -97,7 +106,7 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
|
||||
$request = $event->getRequest();
|
||||
$hasRun = &$this->hasTerminatedWithException;
|
||||
$this->exceptionHandler = function (\Exception $e) use ($kernel, $request, &$hasRun) {
|
||||
$this->exceptionHandler = static function (\Exception $e) use ($kernel, $request, &$hasRun) {
|
||||
if ($hasRun) {
|
||||
throw $e;
|
||||
}
|
||||
@@ -137,10 +146,10 @@ class DebugHandlersListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
$events = array(KernelEvents::REQUEST => array('configure', 2048));
|
||||
$events = [KernelEvents::REQUEST => ['configure', 2048]];
|
||||
|
||||
if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
|
||||
$events[ConsoleEvents::COMMAND] = array('configure', 2048);
|
||||
if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
|
||||
$events[ConsoleEvents::COMMAND] = ['configure', 2048];
|
||||
}
|
||||
|
||||
return $events;
|
||||
|
||||
@@ -45,7 +45,11 @@ class DumpListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
if (!class_exists(ConsoleEvents::class)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Register early to have a working dump() as early as possible
|
||||
return array(ConsoleEvents::COMMAND => array('configure', 1024));
|
||||
return [ConsoleEvents::COMMAND => ['configure', 1024]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,15 +56,14 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
} catch (\Exception $e) {
|
||||
$this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', \get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()));
|
||||
|
||||
$wrapper = $e;
|
||||
|
||||
while ($prev = $wrapper->getPrevious()) {
|
||||
$prev = $e;
|
||||
do {
|
||||
if ($exception === $wrapper = $prev) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
} while ($prev = $wrapper->getPrevious());
|
||||
|
||||
$prev = new \ReflectionProperty('Exception', 'previous');
|
||||
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
|
||||
$prev->setAccessible(true);
|
||||
$prev->setValue($wrapper, $exception);
|
||||
|
||||
@@ -84,9 +83,9 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::EXCEPTION => array('onKernelException', -128),
|
||||
);
|
||||
return [
|
||||
KernelEvents::EXCEPTION => ['onKernelException', -128],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +98,9 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
|
||||
$this->logger->critical($message, array('exception' => $exception));
|
||||
$this->logger->critical($message, ['exception' => $exception]);
|
||||
} else {
|
||||
$this->logger->error($message, array('exception' => $exception));
|
||||
$this->logger->error($message, ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,15 +115,11 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
*/
|
||||
protected function duplicateRequest(\Exception $exception, Request $request)
|
||||
{
|
||||
$attributes = array(
|
||||
$attributes = [
|
||||
'_controller' => $this->controller,
|
||||
'exception' => FlattenException::create($exception),
|
||||
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
|
||||
// keep for BC -- as $format can be an argument of the controller callable
|
||||
// see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
|
||||
// @deprecated since version 2.4, to be removed in 3.0
|
||||
'format' => $request->getRequestFormat(),
|
||||
);
|
||||
];
|
||||
$request = $request->duplicate(null, null, $attributes);
|
||||
$request->setMethod('GET');
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ use Symfony\Component\HttpKernel\UriSigner;
|
||||
* All URL paths starting with /_fragment are handled as
|
||||
* content fragments by this listener.
|
||||
*
|
||||
* If throws an AccessDeniedHttpException exception if the request
|
||||
* Throws an AccessDeniedHttpException exception if the request
|
||||
* is not signed or if it is not an internal sub-request.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@@ -70,7 +70,7 @@ class FragmentListener implements EventSubscriberInterface
|
||||
|
||||
parse_str($request->query->get('_path', ''), $attributes);
|
||||
$request->attributes->add($attributes);
|
||||
$request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes));
|
||||
$request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes));
|
||||
$request->query->remove('_path');
|
||||
}
|
||||
|
||||
@@ -90,22 +90,10 @@ class FragmentListener implements EventSubscriberInterface
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 2.3.19, to be removed in 3.0.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getLocalIpAddresses()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3.19 and will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
|
||||
return array('127.0.0.1', 'fe80::1', '::1');
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array(array('onKernelRequest', 48)),
|
||||
);
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 48]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,6 @@ use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
/**
|
||||
* Initializes the locale based on the current request.
|
||||
*
|
||||
* This listener works in 2 modes:
|
||||
*
|
||||
* * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
|
||||
* * 2.4+ mode where you must pass a RequestStack instance in the constructor.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class LocaleListener implements EventSubscriberInterface
|
||||
@@ -36,62 +31,17 @@ class LocaleListener implements EventSubscriberInterface
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
* RequestStack will become required in 3.0.
|
||||
*
|
||||
* @param RequestStack $requestStack A RequestStack instance
|
||||
* @param string $defaultLocale The default locale
|
||||
* @param RequestContextAwareInterface|null $router The router
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($requestStack = null, $defaultLocale = 'en', $router = null)
|
||||
public function __construct(RequestStack $requestStack, $defaultLocale = 'en', RequestContextAwareInterface $router = null)
|
||||
{
|
||||
if ((null !== $requestStack && !$requestStack instanceof RequestStack) || $defaultLocale instanceof RequestContextAwareInterface || $router instanceof RequestStack) {
|
||||
$tmp = $router;
|
||||
$router = \func_num_args() < 2 ? null : $defaultLocale;
|
||||
$defaultLocale = $requestStack;
|
||||
$requestStack = \func_num_args() < 3 ? null : $tmp;
|
||||
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as first argument as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
} elseif (!$requestStack instanceof RequestStack) {
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (null !== $requestStack && !$requestStack instanceof RequestStack) {
|
||||
throw new \InvalidArgumentException('RequestStack instance expected.');
|
||||
}
|
||||
if (null !== $router && !$router instanceof RequestContextAwareInterface) {
|
||||
throw new \InvalidArgumentException('Router must implement RequestContextAwareInterface.');
|
||||
}
|
||||
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
$this->requestStack = $requestStack;
|
||||
$this->router = $router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current Request.
|
||||
*
|
||||
* This method was used to synchronize the Request, but as the HttpKernel
|
||||
* is doing that automatically now, you should never call it directly.
|
||||
* It is kept public for BC with the 2.3 version.
|
||||
*
|
||||
* @param Request|null $request A Request instance
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0.
|
||||
*/
|
||||
public function setRequest(Request $request = null)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === $request) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setLocale($request);
|
||||
$this->setRouterContext($request);
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
@@ -103,10 +53,6 @@ class LocaleListener implements EventSubscriberInterface
|
||||
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if (null === $this->requestStack) {
|
||||
return; // removed when requestStack is required
|
||||
}
|
||||
|
||||
if (null !== $parentRequest = $this->requestStack->getParentRequest()) {
|
||||
$this->setRouterContext($parentRequest);
|
||||
}
|
||||
@@ -128,10 +74,10 @@ class LocaleListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
// must be registered after the Router to have access to the _locale
|
||||
KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
|
||||
KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
|
||||
);
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 16]],
|
||||
KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
@@ -33,7 +32,6 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
protected $onlyException;
|
||||
protected $onlyMasterRequests;
|
||||
protected $exception;
|
||||
protected $requests = array();
|
||||
protected $profiles;
|
||||
protected $requestStack;
|
||||
protected $parents;
|
||||
@@ -45,27 +43,8 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
* @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
|
||||
*/
|
||||
public function __construct(Profiler $profiler, $requestStack = null, $matcher = null, $onlyException = false, $onlyMasterRequests = false)
|
||||
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false)
|
||||
{
|
||||
if ($requestStack instanceof RequestMatcherInterface || (null !== $matcher && !$matcher instanceof RequestMatcherInterface) || $onlyMasterRequests instanceof RequestStack) {
|
||||
$tmp = $onlyMasterRequests;
|
||||
$onlyMasterRequests = $onlyException;
|
||||
$onlyException = $matcher;
|
||||
$matcher = $requestStack;
|
||||
$requestStack = \func_num_args() < 5 ? null : $tmp;
|
||||
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as second argument as '.__CLASS__.'::onKernelRequest method will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
} elseif (!$requestStack instanceof RequestStack) {
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::onKernelRequest method will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (null !== $requestStack && !$requestStack instanceof RequestStack) {
|
||||
throw new \InvalidArgumentException('RequestStack instance expected.');
|
||||
}
|
||||
if (null !== $matcher && !$matcher instanceof RequestMatcherInterface) {
|
||||
throw new \InvalidArgumentException('Matcher must implement RequestMatcherInterface.');
|
||||
}
|
||||
|
||||
$this->profiler = $profiler;
|
||||
$this->matcher = $matcher;
|
||||
$this->onlyException = (bool) $onlyException;
|
||||
@@ -87,16 +66,6 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
$this->exception = $event->getException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 2.4, to be removed in 3.0.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
if (null === $this->requestStack) {
|
||||
$this->requests[] = $event->getRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the onKernelResponse event.
|
||||
*/
|
||||
@@ -125,22 +94,14 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
|
||||
$this->profiles[$request] = $profile;
|
||||
|
||||
if (null !== $this->requestStack) {
|
||||
$this->parents[$request] = $this->requestStack->getParentRequest();
|
||||
} elseif (!$master) {
|
||||
// to be removed when requestStack is required
|
||||
array_pop($this->requests);
|
||||
|
||||
$this->parents[$request] = end($this->requests);
|
||||
}
|
||||
$this->parents[$request] = $this->requestStack->getParentRequest();
|
||||
}
|
||||
|
||||
public function onKernelTerminate(PostResponseEvent $event)
|
||||
{
|
||||
// attach children to parents
|
||||
foreach ($this->profiles as $request) {
|
||||
// isset call should be removed when requestStack is required
|
||||
if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) {
|
||||
if (null !== $parentRequest = $this->parents[$request]) {
|
||||
if (isset($this->profiles[$parentRequest])) {
|
||||
$this->profiles[$parentRequest]->addChild($this->profiles[$request]);
|
||||
}
|
||||
@@ -154,18 +115,14 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
|
||||
$this->profiles = new \SplObjectStorage();
|
||||
$this->parents = new \SplObjectStorage();
|
||||
$this->requests = array();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
// kernel.request must be registered as early as possible to not break
|
||||
// when an exception is thrown in any other kernel.request listener
|
||||
KernelEvents::REQUEST => array('onKernelRequest', 1024),
|
||||
KernelEvents::RESPONSE => array('onKernelResponse', -100),
|
||||
return [
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -100],
|
||||
KernelEvents::EXCEPTION => 'onKernelException',
|
||||
KernelEvents::TERMINATE => array('onKernelTerminate', -1024),
|
||||
);
|
||||
KernelEvents::TERMINATE => ['onKernelTerminate', -1024],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ class ResponseListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
KernelEvents::RESPONSE => 'onKernelResponse',
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@ use Psr\Log\LoggerInterface;
|
||||
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\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\NoConfigurationException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
|
||||
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
|
||||
@@ -31,54 +35,30 @@ use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
/**
|
||||
* Initializes the context from the request and sets request attributes based on a matching route.
|
||||
*
|
||||
* This listener works in 2 modes:
|
||||
*
|
||||
* * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
|
||||
* * 2.4+ mode where you must pass a RequestStack instance in the constructor.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*/
|
||||
class RouterListener implements EventSubscriberInterface
|
||||
{
|
||||
private $matcher;
|
||||
private $context;
|
||||
private $logger;
|
||||
private $request;
|
||||
private $requestStack;
|
||||
private $projectDir;
|
||||
private $debug;
|
||||
|
||||
/**
|
||||
* RequestStack will become required in 3.0.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($matcher, $requestStack = null, $context = null, $logger = null)
|
||||
public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, $projectDir = null, $debug = true)
|
||||
{
|
||||
if ($requestStack instanceof RequestContext || $context instanceof LoggerInterface || $logger instanceof RequestStack) {
|
||||
$tmp = $requestStack;
|
||||
$requestStack = $logger;
|
||||
$logger = $context;
|
||||
$context = $tmp;
|
||||
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as second argument as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
} elseif (!$requestStack instanceof RequestStack) {
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (null !== $requestStack && !$requestStack instanceof RequestStack) {
|
||||
throw new \InvalidArgumentException('RequestStack instance expected.');
|
||||
}
|
||||
if (null !== $context && !$context instanceof RequestContext) {
|
||||
throw new \InvalidArgumentException('RequestContext instance expected.');
|
||||
}
|
||||
if (null !== $logger && !$logger instanceof LoggerInterface) {
|
||||
throw new \InvalidArgumentException('Logger must implement LoggerInterface.');
|
||||
}
|
||||
|
||||
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
|
||||
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
|
||||
}
|
||||
@@ -91,45 +71,27 @@ class RouterListener implements EventSubscriberInterface
|
||||
$this->context = $context ?: $matcher->getContext();
|
||||
$this->requestStack = $requestStack;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current Request.
|
||||
*
|
||||
* This method was used to synchronize the Request, but as the HttpKernel
|
||||
* is doing that automatically now, you should never call it directly.
|
||||
* It is kept public for BC with the 2.3 version.
|
||||
*
|
||||
* @param Request|null $request A Request instance
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0.
|
||||
*/
|
||||
public function setRequest(Request $request = null)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be made private in 3.0.', E_USER_DEPRECATED);
|
||||
|
||||
$this->setCurrentRequest($request);
|
||||
$this->projectDir = $projectDir;
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
private function setCurrentRequest(Request $request = null)
|
||||
{
|
||||
if (null !== $request && $this->request !== $request) {
|
||||
if (null !== $request) {
|
||||
try {
|
||||
$this->context->fromRequest($request);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function onKernelFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if (null === $this->requestStack) {
|
||||
return; // removed when requestStack is required
|
||||
}
|
||||
|
||||
$this->setCurrentRequest($this->requestStack->getParentRequest());
|
||||
}
|
||||
|
||||
@@ -137,13 +99,7 @@ class RouterListener implements EventSubscriberInterface
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
|
||||
// initialize the context that is also used by the generator (assuming matcher and generator share the same context instance)
|
||||
// we call setCurrentRequest even if most of the time, it has already been done to keep compatibility
|
||||
// with frameworks which do not use the Symfony service container
|
||||
// when we have a RequestStack, no need to do it
|
||||
if (null !== $this->requestStack) {
|
||||
$this->setCurrentRequest($request);
|
||||
}
|
||||
$this->setCurrentRequest($request);
|
||||
|
||||
if ($request->attributes->has('_controller')) {
|
||||
// routing is already done
|
||||
@@ -160,10 +116,12 @@ class RouterListener implements EventSubscriberInterface
|
||||
}
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info(sprintf('Matched route "%s".', isset($parameters['_route']) ? $parameters['_route'] : 'n/a'), array(
|
||||
$this->logger->info('Matched route "{route}".', [
|
||||
'route' => isset($parameters['_route']) ? $parameters['_route'] : 'n/a',
|
||||
'route_parameters' => $parameters,
|
||||
'request_uri' => $request->getUri(),
|
||||
));
|
||||
'method' => $request->getMethod(),
|
||||
]);
|
||||
}
|
||||
|
||||
$request->attributes->add($parameters);
|
||||
@@ -184,11 +142,35 @@ class RouterListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function onKernelException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
if (!$this->debug || !($e = $event->getException()) instanceof NotFoundHttpException) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($e->getPrevious() instanceof NoConfigurationException) {
|
||||
$event->setResponse($this->createWelcomeResponse());
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
|
||||
KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
|
||||
);
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 32]],
|
||||
KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]],
|
||||
KernelEvents::EXCEPTION => ['onKernelException', -64],
|
||||
];
|
||||
}
|
||||
|
||||
private function createWelcomeResponse()
|
||||
{
|
||||
$version = Kernel::VERSION;
|
||||
$baseDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR;
|
||||
$docVersion = substr(Kernel::VERSION, 0, 3);
|
||||
|
||||
ob_start();
|
||||
include __DIR__.'/../Resources/welcome.html.php';
|
||||
|
||||
return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
* 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.
|
||||
@@ -58,9 +58,9 @@ class SaveSessionListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
// low priority but higher than StreamedResponseListener
|
||||
KernelEvents::RESPONSE => array(array('onKernelResponse', -1000)),
|
||||
);
|
||||
KernelEvents::RESPONSE => [['onKernelResponse', -1000]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,44 +11,30 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Sets the session in the request.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since version 3.3
|
||||
*/
|
||||
abstract class SessionListener implements EventSubscriberInterface
|
||||
class SessionListener extends AbstractSessionListener
|
||||
{
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $event->getRequest();
|
||||
$session = $this->getSession();
|
||||
if (null === $session || $request->hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request->setSession($session);
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
protected function getSession()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array('onKernelRequest', 128),
|
||||
);
|
||||
}
|
||||
if (!$this->container->has('session')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
return $this->container->get('session');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ class StreamedResponseListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::RESPONSE => array('onKernelResponse', -1024),
|
||||
);
|
||||
return [
|
||||
KernelEvents::RESPONSE => ['onKernelResponse', -1024],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
|
||||
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
@@ -35,17 +36,30 @@ class SurrogateListener implements EventSubscriberInterface
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
{
|
||||
if (!$event->isMasterRequest() || null === $this->surrogate) {
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->surrogate->addSurrogateControl($event->getResponse());
|
||||
$kernel = $event->getKernel();
|
||||
$surrogate = $this->surrogate;
|
||||
if ($kernel instanceof HttpCache) {
|
||||
$surrogate = $kernel->getSurrogate();
|
||||
if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) {
|
||||
$surrogate = $this->surrogate;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $surrogate) {
|
||||
return;
|
||||
}
|
||||
|
||||
$surrogate->addSurrogateControl($event->getResponse());
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
KernelEvents::RESPONSE => 'onKernelResponse',
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,72 +11,30 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* TestSessionListener.
|
||||
* Sets the session in the request.
|
||||
*
|
||||
* Saves session in test environment.
|
||||
*
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final since version 3.3
|
||||
*/
|
||||
abstract class TestSessionListener implements EventSubscriberInterface
|
||||
class TestSessionListener extends AbstractTestSessionListener
|
||||
{
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// bootstrap the session
|
||||
$session = $this->getSession();
|
||||
if (!$session) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cookies = $event->getRequest()->cookies;
|
||||
|
||||
if ($cookies->has($session->getName())) {
|
||||
$session->setId($cookies->get($session->getName()));
|
||||
}
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if session was initialized and saves if current request is master
|
||||
* Runs on 'kernel.response' in test environment.
|
||||
*/
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
protected function getSession()
|
||||
{
|
||||
if (!$event->isMasterRequest()) {
|
||||
return;
|
||||
if (!$this->container->has('session')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$session = $event->getRequest()->getSession();
|
||||
if ($session && $session->isStarted()) {
|
||||
$session->save();
|
||||
$params = session_get_cookie_params();
|
||||
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
|
||||
}
|
||||
return $this->container->get('session');
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array('onKernelRequest', 192),
|
||||
KernelEvents::RESPONSE => array('onKernelResponse', -128),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session object.
|
||||
*
|
||||
* @return SessionInterface|null A SessionInterface instance or null if no session is available
|
||||
*/
|
||||
abstract protected function getSession();
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@ class TranslatorListener implements EventSubscriberInterface
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
return [
|
||||
// must be registered after the Locale listener
|
||||
KernelEvents::REQUEST => array(array('onKernelRequest', 10)),
|
||||
KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
|
||||
);
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 10]],
|
||||
KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]],
|
||||
];
|
||||
}
|
||||
|
||||
private function setLocale(Request $request)
|
||||
|
||||
@@ -16,8 +16,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* Validates that the headers and other information indicating the
|
||||
* client IP address of a request are consistent.
|
||||
* Validates Requests.
|
||||
*
|
||||
* @author Magnus Nordlander <magnus@fervo.se>
|
||||
*/
|
||||
@@ -34,9 +33,10 @@ class ValidateRequestListener implements EventSubscriberInterface
|
||||
$request = $event->getRequest();
|
||||
|
||||
if ($request::getTrustedProxies()) {
|
||||
// This will throw an exception if the headers are inconsistent.
|
||||
$request->getClientIps();
|
||||
}
|
||||
|
||||
$request->getHost();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,10 +44,10 @@ class ValidateRequestListener implements EventSubscriberInterface
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array(
|
||||
array('onKernelRequest', 256),
|
||||
),
|
||||
);
|
||||
return [
|
||||
KernelEvents::REQUEST => [
|
||||
['onKernelRequest', 256],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ class AccessDeniedHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(403, $message, $previous, array(), $code);
|
||||
parent::__construct(403, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class BadRequestHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(400, $message, $previous, array(), $code);
|
||||
parent::__construct(400, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class ConflictHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(409, $message, $previous, array(), $code);
|
||||
parent::__construct(409, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class GoneHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(410, $message, $previous, array(), $code);
|
||||
parent::__construct(410, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface
|
||||
private $statusCode;
|
||||
private $headers;
|
||||
|
||||
public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0)
|
||||
public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = [], $code = 0)
|
||||
{
|
||||
$this->statusCode = $statusCode;
|
||||
$this->headers = $headers;
|
||||
@@ -38,4 +38,14 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set response headers.
|
||||
*
|
||||
* @param array $headers Response headers
|
||||
*/
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class LengthRequiredHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(411, $message, $previous, array(), $code);
|
||||
parent::__construct(411, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class MethodNotAllowedHttpException extends HttpException
|
||||
*/
|
||||
public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
$headers = array('Allow' => strtoupper(implode(', ', $allow)));
|
||||
$headers = ['Allow' => strtoupper(implode(', ', $allow))];
|
||||
|
||||
parent::__construct(405, $message, $previous, $headers, $code);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class NotAcceptableHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(406, $message, $previous, array(), $code);
|
||||
parent::__construct(406, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class NotFoundHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(404, $message, $previous, array(), $code);
|
||||
parent::__construct(404, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class PreconditionFailedHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(412, $message, $previous, array(), $code);
|
||||
parent::__construct(412, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@ class PreconditionRequiredHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(428, $message, $previous, array(), $code);
|
||||
parent::__construct(428, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ class ServiceUnavailableHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
if ($retryAfter) {
|
||||
$headers = array('Retry-After' => $retryAfter);
|
||||
$headers = ['Retry-After' => $retryAfter];
|
||||
}
|
||||
|
||||
parent::__construct(503, $message, $previous, $headers, $code);
|
||||
|
||||
@@ -26,9 +26,9 @@ class TooManyRequestsHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
if ($retryAfter) {
|
||||
$headers = array('Retry-After' => $retryAfter);
|
||||
$headers = ['Retry-After' => $retryAfter];
|
||||
}
|
||||
|
||||
parent::__construct(429, $message, $previous, $headers, $code);
|
||||
|
||||
@@ -24,7 +24,7 @@ class UnauthorizedHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
$headers = array('WWW-Authenticate' => $challenge);
|
||||
$headers = ['WWW-Authenticate' => $challenge];
|
||||
|
||||
parent::__construct(401, $message, $previous, $headers, $code);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class UnprocessableEntityHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(422, $message, $previous, array(), $code);
|
||||
parent::__construct(422, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class UnsupportedMediaTypeHttpException extends HttpException
|
||||
*/
|
||||
public function __construct($message = null, \Exception $previous = null, $code = 0)
|
||||
{
|
||||
parent::__construct(415, $message, $previous, array(), $code);
|
||||
parent::__construct(415, $message, $previous, [], $code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +59,13 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
|
||||
*
|
||||
* @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
|
||||
*/
|
||||
public function render($uri, Request $request, array $options = array())
|
||||
public function render($uri, Request $request, array $options = [])
|
||||
{
|
||||
if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
|
||||
if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) {
|
||||
@trigger_error('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is deprecated since Symfony 3.1, and will be removed in 4.0. Use a different rendering strategy or pass scalar values.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
return $this->inlineStrategy->render($uri, $request, $options);
|
||||
}
|
||||
|
||||
@@ -90,4 +94,17 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
|
||||
|
||||
return substr($fragmentUri, \strlen($request->getSchemeAndHttpHost()));
|
||||
}
|
||||
|
||||
private function containsNonScalars(array $values)
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
if (\is_array($value)) {
|
||||
return $this->containsNonScalars($value);
|
||||
} elseif (!is_scalar($value) && null !== $value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Fragment;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@@ -23,11 +22,6 @@ use Symfony\Component\HttpKernel\Controller\ControllerReference;
|
||||
* This class handles the rendering of resource fragments that are included into
|
||||
* a main resource. The handling of the rendering is managed by specialized renderers.
|
||||
*
|
||||
* This listener works in 2 modes:
|
||||
*
|
||||
* * 2.3 compatibility mode where you must call setRequest whenever the Request changes.
|
||||
* * 2.4+ mode where you must pass a RequestStack instance in the constructor.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @see FragmentRendererInterface
|
||||
@@ -35,37 +29,16 @@ use Symfony\Component\HttpKernel\Controller\ControllerReference;
|
||||
class FragmentHandler
|
||||
{
|
||||
private $debug;
|
||||
private $renderers = array();
|
||||
private $request;
|
||||
private $renderers = [];
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
* RequestStack will become required in 3.0.
|
||||
*
|
||||
* @param RequestStack $requestStack The Request stack that controls the lifecycle of requests
|
||||
* @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances
|
||||
* @param bool $debug Whether the debug mode is enabled or not
|
||||
*/
|
||||
public function __construct($requestStack = null, $renderers = array(), $debug = false)
|
||||
public function __construct(RequestStack $requestStack, array $renderers = [], $debug = false)
|
||||
{
|
||||
if (\is_array($requestStack)) {
|
||||
$tmp = $debug;
|
||||
$debug = \func_num_args() < 2 ? false : $renderers;
|
||||
$renderers = $requestStack;
|
||||
$requestStack = \func_num_args() < 3 ? null : $tmp;
|
||||
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as first argument as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
} elseif (!$requestStack instanceof RequestStack) {
|
||||
@trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (null !== $requestStack && !$requestStack instanceof RequestStack) {
|
||||
throw new \InvalidArgumentException('RequestStack instance expected.');
|
||||
}
|
||||
if (!\is_array($renderers)) {
|
||||
throw new \InvalidArgumentException('Renderers must be an array.');
|
||||
}
|
||||
|
||||
$this->requestStack = $requestStack;
|
||||
foreach ($renderers as $renderer) {
|
||||
$this->addRenderer($renderer);
|
||||
@@ -81,24 +54,6 @@ class FragmentHandler
|
||||
$this->renderers[$renderer->getName()] = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current Request.
|
||||
*
|
||||
* This method was used to synchronize the Request, but as the HttpKernel
|
||||
* is doing that automatically now, you should never call it directly.
|
||||
* It is kept public for BC with the 2.3 version.
|
||||
*
|
||||
* @param Request|null $request A Request instance
|
||||
*
|
||||
* @deprecated since version 2.4, to be removed in 3.0.
|
||||
*/
|
||||
public function setRequest(Request $request = null)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a URI and returns the Response content.
|
||||
*
|
||||
@@ -115,7 +70,7 @@ class FragmentHandler
|
||||
* @throws \InvalidArgumentException when the renderer does not exist
|
||||
* @throws \LogicException when no master request is being handled
|
||||
*/
|
||||
public function render($uri, $renderer = 'inline', array $options = array())
|
||||
public function render($uri, $renderer = 'inline', array $options = [])
|
||||
{
|
||||
if (!isset($options['ignore_errors'])) {
|
||||
$options['ignore_errors'] = !$this->debug;
|
||||
@@ -125,7 +80,7 @@ class FragmentHandler
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer));
|
||||
}
|
||||
|
||||
if (!$request = $this->getRequest()) {
|
||||
if (!$request = $this->requestStack->getCurrentRequest()) {
|
||||
throw new \LogicException('Rendering a fragment can only be done when handling a Request.');
|
||||
}
|
||||
|
||||
@@ -145,7 +100,7 @@ class FragmentHandler
|
||||
protected function deliver(Response $response)
|
||||
{
|
||||
if (!$response->isSuccessful()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->getRequest()->getUri(), $response->getStatusCode()));
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
if (!$response instanceof StreamedResponse) {
|
||||
@@ -153,10 +108,7 @@ class FragmentHandler
|
||||
}
|
||||
|
||||
$response->sendContent();
|
||||
}
|
||||
|
||||
private function getRequest()
|
||||
{
|
||||
return $this->requestStack ? $this->requestStack->getCurrentRequest() : $this->request;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ interface FragmentRendererInterface
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*/
|
||||
public function render($uri, Request $request, array $options = array());
|
||||
public function render($uri, Request $request, array $options = []);
|
||||
|
||||
/**
|
||||
* Gets the name of the strategy.
|
||||
|
||||
@@ -19,6 +19,7 @@ use Symfony\Component\Templating\EngineInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Loader\ExistsLoaderInterface;
|
||||
use Twig\Loader\SourceContextLoaderInterface;
|
||||
|
||||
/**
|
||||
* Implements the Hinclude rendering strategy.
|
||||
@@ -81,7 +82,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
|
||||
* * id: An optional hx:include tag id attribute
|
||||
* * attributes: An optional array of hx:include tag attributes
|
||||
*/
|
||||
public function render($uri, Request $request, array $options = array())
|
||||
public function render($uri, Request $request, array $options = [])
|
||||
{
|
||||
if ($uri instanceof ControllerReference) {
|
||||
if (null === $this->signer) {
|
||||
@@ -102,17 +103,13 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
|
||||
$content = $template;
|
||||
}
|
||||
|
||||
$attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : array();
|
||||
$attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : [];
|
||||
if (isset($options['id']) && $options['id']) {
|
||||
$attributes['id'] = $options['id'];
|
||||
}
|
||||
$renderedAttributes = '';
|
||||
if (\count($attributes) > 0) {
|
||||
if (\PHP_VERSION_ID >= 50400) {
|
||||
$flags = ENT_QUOTES | ENT_SUBSTITUTE;
|
||||
} else {
|
||||
$flags = ENT_QUOTES;
|
||||
}
|
||||
$flags = ENT_QUOTES | ENT_SUBSTITUTE;
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
$renderedAttributes .= sprintf(
|
||||
' %s="%s"',
|
||||
@@ -141,22 +138,23 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
|
||||
}
|
||||
|
||||
$loader = $this->templating->getLoader();
|
||||
if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
|
||||
return $loader->exists($template);
|
||||
}
|
||||
|
||||
try {
|
||||
if (method_exists($loader, 'getSourceContext')) {
|
||||
$loader->getSourceContext($template);
|
||||
} else {
|
||||
$loader->getSource($template);
|
||||
if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) {
|
||||
try {
|
||||
if ($loader instanceof SourceContextLoaderInterface) {
|
||||
$loader->getSourceContext($template);
|
||||
} else {
|
||||
$loader->getSource($template);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (LoaderError $e) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (LoaderError $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $loader->exists($template);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
|
||||
*
|
||||
* * alt: an alternative URI to render in case of an error
|
||||
*/
|
||||
public function render($uri, Request $request, array $options = array())
|
||||
public function render($uri, Request $request, array $options = [])
|
||||
{
|
||||
$reference = null;
|
||||
if ($uri instanceof ControllerReference) {
|
||||
@@ -54,10 +54,10 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
|
||||
// want that as we want to preserve objects (so we manually set Request attributes
|
||||
// below instead)
|
||||
$attributes = $reference->attributes;
|
||||
$reference->attributes = array();
|
||||
$reference->attributes = [];
|
||||
|
||||
// The request format and locale might have been overridden by the user
|
||||
foreach (array('_format', '_locale') as $key) {
|
||||
foreach (['_format', '_locale'] as $key) {
|
||||
if (isset($attributes[$key])) {
|
||||
$reference->attributes[$key] = $attributes[$key];
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
|
||||
return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false);
|
||||
} catch (\Exception $e) {
|
||||
// we dispatch the exception event to trigger the logging
|
||||
// the response that comes back is simply ignored
|
||||
// the response that comes back is ignored
|
||||
if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) {
|
||||
$event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e);
|
||||
|
||||
@@ -113,7 +113,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
|
||||
unset($server['HTTP_IF_MODIFIED_SINCE']);
|
||||
unset($server['HTTP_IF_NONE_MATCH']);
|
||||
|
||||
$subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server);
|
||||
$subRequest = Request::create($uri, 'get', [], $cookies, [], $server);
|
||||
if ($request->headers->has('Surrogate-Capability')) {
|
||||
$subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
|
||||
}
|
||||
|
||||
136
vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php
vendored
Normal file
136
vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?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\HttpCache;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Abstract class implementing Surrogate capabilities to Request and Response instances.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
*/
|
||||
abstract class AbstractSurrogate implements SurrogateInterface
|
||||
{
|
||||
protected $contentTypes;
|
||||
protected $phpEscapeMap = [
|
||||
['<?', '<%', '<s', '<S'],
|
||||
['<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $contentTypes An array of content-type that should be parsed for Surrogate information
|
||||
* (default: text/html, text/xml, application/xhtml+xml, and application/xml)
|
||||
*/
|
||||
public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'])
|
||||
{
|
||||
$this->contentTypes = $contentTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new cache strategy instance.
|
||||
*
|
||||
* @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance
|
||||
*/
|
||||
public function createCacheStrategy()
|
||||
{
|
||||
return new ResponseCacheStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasSurrogateCapability(Request $request)
|
||||
{
|
||||
if (null === $value = $request->headers->get('Surrogate-Capability')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false !== strpos($value, sprintf('%s/1.0', strtoupper($this->getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSurrogateCapability(Request $request)
|
||||
{
|
||||
$current = $request->headers->get('Surrogate-Capability');
|
||||
$new = sprintf('symfony="%s/1.0"', strtoupper($this->getName()));
|
||||
|
||||
$request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function needsParsing(Response $response)
|
||||
{
|
||||
if (!$control = $response->headers->get('Surrogate-Control')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName()));
|
||||
|
||||
return (bool) preg_match($pattern, $control);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors)
|
||||
{
|
||||
$subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all());
|
||||
|
||||
try {
|
||||
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
return $response->getContent();
|
||||
} catch (\Exception $e) {
|
||||
if ($alt) {
|
||||
return $this->handle($cache, $alt, '', $ignoreErrors);
|
||||
}
|
||||
|
||||
if (!$ignoreErrors) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the Surrogate from the Surrogate-Control header.
|
||||
*/
|
||||
protected function removeFromControl(Response $response)
|
||||
{
|
||||
if (!$response->headers->has('Surrogate-Control')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$value = $response->headers->get('Surrogate-Control');
|
||||
$upperName = strtoupper($this->getName());
|
||||
|
||||
if (sprintf('content="%s/1.0"', $upperName) == $value) {
|
||||
$response->headers->remove('Surrogate-Control');
|
||||
} elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value));
|
||||
} elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
179
vendor/symfony/http-kernel/HttpCache/Esi.php
vendored
179
vendor/symfony/http-kernel/HttpCache/Esi.php
vendored
@@ -13,7 +13,6 @@ namespace Symfony\Component\HttpKernel\HttpCache;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Esi implements the ESI capabilities to Request and Response instances.
|
||||
@@ -26,97 +25,15 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Esi implements SurrogateInterface
|
||||
class Esi extends AbstractSurrogate
|
||||
{
|
||||
private $contentTypes;
|
||||
private $phpEscapeMap = array(
|
||||
array('<?', '<%', '<s', '<S'),
|
||||
array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
|
||||
);
|
||||
|
||||
/**
|
||||
* @param array $contentTypes An array of content-type that should be parsed for ESI information
|
||||
* (default: text/html, text/xml, application/xhtml+xml, and application/xml)
|
||||
*/
|
||||
public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'))
|
||||
{
|
||||
$this->contentTypes = $contentTypes;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'esi';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new cache strategy instance.
|
||||
*
|
||||
* @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance
|
||||
*/
|
||||
public function createCacheStrategy()
|
||||
{
|
||||
return new ResponseCacheStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that at least one surrogate has ESI/1.0 capability.
|
||||
*
|
||||
* @return bool true if one surrogate has ESI/1.0 capability, false otherwise
|
||||
*/
|
||||
public function hasSurrogateCapability(Request $request)
|
||||
{
|
||||
if (null === $value = $request->headers->get('Surrogate-Capability')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false !== strpos($value, 'ESI/1.0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that at least one surrogate has ESI/1.0 capability.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
*
|
||||
* @return bool true if one surrogate has ESI/1.0 capability, false otherwise
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0. Use hasSurrogateCapability() instead
|
||||
*/
|
||||
public function hasSurrogateEsiCapability(Request $request)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the hasSurrogateCapability() method instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->hasSurrogateCapability($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ESI/1.0 capability to the given Request.
|
||||
*/
|
||||
public function addSurrogateCapability(Request $request)
|
||||
{
|
||||
$current = $request->headers->get('Surrogate-Capability');
|
||||
$new = 'symfony2="ESI/1.0"';
|
||||
|
||||
$request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ESI/1.0 capability to the given Request.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0. Use addSurrogateCapability() instead
|
||||
*/
|
||||
public function addSurrogateEsiCapability(Request $request)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the addSurrogateCapability() method instead.', E_USER_DEPRECATED);
|
||||
|
||||
$this->addSurrogateCapability($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds HTTP headers to specify that the Response needs to be parsed for ESI.
|
||||
*
|
||||
* This method only adds an ESI HTTP header if the Response has some ESI tags.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSurrogateControl(Response $response)
|
||||
{
|
||||
@@ -126,44 +43,7 @@ class Esi implements SurrogateInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the Response needs to be parsed for ESI tags.
|
||||
*
|
||||
* @return bool true if the Response needs to be parsed, false otherwise
|
||||
*/
|
||||
public function needsParsing(Response $response)
|
||||
{
|
||||
if (!$control = $response->headers->get('Surrogate-Control')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) preg_match('#content="[^"]*ESI/1.0[^"]*"#', $control);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the Response needs to be parsed for ESI tags.
|
||||
*
|
||||
* @param Response $response A Response instance
|
||||
*
|
||||
* @return bool true if the Response needs to be parsed, false otherwise
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0. Use needsParsing() instead
|
||||
*/
|
||||
public function needsEsiParsing(Response $response)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the needsParsing() method instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->needsParsing($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an ESI tag.
|
||||
*
|
||||
* @param string $uri A URI
|
||||
* @param string $alt An alternate URI
|
||||
* @param bool $ignoreErrors Whether to ignore errors or not
|
||||
* @param string $comment A comment to add as an esi:include tag
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '')
|
||||
{
|
||||
@@ -181,9 +61,7 @@ class Esi implements SurrogateInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a Response ESI tags with the included resource content.
|
||||
*
|
||||
* @return Response
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(Request $request, Response $response)
|
||||
{
|
||||
@@ -207,7 +85,7 @@ class Esi implements SurrogateInterface
|
||||
|
||||
$i = 1;
|
||||
while (isset($chunks[$i])) {
|
||||
$options = array();
|
||||
$options = [];
|
||||
preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $set) {
|
||||
$options[$set[1]] = $set[2];
|
||||
@@ -232,51 +110,8 @@ class Esi implements SurrogateInterface
|
||||
$response->headers->set('X-Body-Eval', 'ESI');
|
||||
|
||||
// remove ESI/1.0 from the Surrogate-Control header
|
||||
if ($response->headers->has('Surrogate-Control')) {
|
||||
$value = $response->headers->get('Surrogate-Control');
|
||||
if ('content="ESI/1.0"' == $value) {
|
||||
$response->headers->remove('Surrogate-Control');
|
||||
} elseif (preg_match('#,\s*content="ESI/1.0"#', $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace('#,\s*content="ESI/1.0"#', '', $value));
|
||||
} elseif (preg_match('#content="ESI/1.0",\s*#', $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace('#content="ESI/1.0",\s*#', '', $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->removeFromControl($response);
|
||||
|
||||
/**
|
||||
* Handles an ESI from the cache.
|
||||
*
|
||||
* @param HttpCache $cache An HttpCache instance
|
||||
* @param string $uri The main URI
|
||||
* @param string $alt An alternative URI
|
||||
* @param bool $ignoreErrors Whether to ignore errors or not
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors)
|
||||
{
|
||||
$subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all());
|
||||
|
||||
try {
|
||||
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
return $response->getContent();
|
||||
} catch (\Exception $e) {
|
||||
if ($alt) {
|
||||
return $this->handle($cache, $alt, '', $ignoreErrors);
|
||||
}
|
||||
|
||||
if (!$ignoreErrors) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
213
vendor/symfony/http-kernel/HttpCache/HttpCache.php
vendored
213
vendor/symfony/http-kernel/HttpCache/HttpCache.php
vendored
@@ -32,8 +32,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
private $request;
|
||||
private $surrogate;
|
||||
private $surrogateCacheStrategy;
|
||||
private $options = array();
|
||||
private $traces = array();
|
||||
private $options = [];
|
||||
private $traces = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -70,24 +70,24 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
* This setting is overridden by the stale-if-error HTTP Cache-Control extension
|
||||
* (see RFC 5861).
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = array())
|
||||
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = [])
|
||||
{
|
||||
$this->store = $store;
|
||||
$this->kernel = $kernel;
|
||||
$this->surrogate = $surrogate;
|
||||
|
||||
// needed in case there is a fatal error because the backend is too slow to respond
|
||||
register_shutdown_function(array($this->store, 'cleanup'));
|
||||
register_shutdown_function([$this->store, 'cleanup']);
|
||||
|
||||
$this->options = array_merge(array(
|
||||
$this->options = array_merge([
|
||||
'debug' => false,
|
||||
'default_ttl' => 0,
|
||||
'private_headers' => array('Authorization', 'Cookie'),
|
||||
'private_headers' => ['Authorization', 'Cookie'],
|
||||
'allow_reload' => false,
|
||||
'allow_revalidate' => false,
|
||||
'stale_while_revalidate' => 2,
|
||||
'stale_if_error' => 60,
|
||||
), $options);
|
||||
], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +117,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
$log = array();
|
||||
$log = [];
|
||||
foreach ($this->traces as $request => $traces) {
|
||||
$log[] = sprintf('%s: %s', $request, implode(', ', $traces));
|
||||
}
|
||||
@@ -154,29 +154,9 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
*/
|
||||
public function getSurrogate()
|
||||
{
|
||||
if (!$this->surrogate instanceof Esi) {
|
||||
throw new \LogicException('This instance of HttpCache was not set up to use ESI as surrogate handler. You must overwrite and use createSurrogate');
|
||||
}
|
||||
|
||||
return $this->surrogate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Esi instance.
|
||||
*
|
||||
* @return Esi An Esi instance
|
||||
*
|
||||
* @throws \LogicException
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0. Use getSurrogate() instead
|
||||
*/
|
||||
public function getEsi()
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the getSurrogate() method instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->getSurrogate();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -184,7 +164,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
{
|
||||
// FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism
|
||||
if (HttpKernelInterface::MASTER_REQUEST === $type) {
|
||||
$this->traces = array();
|
||||
$this->traces = [];
|
||||
// Keep a clone of the original request for surrogates so they can access it.
|
||||
// We must clone here to get a separate instance because the application will modify the request during
|
||||
// the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1
|
||||
@@ -195,24 +175,25 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
}
|
||||
}
|
||||
|
||||
$path = $request->getPathInfo();
|
||||
if ($qs = $request->getQueryString()) {
|
||||
$path .= '?'.$qs;
|
||||
}
|
||||
$this->traces[$request->getMethod().' '.$path] = array();
|
||||
$this->traces[$this->getTraceKey($request)] = [];
|
||||
|
||||
if (!$request->isMethodSafe(false)) {
|
||||
$response = $this->invalidate($request, $catch);
|
||||
} elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) {
|
||||
$response = $this->pass($request, $catch);
|
||||
} elseif ($this->options['allow_reload'] && $request->isNoCache()) {
|
||||
/*
|
||||
If allow_reload is configured and the client requests "Cache-Control: no-cache",
|
||||
reload the cache by fetching a fresh response and caching it (if possible).
|
||||
*/
|
||||
$this->record($request, 'reload');
|
||||
$response = $this->fetch($request, $catch);
|
||||
} else {
|
||||
$response = $this->lookup($request, $catch);
|
||||
}
|
||||
|
||||
$this->restoreResponseBody($request, $response);
|
||||
|
||||
$response->setDate(\DateTime::createFromFormat('U', time(), new \DateTimeZone('UTC')));
|
||||
|
||||
if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) {
|
||||
$response->headers->set('X-Symfony-Cache', $this->getLog());
|
||||
}
|
||||
@@ -279,9 +260,9 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
$this->store->invalidate($request);
|
||||
|
||||
// As per the RFC, invalidate Location and Content-Location URLs if present
|
||||
foreach (array('Location', 'Content-Location') as $header) {
|
||||
foreach (['Location', 'Content-Location'] as $header) {
|
||||
if ($uri = $response->headers->get($header)) {
|
||||
$subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all());
|
||||
$subRequest = Request::create($uri, 'get', [], [], [], $request->server->all());
|
||||
|
||||
$this->store->invalidate($subRequest);
|
||||
}
|
||||
@@ -318,13 +299,6 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
*/
|
||||
protected function lookup(Request $request, $catch = false)
|
||||
{
|
||||
// if allow_reload and no-cache Cache-Control, allow a cache reload
|
||||
if ($this->options['allow_reload'] && $request->isNoCache()) {
|
||||
$this->record($request, 'reload');
|
||||
|
||||
return $this->fetch($request, $catch);
|
||||
}
|
||||
|
||||
try {
|
||||
$entry = $this->store->lookup($request);
|
||||
} catch (\Exception $e) {
|
||||
@@ -378,12 +352,14 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
}
|
||||
|
||||
// add our cached last-modified validator
|
||||
$subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified'));
|
||||
if ($entry->headers->has('Last-Modified')) {
|
||||
$subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified'));
|
||||
}
|
||||
|
||||
// Add our cached etag validator to the environment.
|
||||
// We keep the etags from the client to handle the case when the client
|
||||
// has a different private valid entry which is not cached here.
|
||||
$cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array();
|
||||
$cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : [];
|
||||
$requestEtags = $request->getETags();
|
||||
if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) {
|
||||
$subRequest->headers->set('if_none_match', implode(', ', $etags));
|
||||
@@ -403,7 +379,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
$entry = clone $entry;
|
||||
$entry->headers->remove('Date');
|
||||
|
||||
foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) {
|
||||
foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) {
|
||||
if ($response->headers->has($name)) {
|
||||
$entry->headers->set($name, $response->headers->get($name));
|
||||
}
|
||||
@@ -422,9 +398,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the Request to the backend and determines whether the response should be stored.
|
||||
*
|
||||
* This methods is triggered when the cache missed or a reload is required.
|
||||
* Unconditionally fetches a fresh response from the backend and
|
||||
* stores it in the cache if is cacheable.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
* @param bool $catch Whether to process exceptions
|
||||
@@ -456,9 +431,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
/**
|
||||
* Forwards the Request to the backend and returns the Response.
|
||||
*
|
||||
* @param Request $request A Request instance
|
||||
* @param bool $catch Whether to catch exceptions or not
|
||||
* @param Response $entry A Response instance (the stale entry if present, null otherwise)
|
||||
* All backend requests (cache passes, fetches, cache validations)
|
||||
* run through this method.
|
||||
*
|
||||
* @param bool $catch Whether to catch exceptions or not
|
||||
* @param Response|null $entry A Response instance (the stale entry if present, null otherwise)
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*/
|
||||
@@ -472,7 +449,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
$response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch);
|
||||
|
||||
// we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC
|
||||
if (null !== $entry && \in_array($response->getStatusCode(), array(500, 502, 503, 504))) {
|
||||
if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) {
|
||||
if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
|
||||
$age = $this->options['stale_if_error'];
|
||||
}
|
||||
@@ -484,6 +461,17 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate
|
||||
clock MUST NOT send a "Date" header, although it MUST send one in most other cases
|
||||
except for 1xx or 5xx responses where it MAY do so.
|
||||
|
||||
Anyway, a client that received a message without a "Date" header MUST add it.
|
||||
*/
|
||||
if (!$response->headers->has('Date')) {
|
||||
$response->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
|
||||
$this->processResponseBody($request, $response);
|
||||
|
||||
if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) {
|
||||
@@ -523,49 +511,39 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
// try to acquire a lock to call the backend
|
||||
$lock = $this->store->lock($request);
|
||||
|
||||
if (true === $lock) {
|
||||
// we have the lock, call the backend
|
||||
return false;
|
||||
}
|
||||
|
||||
// there is already another process calling the backend
|
||||
if (true !== $lock) {
|
||||
// check if we can serve the stale entry
|
||||
if (null === $age = $entry->headers->getCacheControlDirective('stale-while-revalidate')) {
|
||||
$age = $this->options['stale_while_revalidate'];
|
||||
}
|
||||
|
||||
if (abs($entry->getTtl()) < $age) {
|
||||
$this->record($request, 'stale-while-revalidate');
|
||||
|
||||
// server the stale response while there is a revalidation
|
||||
return true;
|
||||
}
|
||||
|
||||
// wait for the lock to be released
|
||||
$wait = 0;
|
||||
while ($this->store->isLocked($request) && $wait < 5000000) {
|
||||
usleep(50000);
|
||||
$wait += 50000;
|
||||
}
|
||||
|
||||
if ($wait < 5000000) {
|
||||
// replace the current entry with the fresh one
|
||||
$new = $this->lookup($request);
|
||||
$entry->headers = $new->headers;
|
||||
$entry->setContent($new->getContent());
|
||||
$entry->setStatusCode($new->getStatusCode());
|
||||
$entry->setProtocolVersion($new->getProtocolVersion());
|
||||
foreach ($new->headers->getCookies() as $cookie) {
|
||||
$entry->headers->setCookie($cookie);
|
||||
}
|
||||
} else {
|
||||
// backend is slow as hell, send a 503 response (to avoid the dog pile effect)
|
||||
$entry->setStatusCode(503);
|
||||
$entry->setContent('503 Service Unavailable');
|
||||
$entry->headers->set('Retry-After', 10);
|
||||
}
|
||||
// May we serve a stale response?
|
||||
if ($this->mayServeStaleWhileRevalidate($entry)) {
|
||||
$this->record($request, 'stale-while-revalidate');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// we have the lock, call the backend
|
||||
return false;
|
||||
// wait for the lock to be released
|
||||
if ($this->waitForLock($request)) {
|
||||
// replace the current entry with the fresh one
|
||||
$new = $this->lookup($request);
|
||||
$entry->headers = $new->headers;
|
||||
$entry->setContent($new->getContent());
|
||||
$entry->setStatusCode($new->getStatusCode());
|
||||
$entry->setProtocolVersion($new->getProtocolVersion());
|
||||
foreach ($new->headers->getCookies() as $cookie) {
|
||||
$entry->headers->setCookie($cookie);
|
||||
}
|
||||
} else {
|
||||
// backend is slow as hell, send a 503 response (to avoid the dog pile effect)
|
||||
$entry->setStatusCode(503);
|
||||
$entry->setContent('503 Service Unavailable');
|
||||
$entry->headers->set('Retry-After', 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -575,9 +553,6 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
*/
|
||||
protected function store(Request $request, Response $response)
|
||||
{
|
||||
if (!$response->headers->has('Date')) {
|
||||
$response->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
try {
|
||||
$this->store->write($request, $response);
|
||||
|
||||
@@ -665,11 +640,57 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
* @param string $event The event name
|
||||
*/
|
||||
private function record(Request $request, $event)
|
||||
{
|
||||
$this->traces[$this->getTraceKey($request)][] = $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the key we use in the "trace" array for a given request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getTraceKey(Request $request)
|
||||
{
|
||||
$path = $request->getPathInfo();
|
||||
if ($qs = $request->getQueryString()) {
|
||||
$path .= '?'.$qs;
|
||||
}
|
||||
$this->traces[$request->getMethod().' '.$path][] = $event;
|
||||
|
||||
return $request->getMethod().' '.$path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given (cached) response may be served as "stale" when a revalidation
|
||||
* is currently in progress.
|
||||
*
|
||||
* @return bool true when the stale response may be served, false otherwise
|
||||
*/
|
||||
private function mayServeStaleWhileRevalidate(Response $entry)
|
||||
{
|
||||
$timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate');
|
||||
|
||||
if (null === $timeout) {
|
||||
$timeout = $this->options['stale_while_revalidate'];
|
||||
}
|
||||
|
||||
return abs($entry->getTtl()) < $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the store to release a locked entry.
|
||||
*
|
||||
* @param Request $request The request to wait for
|
||||
*
|
||||
* @return bool true if the lock was released before the internal timeout was hit; false if the wait timeout was exceeded
|
||||
*/
|
||||
private function waitForLock(Request $request)
|
||||
{
|
||||
$wait = 0;
|
||||
while ($this->store->isLocked($request) && $wait < 100) {
|
||||
usleep(50000);
|
||||
++$wait;
|
||||
}
|
||||
|
||||
return $wait < 100;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* This code is partially based on the Rack-Cache library by Ryan Tomayko,
|
||||
* which is released under the MIT license.
|
||||
* (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
@@ -28,30 +24,69 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
*/
|
||||
class ResponseCacheStrategy implements ResponseCacheStrategyInterface
|
||||
{
|
||||
private $cacheable = true;
|
||||
/**
|
||||
* Cache-Control headers that are sent to the final response if they appear in ANY of the responses.
|
||||
*/
|
||||
private static $overrideDirectives = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate'];
|
||||
|
||||
/**
|
||||
* Cache-Control headers that are sent to the final response if they appear in ALL of the responses.
|
||||
*/
|
||||
private static $inheritDirectives = ['public', 'immutable'];
|
||||
|
||||
private $embeddedResponses = 0;
|
||||
private $ttls = array();
|
||||
private $maxAges = array();
|
||||
private $isNotCacheableResponseEmbedded = false;
|
||||
private $age = 0;
|
||||
private $flagDirectives = [
|
||||
'no-cache' => null,
|
||||
'no-store' => null,
|
||||
'no-transform' => null,
|
||||
'must-revalidate' => null,
|
||||
'proxy-revalidate' => null,
|
||||
'public' => null,
|
||||
'private' => null,
|
||||
'immutable' => null,
|
||||
];
|
||||
private $ageDirectives = [
|
||||
'max-age' => null,
|
||||
's-maxage' => null,
|
||||
'expires' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(Response $response)
|
||||
{
|
||||
if (!$response->isFresh() || !$response->isCacheable()) {
|
||||
$this->cacheable = false;
|
||||
} else {
|
||||
$maxAge = $response->getMaxAge();
|
||||
$this->ttls[] = $response->getTtl();
|
||||
$this->maxAges[] = $maxAge;
|
||||
++$this->embeddedResponses;
|
||||
|
||||
if (null === $maxAge) {
|
||||
$this->isNotCacheableResponseEmbedded = true;
|
||||
foreach (self::$overrideDirectives as $directive) {
|
||||
if ($response->headers->hasCacheControlDirective($directive)) {
|
||||
$this->flagDirectives[$directive] = true;
|
||||
}
|
||||
}
|
||||
|
||||
++$this->embeddedResponses;
|
||||
foreach (self::$inheritDirectives as $directive) {
|
||||
if (false !== $this->flagDirectives[$directive]) {
|
||||
$this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive);
|
||||
}
|
||||
}
|
||||
|
||||
$age = $response->getAge();
|
||||
$this->age = max($this->age, $age);
|
||||
|
||||
if ($this->willMakeFinalResponseUncacheable($response)) {
|
||||
$this->isNotCacheableResponseEmbedded = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->storeRelativeAgeDirective('max-age', $response->headers->getCacheControlDirective('max-age'), $age);
|
||||
$this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age);
|
||||
|
||||
$expires = $response->getExpires();
|
||||
$expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null;
|
||||
$this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,33 +99,123 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove validation related headers in order to avoid browsers using
|
||||
// their own cache, because some of the response content comes from
|
||||
// at least one embedded response (which likely has a different caching strategy).
|
||||
if ($response->isValidateable()) {
|
||||
$response->setEtag(null);
|
||||
$response->setLastModified(null);
|
||||
}
|
||||
// Remove validation related headers of the master response,
|
||||
// because some of the response content comes from at least
|
||||
// one embedded response (which likely has a different caching strategy).
|
||||
$response->setEtag(null);
|
||||
$response->setLastModified(null);
|
||||
|
||||
if (!$response->isFresh() || !$response->isCacheable()) {
|
||||
$this->cacheable = false;
|
||||
}
|
||||
$this->add($response);
|
||||
|
||||
if (!$this->cacheable) {
|
||||
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
|
||||
$response->headers->set('Age', $this->age);
|
||||
|
||||
if ($this->isNotCacheableResponseEmbedded) {
|
||||
$response->setExpires($response->getDate());
|
||||
|
||||
if ($this->flagDirectives['no-store']) {
|
||||
$response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
} else {
|
||||
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ttls[] = $response->getTtl();
|
||||
$this->maxAges[] = $response->getMaxAge();
|
||||
$flags = array_filter($this->flagDirectives);
|
||||
|
||||
if ($this->isNotCacheableResponseEmbedded) {
|
||||
$response->headers->removeCacheControlDirective('s-maxage');
|
||||
} elseif (null !== $maxAge = min($this->maxAges)) {
|
||||
$response->setSharedMaxAge($maxAge);
|
||||
$response->headers->set('Age', $maxAge - min($this->ttls));
|
||||
if (isset($flags['must-revalidate'])) {
|
||||
$flags['no-cache'] = true;
|
||||
}
|
||||
|
||||
$response->headers->set('Cache-Control', implode(', ', array_keys($flags)));
|
||||
|
||||
$maxAge = null;
|
||||
|
||||
if (is_numeric($this->ageDirectives['max-age'])) {
|
||||
$maxAge = $this->ageDirectives['max-age'] + $this->age;
|
||||
$response->headers->addCacheControlDirective('max-age', $maxAge);
|
||||
}
|
||||
|
||||
if (is_numeric($this->ageDirectives['s-maxage'])) {
|
||||
$sMaxage = $this->ageDirectives['s-maxage'] + $this->age;
|
||||
|
||||
if ($maxAge !== $sMaxage) {
|
||||
$response->headers->addCacheControlDirective('s-maxage', $sMaxage);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_numeric($this->ageDirectives['expires'])) {
|
||||
$date = clone $response->getDate();
|
||||
$date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds');
|
||||
$response->setExpires($date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC2616, Section 13.4.
|
||||
*
|
||||
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function willMakeFinalResponseUncacheable(Response $response)
|
||||
{
|
||||
// RFC2616: A response received with a status code of 200, 203, 300, 301 or 410
|
||||
// MAY be stored by a cache […] unless a cache-control directive prohibits caching.
|
||||
if ($response->headers->hasCacheControlDirective('no-cache')
|
||||
|| $response->headers->getCacheControlDirective('no-store')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Last-Modified and Etag headers cannot be merged, they render the response uncacheable
|
||||
// by default (except if the response also has max-age etc.).
|
||||
if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410])
|
||||
&& null === $response->getLastModified()
|
||||
&& null === $response->getEtag()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// RFC2616: A response received with any other status code (e.g. status codes 302 and 307)
|
||||
// MUST NOT be returned in a reply to a subsequent request unless there are
|
||||
// cache-control directives or another header(s) that explicitly allow it.
|
||||
$cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private'];
|
||||
foreach ($cacheControl as $key) {
|
||||
if ($response->headers->hasCacheControlDirective($key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($response->headers->has('Expires')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store lowest max-age/s-maxage/expires for the final response.
|
||||
*
|
||||
* The response might have been stored in cache a while ago. To keep things comparable,
|
||||
* we have to subtract the age so that the value is normalized for an age of 0.
|
||||
*
|
||||
* If the value is lower than the currently stored value, we update the value, to keep a rolling
|
||||
* minimal value of each instruction. If the value is NULL, the directive will not be set on the final response.
|
||||
*
|
||||
* @param string $directive
|
||||
* @param int|null $value
|
||||
* @param int $age
|
||||
*/
|
||||
private function storeRelativeAgeDirective($directive, $value, $age)
|
||||
{
|
||||
if (null === $value) {
|
||||
$this->ageDirectives[$directive] = false;
|
||||
}
|
||||
|
||||
if (false !== $this->ageDirectives[$directive]) {
|
||||
$value -= $age;
|
||||
$this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value;
|
||||
}
|
||||
$response->setMaxAge(0);
|
||||
}
|
||||
}
|
||||
|
||||
100
vendor/symfony/http-kernel/HttpCache/Ssi.php
vendored
100
vendor/symfony/http-kernel/HttpCache/Ssi.php
vendored
@@ -13,30 +13,14 @@ namespace Symfony\Component\HttpKernel\HttpCache;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Ssi implements the SSI capabilities to Request and Response instances.
|
||||
*
|
||||
* @author Sebastian Krebs <krebs.seb@gmail.com>
|
||||
*/
|
||||
class Ssi implements SurrogateInterface
|
||||
class Ssi extends AbstractSurrogate
|
||||
{
|
||||
private $contentTypes;
|
||||
private $phpEscapeMap = array(
|
||||
array('<?', '<%', '<s', '<S'),
|
||||
array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
|
||||
);
|
||||
|
||||
/**
|
||||
* @param array $contentTypes An array of content-type that should be parsed for SSI information
|
||||
* (default: text/html, text/xml, application/xhtml+xml, and application/xml)
|
||||
*/
|
||||
public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml'))
|
||||
{
|
||||
$this->contentTypes = $contentTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -45,37 +29,6 @@ class Ssi implements SurrogateInterface
|
||||
return 'ssi';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createCacheStrategy()
|
||||
{
|
||||
return new ResponseCacheStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasSurrogateCapability(Request $request)
|
||||
{
|
||||
if (null === $value = $request->headers->get('Surrogate-Capability')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false !== strpos($value, 'SSI/1.0');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSurrogateCapability(Request $request)
|
||||
{
|
||||
$current = $request->headers->get('Surrogate-Capability');
|
||||
$new = 'symfony2="SSI/1.0"';
|
||||
|
||||
$request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -86,18 +39,6 @@ class Ssi implements SurrogateInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function needsParsing(Response $response)
|
||||
{
|
||||
if (!$control = $response->headers->get('Surrogate-Control')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) preg_match('#content="[^"]*SSI/1.0[^"]*"#', $control);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -129,7 +70,7 @@ class Ssi implements SurrogateInterface
|
||||
|
||||
$i = 1;
|
||||
while (isset($chunks[$i])) {
|
||||
$options = array();
|
||||
$options = [];
|
||||
preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $set) {
|
||||
$options[$set[1]] = $set[2];
|
||||
@@ -152,41 +93,8 @@ class Ssi implements SurrogateInterface
|
||||
$response->headers->set('X-Body-Eval', 'SSI');
|
||||
|
||||
// remove SSI/1.0 from the Surrogate-Control header
|
||||
if ($response->headers->has('Surrogate-Control')) {
|
||||
$value = $response->headers->get('Surrogate-Control');
|
||||
if ('content="SSI/1.0"' == $value) {
|
||||
$response->headers->remove('Surrogate-Control');
|
||||
} elseif (preg_match('#,\s*content="SSI/1.0"#', $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace('#,\s*content="SSI/1.0"#', '', $value));
|
||||
} elseif (preg_match('#content="SSI/1.0",\s*#', $value)) {
|
||||
$response->headers->set('Surrogate-Control', preg_replace('#content="SSI/1.0",\s*#', '', $value));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->removeFromControl($response);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors)
|
||||
{
|
||||
$subRequest = Request::create($uri, 'get', array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all());
|
||||
|
||||
try {
|
||||
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
return $response->getContent();
|
||||
} catch (\Exception $e) {
|
||||
if ($alt) {
|
||||
return $this->handle($cache, $alt, '', $ignoreErrors);
|
||||
}
|
||||
|
||||
if (!$ignoreErrors) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user