package and depencies

This commit is contained in:
RafficMohammed
2023-01-08 02:57:24 +05:30
parent d5332eb421
commit 1d54b8bc7f
4309 changed files with 193331 additions and 172289 deletions

View File

@@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolve
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
@@ -27,11 +28,11 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInter
*/
final class ArgumentResolver implements ArgumentResolverInterface
{
private $argumentMetadataFactory;
private $argumentValueResolvers;
private ArgumentMetadataFactoryInterface $argumentMetadataFactory;
private iterable $argumentValueResolvers;
/**
* @param iterable<mixed, ArgumentValueResolverInterface> $argumentValueResolvers
* @param iterable<mixed, ArgumentValueResolverInterface|ValueResolverInterface> $argumentValueResolvers
*/
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [])
{
@@ -39,33 +40,34 @@ final class ArgumentResolver implements ArgumentResolverInterface
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
}
/**
* {@inheritdoc}
*/
public function getArguments(Request $request, callable $controller): array
public function getArguments(Request $request, callable $controller, \ReflectionFunctionAbstract $reflector = null): array
{
$arguments = [];
foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller, $reflector) as $metadata) {
foreach ($this->argumentValueResolvers as $resolver) {
if (!$resolver->supports($request, $metadata)) {
if ((!$resolver instanceof ValueResolverInterface || $resolver instanceof TraceableValueResolver) && !$resolver->supports($request, $metadata)) {
continue;
}
$resolved = $resolver->resolve($request, $metadata);
$atLeastOne = false;
foreach ($resolved as $append) {
$atLeastOne = true;
$arguments[] = $append;
$count = 0;
foreach ($resolver->resolve($request, $metadata) as $argument) {
++$count;
$arguments[] = $argument;
}
if (!$atLeastOne) {
if (1 < $count && !$metadata->isVariadic()) {
throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at most one value for non-variadic arguments.', get_debug_type($resolver)));
}
if ($count) {
// continue to the next controller argument
continue 2;
}
if (!$resolver instanceof ValueResolverInterface) {
throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', get_debug_type($resolver)));
}
// continue to the next controller argument
continue 2;
}
$representative = $controller;
@@ -73,7 +75,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
if (\is_array($representative)) {
$representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]);
} elseif (\is_object($representative)) {
$representative = \get_class($representative);
$representative = get_debug_type($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()));

View File

@@ -0,0 +1,93 @@
<?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\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Attempt to resolve backed enum cases from request attributes, for a route path parameter,
* leading to a 404 Not Found if the attribute value isn't a valid backing value for the enum type.
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*
* @final since Symfony 6.2
*/
class BackedEnumValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
if (!is_subclass_of($argument->getType(), \BackedEnum::class)) {
return false;
}
if ($argument->isVariadic()) {
// only target route path parameters, which cannot be variadic.
return false;
}
// do not support if no value can be resolved at all
// letting the \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver be used
// or \Symfony\Component\HttpKernel\Controller\ArgumentResolver fail with a meaningful error.
return $request->attributes->has($argument->getName());
}
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
if (!is_subclass_of($argument->getType(), \BackedEnum::class)) {
return [];
}
if ($argument->isVariadic()) {
// only target route path parameters, which cannot be variadic.
return [];
}
// do not support if no value can be resolved at all
// letting the \Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver be used
// or \Symfony\Component\HttpKernel\Controller\ArgumentResolver fail with a meaningful error.
if (!$request->attributes->has($argument->getName())) {
return [];
}
$value = $request->attributes->get($argument->getName());
if (null === $value) {
return [null];
}
if ($value instanceof \BackedEnum) {
return [$value];
}
if (!\is_int($value) && !\is_string($value)) {
throw new \LogicException(sprintf('Could not resolve the "%s $%s" controller argument: expecting an int or string, got "%s".', $argument->getType(), $argument->getName(), get_debug_type($value)));
}
/** @var class-string<\BackedEnum> $enumType */
$enumType = $argument->getType();
try {
return [$enumType::from($value)];
} catch (\ValueError $e) {
throw new NotFoundHttpException(sprintf('Could not resolve the "%s $%s" controller argument: ', $argument->getType(), $argument->getName()).$e->getMessage(), $e);
}
}
}

View File

@@ -0,0 +1,86 @@
<?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\Attribute\MapDateTime;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Convert DateTime instances from request attribute variable.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Tim Goudriaan <tim@codedmonkey.com>
*/
final class DateTimeValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return is_a($argument->getType(), \DateTimeInterface::class, true) && $request->attributes->has($argument->getName());
}
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if (!is_a($argument->getType(), \DateTimeInterface::class, true) || !$request->attributes->has($argument->getName())) {
return [];
}
$value = $request->attributes->get($argument->getName());
$class = \DateTimeInterface::class === $argument->getType() ? \DateTimeImmutable::class : $argument->getType();
if ($value instanceof \DateTimeInterface) {
return [$value instanceof $class ? $value : $class::createFromInterface($value)];
}
if ($argument->isNullable() && !$value) {
return [null];
}
$format = null;
if ($attributes = $argument->getAttributes(MapDateTime::class, ArgumentMetadata::IS_INSTANCEOF)) {
$attribute = $attributes[0];
$format = $attribute->format;
}
if (null !== $format) {
$date = $class::createFromFormat($format, $value);
if (($class::getLastErrors() ?: ['warning_count' => 0])['warning_count']) {
$date = false;
}
} else {
if (false !== filter_var($value, \FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
$value = '@'.$value;
}
try {
$date = new $class($value ?? 'now');
} catch (\Exception) {
$date = false;
}
}
if (!$date) {
throw new NotFoundHttpException(sprintf('Invalid date given for parameter "%s".', $argument->getName()));
}
return [$date];
}
}

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -20,21 +21,28 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class DefaultValueResolver implements ArgumentValueResolverInterface
final class DefaultValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic());
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null;
if ($argument->hasDefaultValue()) {
return [$argument->getDefaultValue()];
}
if (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()) {
return [null];
}
return [];
}
}

View File

@@ -15,6 +15,7 @@ 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\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -22,9 +23,9 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Simeon Kolev <simeon.kolev9@gmail.com>
*/
final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface
final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
private $container;
private ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
@@ -32,10 +33,12 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
}
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
$controller = $request->attributes->get('_controller');
if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
@@ -55,13 +58,14 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
return false === $this->container->has($controller);
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if (\is_array($controller = $request->attributes->get('_controller'))) {
$controller = $request->attributes->get('_controller');
if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
$controller = $controller[0].'::'.$controller[1];
} elseif (!\is_string($controller) || '' === $controller) {
return [];
}
if ('\\' === $controller[0]) {
@@ -74,6 +78,10 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
: $controller.'::__invoke';
}
if ($this->container->has($controller)) {
return [];
}
$what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
$message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what);

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -20,21 +21,20 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class RequestAttributeValueResolver implements ArgumentValueResolverInterface
final class RequestAttributeValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return !$argument->isVariadic() && $request->attributes->has($argument->getName());
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
yield $request->attributes->get($argument->getName());
return !$argument->isVariadic() && $request->attributes->has($argument->getName()) ? [$request->attributes->get($argument->getName())] : [];
}
}

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -20,21 +21,20 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class RequestValueResolver implements ArgumentValueResolverInterface
final class RequestValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
yield $request;
return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class) ? [$request] : [];
}
}

View File

@@ -15,6 +15,7 @@ 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\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -22,9 +23,9 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Nicolas Grekas <p@tchwork.com>
*/
final class ServiceValueResolver implements ArgumentValueResolverInterface
final class ServiceValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
private $container;
private ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
@@ -32,10 +33,12 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
}
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
$controller = $request->attributes->get('_controller');
if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
@@ -55,26 +58,30 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if (\is_array($controller = $request->attributes->get('_controller'))) {
$controller = $request->attributes->get('_controller');
if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) {
$controller = $controller[0].'::'.$controller[1];
} elseif (!\is_string($controller) || '' === $controller) {
return [];
}
if ('\\' === $controller[0]) {
$controller = ltrim($controller, '\\');
}
if (!$this->container->has($controller)) {
$i = strrpos($controller, ':');
if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) {
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
}
if (!$this->container->has($controller) || !$this->container->get($controller)->has($argument->getName())) {
return [];
}
try {
yield $this->container->get($controller)->get($argument->getName());
return [$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());
@@ -84,7 +91,6 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
}
$r = new \ReflectionProperty($e, 'message');
$r->setAccessible(true);
$r->setValue($e, $message);
throw $e;

View File

@@ -14,6 +14,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -21,13 +22,15 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class SessionValueResolver implements ArgumentValueResolverInterface
final class SessionValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
if (!$request->hasSession()) {
return false;
}
@@ -40,11 +43,17 @@ final class SessionValueResolver implements ArgumentValueResolverInterface
return $request->getSession() instanceof $type;
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
yield $request->getSession();
if (!$request->hasSession()) {
return [];
}
$type = $argument->getType();
if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
return [];
}
return $request->getSession() instanceof $type ? [$request->getSession()] : [];
}
}

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\Stopwatch\Stopwatch;
@@ -21,22 +22,26 @@ use Symfony\Component\Stopwatch\Stopwatch;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class TraceableValueResolver implements ArgumentValueResolverInterface
final class TraceableValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
private $inner;
private $stopwatch;
private ArgumentValueResolverInterface|ValueResolverInterface $inner;
private Stopwatch $stopwatch;
public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch)
public function __construct(ArgumentValueResolverInterface|ValueResolverInterface $inner, Stopwatch $stopwatch)
{
$this->inner = $inner;
$this->stopwatch = $stopwatch;
}
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
if ($this->inner instanceof ValueResolverInterface) {
return true;
}
$method = \get_class($this->inner).'::'.__FUNCTION__;
$this->stopwatch->start($method, 'controller.argument_value_resolver');
@@ -47,9 +52,6 @@ final class TraceableValueResolver implements ArgumentValueResolverInterface
return $return;
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
$method = \get_class($this->inner).'::'.__FUNCTION__;

View File

@@ -0,0 +1,53 @@
<?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\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Uid\AbstractUid;
final class UidValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return !$argument->isVariadic()
&& \is_string($request->attributes->get($argument->getName()))
&& null !== $argument->getType()
&& is_subclass_of($argument->getType(), AbstractUid::class, true);
}
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if ($argument->isVariadic()
|| !\is_string($value = $request->attributes->get($argument->getName()))
|| null === ($uidClass = $argument->getType())
|| !is_subclass_of($argument->getType(), AbstractUid::class, true)
) {
return [];
}
/* @var class-string<AbstractUid> $uidClass */
try {
return [$uidClass::fromString($value)];
} catch (\InvalidArgumentException $e) {
throw new NotFoundHttpException(sprintf('The uid for the "%s" parameter is invalid.', $argument->getName()), $e);
}
}
}

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
@@ -20,27 +21,30 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
*
* @author Iltar van der Berg <kjarli@gmail.com>
*/
final class VariadicValueResolver implements ArgumentValueResolverInterface
final class VariadicValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
{
/**
* {@inheritdoc}
* @deprecated since Symfony 6.2, use resolve() instead
*/
public function supports(Request $request, ArgumentMetadata $argument): bool
{
@trigger_deprecation('symfony/http-kernel', '6.2', 'The "%s()" method is deprecated, use "resolve()" instead.', __METHOD__);
return $argument->isVariadic() && $request->attributes->has($argument->getName());
}
/**
* {@inheritdoc}
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable
public function resolve(Request $request, ArgumentMetadata $argument): array
{
if (!$argument->isVariadic() || !$request->attributes->has($argument->getName())) {
return [];
}
$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(), get_debug_type($values)));
}
yield from $values;
return $values;
}
}

View File

@@ -24,9 +24,9 @@ interface ArgumentResolverInterface
/**
* Returns the arguments to pass to the controller.
*
* @return array
* @param \ReflectionFunctionAbstract|null $reflector
*
* @throws \RuntimeException When no value could be provided for a required argument
*/
public function getArguments(Request $request, callable $controller);
public function getArguments(Request $request, callable $controller/* , \ReflectionFunctionAbstract $reflector = null */): array;
}

View File

@@ -18,20 +18,18 @@ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
* Responsible for resolving the value of an argument based on its metadata.
*
* @author Iltar van der Berg <kjarli@gmail.com>
*
* @deprecated since Symfony 6.2, implement ValueResolverInterface instead
*/
interface ArgumentValueResolverInterface
{
/**
* Whether this resolver can resolve the value for the given ArgumentMetadata.
*
* @return bool
*/
public function supports(Request $request, ArgumentMetadata $argument);
public function supports(Request $request, ArgumentMetadata $argument): bool;
/**
* Returns the possible value(s).
*
* @return iterable
*/
public function resolve(Request $request, ArgumentMetadata $argument);
public function resolve(Request $request, ArgumentMetadata $argument): iterable;
}

View File

@@ -32,20 +32,7 @@ class ContainerControllerResolver extends ControllerResolver
parent::__construct($logger);
}
protected function createController(string $controller)
{
if (1 === substr_count($controller, ':')) {
$controller = str_replace(':', '::', $controller);
trigger_deprecation('symfony/http-kernel', '5.1', 'Referencing controllers with a single colon is deprecated. Use "%s" instead.', $controller);
}
return parent::createController($controller);
}
/**
* {@inheritdoc}
*/
protected function instantiateController(string $class)
protected function instantiateController(string $class): object
{
$class = ltrim($class, '\\');

View File

@@ -23,22 +23,17 @@ use Symfony\Component\HttpFoundation\Request;
*/
class ControllerResolver implements ControllerResolverInterface
{
private $logger;
private ?LoggerInterface $logger;
public function __construct(LoggerInterface $logger = null)
{
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public function getController(Request $request)
public function getController(Request $request): callable|false
{
if (!$controller = $request->attributes->get('_controller')) {
if (null !== $this->logger) {
$this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
}
$this->logger?->warning('Unable to look for the controller as the "_controller" parameter is missing.');
return false;
}
@@ -48,15 +43,8 @@ class ControllerResolver implements ControllerResolverInterface
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;
if (\is_callable($controller)) {
return $controller;
}
throw $e;
@@ -98,11 +86,9 @@ class ControllerResolver implements ControllerResolverInterface
/**
* Returns a callable for the given controller.
*
* @return callable
*
* @throws \InvalidArgumentException When the controller cannot be created
*/
protected function createController(string $controller)
protected function createController(string $controller): callable
{
if (!str_contains($controller, '::')) {
$controller = $this->instantiateController($controller);
@@ -123,7 +109,7 @@ class ControllerResolver implements ControllerResolverInterface
if ((new \ReflectionMethod($class, $method))->isStatic()) {
return $class.'::'.$method;
}
} catch (\ReflectionException $reflectionException) {
} catch (\ReflectionException) {
throw $e;
}
@@ -139,15 +125,13 @@ class ControllerResolver implements ControllerResolverInterface
/**
* Returns an instantiated controller.
*
* @return object
*/
protected function instantiateController(string $class)
protected function instantiateController(string $class): object
{
return new $class();
}
private function getControllerError($callable): string
private function getControllerError(mixed $callable): string
{
if (\is_string($callable)) {
if (str_contains($callable, '::')) {

View File

@@ -37,5 +37,5 @@ interface ControllerResolverInterface
*
* @throws \LogicException If a controller was found based on the request but it is not callable
*/
public function getController(Request $request);
public function getController(Request $request): callable|false;
}

View File

@@ -25,11 +25,11 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
*/
class ErrorController
{
private $kernel;
private $controller;
private $errorRenderer;
private HttpKernelInterface $kernel;
private string|object|array|null $controller;
private ErrorRendererInterface $errorRenderer;
public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer)
public function __construct(HttpKernelInterface $kernel, string|object|array|null $controller, ErrorRendererInterface $errorRenderer)
{
$this->kernel = $kernel;
$this->controller = $controller;

View File

@@ -19,8 +19,8 @@ use Symfony\Component\Stopwatch\Stopwatch;
*/
class TraceableArgumentResolver implements ArgumentResolverInterface
{
private $resolver;
private $stopwatch;
private ArgumentResolverInterface $resolver;
private Stopwatch $stopwatch;
public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch)
{
@@ -29,13 +29,14 @@ class TraceableArgumentResolver implements ArgumentResolverInterface
}
/**
* {@inheritdoc}
* @param \ReflectionFunctionAbstract|null $reflector
*/
public function getArguments(Request $request, callable $controller)
public function getArguments(Request $request, callable $controller/* , \ReflectionFunctionAbstract $reflector = null */): array
{
$reflector = 2 < \func_num_args() ? func_get_arg(2) : null;
$e = $this->stopwatch->start('controller.get_arguments');
$ret = $this->resolver->getArguments($request, $controller);
$ret = $this->resolver->getArguments($request, $controller, $reflector);
$e->stop();

View File

@@ -19,8 +19,8 @@ use Symfony\Component\Stopwatch\Stopwatch;
*/
class TraceableControllerResolver implements ControllerResolverInterface
{
private $resolver;
private $stopwatch;
private ControllerResolverInterface $resolver;
private Stopwatch $stopwatch;
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
{
@@ -28,10 +28,7 @@ class TraceableControllerResolver implements ControllerResolverInterface
$this->stopwatch = $stopwatch;
}
/**
* {@inheritdoc}
*/
public function getController(Request $request)
public function getController(Request $request): callable|false
{
$e = $this->stopwatch->start('controller.get_callable');

View File

@@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
* Responsible for resolving the value of an argument based on its metadata.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface ValueResolverInterface
{
/**
* Returns the possible value(s).
*/
public function resolve(Request $request, ArgumentMetadata $argument): iterable;
}