update to laravel 5.7 and try getting autologin saved

This commit is contained in:
Kode
2018-10-14 20:50:32 +01:00
parent c3da17befc
commit 6501aacb1b
2402 changed files with 79064 additions and 28971 deletions

View File

@@ -11,11 +11,10 @@
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\Container;
use Symfony\Component\Console\Application;
use Symfony\Component\Finder\Finder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
/**
@@ -34,23 +33,21 @@ abstract class Bundle implements BundleInterface
private $namespace;
/**
* Boots the Bundle.
* {@inheritdoc}
*/
public function boot()
{
}
/**
* Shutdowns the Bundle.
* {@inheritdoc}
*/
public function shutdown()
{
}
/**
* Builds the bundle.
*
* It is only ever called once when the cache is empty.
* {@inheritdoc}
*
* This method can be overridden to register compilation passes,
* other extensions, ...
@@ -73,7 +70,7 @@ abstract class Bundle implements BundleInterface
if (null !== $extension) {
if (!$extension instanceof ExtensionInterface) {
throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_class($extension)));
throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension)));
}
// check naming convention
@@ -81,10 +78,7 @@ abstract class Bundle implements BundleInterface
$expectedAlias = Container::underscore($basename);
if ($expectedAlias != $extension->getAlias()) {
throw new \LogicException(sprintf(
'Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.',
$expectedAlias, $extension->getAlias()
));
throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias()));
}
$this->extension = $extension;
@@ -99,9 +93,7 @@ abstract class Bundle implements BundleInterface
}
/**
* Gets the Bundle namespace.
*
* @return string The Bundle namespace
* {@inheritdoc}
*/
public function getNamespace()
{
@@ -113,29 +105,18 @@ abstract class Bundle implements BundleInterface
}
/**
* Gets the Bundle directory path.
*
* @return string The Bundle absolute path
* {@inheritdoc}
*/
public function getPath()
{
if (null === $this->path) {
$reflected = new \ReflectionObject($this);
$this->path = dirname($reflected->getFileName());
$this->path = \dirname($reflected->getFileName());
}
return $this->path;
}
/**
* Returns the bundle parent name.
*
* @return string|null The Bundle parent name it overrides or null if no parent
*/
public function getParent()
{
}
/**
* Returns the bundle name (the class short name).
*
@@ -150,48 +131,8 @@ abstract class Bundle implements BundleInterface
return $this->name;
}
/**
* Finds and registers Commands.
*
* Override this method if your bundle commands do not follow the conventions:
*
* * Commands are in the 'Command' sub-directory
* * Commands extend Symfony\Component\Console\Command\Command
*/
public function registerCommands(Application $application)
{
if (!is_dir($dir = $this->getPath().'/Command')) {
return;
}
if (!class_exists('Symfony\Component\Finder\Finder')) {
throw new \RuntimeException('You need the symfony/finder component to register bundle commands.');
}
$finder = new Finder();
$finder->files()->name('*Command.php')->in($dir);
$prefix = $this->getNamespace().'\\Command';
foreach ($finder as $file) {
$ns = $prefix;
if ($relativePath = $file->getRelativePath()) {
$ns .= '\\'.str_replace('/', '\\', $relativePath);
}
$class = $ns.'\\'.$file->getBasename('.php');
if ($this->container) {
$commandIds = $this->container->hasParameter('console.command.ids') ? $this->container->getParameter('console.command.ids') : array();
$alias = 'console.command.'.strtolower(str_replace('\\', '_', $class));
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());
}
}
}
/**

View File

@@ -46,19 +46,6 @@ interface BundleInterface extends ContainerAwareInterface
*/
public function getContainerExtension();
/**
* Returns the bundle name that this bundle overrides.
*
* Despite its name, this method does not imply any parent/child relationship
* between the bundles, just a way to extend and override an existing
* 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();
/**
* Returns the bundle name (the class short name).
*

View File

@@ -1,6 +1,39 @@
CHANGELOG
=========
4.1.0
-----
* added orphaned events support to `EventDataCollector`
* `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`)
* Deprecated `service:action` syntax with a single colon to reference controllers. Use `service::method` instead.
* Added the ability to profile individual argument value resolvers via the
`Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver`
4.0.0
-----
* removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()`
instead
* using the `DataCollector::cloneVar()` method requires the VarDumper component
* removed the `ValueExporter` class
* removed `ControllerResolverInterface::getArguments()`
* removed `TraceableControllerResolver::getArguments()`
* removed `ControllerResolver::getArguments()` and the ability to resolve arguments
* removed the `argument_resolver` service dependency from the `debug.controller_resolver`
* removed `LazyLoadingFragmentHandler::addRendererService()`
* removed `Psr6CacheClearer::addPool()`
* removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()`
* removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`,
and `Kernel::getEnvParameters()`
* support for the `X-Status-Code` when handling exceptions in the `HttpKernel`
has been dropped, use the `HttpKernel::allowCustomResponseCode()` method
instead
* removed convention-based commands registration
* removed the `ChainCacheClearer::add()` method
* removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods
* made `CacheWarmerAggregate` and `ChainCacheClearer` classes final
3.4.0
-----

View File

@@ -16,18 +16,13 @@ namespace Symfony\Component\HttpKernel\CacheClearer;
*
* @author Dustin Dobervich <ddobervich@gmail.com>
*
* @final since version 3.4
* @final
*/
class ChainCacheClearer implements CacheClearerInterface
{
protected $clearers;
private $clearers;
/**
* Constructs a new instance of ChainCacheClearer.
*
* @param array $clearers The initial clearers
*/
public function __construct($clearers = array())
public function __construct(iterable $clearers = array())
{
$this->clearers = $clearers;
}
@@ -41,16 +36,4 @@ class ChainCacheClearer implements CacheClearerInterface
$clearer->clear($cacheDir);
}
}
/**
* 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;
}
}

View File

@@ -11,8 +11,6 @@
namespace Symfony\Component\HttpKernel\CacheClearer;
use Psr\Cache\CacheItemPoolInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
@@ -25,18 +23,20 @@ class Psr6CacheClearer implements CacheClearerInterface
$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 getPool($name)
{
if (!$this->hasPool($name)) {
throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
}
return $this->pools[$name];
}
public function clearPool($name)
{
if (!isset($this->pools[$name])) {

View File

@@ -20,7 +20,7 @@ abstract class CacheWarmer implements CacheWarmerInterface
{
protected function writeCacheFile($file, $content)
{
$tmpFile = @tempnam(dirname($file), basename($file));
$tmpFile = @tempnam(\dirname($file), basename($file));
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
@chmod($file, 0666 & ~umask());

View File

@@ -16,20 +16,17 @@ namespace Symfony\Component\HttpKernel\CacheWarmer;
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since version 3.4
* @final
*/
class CacheWarmerAggregate implements CacheWarmerInterface
{
protected $warmers = array();
protected $optionalsEnabled = false;
private $triggerDeprecation = false;
private $warmers;
private $optionalsEnabled = false;
private $onlyOptionalsEnabled = false;
public function __construct($warmers = array())
public function __construct(iterable $warmers = array())
{
foreach ($warmers as $warmer) {
$this->add($warmer);
}
$this->triggerDeprecation = true;
$this->warmers = $warmers;
}
public function enableOptionalWarmers()
@@ -37,6 +34,11 @@ class CacheWarmerAggregate implements CacheWarmerInterface
$this->optionalsEnabled = true;
}
public function enableOnlyOptionalWarmers()
{
$this->onlyOptionalsEnabled = $this->optionalsEnabled = true;
}
/**
* Warms up the cache.
*
@@ -48,6 +50,9 @@ class CacheWarmerAggregate implements CacheWarmerInterface
if (!$this->optionalsEnabled && $warmer->isOptional()) {
continue;
}
if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) {
continue;
}
$warmer->warmUp($cacheDir);
}
@@ -62,29 +67,4 @@ 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)
{
@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 = array();
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;
}
}

View File

@@ -12,10 +12,10 @@
namespace Symfony\Component\HttpKernel;
use Symfony\Component\BrowserKit\Client as BaseClient;
use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\BrowserKit\History;
use Symfony\Component\BrowserKit\Request as DomRequest;
use Symfony\Component\BrowserKit\Response as DomResponse;
use Symfony\Component\BrowserKit\History;
use Symfony\Component\BrowserKit\CookieJar;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -25,8 +25,8 @@ use Symfony\Component\HttpFoundation\Response;
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @method Request|null getRequest() A Request instance
* @method Response|null getResponse() A Response instance
* @method Request getRequest() A Request instance
* @method Response getResponse() A Response instance
*/
class Client extends BaseClient
{
@@ -81,17 +81,18 @@ class Client extends BaseClient
*/
protected function getScript($request)
{
$kernel = str_replace("'", "\\'", serialize($this->kernel));
$request = str_replace("'", "\\'", serialize($request));
$kernel = var_export(serialize($this->kernel), true);
$request = var_export(serialize($request), true);
$errorReporting = error_reporting();
$requires = '';
foreach (get_declared_classes() as $class) {
if (0 === strpos($class, 'ComposerAutoloaderInit')) {
$r = new \ReflectionClass($class);
$file = dirname(dirname($r->getFileName())).'/autoload.php';
$file = \dirname(\dirname($r->getFileName())).'/autoload.php';
if (file_exists($file)) {
$requires .= "require_once '".str_replace("'", "\\'", $file)."';\n";
$requires .= 'require_once '.var_export($file, true).";\n";
}
}
}
@@ -107,8 +108,8 @@ error_reporting($errorReporting);
$requires
\$kernel = unserialize('$kernel');
\$request = unserialize('$request');
\$kernel = unserialize($kernel);
\$request = unserialize($request);
EOF;
return $code.$this->getHandleScript();
@@ -160,7 +161,7 @@ EOF;
{
$filtered = array();
foreach ($files as $key => $value) {
if (is_array($value)) {
if (\is_array($value)) {
$filtered[$key] = $this->filterFiles($value);
} elseif ($value instanceof UploadedFile) {
if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
@@ -168,7 +169,6 @@ EOF;
'',
$value->getClientOriginalName(),
$value->getClientMimeType(),
0,
UPLOAD_ERR_INI_SIZE,
true
);
@@ -177,7 +177,6 @@ EOF;
$value->getPathname(),
$value->getClientOriginalName(),
$value->getClientMimeType(),
$value->getClientSize(),
$value->getError(),
true
);

View File

@@ -1,99 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Config;
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
{
/**
* @var string
*/
private $prefix;
/**
* @var string
*/
private $variables;
/**
* @param string $prefix
*/
public function __construct($prefix)
{
$this->prefix = $prefix;
$this->variables = $this->findVariables();
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return serialize($this->getResource());
}
/**
* @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);
}
/**
* {@inheritdoc}
*/
public function isFresh($timestamp)
{
return $this->findVariables() === $this->variables;
}
public function serialize()
{
return serialize(array('prefix' => $this->prefix, 'variables' => $this->variables));
}
public function unserialize($serialized)
{
if (\PHP_VERSION_ID >= 70000) {
$unserialized = unserialize($serialized, array('allowed_classes' => false));
} else {
$unserialized = unserialize($serialized);
}
$this->prefix = $unserialized['prefix'];
$this->variables = $unserialized['variables'];
}
private function findVariables()
{
$variables = array();
foreach ($_SERVER as $key => $value) {
if (0 === strpos($key, $this->prefix)) {
$variables[$key] = $value;
}
}
ksort($variables);
return $variables;
}
}

View File

@@ -26,10 +26,10 @@ class FileLocator extends BaseFileLocator
/**
* @param KernelInterface $kernel A KernelInterface instance
* @param null|string $path The path the global resource directory
* @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, string $path = null, array $paths = array())
{
$this->kernel = $kernel;
if (null !== $path) {

View File

@@ -34,7 +34,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
*/
private $argumentValueResolvers;
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = array())
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = array())
{
$this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
@@ -56,7 +56,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
$resolved = $resolver->resolve($request, $metadata);
if (!$resolved instanceof \Generator) {
throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver)));
throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver)));
}
foreach ($resolved as $append) {
@@ -69,10 +69,10 @@ final class ArgumentResolver implements ArgumentResolverInterface
$representative = $controller;
if (is_array($representative)) {
$representative = sprintf('%s::%s()', get_class($representative[0]), $representative[1]);
} elseif (is_object($representative)) {
$representative = get_class($representative);
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()));
@@ -81,7 +81,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
return $arguments;
}
public static function getDefaultArgumentValueResolvers()
public static function getDefaultArgumentValueResolvers(): iterable
{
return array(
new RequestAttributeValueResolver(),

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
@@ -47,6 +48,10 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
$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());
}
@@ -63,6 +68,26 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
$controller = ltrim($controller, '\\');
}
yield $this->container->get($controller)->get($argument->getName());
if (!$this->container->has($controller)) {
$i = strrpos($controller, ':');
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
}
try {
yield $this->container->get($controller)->get($argument->getName());
} catch (RuntimeException $e) {
$what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
$message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
if ($e->getMessage() === $message) {
$message = sprintf('Cannot resolve %s: %s', $what, $message);
}
$r = new \ReflectionProperty($e, 'message');
$r->setAccessible(true);
$r->setValue($e, $message);
throw $e;
}
}
}

View File

@@ -28,6 +28,10 @@ final class SessionValueResolver implements ArgumentValueResolverInterface
*/
public function supports(Request $request, ArgumentMetadata $argument)
{
if (!$request->hasSession()) {
return false;
}
$type = $argument->getType();
if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
return false;

View File

@@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* Provides timing information via the stopwatch.
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class TraceableValueResolver implements ArgumentValueResolverInterface
{
private $inner;
private $stopwatch;
public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch)
{
$this->inner = $inner;
$this->stopwatch = $stopwatch;
}
/**
* {@inheritdoc}
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
$method = \get_class($this->inner).'::'.__FUNCTION__;
$this->stopwatch->start($method);
$return = $this->inner->supports($request, $argument);
$this->stopwatch->stop($method);
return $return;
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
$method = \get_class($this->inner).'::'.__FUNCTION__;
$this->stopwatch->start($method);
yield from $this->inner->resolve($request, $argument);
$this->stopwatch->stop($method);
}
}

View File

@@ -37,8 +37,8 @@ final class VariadicValueResolver implements ArgumentValueResolverInterface
{
$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)));
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) {

View File

@@ -14,7 +14,6 @@ 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.
@@ -33,58 +32,14 @@ class ContainerControllerResolver extends ControllerResolver
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);
if (1 === substr_count($controller, ':')) {
$controller = str_replace(':', '::', $controller);
@trigger_error(sprintf('Referencing controllers with a single colon is deprecated since Symfony 4.1. Use %s instead.', $controller), E_USER_DEPRECATED);
}
$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 array($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;
return parent::createController($controller);
}
/**
@@ -98,24 +53,22 @@ class ContainerControllerResolver extends ControllerResolver
try {
return parent::instantiateController($class);
} catch (\ArgumentCountError $e) {
} catch (\ErrorException $e) {
} catch (\TypeError $e) {
} catch (\Error $e) {
}
$this->throwExceptionIfControllerWasRemoved($class, $e);
throw $e;
if ($e instanceof \ArgumentCountError) {
throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', $class), 0, $e);
}
throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e);
}
/**
* @param string $controller
* @param \Exception|\Throwable|null $previous
*/
private function throwExceptionIfControllerWasRemoved($controller, $previous = null)
private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous)
{
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);
throw new \InvalidArgumentException(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);
}
}
}

View File

@@ -35,7 +35,7 @@ class ControllerReference
* @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(string $controller, array $attributes = array(), array $query = array())
{
$this->controller = $controller;
$this->attributes = $attributes;

View File

@@ -16,44 +16,22 @@ use Symfony\Component\HttpFoundation\Request;
/**
* This implementation uses the '_controller' request attribute to determine
* the controller to execute and uses the request attributes to determine
* the controller method arguments.
* the controller to execute.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Tobias Schultze <http://tobion.de>
*/
class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface
class ControllerResolver implements ControllerResolverInterface
{
private $logger;
/**
* If the ...$arg functionality is available.
*
* Requires at least PHP 5.6.0 or HHVM 3.9.1
*
* @var bool
*/
private $supportsVariadic;
/**
* If scalar types exists.
*
* @var bool
*/
private $supportsScalarTypes;
public function __construct(LoggerInterface $logger = null)
{
$this->logger = $logger;
$this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic');
$this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType');
}
/**
* {@inheritdoc}
*
* This method looks for a '_controller' request attribute that represents
* the controller name (a string like ClassName::MethodName).
*/
public function getController(Request $request)
{
@@ -65,122 +43,82 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve
return false;
}
if (is_array($controller)) {
if (\is_array($controller)) {
if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) {
try {
$controller[0] = $this->instantiateController($controller[0]);
} catch (\Error | \LogicException $e) {
try {
// We cannot just check is_callable but have to use reflection because a non-static method
// can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we
// could simplify this with PHP 8.
if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) {
return $controller;
}
} catch (\ReflectionException $reflectionException) {
throw $e;
}
throw $e;
}
}
if (!\is_callable($controller)) {
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller)));
}
return $controller;
}
if (is_object($controller)) {
if (method_exists($controller, '__invoke')) {
return $controller;
if (\is_object($controller)) {
if (!\is_callable($controller)) {
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller)));
}
throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
return $controller;
}
if (false === strpos($controller, ':')) {
if (method_exists($controller, '__invoke')) {
return $this->instantiateController($controller);
} elseif (function_exists($controller)) {
return $controller;
}
if (\function_exists($controller)) {
return $controller;
}
$callable = $this->createController($controller);
if (!is_callable($callable)) {
if (!\is_callable($callable)) {
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable)));
}
return $callable;
}
/**
* {@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('%s 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) {
$r = new \ReflectionObject($controller);
$r = $r->getMethod('__invoke');
} else {
$r = new \ReflectionFunction($controller);
}
return $this->doGetArguments($request, $controller, $r->getParameters());
}
/**
* @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('%s 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();
foreach ($parameters as $param) {
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 {
$arguments[] = $attributes[$param->name];
}
} elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
$arguments[] = $request;
} elseif ($param->isDefaultValueAvailable()) {
$arguments[] = $param->getDefaultValue();
} elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) {
$arguments[] = null;
} else {
if (is_array($controller)) {
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
} elseif (is_object($controller)) {
$repr = get_class($controller);
} else {
$repr = $controller;
}
throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
}
}
return $arguments;
}
/**
* Returns a callable for the given controller.
*
* @param string $controller A Controller string
*
* @return callable A PHP callable
*
* @throws \InvalidArgumentException
*/
protected function createController($controller)
{
if (false === strpos($controller, '::')) {
throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
return $this->instantiateController($controller);
}
list($class, $method) = explode('::', $controller, 2);
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
try {
return array($this->instantiateController($class), $method);
} catch (\Error | \LogicException $e) {
try {
if ((new \ReflectionMethod($class, $method))->isStatic()) {
return $class.'::'.$method;
}
} catch (\ReflectionException $reflectionException) {
throw $e;
}
return array($this->instantiateController($class), $method);
throw $e;
}
}
/**
@@ -197,48 +135,49 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve
private function getControllerError($callable)
{
if (is_string($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)) {
$callable = explode('::', $callable, 2);
} else {
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 (\is_object($callable)) {
$availableMethods = $this->getClassMethodsWithoutMagicMethods($callable);
$alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : '';
return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', \get_class($callable), $alternativeMsg);
}
if (2 !== count($callable)) {
return 'Invalid format for controller, expected array(controller, method) or controller::method.';
if (!\is_array($callable)) {
return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', \gettype($callable));
}
if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) {
return 'Invalid array callable, expected array(controller, method).';
}
list($controller, $method) = $callable;
if (is_string($controller) && !class_exists($controller)) {
if (\is_string($controller) && !class_exists($controller)) {
return sprintf('Class "%s" does not exist.', $controller);
}
$className = is_object($controller) ? get_class($controller) : $controller;
$className = \is_object($controller) ? \get_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);
$collection = $this->getClassMethodsWithoutMagicMethods($controller);
$alternatives = array();
foreach ($collection as $item) {
$lev = levenshtein($method, $item);
if ($lev <= strlen($method) / 3 || false !== strpos($item, $method)) {
if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) {
$alternatives[] = $item;
}
}
@@ -247,7 +186,7 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve
$message = sprintf('Expected method "%s" on class "%s"', $method, $className);
if (count($alternatives) > 0) {
if (\count($alternatives) > 0) {
$message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives));
} else {
$message .= sprintf('. Available methods: "%s".', implode('", "', $collection));
@@ -255,4 +194,13 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve
return $message;
}
private function getClassMethodsWithoutMagicMethods($classOrObject)
{
$methods = get_class_methods($classOrObject);
return array_filter($methods, function (string $method) {
return 0 !== strncmp($method, '__', 2);
});
}
}

View File

@@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\Request;
* A ControllerResolverInterface implementation knows how to determine the
* controller to execute based on a Request object.
*
* It can also determine the arguments to pass to the Controller.
*
* A Controller can be any valid PHP callable.
*
* @author Fabien Potencier <fabien@symfony.com>
@@ -37,21 +35,7 @@ interface ControllerResolverInterface
* @return callable|false A PHP callable representing the Controller,
* or false if this resolver is not able to determine the controller
*
* @throws \LogicException If the controller can't be found
* @throws \LogicException If a controller was found based on the request but it is not callable
*/
public function getController(Request $request);
/**
* Returns the arguments to pass to the controller.
*
* @param Request $request A Request instance
* @param callable $controller A PHP callable
*
* @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);
}

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Controller;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* @author Fabien Potencier <fabien@symfony.com>

View File

@@ -11,32 +11,21 @@
namespace Symfony\Component\HttpKernel\Controller;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface
class TraceableControllerResolver implements ControllerResolverInterface
{
private $resolver;
private $stopwatch;
private $argumentResolver;
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null)
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
{
$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);
}
}
/**
@@ -52,18 +41,4 @@ class TraceableControllerResolver implements ControllerResolverInterface, Argume
return $ret;
}
/**
* {@inheritdoc}
*
* @deprecated This method is deprecated as of 3.1 and will be removed in 4.0.
*/
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. Please use the %s instead.', __METHOD__, TraceableArgumentResolver::class), E_USER_DEPRECATED);
$ret = $this->argumentResolver->getArguments($request, $controller);
return $ret;
}
}

View File

@@ -25,15 +25,7 @@ class ArgumentMetadata
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)
public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false)
{
$this->name = $name;
$this->type = $type;

View File

@@ -18,30 +18,6 @@ namespace Symfony\Component\HttpKernel\ControllerMetadata;
*/
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}
*/
@@ -49,80 +25,34 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
{
$arguments = array();
if (is_array($controller)) {
if (\is_array($controller)) {
$reflection = new \ReflectionMethod($controller[0], $controller[1]);
} elseif (is_object($controller) && !$controller instanceof \Closure) {
} 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());
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull());
}
return $arguments;
}
/**
* Returns whether an argument is variadic.
*
* @param \ReflectionParameter $parameter
*
* @return bool
*/
private function isVariadic(\ReflectionParameter $parameter)
{
return $this->supportsVariadic && $parameter->isVariadic();
}
/**
* Determines whether an argument has a default value.
*
* @param \ReflectionParameter $parameter
*
* @return bool
*/
private function hasDefaultValue(\ReflectionParameter $parameter)
{
return $parameter->isDefaultValueAvailable();
}
/**
* Returns a default value if available.
*
* @param \ReflectionParameter $parameter
*
* @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.
*
* @param \ReflectionParameter $parameter
*
* @return null|string
* @return string|null
*/
private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
{
if ($this->supportsParameterType) {
if (!$type = $parameter->getType()) {
return;
}
$name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString();
if ('array' === $name && !$type->isBuiltin()) {
// Special case for HHVM with variadics
return;
}
} elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $name)) {
$name = $name[1];
} else {
if (!$type = $parameter->getType()) {
return;
}
$name = $type->getName();
$lcName = strtolower($name);
if ('self' !== $lcName && 'parent' !== $lcName) {

View File

@@ -11,10 +11,10 @@
namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpKernel\Kernel;
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;
/**
@@ -34,7 +34,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
* @param string $name The name of the application using the web profiler
* @param string $version The version of the application using the web profiler
*/
public function __construct($name = null, $version = null)
public function __construct(string $name = null, string $version = null)
{
$this->name = $name;
$this->version = $version;
@@ -67,11 +67,11 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
'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'),
'apcu_enabled' => extension_loaded('apcu') && ini_get('apc.enabled'),
'zend_opcache_enabled' => extension_loaded('Zend OPcache') && ini_get('opcache.enable'),
'xdebug_enabled' => \extension_loaded('xdebug'),
'apcu_enabled' => \extension_loaded('apcu') && ini_get('apc.enabled'),
'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && ini_get('opcache.enable'),
'bundles' => array(),
'sapi_name' => PHP_SAPI,
'sapi_name' => \PHP_SAPI,
);
if (isset($this->kernel)) {

View File

@@ -11,7 +11,6 @@
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;
@@ -30,11 +29,6 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
{
protected $data = array();
/**
* @var ValueExporter
*/
private $valueExporter;
/**
* @var ClonerInterface
*/
@@ -66,46 +60,17 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
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 (!class_exists(CutStub::class)) {
throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.4 or above.', __METHOD__));
}
}
if (false === $this->cloner) {
if (null === $this->valueExporter) {
$this->valueExporter = new ValueExporter();
}
return $this->valueExporter->exportValue($var);
$this->cloner = new VarCloner();
$this->cloner->setMaxItems(-1);
$this->cloner->addCasters($this->getCasters());
}
return $this->cloner->cloneVar($var);
}
/**
* Converts a PHP variable to a string.
*
* @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
*/
@@ -115,7 +80,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
'*' => 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) {
if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
$a[$k] = new CutStub($v);
}
}

View File

@@ -18,8 +18,6 @@ use Symfony\Component\HttpFoundation\Response;
* DataCollectorInterface.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @method reset() Resets this data collector to its initial state.
*/
interface DataCollectorInterface
{
@@ -34,4 +32,9 @@ interface DataCollectorInterface
* @return string The collector name
*/
public function getName();
/**
* Resets this data collector to its initial state.
*/
public function reset();
}

View File

@@ -18,9 +18,10 @@ use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
use Twig\Template;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\Server\Connection;
/**
* @author Nicolas Grekas <p@tchwork.com>
@@ -37,16 +38,18 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
private $charset;
private $requestStack;
private $dumper;
private $dumperIsInjected;
private $sourceContextProvider;
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null)
/**
* @param DataDumperInterface|Connection|null $dumper
*/
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null)
{
$this->stopwatch = $stopwatch;
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
$this->requestStack = $requestStack;
$this->dumper = $dumper;
$this->dumperIsInjected = null !== $dumper;
// All clones share these properties by reference:
$this->rootRefs = array(
@@ -55,6 +58,8 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
&$this->isCollected,
&$this->clonesCount,
);
$this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
}
public function __clone()
@@ -67,65 +72,17 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
if ($this->stopwatch) {
$this->stopwatch->start('dump');
}
if ($this->isCollected && !$this->dumper) {
$this->isCollected = false;
}
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 7);
list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext();
$file = $trace[0]['file'];
$line = $trace[0]['line'];
$name = false;
$fileExcerpt = false;
for ($i = 1; $i < 7; ++$i) {
if (isset($trace[$i]['class'], $trace[$i]['function'])
&& 'dump' === $trace[$i]['function']
&& 'Symfony\Component\VarDumper\VarDumper' === $trace[$i]['class']
) {
$file = $trace[$i]['file'];
$line = $trace[$i]['line'];
while (++$i < 7) {
if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) {
$file = $trace[$i]['file'];
$line = $trace[$i]['line'];
break;
} elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) {
$template = $trace[$i]['object'];
$name = $template->getTemplateName();
$src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false);
$info = $template->getDebugInfo();
if (isset($info[$trace[$i - 1]['line']])) {
$line = $info[$trace[$i - 1]['line']];
$file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null;
if ($src) {
$src = explode("\n", $src);
$fileExcerpt = array();
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>';
}
$fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>';
}
}
break;
}
}
break;
if ($this->dumper instanceof Connection) {
if (!$this->dumper->write($data)) {
$this->isCollected = false;
}
}
if (false === $name) {
$name = str_replace('\\', '/', $file);
$name = substr($name, strrpos($name, '/') + 1);
}
if ($this->dumper) {
$this->doDump($data, $name, $file, $line);
} elseif ($this->dumper) {
$this->doDump($this->dumper, $data, $name, $file, $line);
} else {
$this->isCollected = false;
}
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
@@ -152,14 +109,14 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|| false === strripos($response->getContent(), '</body>')
) {
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(array('fileLinkFormat' => $this->fileLinkFormat));
$dumper = new HtmlDumper('php://output', $this->charset);
$dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat));
} else {
$this->dumper = new CliDumper('php://output', $this->charset);
$dumper = new CliDumper('php://output', $this->charset);
}
foreach ($this->data as $dump) {
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
$this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']);
}
}
}
@@ -171,7 +128,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
}
$this->data = array();
$this->dataCount = 0;
$this->isCollected = false;
$this->isCollected = true;
$this->clonesCount = 0;
$this->clonesIndex = 0;
}
@@ -188,9 +145,6 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
$this->data = array();
$this->dataCount = 0;
$this->isCollected = true;
if (!$this->dumperIsInjected) {
$this->dumper = null;
}
return $ser;
}
@@ -200,7 +154,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
parent::unserialize($data);
$charset = array_pop($this->data);
$fileLinkFormat = array_pop($this->data);
$this->dataCount = count($this->data);
$this->dataCount = \count($this->data);
self::__construct($this->stopwatch, $fileLinkFormat, $charset);
}
@@ -244,22 +198,22 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
$this->isCollected = true;
$h = headers_list();
$i = count($h);
$i = \count($h);
array_unshift($h, 'Content-Type: '.ini_get('default_mimetype'));
while (0 !== stripos($h[$i], 'Content-Type:')) {
--$i;
}
if (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true) && stripos($h[$i], 'html')) {
$this->dumper = new HtmlDumper('php://output', $this->charset);
$this->dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat));
if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true) && stripos($h[$i], 'html')) {
$dumper = new HtmlDumper('php://output', $this->charset);
$dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat));
} else {
$this->dumper = new CliDumper('php://output', $this->charset);
$dumper = new CliDumper('php://output', $this->charset);
}
foreach ($this->data as $i => $dump) {
$this->data[$i] = null;
$this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
$this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']);
}
$this->data = array();
@@ -267,16 +221,16 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
}
}
private function doDump($data, $name, $file, $line)
private function doDump(DataDumperInterface $dumper, $data, $name, $file, $line)
{
if ($this->dumper instanceof CliDumper) {
if ($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));
if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line)) {
if ($fmt && $link = \is_string($fmt) ? strtr($fmt, array('%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>', $f, $name);
@@ -290,26 +244,12 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
}
$this->dumpLine(0);
};
$contextDumper = $contextDumper->bindTo($this->dumper, $this->dumper);
$contextDumper = $contextDumper->bindTo($dumper, $dumper);
$contextDumper($name, $file, $line, $this->fileLinkFormat);
} else {
$cloner = new VarCloner();
$this->dumper->dump($cloner->cloneVar($name.' on line '.$line.':'));
$dumper->dump($cloner->cloneVar($name.' on line '.$line.':'));
}
$this->dumper->dump($data);
}
private function htmlEncode($s)
{
$html = '';
$dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset);
$dumper->setDumpHeader('');
$dumper->setDumpBoundaries('', '');
$cloner = new VarCloner();
$dumper->dump($cloner->cloneVar($s));
return substr(strip_tags($html), 1, -1);
$dumper->dump($data);
}
}

View File

@@ -11,10 +11,11 @@
namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
/**
* EventDataCollector.
@@ -27,9 +28,6 @@ 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;
}
@@ -41,6 +39,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
$this->data = array(
'called_listeners' => array(),
'not_called_listeners' => array(),
'orphaned_events' => array(),
);
}
@@ -49,10 +48,6 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
$this->data = array();
if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
if (!method_exists($this->dispatcher, 'reset')) {
return; // @deprecated
}
$this->dispatcher->reset();
}
}
@@ -63,6 +58,11 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
$this->setCalledListeners($this->dispatcher->getCalledListeners());
$this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
}
if ($this->dispatcher instanceof TraceableEventDispatcher) {
$this->setOrphanedEvents($this->dispatcher->getOrphanedEvents());
}
$this->data = $this->cloneVar($this->data);
}
@@ -71,7 +71,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
*
* @param array $listeners An array of called listeners
*
* @see TraceableEventDispatcherInterface
* @see TraceableEventDispatcher
*/
public function setCalledListeners(array $listeners)
{
@@ -83,7 +83,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
*
* @return array An array of called listeners
*
* @see TraceableEventDispatcherInterface
* @see TraceableEventDispatcher
*/
public function getCalledListeners()
{
@@ -93,9 +93,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
/**
* Sets the not called listeners.
*
* @param array $listeners An array of not called listeners
* @param array $listeners
*
* @see TraceableEventDispatcherInterface
* @see TraceableEventDispatcher
*/
public function setNotCalledListeners(array $listeners)
{
@@ -105,15 +105,39 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
/**
* Gets the not called listeners.
*
* @return array An array of not called listeners
* @return array
*
* @see TraceableEventDispatcherInterface
* @see TraceableEventDispatcher
*/
public function getNotCalledListeners()
{
return $this->data['not_called_listeners'];
}
/**
* Sets the orphaned events.
*
* @param array $events An array of orphaned events
*
* @see TraceableEventDispatcher
*/
public function setOrphanedEvents(array $events)
{
$this->data['orphaned_events'] = $events;
}
/**
* Gets the orphaned events.
*
* @return array An array of orphaned events
*
* @see TraceableEventDispatcher
*/
public function getOrphanedEvents()
{
return $this->data['orphaned_events'];
}
/**
* {@inheritdoc}
*/

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\Debug\Exception\SilencedErrorContext;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
@@ -25,18 +26,17 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
{
private $logger;
private $containerPathPrefix;
private $currentRequest;
private $requestStack;
public function __construct($logger = null, $containerPathPrefix = null)
public function __construct($logger = null, string $containerPathPrefix = null, RequestStack $requestStack = 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;
$this->requestStack = $requestStack;
}
/**
@@ -44,7 +44,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{
// everything is done as late as possible
$this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null;
}
/**
@@ -52,7 +52,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
*/
public function reset()
{
if ($this->logger && method_exists($this->logger, 'clear')) {
if ($this->logger instanceof DebugLoggerInterface) {
$this->logger->clear();
}
$this->data = array();
@@ -67,9 +67,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
$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['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs));
$this->data = $this->cloneVar($this->data);
}
$this->currentRequest = null;
}
/**
@@ -222,7 +223,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
return true;
}
if ($exception instanceof \ErrorException && in_array($exception->getSeverity(), array(E_DEPRECATED, E_USER_DEPRECATED), true)) {
if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), array(E_DEPRECATED, E_USER_DEPRECATED), true)) {
return true;
}
@@ -233,14 +234,14 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
{
$silencedLogs = array();
$count = array(
'error_count' => $this->logger->countErrors(),
'error_count' => $this->logger->countErrors($this->currentRequest),
'deprecation_count' => 0,
'warning_count' => 0,
'scream_count' => 0,
'priorities' => array(),
);
foreach ($this->logger->getLogs() as $log) {
foreach ($this->logger->getLogs($this->currentRequest) as $log) {
if (isset($count['priorities'][$log['priority']])) {
++$count['priorities'][$log['priority']]['count'];
} else {

View File

@@ -98,9 +98,9 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
$memoryLimit = strtolower($memoryLimit);
$max = strtolower(ltrim($memoryLimit, '+'));
if (0 === strpos($max, '0x')) {
$max = intval($max, 16);
$max = \intval($max, 16);
} elseif (0 === strpos($max, '0')) {
$max = intval($max, 8);
$max = \intval($max, 8);
} else {
$max = (int) $max;
}

View File

@@ -11,14 +11,14 @@
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;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* @author Fabien Potencier <fabien@symfony.com>
@@ -42,7 +42,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
$route = '';
foreach ($request->attributes->all() as $key => $value) {
if ('_route' === $key) {
$route = is_object($value) ? $value->getPath() : $value;
$route = \is_object($value) ? $value->getPath() : $value;
$attributes[$key] = $route;
} else {
$attributes[$key] = $value;
@@ -79,6 +79,13 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
$responseCookies[$cookie->getName()] = $cookie;
}
$dotenvVars = array();
foreach (explode(',', getenv('SYMFONY_DOTENV_VARS')) as $name) {
if ('' !== $name && false !== $value = getenv($name)) {
$dotenvVars[$name] = $value;
}
}
$this->data = array(
'method' => $request->getMethod(),
'format' => $request->getRequestFormat(),
@@ -101,6 +108,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
'path_info' => $request->getPathInfo(),
'controller' => 'n/a',
'locale' => $request->getLocale(),
'dotenv_vars' => $dotenvVars,
);
if (isset($this->data['request_headers']['php-auth-pw'])) {
@@ -116,7 +124,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
}
foreach ($this->data as $key => $value) {
if (!is_array($value)) {
if (!\is_array($value)) {
continue;
}
if ('request_headers' === $key || 'response_headers' === $key) {
@@ -149,7 +157,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
));
}
$this->data['identifier'] = $this->data['route'] ?: (is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
$this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
if ($response->headers->has('x-previous-debug-token')) {
$this->data['forward_token'] = $response->headers->get('x-previous-debug-token');
}
}
public function lateCollect()
@@ -258,6 +270,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
return $this->data['locale'];
}
public function getDotenvVars()
{
return new ParameterBag($this->data['dotenv_vars']->getValue());
}
/**
* Gets the route name.
*
@@ -309,6 +326,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
return isset($this->data['redirect']) ? $this->data['redirect'] : false;
}
public function getForwardToken()
{
return isset($this->data['forward_token']) ? $this->data['forward_token'] : null;
}
public function onKernelController(FilterControllerEvent $event)
{
$this->controllers[$event->getRequest()] = $event->getController();
@@ -350,25 +372,25 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
*/
protected function parseController($controller)
{
if (is_string($controller) && false !== strpos($controller, '::')) {
if (\is_string($controller) && false !== strpos($controller, '::')) {
$controller = explode('::', $controller);
}
if (is_array($controller)) {
if (\is_array($controller)) {
try {
$r = new \ReflectionMethod($controller[0], $controller[1]);
return array(
'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
'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)) {
if (\is_callable($controller)) {
// using __call or __callStatic
return array(
'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0],
'method' => $controller[1],
'file' => 'n/a',
'line' => 'n/a',
@@ -388,7 +410,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
);
}
if (is_object($controller)) {
if (\is_object($controller)) {
$r = new \ReflectionClass($controller);
return array(
@@ -399,6 +421,6 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
);
}
return is_string($controller) ? $controller : 'n/a';
return \is_string($controller) ? $controller : 'n/a';
}
}

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
/**

View File

@@ -1,99 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\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
{
/**
* Converts a PHP value to a string.
*
* @param mixed $value The PHP value
* @param int $depth Only for internal usage
* @param bool $deep Only for internal usage
*
* @return string The string representation of the given value
*/
public function exportValue($value, $depth = 1, $deep = false)
{
if ($value instanceof \__PHP_Incomplete_Class) {
return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value));
}
if (is_object($value)) {
if ($value instanceof \DateTimeInterface) {
return sprintf('Object(%s) - %s', get_class($value), $value->format(\DateTime::ATOM));
}
return sprintf('Object(%s)', get_class($value));
}
if (is_array($value)) {
if (empty($value)) {
return '[]';
}
$indent = str_repeat(' ', $depth);
$a = array();
foreach ($value as $k => $v) {
if (is_array($v)) {
$deep = true;
}
$a[] = sprintf('%s => %s', $k, $this->exportValue($v, $depth + 1, $deep));
}
if ($deep) {
return sprintf("[\n%s%s\n%s]", $indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1));
}
$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)) {
return sprintf('Resource(%s#%d)', get_resource_type($value), $value);
}
if (null === $value) {
return 'null';
}
if (false === $value) {
return 'false';
}
if (true === $value) {
return 'true';
}
return (string) $value;
}
private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
{
$array = new \ArrayObject($value);
return $array['__PHP_Incomplete_Class_Name'];
}
}

View File

@@ -31,11 +31,11 @@ class FileLinkFormatter implements \Serializable
/**
* @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)
public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null)
{
$fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
if ($fileLinkFormat && !is_array($fileLinkFormat)) {
$i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f);
if ($fileLinkFormat && !\is_array($fileLinkFormat)) {
$i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f);
$fileLinkFormat = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE);
}
@@ -50,7 +50,7 @@ class FileLinkFormatter implements \Serializable
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));
$file = substr_replace($file, $fmt[$i], 0, \strlen($k));
break;
}
}
@@ -68,11 +68,7 @@ class FileLinkFormatter implements \Serializable
public function unserialize($serialized)
{
if (\PHP_VERSION_ID >= 70000) {
$this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false));
} else {
$this->fileLinkFormat = unserialize($serialized);
}
$this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false));
}
/**
@@ -100,8 +96,8 @@ class FileLinkFormatter implements \Serializable
}
return array(
$request->getSchemeAndHttpHost().$request->getBaseUrl().$this->urlFormat,
$this->baseDir.DIRECTORY_SEPARATOR, '',
$request->getSchemeAndHttpHost().$request->getBasePath().$this->urlFormat,
$this->baseDir.\DIRECTORY_SEPARATOR, '',
);
}
}

View File

@@ -12,8 +12,8 @@
namespace Symfony\Component\HttpKernel\Debug;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Collects some data about event listeners.

View File

@@ -13,8 +13,8 @@ namespace Symfony\Component\HttpKernel\DependencyInjection;
use Composer\Autoload\ClassLoader;
use Symfony\Component\Debug\DebugClassLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
/**
@@ -36,23 +36,15 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
*/
public function process(ContainerBuilder $container)
{
$classes = array();
$annotatedClasses = array();
$annotatedClasses = $this->kernel->getAnnotatedClassesToCompile();
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));
}
@@ -96,7 +88,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
$classes = array();
foreach (spl_autoload_functions() as $function) {
if (!is_array($function)) {
if (!\is_array($function)) {
continue;
}
@@ -104,7 +96,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
$function = $function[0]->getClassLoader();
}
if (is_array($function) && $function[0] instanceof ClassLoader) {
if (\is_array($function) && $function[0] instanceof ClassLoader) {
$classes += array_filter($function[0]->getClassMap());
}
}

View File

@@ -1,25 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\DependencyInjection;
@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 extends AddAnnotatedClassesToCachePass
{
}

View File

@@ -15,6 +15,9 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* Gathers and configures the argument value resolvers.
@@ -27,11 +30,13 @@ class ControllerArgumentValueResolverPass implements CompilerPassInterface
private $argumentResolverService;
private $argumentValueResolverTag;
private $traceableResolverStopwatch;
public function __construct($argumentResolverService = 'argument_resolver', $argumentValueResolverTag = 'controller.argument_value_resolver')
public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch')
{
$this->argumentResolverService = $argumentResolverService;
$this->argumentValueResolverTag = $argumentValueResolverTag;
$this->traceableResolverStopwatch = $traceableResolverStopwatch;
}
public function process(ContainerBuilder $container)
@@ -40,9 +45,20 @@ class ControllerArgumentValueResolverPass implements CompilerPassInterface
return;
}
$resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container);
if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) {
foreach ($resolvers as $resolverReference) {
$id = (string) $resolverReference;
$container->register("debug.$id", TraceableValueResolver::class)
->setDecoratedService($id)
->setArguments(array(new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)));
}
}
$container
->getDefinition($this->argumentResolverService)
->replaceArgument(1, new IteratorArgument($this->findAndSortTaggedServices($this->argumentValueResolverTag, $container)))
->replaceArgument(1, new IteratorArgument($resolvers))
;
}
}

View File

@@ -20,25 +20,8 @@ use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;
*/
abstract class Extension extends BaseExtension
{
private $classes = array();
private $annotatedClasses = array();
/**
* 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.
*
@@ -49,22 +32,6 @@ abstract class Extension extends BaseExtension
return $this->annotatedClasses;
}
/**
* Adds classes to the class cache.
*
* @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.
*

View File

@@ -11,9 +11,9 @@
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\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
@@ -28,11 +28,7 @@ class FragmentRendererPass implements CompilerPassInterface
private $handlerService;
private $rendererTag;
/**
* @param string $handlerService Service name of the fragment handler in the container
* @param string $rendererTag Tag name used for fragments
*/
public function __construct($handlerService = 'fragment.handler', $rendererTag = 'kernel.fragment_renderer')
public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer')
{
$this->handlerService = $handlerService;
$this->rendererTag = $rendererTag;

View File

@@ -23,52 +23,20 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
class LazyLoadingFragmentHandler extends FragmentHandler
{
private $container;
/**
* @deprecated since version 3.3, to be removed in 4.0
*/
private $rendererIds = array();
private $initialized = array();
/**
* @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 $requestStack, $debug = false)
public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false)
{
$this->container = $container;
parent::__construct($requestStack, array(), $debug);
}
/**
* Adds a service as a fragment renderer.
*
* @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())
{
// 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;

View File

@@ -12,9 +12,9 @@
namespace Symfony\Component\HttpKernel\DependencyInjection;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Log\Logger;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Log\Logger;
/**
* Registers the default logger if necessary.

View File

@@ -31,7 +31,7 @@ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPas
public function process(ContainerBuilder $container)
{
foreach ($this->extensions as $extension) {
if (!count($container->getExtensionConfig($extension))) {
if (!\count($container->getExtensionConfig($extension))) {
$container->loadFromExtension($extension, array());
}
}

View File

@@ -33,11 +33,13 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
{
private $resolverServiceId;
private $controllerTag;
private $controllerLocator;
public function __construct($resolverServiceId = 'argument_resolver.service', $controllerTag = 'controller.service_arguments')
public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator')
{
$this->resolverServiceId = $resolverServiceId;
$this->controllerTag = $controllerTag;
$this->controllerLocator = $controllerLocator;
}
public function process(ContainerBuilder $container)
@@ -60,7 +62,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
while ($def instanceof ChildDefinition) {
$def = $container->findDefinition($def->getParent());
$class = $class ?: $def->getClass();
$bindings = $def->getBindings();
$bindings += $def->getBindings();
}
$class = $parameterBag->resolveValue($class);
@@ -126,7 +128,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
if (isset($arguments[$r->name][$p->name])) {
$target = $arguments[$r->name][$p->name];
if ('?' !== $target[0]) {
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
$invalidBehavior = ContainerInterface::RUNTIME_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()) {
@@ -136,17 +138,22 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
$binding = $bindings[$bindingName];
list($bindingValue, $bindingId) = $binding->getValues();
$binding->setValues(array($bindingValue, $bindingId, true));
if (!$bindingValue instanceof Reference) {
continue;
$args[$p->name] = new Reference('.value.'.$container->hash($bindingValue));
$container->register((string) $args[$p->name], 'mixed')
->setFactory('current')
->addArgument(array($bindingValue));
} else {
$args[$p->name] = $bindingValue;
}
$binding->setValues(array($bindingValue, $bindingId, true));
$args[$p->name] = $bindingValue;
continue;
} elseif (!$type || !$autowire) {
continue;
} elseif (!$p->allowsNull()) {
$invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
}
if (Request::class === $type) {
@@ -164,16 +171,18 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
throw new InvalidArgumentException($message);
}
$args[$p->name] = $type ? new TypedReference($target, $type, $r->class, $invalidBehavior) : new Reference($target, $invalidBehavior);
$args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior) : new Reference($target, $invalidBehavior);
}
// register the maps as a per-method service-locators
if ($args) {
$controllers[$id.':'.$r->name] = ServiceLocatorTagPass::register($container, $args);
$controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args);
}
}
}
$container->getDefinition($this->resolverServiceId)
->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers));
->replaceArgument(0, $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers));
$container->setAlias($this->controllerLocator, (string) $controllerLocatorRef);
}
}

View File

@@ -21,21 +21,16 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*/
class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
{
private $resolverServiceId;
private $controllerLocator;
public function __construct($resolverServiceId = 'argument_resolver.service')
public function __construct(string $controllerLocator = 'argument_resolver.controller_locator')
{
$this->resolverServiceId = $resolverServiceId;
$this->controllerLocator = $controllerLocator;
}
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition($this->resolverServiceId)) {
return;
}
$serviceResolver = $container->getDefinition($this->resolverServiceId);
$controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0));
$controllerLocator = $container->findDefinition($this->controllerLocator);
$controllers = $controllerLocator->getArgument(0);
foreach ($controllers as $controller => $argumentRef) {
@@ -47,8 +42,7 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
} 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));
list($id, $action) = explode('::', $controller);
$controllerDef = $container->getDefinition($id);
foreach ($controllerDef->getMethodCalls() as list($method)) {
if (0 === strcasecmp($action, $method)) {
@@ -57,9 +51,9 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
}
}
if (!$reason) {
if ($controllerDef->getClass() === $id) {
$controllers[$id.'::'.$action] = $argumentRef;
}
// Deprecated since Symfony 4.1. See Symfony\Component\HttpKernel\Controller\ContainerControllerResolver
$controllers[$id.':'.$action] = $argumentRef;
if ('__invoke' === $action) {
$controllers[$id] = $argumentRef;
}

View File

@@ -25,7 +25,7 @@ class ResettableServicePass implements CompilerPassInterface
{
private $tagName;
public function __construct($tagName = 'kernel.reset')
public function __construct(string $tagName = 'kernel.reset')
{
$this->tagName = $tagName;
}

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows filtering of controller arguments.
@@ -30,7 +30,7 @@ class FilterControllerArgumentsEvent extends FilterControllerEvent
{
private $arguments;
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, $requestType)
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType)
{
parent::__construct($kernel, $controller, $request, $requestType);

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows filtering of a controller callable.
@@ -29,7 +29,7 @@ class FilterControllerEvent extends KernelEvent
{
private $controller;
public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, $requestType)
public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType)
{
parent::__construct($kernel, $request, $requestType);

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows to filter a Response object.
@@ -28,7 +28,7 @@ class FilterResponseEvent extends KernelEvent
{
private $response;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response)
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response)
{
parent::__construct($kernel, $request, $requestType);

View File

@@ -29,7 +29,7 @@ class GetResponseEvent extends KernelEvent
/**
* Returns the response object.
*
* @return Response
* @return Response|null
*/
public function getResponse()
{

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows to create a response for the return value of a controller.
@@ -32,7 +32,7 @@ class GetResponseForControllerResultEvent extends GetResponseEvent
*/
private $controllerResult;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult)
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult)
{
parent::__construct($kernel, $request, $requestType);

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows to create a response for a thrown exception.
@@ -41,7 +41,7 @@ class GetResponseForExceptionEvent extends GetResponseEvent
*/
private $allowCustomResponseCode = false;
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Exception $e)
{
parent::__construct($kernel, $request, $requestType);

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Base class for events thrown in the HttpKernel component.
@@ -32,7 +32,7 @@ class KernelEvent extends Event
* @param int $requestType The request type the kernel is currently processing; one of
* HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST
*/
public function __construct(HttpKernelInterface $kernel, Request $request, $requestType)
public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType)
{
$this->kernel = $kernel;
$this->request = $request;

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Allows to execute logic after a response was sent.

View File

@@ -11,33 +11,58 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Container\ContainerInterface;
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;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Sets the session in the request.
* Sets the session onto the request on the "kernel.request" event and saves
* it on the "kernel.response" event.
*
* In addition, if the session has been started it overrides the Cache-Control
* header in such a way that all caching is disabled in that case.
* If you have a scenario where caching responses with session information in
* them makes sense, you can disable this behaviour by setting the header
* AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*/
abstract class AbstractSessionListener implements EventSubscriberInterface
{
const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
protected $container;
private $sessionUsageStack = array();
public function __construct(ContainerInterface $container = null)
{
$this->container = $container;
}
public function onKernelRequest(GetResponseEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
$session = null;
$request = $event->getRequest();
$session = $this->getSession();
if (null === $session || $request->hasSession()) {
return;
if ($request->hasSession()) {
// no-op
} elseif (method_exists($request, 'setSessionFactory')) {
$request->setSessionFactory(function () { return $this->getSession(); });
} elseif ($session = $this->getSession()) {
$request->setSession($session);
}
$request->setSession($session);
$session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null);
$this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0;
}
public function onKernelResponse(FilterResponseEvent $event)
@@ -46,15 +71,61 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
return;
}
if (!$session = $event->getRequest()->getSession()) {
if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) {
return;
}
if ($session->isStarted() || ($session instanceof Session && $session->hasBeenStarted())) {
$event->getResponse()
->setPrivate()
->setMaxAge(0)
->headers->addCacheControlDirective('must-revalidate');
$response = $event->getResponse();
if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) {
if (!$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER)) {
$response
->setPrivate()
->setMaxAge(0)
->headers->addCacheControlDirective('must-revalidate');
}
}
// Always remove the internal header if present
$response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER);
if ($session->isStarted()) {
/*
* Saves the session, in case it is still open, before sending the response/headers.
*
* This ensures several things in case the developer did not save the session explicitly:
*
* * If a session save handler without locking is used, it ensures the data is available
* on the next request, e.g. after a redirect. PHPs auto-save at script end via
* session_register_shutdown is executed after fastcgi_finish_request. So in this case
* the data could be missing the next request because it might not be saved the moment
* the new request is processed.
* * A locking save handler (e.g. the native 'files') circumvents concurrency problems like
* 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
* 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.
*
* This listener should be executed as one of the last listeners, so that previous listeners
* can still operate on the open session. This prevents the overhead of restarting it.
* Listeners after closing the session can still work with the session as usual because
* Symfonys session implementation starts the session on demand. So writing to it after
* it is saved will just restart it.
*/
$session->save();
}
}
/**
* @internal
*/
public function onFinishRequest(FinishRequestEvent $event)
{
if ($event->isMasterRequest()) {
array_pop($this->sessionUsageStack);
}
}
@@ -62,8 +133,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
{
return array(
KernelEvents::REQUEST => array('onKernelRequest', 128),
// low priority to come after regular response listeners, same as SaveSessionListener
// low priority to come after regular response listeners, but higher than StreamedResponseListener
KernelEvents::RESPONSE => array('onKernelResponse', -1000),
KernelEvents::FINISH_REQUEST => array('onFinishRequest'),
);
}

View File

@@ -11,13 +11,13 @@
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\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* TestSessionListener.
@@ -61,16 +61,25 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface
return;
}
if (!$session = $event->getRequest()->getSession()) {
$request = $event->getRequest();
if (!$request->hasSession()) {
return;
}
$session = $request->getSession();
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();
}

View File

@@ -12,8 +12,8 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Adds configured formats to each request.

View File

@@ -12,15 +12,15 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleEvent;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleEvent;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
/**
* Configures errors and exceptions handlers.
@@ -48,15 +48,15 @@ class DebugHandlersListener implements EventSubscriberInterface
* @param string|array $fileLinkFormat The format for links to source files
* @param bool $scope Enables/disables scoping mode
*/
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true)
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true)
{
$this->exceptionHandler = $exceptionHandler;
$this->logger = $logger;
$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->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null));
$this->scream = $scream;
$this->fileLinkFormat = $fileLinkFormat;
$this->scope = (bool) $scope;
$this->scope = $scope;
}
/**
@@ -70,14 +70,14 @@ class DebugHandlersListener implements EventSubscriberInterface
$this->firstCall = $this->hasTerminatedWithException = false;
$handler = set_exception_handler('var_dump');
$handler = is_array($handler) ? $handler[0] : null;
$handler = \is_array($handler) ? $handler[0] : null;
restore_exception_handler();
if ($this->logger || null !== $this->throwAt) {
if ($handler instanceof ErrorHandler) {
if ($this->logger) {
$handler->setDefaultLogger($this->logger, $this->levels);
if (is_array($this->levels)) {
if (\is_array($this->levels)) {
$levels = 0;
foreach ($this->levels as $type => $log) {
$levels |= $type;
@@ -126,7 +126,7 @@ class DebugHandlersListener implements EventSubscriberInterface
if ($this->exceptionHandler) {
if ($handler instanceof ErrorHandler) {
$h = $handler->setExceptionHandler('var_dump');
if (is_array($h) && $h[0] instanceof ExceptionHandler) {
if (\is_array($h) && $h[0] instanceof ExceptionHandler) {
$handler->setExceptionHandler($h);
$handler = $h[0];
} else {
@@ -147,7 +147,7 @@ class DebugHandlersListener implements EventSubscriberInterface
{
$events = array(KernelEvents::REQUEST => array('configure', 2048));
if ('cli' === PHP_SAPI && defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
$events[ConsoleEvents::COMMAND] = array('configure', 2048);
}

View File

@@ -15,6 +15,7 @@ use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
use Symfony\Component\VarDumper\Server\Connection;
use Symfony\Component\VarDumper\VarDumper;
/**
@@ -26,20 +27,27 @@ class DumpListener implements EventSubscriberInterface
{
private $cloner;
private $dumper;
private $connection;
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper)
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null)
{
$this->cloner = $cloner;
$this->dumper = $dumper;
$this->connection = $connection;
}
public function configure()
{
$cloner = $this->cloner;
$dumper = $this->dumper;
$connection = $this->connection;
VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
$dumper->dump($cloner->cloneVar($var));
VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) {
$data = $cloner->cloneVar($var);
if (!$connection || !$connection->write($data)) {
$dumper->dump($data);
}
});
}

View File

@@ -12,18 +12,16 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
/**
* ExceptionListener.
@@ -35,30 +33,31 @@ class ExceptionListener implements EventSubscriberInterface
protected $controller;
protected $logger;
protected $debug;
private $charset;
public function __construct($controller, LoggerInterface $logger = null, $debug = false, $charset = null)
public function __construct($controller, LoggerInterface $logger = null, $debug = false)
{
$this->controller = $controller;
$this->logger = $logger;
$this->debug = $debug;
$this->charset = $charset;
}
public function logKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', \get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$request = $event->getRequest();
$eventDispatcher = func_num_args() > 2 ? func_get_arg(2) : null;
$this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
$request = $this->duplicateRequest($exception, $request);
$request = $this->duplicateRequest($exception, $event->getRequest());
$eventDispatcher = \func_num_args() > 2 ? func_get_arg(2) : null;
try {
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false);
} catch (\Exception $e) {
$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()));
$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;
@@ -68,7 +67,7 @@ class ExceptionListener implements EventSubscriberInterface
}
}
$prev = new \ReflectionProperty('Exception', 'previous');
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
$prev->setAccessible(true);
$prev->setValue($wrapper, $exception);
@@ -89,7 +88,10 @@ class ExceptionListener implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
KernelEvents::EXCEPTION => array('onKernelException', -128),
KernelEvents::EXCEPTION => array(
array('logKernelException', 0),
array('onKernelException', -128),
),
);
}
@@ -121,12 +123,8 @@ class ExceptionListener implements EventSubscriberInterface
protected function duplicateRequest(\Exception $exception, Request $request)
{
$attributes = array(
'exception' => $exception = FlattenException::create($exception),
'_controller' => $this->controller ?: function () use ($exception) {
$handler = new ExceptionHandler($this->debug, $this->charset);
return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
},
'_controller' => $this->controller,
'exception' => FlattenException::create($exception),
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
);
$request = $request->duplicate(null, null, $attributes);

View File

@@ -11,12 +11,12 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Handles content fragments represented by special URIs.
@@ -38,7 +38,7 @@ class FragmentListener implements EventSubscriberInterface
* @param UriSigner $signer A UriSigner instance
* @param string $fragmentPath The path that triggers this listener
*/
public function __construct(UriSigner $signer, $fragmentPath = '/_fragment')
public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment')
{
$this->signer = $signer;
$this->fragmentPath = $fragmentPath;

View File

@@ -11,13 +11,13 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RequestContextAwareInterface;
/**
* Initializes the locale based on the current request.
@@ -35,7 +35,7 @@ class LocaleListener implements EventSubscriberInterface
* @param string $defaultLocale The default locale
* @param RequestContextAwareInterface|null $router The router
*/
public function __construct(RequestStack $requestStack, $defaultLocale = 'en', RequestContextAwareInterface $router = null)
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null)
{
$this->defaultLocale = $defaultLocale;
$this->requestStack = $requestStack;

View File

@@ -11,14 +11,14 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
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\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* ProfilerListener collects data for the current request by listening to the kernel events.
@@ -43,12 +43,12 @@ 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 $requestStack, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false)
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMasterRequests = false)
{
$this->profiler = $profiler;
$this->matcher = $matcher;
$this->onlyException = (bool) $onlyException;
$this->onlyMasterRequests = (bool) $onlyMasterRequests;
$this->onlyException = $onlyException;
$this->onlyMasterRequests = $onlyMasterRequests;
$this->profiles = new \SplObjectStorage();
$this->parents = new \SplObjectStorage();
$this->requestStack = $requestStack;
@@ -121,7 +121,7 @@ class ProfilerListener implements EventSubscriberInterface
{
return array(
KernelEvents::RESPONSE => array('onKernelResponse', -100),
KernelEvents::EXCEPTION => 'onKernelException',
KernelEvents::EXCEPTION => array('onKernelException', 0),
KernelEvents::TERMINATE => array('onKernelTerminate', -1024),
);
}

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* ResponseListener fixes the Response headers based on the Request.
@@ -24,7 +24,7 @@ class ResponseListener implements EventSubscriberInterface
{
private $charset;
public function __construct($charset)
public function __construct(string $charset)
{
$this->charset = $charset;
}

View File

@@ -12,25 +12,25 @@
namespace Symfony\Component\HttpKernel\EventListener;
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\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\RequestStack;
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\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Initializes the context from the request and sets request attributes based on a matching route.
@@ -57,7 +57,7 @@ class RouterListener implements EventSubscriberInterface
*
* @throws \InvalidArgumentException
*/
public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, $projectDir = null, $debug = true)
public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true)
{
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
@@ -167,7 +167,7 @@ class RouterListener implements EventSubscriberInterface
private function createWelcomeResponse()
{
$version = Kernel::VERSION;
$baseDir = realpath($this->projectDir).DIRECTORY_SEPARATOR;
$baseDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR;
$docVersion = substr(Kernel::VERSION, 0, 3);
ob_start();

View File

@@ -11,36 +11,16 @@
namespace Symfony\Component\HttpKernel\EventListener;
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1, use AbstractSessionListener instead.', SaveSessionListener::class), E_USER_DEPRECATED);
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Saves the session, in case it is still open, before sending the response/headers.
*
* This ensures several things in case the developer did not save the session explicitly:
*
* * If a session save handler without locking is used, it ensures the data is available
* on the next request, e.g. after a redirect. PHPs auto-save at script end via
* session_register_shutdown is executed after fastcgi_finish_request. So in this case
* the data could be missing the next request because it might not be saved the moment
* the new request is processed.
* * A locking save handler (e.g. the native 'files') circumvents concurrency problems like
* 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
* 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.
*
* This listener should be executed as one of the last listeners, so that previous listeners
* can still operate on the open session. This prevents the overhead of restarting it.
* Listeners after closing the session can still work with the session as usual because
* Symfonys session implementation starts the session on demand. So writing to it after
* it is saved will just restart it.
*
* @author Tobias Schultze <http://tobion.de>
*
* @deprecated since Symfony 4.1, use AbstractSessionListener instead
*/
class SaveSessionListener implements EventSubscriberInterface
{

View File

@@ -18,12 +18,10 @@ use Psr\Container\ContainerInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since version 3.3
* @final
*/
class SessionListener extends AbstractSessionListener
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;

View File

@@ -11,10 +11,10 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* StreamedResponseListener is responsible for sending the Response

View File

@@ -11,11 +11,11 @@
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;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates.

View File

@@ -18,7 +18,7 @@ use Psr\Container\ContainerInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since version 3.3
* @final
*/
class TestSessionListener extends AbstractTestSessionListener
{

View File

@@ -13,10 +13,10 @@ namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Translation\TranslatorInterface;
/**

View File

@@ -21,9 +21,10 @@ class AccessDeniedHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(403, $message, $previous, array(), $code);
parent::__construct(403, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class BadRequestHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(400, $message, $previous, array(), $code);
parent::__construct(400, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class ConflictHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(409, $message, $previous, array(), $code);
parent::__construct(409, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class GoneHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(410, $message, $previous, array(), $code);
parent::__construct(410, $message, $previous, $headers, $code);
}
}

View File

@@ -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(int $statusCode, string $message = null, \Exception $previous = null, array $headers = array(), ?int $code = 0)
{
$this->statusCode = $statusCode;
$this->headers = $headers;

View File

@@ -20,9 +20,10 @@ class LengthRequiredHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(411, $message, $previous, array(), $code);
parent::__construct(411, $message, $previous, $headers, $code);
}
}

View File

@@ -21,10 +21,11 @@ class MethodNotAllowedHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0)
public function __construct(array $allow, string $message = null, \Exception $previous = null, ?int $code = 0, array $headers = array())
{
$headers = array('Allow' => strtoupper(implode(', ', $allow)));
$headers['Allow'] = strtoupper(implode(', ', $allow));
parent::__construct(405, $message, $previous, $headers, $code);
}

View File

@@ -20,9 +20,10 @@ class NotAcceptableHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(406, $message, $previous, array(), $code);
parent::__construct(406, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class NotFoundHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(404, $message, $previous, array(), $code);
parent::__construct(404, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class PreconditionFailedHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(412, $message, $previous, array(), $code);
parent::__construct(412, $message, $previous, $headers, $code);
}
}

View File

@@ -22,9 +22,10 @@ class PreconditionRequiredHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(428, $message, $previous, array(), $code);
parent::__construct(428, $message, $previous, $headers, $code);
}
}

View File

@@ -21,12 +21,12 @@ class ServiceUnavailableHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
public function __construct($retryAfter = null, string $message = null, \Exception $previous = null, ?int $code = 0, array $headers = array())
{
$headers = array();
if ($retryAfter) {
$headers = array('Retry-After' => $retryAfter);
$headers['Retry-After'] = $retryAfter;
}
parent::__construct(503, $message, $previous, $headers, $code);

View File

@@ -23,12 +23,12 @@ class TooManyRequestsHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
public function __construct($retryAfter = null, string $message = null, \Exception $previous = null, ?int $code = 0, array $headers = array())
{
$headers = array();
if ($retryAfter) {
$headers = array('Retry-After' => $retryAfter);
$headers['Retry-After'] = $retryAfter;
}
parent::__construct(429, $message, $previous, $headers, $code);

View File

@@ -21,10 +21,11 @@ class UnauthorizedHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0)
public function __construct(string $challenge, string $message = null, \Exception $previous = null, ?int $code = 0, array $headers = array())
{
$headers = array('WWW-Authenticate' => $challenge);
$headers['WWW-Authenticate'] = $challenge;
parent::__construct(401, $message, $previous, $headers, $code);
}

View File

@@ -20,9 +20,10 @@ class UnprocessableEntityHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(422, $message, $previous, array(), $code);
parent::__construct(422, $message, $previous, $headers, $code);
}
}

View File

@@ -20,9 +20,10 @@ class UnsupportedMediaTypeHttpException extends HttpException
* @param string $message The internal exception message
* @param \Exception $previous The previous exception
* @param int $code The internal exception code
* @param array $headers
*/
public function __construct($message = null, \Exception $previous = null, $code = 0)
public function __construct(string $message = null, \Exception $previous = null, int $code = 0, array $headers = array())
{
parent::__construct(415, $message, $previous, array(), $code);
parent::__construct(415, $message, $previous, $headers, $code);
}
}

View File

@@ -63,7 +63,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
{
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);
throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.');
}
return $this->inlineStrategy->render($uri, $request, $options);
@@ -83,7 +83,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
return new Response($tag);
}
private function generateSignedFragmentUri($uri, Request $request)
private function generateSignedFragmentUri($uri, Request $request): string
{
if (null === $this->signer) {
throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
@@ -92,13 +92,13 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
// we need to sign the absolute URI, but want to return the path only.
$fragmentUri = $this->signer->sign($this->generateFragmentUri($uri, $request, true));
return substr($fragmentUri, strlen($request->getSchemeAndHttpHost()));
return substr($fragmentUri, \strlen($request->getSchemeAndHttpHost()));
}
private function containsNonScalars(array $values)
private function containsNonScalars(array $values): bool
{
foreach ($values as $value) {
if (is_array($value)) {
if (\is_array($value)) {
return $this->containsNonScalars($value);
} elseif (!is_scalar($value) && null !== $value) {
return true;

View File

@@ -11,9 +11,9 @@
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
@@ -37,7 +37,7 @@ class FragmentHandler
* @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances
* @param bool $debug Whether the debug mode is enabled or not
*/
public function __construct(RequestStack $requestStack, array $renderers = array(), $debug = false)
public function __construct(RequestStack $requestStack, array $renderers = array(), bool $debug = false)
{
$this->requestStack = $requestStack;
foreach ($renderers as $renderer) {

View File

@@ -12,8 +12,8 @@
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* Interface implemented by all rendering strategies.

View File

@@ -13,9 +13,9 @@ namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\Templating\EngineInterface;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Loader\ExistsLoaderInterface;
@@ -38,7 +38,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
* @param string $globalDefaultTemplate The global default content (it can be a template name or the content)
* @param string $charset
*/
public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8')
public function __construct($templating = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8')
{
$this->setTemplating($templating);
$this->globalDefaultTemplate = $globalDefaultTemplate;
@@ -89,7 +89,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
}
// we need to sign the absolute URI, but want to return the path only.
$uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost()));
$uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), \strlen($request->getSchemeAndHttpHost()));
}
// We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
@@ -102,12 +102,12 @@ 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'] : array();
if (isset($options['id']) && $options['id']) {
$attributes['id'] = $options['id'];
}
$renderedAttributes = '';
if (count($attributes) > 0) {
if (\count($attributes) > 0) {
$flags = ENT_QUOTES | ENT_SUBSTITUTE;
foreach ($attributes as $attribute => $value) {
$renderedAttributes .= sprintf(
@@ -121,17 +121,12 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
}
/**
* @param string $template
*
* @return bool
*/
private function templateExists($template)
private function templateExists(string $template): bool
{
if ($this->templating instanceof EngineInterface) {
try {
return $this->templating->exists($template);
} catch (\InvalidArgumentException $e) {
} catch (\Exception $e) {
return false;
}
}

View File

@@ -11,13 +11,14 @@
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel.
@@ -76,7 +77,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
$level = ob_get_level();
try {
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
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
@@ -109,24 +110,6 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
$cookies = $request->cookies->all();
$server = $request->server->all();
// Override the arguments to emulate a sub-request.
// Sub-request object will point to localhost as client ip and real client ip
// will be included into trusted header for client ip
try {
if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) {
$currentXForwardedFor = $request->headers->get('X_FORWARDED_FOR', '');
$server['HTTP_X_FORWARDED_FOR'] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp();
} elseif (method_exists(Request::class, 'getTrustedHeaderName') && $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP, false)) {
$currentXForwardedFor = $request->headers->get($trustedHeaderName, '');
$server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp();
}
} catch (\InvalidArgumentException $e) {
// Do nothing
}
$server['REMOTE_ADDR'] = '127.0.0.1';
unset($server['HTTP_IF_MODIFIED_SINCE']);
unset($server['HTTP_IF_NONE_MATCH']);
@@ -135,8 +118,18 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
$subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
}
if ($session = $request->getSession()) {
$subRequest->setSession($session);
static $setSession;
if (null === $setSession) {
$setSession = \Closure::bind(function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class);
}
$setSession($subRequest, $request);
if ($request->get('_format')) {
$subRequest->attributes->set('_format', $request->get('_format'));
}
if ($request->getDefaultLocale() !== $request->getLocale()) {
$subRequest->setLocale($request->getLocale());
}
return $subRequest;

View File

@@ -11,8 +11,8 @@
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\EventListener\FragmentListener;
/**
@@ -80,7 +80,7 @@ abstract class RoutableFragmentRenderer implements FragmentRendererInterface
private function checkNonScalar($values)
{
foreach ($values as $key => $value) {
if (is_array($value)) {
if (\is_array($value)) {
$this->checkNonScalar($value);
} elseif (!is_scalar($value) && null !== $value) {
throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key));

View File

@@ -71,7 +71,7 @@ class Esi extends AbstractSurrogate
}
$parts = explode(';', $type);
if (!in_array($parts[0], $this->contentTypes)) {
if (!\in_array($parts[0], $this->contentTypes)) {
return $response;
}

View File

@@ -15,10 +15,10 @@
namespace Symfony\Component\HttpKernel\HttpCache;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
/**
* Cache provides HTTP caching.
@@ -165,7 +165,11 @@ 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->request = $request;
// 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
// and adding the X-Forwarded-For header, see HttpCache::forward()).
$this->request = clone $request;
if (null !== $this->surrogate) {
$this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy();
}
@@ -366,7 +370,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
// return the response and not the cache entry if the response is valid but not cached
$etag = $response->getEtag();
if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) {
if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) {
return $response;
}
@@ -440,30 +444,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
$this->surrogate->addSurrogateCapability($request);
}
// modify the X-Forwarded-For header if needed
$forwardedFor = $request->headers->get('X-Forwarded-For');
if ($forwardedFor) {
$request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR'));
} else {
$request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR'));
}
// fix the client IP address by setting it to 127.0.0.1 as HttpCache
// is always called from the same process as the backend.
$request->server->set('REMOTE_ADDR', '127.0.0.1');
// make sure HttpCache is a trusted proxy
if (!in_array('127.0.0.1', $trustedProxies = Request::getTrustedProxies())) {
$trustedProxies[] = '127.0.0.1';
Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL);
}
// always a "master" request (as the real master request can be in cache)
$response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch);
// FIXME: we probably need to also catch exceptions if raw === true
$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(), array(500, 502, 503, 504))) {
if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
$age = $this->options['stale_if_error'];
}
@@ -602,7 +587,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
$response->setContent(ob_get_clean());
$response->headers->remove('X-Body-Eval');
if (!$response->headers->has('Transfer-Encoding')) {
$response->headers->set('Content-Length', strlen($response->getContent()));
$response->headers->set('Content-Length', \strlen($response->getContent()));
}
} elseif ($response->headers->has('X-Body-File')) {
// Response does not include possibly dynamic content (ESI, SSI), so we need
@@ -636,7 +621,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
$key = strtolower(str_replace('HTTP_', '', $key));
if ('cookie' === $key) {
if (count($request->cookies->all())) {
if (\count($request->cookies->all())) {
return true;
}
} elseif ($request->headers->has($key)) {
@@ -649,23 +634,16 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
/**
* Records that an event took place.
*
* @param Request $request A Request instance
* @param string $event The event name
*/
private function record(Request $request, $event)
private function record(Request $request, string $event)
{
$this->traces[$this->getTraceKey($request)][] = $event;
}
/**
* Calculates the key we use in the "trace" array for a given request.
*
* @param Request $request
*
* @return string
*/
private function getTraceKey(Request $request)
private function getTraceKey(Request $request): string
{
$path = $request->getPathInfo();
if ($qs = $request->getQueryString()) {
@@ -678,12 +656,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
/**
* Checks whether the given (cached) response may be served as "stale" when a revalidation
* is currently in progress.
*
* @param Response $entry
*
* @return bool true when the stale response may be served, false otherwise
*/
private function mayServeStaleWhileRevalidate(Response $entry)
private function mayServeStaleWhileRevalidate(Response $entry): bool
{
$timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate');
@@ -696,12 +670,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
/**
* 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)
private function waitForLock(Request $request): bool
{
$wait = 0;
while ($this->store->isLocked($request) && $wait < 100) {

View File

@@ -58,7 +58,7 @@ class Ssi extends AbstractSurrogate
}
$parts = explode(';', $type);
if (!in_array($parts[0], $this->contentTypes)) {
if (!\in_array($parts[0], $this->contentTypes)) {
return $response;
}

View File

@@ -29,11 +29,9 @@ class Store implements StoreInterface
private $locks;
/**
* @param string $root The path to the cache directory
*
* @throws \RuntimeException
*/
public function __construct($root)
public function __construct(string $root)
{
$this->root = $root;
if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
@@ -68,7 +66,7 @@ class Store implements StoreInterface
if (!isset($this->locks[$key])) {
$path = $this->getPath($key);
if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) {
return $path;
}
$h = fopen($path, 'cb');
@@ -187,7 +185,7 @@ class Store implements StoreInterface
$response->headers->set('X-Content-Digest', $digest);
if (!$response->headers->has('Transfer-Encoding')) {
$response->headers->set('Content-Length', strlen($response->getContent()));
$response->headers->set('Content-Length', \strlen($response->getContent()));
}
}
@@ -375,17 +373,17 @@ class Store implements StoreInterface
@ftruncate($fp, 0);
@fseek($fp, 0);
$len = @fwrite($fp, $data);
if (strlen($data) !== $len) {
if (\strlen($data) !== $len) {
@ftruncate($fp, 0);
return false;
}
} else {
if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) {
return false;
}
$tmpFile = tempnam(dirname($path), basename($path));
$tmpFile = tempnam(\dirname($path), basename($path));
if (false === $fp = @fopen($tmpFile, 'wb')) {
@unlink($tmpFile);
@@ -412,7 +410,7 @@ class Store implements StoreInterface
public function getPath($key)
{
return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6);
return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6);
}
/**

View File

@@ -0,0 +1,91 @@
<?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\IpUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal
*/
class SubRequestHandler
{
public static function handle(HttpKernelInterface $kernel, Request $request, $type, $catch): Response
{
// save global state related to trusted headers and proxies
$trustedProxies = Request::getTrustedProxies();
$trustedHeaderSet = Request::getTrustedHeaderSet();
// remove untrusted values
$remoteAddr = $request->server->get('REMOTE_ADDR');
if (!IpUtils::checkIp($remoteAddr, $trustedProxies)) {
$trustedHeaders = array(
'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED,
'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR,
'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST,
'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO,
'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT,
);
foreach (array_filter($trustedHeaders) as $name => $key) {
$request->headers->remove($name);
$request->server->remove('HTTP_'.$name);
}
}
// compute trusted values, taking any trusted proxies into account
$trustedIps = array();
$trustedValues = array();
foreach (array_reverse($request->getClientIps()) as $ip) {
$trustedIps[] = $ip;
$trustedValues[] = sprintf('for="%s"', $ip);
}
if ($ip !== $remoteAddr) {
$trustedIps[] = $remoteAddr;
$trustedValues[] = sprintf('for="%s"', $remoteAddr);
}
// set trusted values, reusing as much as possible the global trusted settings
if (Request::HEADER_FORWARDED & $trustedHeaderSet) {
$trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme());
$request->headers->set('Forwarded', $v = implode(', ', $trustedValues));
$request->server->set('HTTP_FORWARDED', $v);
}
if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) {
$request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps));
$request->server->set('HTTP_X_FORWARDED_FOR', $v);
} elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) {
Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR);
$request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps));
$request->server->set('HTTP_X_FORWARDED_FOR', $v);
}
// fix the client IP address by setting it to 127.0.0.1,
// which is the core responsibility of this method
$request->server->set('REMOTE_ADDR', '127.0.0.1');
// ensure 127.0.0.1 is set as trusted proxy
if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) {
Request::setTrustedProxies(array_merge($trustedProxies, array('127.0.0.1')), Request::getTrustedHeaderSet());
}
try {
return $kernel->handle($request, $type, $catch);
} finally {
// restore global state
Request::setTrustedProxies($trustedProxies, $trustedHeaderSet);
}
}
}

View File

@@ -11,13 +11,15 @@
namespace Symfony\Component\HttpKernel;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
@@ -25,11 +27,9 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* HttpKernel notifies events to convert a Request object to a Response one.
@@ -51,9 +51,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
$this->argumentResolver = $argumentResolver;
if (null === $this->argumentResolver) {
@trigger_error(sprintf('As of 3.1 an %s is used to resolve arguments. In 4.0 the $argumentResolver becomes the %s if no other is provided instead of using the $resolver argument.', ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED);
// fallback in case of deprecations
$this->argumentResolver = $resolver;
$this->argumentResolver = new ArgumentResolver();
}
}
@@ -118,7 +116,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
* @throws \LogicException If one of the listener does not behave as expected
* @throws NotFoundHttpException When controller cannot be found
*/
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
private function handleRaw(Request $request, int $type = self::MASTER_REQUEST)
{
$this->requestStack->push($request);
@@ -157,9 +155,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
if ($event->hasResponse()) {
$response = $event->getResponse();
}
if (!$response instanceof Response) {
} else {
$msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));
// the user may have forgotten to return something
@@ -184,7 +180,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
*
* @throws \RuntimeException if the passed object is not a Response instance
*/
private function filterResponse(Response $response, Request $request, $type)
private function filterResponse(Response $response, Request $request, int $type)
{
$event = new FilterResponseEvent($this, $request, $type, $response);
@@ -201,11 +197,8 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
* Note that the order of the operations is important here, otherwise
* operations such as {@link RequestStack::getParentRequest()} can lead to
* weird results.
*
* @param Request $request
* @param int $type
*/
private function finishRequest(Request $request, $type)
private function finishRequest(Request $request, int $type)
{
$this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type));
$this->requestStack->pop();
@@ -216,13 +209,11 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
*
* @param \Exception $e An \Exception instance
* @param Request $request A Request instance
* @param int $type The type of the request
*
* @return Response A Response instance
* @param int $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
*
* @throws \Exception
*/
private function handleException(\Exception $e, $request, $type)
private function handleException(\Exception $e, Request $request, int $type): Response
{
$event = new GetResponseForExceptionEvent($this, $request, $type, $e);
$this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
@@ -239,13 +230,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
$response = $event->getResponse();
// the developer asked for a specific status code
if ($response->headers->has('X-Status-Code')) {
@trigger_error(sprintf('Using the X-Status-Code header is deprecated since Symfony 3.3 and will be removed in 4.0. Use %s::allowCustomResponseCode() instead.', GetResponseForExceptionEvent::class), E_USER_DEPRECATED);
$response->setStatusCode($response->headers->get('X-Status-Code'));
$response->headers->remove('X-Status-Code');
} elseif (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
// ensure that we actually have an error response
if ($e instanceof HttpExceptionInterface) {
// keep the HTTP status code and headers
@@ -263,13 +248,13 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
}
}
private function varToString($var)
private function varToString($var): string
{
if (is_object($var)) {
return sprintf('Object(%s)', get_class($var));
if (\is_object($var)) {
return sprintf('Object(%s)', \get_class($var));
}
if (is_array($var)) {
if (\is_array($var)) {
$a = array();
foreach ($var as $k => $v) {
$a[] = sprintf('%s => %s', $k, $this->varToString($v));
@@ -278,7 +263,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
return sprintf('Array(%s)', implode(', ', $a));
}
if (is_resource($var)) {
if (\is_resource($var)) {
return sprintf('Resource(%s)', get_resource_type($var));
}

View File

@@ -13,30 +13,28 @@ namespace Symfony\Component\HttpKernel;
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Config\EnvParametersResource;
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\ClassLoader\ClassCollectionLoader;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
/**
* The Kernel is the heart of the Symfony system.
@@ -52,7 +50,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
*/
protected $bundles = array();
protected $bundleMap;
protected $container;
protected $rootDir;
protected $environment;
@@ -60,45 +57,32 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
protected $booted = false;
protected $name;
protected $startTime;
protected $loadClassCache;
private $projectDir;
private $warmupDir;
private $requestStackSize = 0;
private $resetServices = false;
const VERSION = '3.4.11';
const VERSION_ID = 30411;
const MAJOR_VERSION = 3;
const MINOR_VERSION = 4;
const RELEASE_VERSION = 11;
const VERSION = '4.1.6';
const VERSION_ID = 40106;
const MAJOR_VERSION = 4;
const MINOR_VERSION = 1;
const RELEASE_VERSION = 6;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '11/2020';
const END_OF_LIFE = '11/2021';
const END_OF_MAINTENANCE = '01/2019';
const END_OF_LIFE = '07/2019';
/**
* @param string $environment The environment
* @param bool $debug Whether to enable debugging or not
*/
public function __construct($environment, $debug)
public function __construct(string $environment, bool $debug)
{
$this->environment = $environment;
$this->debug = (bool) $debug;
$this->debug = $debug;
$this->rootDir = $this->getRootDir();
$this->name = $this->getName();
if ($this->debug) {
$this->startTime = microtime(true);
}
}
public function __clone()
{
if ($this->debug) {
$this->startTime = microtime(true);
}
$this->booted = false;
$this->container = null;
$this->requestStackSize = 0;
@@ -106,7 +90,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
}
/**
* Boots the current kernel.
* {@inheritdoc}
*/
public function boot()
{
@@ -116,20 +100,22 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$this->container->get('services_resetter')->reset();
}
$this->resetServices = false;
if ($this->debug) {
$this->startTime = microtime(true);
}
}
return;
}
if ($this->debug) {
$this->startTime = microtime(true);
}
if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) {
putenv('SHELL_VERBOSITY=3');
$_ENV['SHELL_VERBOSITY'] = 3;
$_SERVER['SHELL_VERBOSITY'] = 3;
}
if ($this->loadClassCache) {
$this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
}
// init bundles
$this->initializeBundles();
@@ -226,26 +212,13 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
/**
* {@inheritdoc}
*/
public function getBundle($name, $first = true/*, $noDeprecation = false */)
public function getBundle($name)
{
$noDeprecation = false;
if (func_num_args() >= 3) {
$noDeprecation = func_get_arg(2);
if (!isset($this->bundles[$name])) {
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, \get_class($this)));
}
if (!$first && !$noDeprecation) {
@trigger_error(sprintf('Passing "false" as the second argument to %s() is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
}
if (!isset($this->bundleMap[$name])) {
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this)));
}
if (true === $first) {
return $this->bundleMap[$name][0];
}
return $this->bundleMap[$name];
return $this->bundles[$name];
}
/**
@@ -272,35 +245,26 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$isResource = 0 === strpos($path, 'Resources') && null !== $dir;
$overridePath = substr($path, 9);
$resourceBundle = null;
$bundles = $this->getBundle($bundleName, false, true);
$bundle = $this->getBundle($bundleName);
$files = array();
foreach ($bundles as $bundle) {
if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
if (null !== $resourceBundle) {
throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
$file,
$resourceBundle,
$dir.'/'.$bundles[0]->getName().$overridePath
));
}
if ($first) {
return $file;
}
$files[] = $file;
if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
if (null !== $resourceBundle) {
throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', $file, $resourceBundle, $dir.'/'.$bundle->getName().$overridePath));
}
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first && !$isResource) {
return $file;
}
$files[] = $file;
$resourceBundle = $bundle->getName();
}
$files[] = $file;
}
if (count($files) > 0) {
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first && !$isResource) {
return $file;
}
$files[] = $file;
$resourceBundle = $bundle->getName();
}
if (\count($files) > 0) {
return $first && $isResource ? $files[0] : $files;
}
@@ -345,7 +309,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
{
if (null === $this->rootDir) {
$r = new \ReflectionObject($this);
$this->rootDir = dirname($r->getFileName());
$this->rootDir = \dirname($r->getFileName());
}
return $this->rootDir;
@@ -360,12 +324,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
{
if (null === $this->projectDir) {
$r = new \ReflectionObject($this);
$dir = $rootDir = dirname($r->getFileName());
$dir = $rootDir = \dirname($r->getFileName());
while (!file_exists($dir.'/composer.json')) {
if ($dir === dirname($dir)) {
if ($dir === \dirname($dir)) {
return $this->projectDir = $rootDir;
}
$dir = dirname($dir);
$dir = \dirname($dir);
}
$this->projectDir = $dir;
}
@@ -381,43 +345,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
return $this->container;
}
/**
* Loads the PHP class cache.
*
* This methods only registers the fact that you want to load the cache classes.
* The cache will actually only be loaded when the Kernel is booted.
*
* That optimization is mainly useful when using the HttpCache class in which
* case the class cache is not loaded if the Response is in the cache.
*
* @param string $name The cache name prefix
* @param string $extension File extension of the resulting file
*
* @deprecated since version 3.3, to be removed in 4.0. The class cache is not needed anymore when using PHP 7.0.
*/
public function loadClassCache($name = 'classes', $extension = '.php')
{
if (\PHP_VERSION_ID >= 70000) {
@trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
}
$this->loadClassCache = array($name, $extension);
}
/**
* @internal
*
* @deprecated since version 3.3, to be removed in 4.0.
*/
public function setClassCache(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);
}
file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
}
/**
* @internal
*/
@@ -459,83 +386,28 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
}
/**
* @deprecated since version 3.3, to be removed in 4.0.
* Gets the patterns defining the classes to parse and cache for annotations.
*/
protected function doLoadClassCache($name, $extension)
public function getAnnotatedClassesToCompile(): array
{
if (\PHP_VERSION_ID >= 70000) {
@trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
}
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
if (!$this->booted && is_file($cacheDir.'/classes.map')) {
ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension);
}
return array();
}
/**
* Initializes the data structures related to the bundle management.
*
* - the bundles property maps a bundle name to the bundle instance,
* - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
* Initializes bundles.
*
* @throws \LogicException if two bundles share a common name
* @throws \LogicException if a bundle tries to extend a non-registered bundle
* @throws \LogicException if a bundle tries to extend itself
* @throws \LogicException if two bundles extend the same ancestor
*/
protected function initializeBundles()
{
// init bundles
$this->bundles = array();
$topMostBundles = array();
$directChildren = array();
foreach ($this->registerBundles() as $bundle) {
$name = $bundle->getName();
if (isset($this->bundles[$name])) {
throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
}
$this->bundles[$name] = $bundle;
if ($parentName = $bundle->getParent()) {
@trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
if (isset($directChildren[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
}
if ($parentName == $name) {
throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
}
$directChildren[$parentName] = $name;
} else {
$topMostBundles[$name] = $bundle;
}
}
// look for orphans
if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
$diff = array_keys($diff);
throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
}
// inheritance
$this->bundleMap = array();
foreach ($topMostBundles as $name => $bundle) {
$bundleMap = array($bundle);
$hierarchy = array($name);
while (isset($directChildren[$name])) {
$name = $directChildren[$name];
array_unshift($bundleMap, $this->bundles[$name]);
$hierarchy[] = $name;
}
foreach ($hierarchy as $hierarchyBundle) {
$this->bundleMap[$hierarchyBundle] = $bundleMap;
array_pop($bundleMap);
}
}
}
@@ -605,7 +477,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
if ($this->debug) {
$collectedLogs = array();
$previousHandler = defined('PHPUNIT_COMPOSER_INSTALL');
$previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL');
$previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
@@ -621,7 +493,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
// Clean the trace by removing first frames added by the error handler itself.
for ($i = 0; isset($backtrace[$i]); ++$i) {
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
$backtrace = array_slice($backtrace, 1 + $i);
$backtrace = \array_slice($backtrace, 1 + $i);
break;
}
}
@@ -660,20 +532,20 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
error_reporting($errorLevel);
}
}
$oldContainer = is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false;
$oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false;
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
$this->container = require $cache->getPath();
$this->container->set('kernel', $this);
if ($oldContainer && get_class($this->container) !== $oldContainer->name) {
if ($oldContainer && \get_class($this->container) !== $oldContainer->name) {
// Because concurrent requests might still be using them,
// old container files are not removed immediately,
// but on a next dump of the container.
static $legacyContainers = array();
$oldContainerDir = dirname($oldContainer->getFileName());
$oldContainerDir = \dirname($oldContainer->getFileName());
$legacyContainers[$oldContainerDir.'.legacy'] = true;
foreach (glob(dirname($oldContainerDir).DIRECTORY_SEPARATOR.'*.legacy') as $legacyContainer) {
foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy') as $legacyContainer) {
if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) {
(new Filesystem())->remove(substr($legacyContainer, 0, -7));
}
@@ -698,58 +570,28 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$bundlesMetadata = array();
foreach ($this->bundles as $name => $bundle) {
$bundles[$name] = get_class($bundle);
$bundles[$name] = \get_class($bundle);
$bundlesMetadata[$name] = array(
'parent' => $bundle->getParent(),
'path' => $bundle->getPath(),
'namespace' => $bundle->getNamespace(),
);
}
return array_merge(
array(
'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(),
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir,
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
'kernel.bundles' => $bundles,
'kernel.bundles_metadata' => $bundlesMetadata,
'kernel.charset' => $this->getCharset(),
'kernel.container_class' => $this->getContainerClass(),
),
$this->getEnvParameters(false)
return array(
'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir,
'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(),
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir,
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
'kernel.bundles' => $bundles,
'kernel.bundles_metadata' => $bundlesMetadata,
'kernel.charset' => $this->getCharset(),
'kernel.container_class' => $this->getContainerClass(),
);
}
/**
* Gets the environment parameters.
*
* Only the parameters starting with "SYMFONY__" are considered.
*
* @return array An array of parameters
*
* @deprecated since version 3.3, to be removed in 4.0
*/
protected function getEnvParameters()
{
if (0 === func_num_args() || func_get_arg(0)) {
@trigger_error(sprintf('The %s() method is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax to get the value of any environment variable from configuration files instead.', __METHOD__), E_USER_DEPRECATED);
}
$parameters = array();
foreach ($_SERVER as $key => $value) {
if (0 === strpos($key, 'SYMFONY__')) {
@trigger_error(sprintf('The support of special environment variables that start with SYMFONY__ (such as "%s") is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax instead to get the value of environment variables in configuration files.', $key), E_USER_DEPRECATED);
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
/**
* Builds the service container.
*
@@ -778,7 +620,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
}
$container->addCompilerPass(new AddAnnotatedClassesToCachePass($this));
$container->addResource(new EnvParametersResource('SYMFONY__'));
return $container;
}
@@ -856,19 +697,18 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
'file' => $cache->getPath(),
'as_files' => true,
'debug' => $this->debug,
'inline_class_loader_parameter' => \PHP_VERSION_ID >= 70000 && !$this->loadClassCache && !class_exists(ClassCollectionLoader::class, false) ? 'container.dumper.inline_class_loader' : null,
'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(),
));
$rootCode = array_pop($content);
$dir = dirname($cache->getPath()).'/';
$dir = \dirname($cache->getPath()).'/';
$fs = new Filesystem();
foreach ($content as $file => $code) {
$fs->dumpFile($dir.$file, $code);
@chmod($dir.$file, 0666 & ~umask());
}
@unlink(dirname($dir.$file).'.legacy');
@unlink(\dirname($dir.$file).'.legacy');
$cache->write($rootCode, $container->getResources());
}
@@ -906,7 +746,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
*/
public static function stripComments($source)
{
if (!function_exists('token_get_all')) {
if (!\function_exists('token_get_all')) {
return $source;
}
@@ -934,7 +774,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
// replace multiple new lines with a single newline
$rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]);
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
} elseif (\in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$ignoreSpace = true;
} else {
$rawChunk .= $token[1];
@@ -948,11 +788,9 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$output .= $rawChunk;
if (\PHP_VERSION_ID >= 70000) {
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
unset($tokens, $rawChunk);
gc_mem_caches();
}
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
unset($tokens, $rawChunk);
gc_mem_caches();
return $output;
}
@@ -964,11 +802,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
public function unserialize($data)
{
if (\PHP_VERSION_ID >= 70000) {
list($environment, $debug) = unserialize($data, array('allowed_classes' => false));
} else {
list($environment, $debug) = unserialize($data);
}
list($environment, $debug) = unserialize($data, array('allowed_classes' => false));
$this->__construct($environment, $debug);
}

Some files were not shown because too many files have changed in this diff Show More