first commit
This commit is contained in:
146
vendor/symfony/http-kernel/Controller/ArgumentResolver.php
vendored
Normal file
146
vendor/symfony/http-kernel/Controller/ArgumentResolver.php
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\ResolverNotFoundException;
|
||||
use Symfony\Contracts\Service\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* Responsible for resolving the arguments passed to an action.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class ArgumentResolver implements ArgumentResolverInterface
|
||||
{
|
||||
private ArgumentMetadataFactoryInterface $argumentMetadataFactory;
|
||||
private iterable $argumentValueResolvers;
|
||||
private ?ContainerInterface $namedResolvers;
|
||||
|
||||
/**
|
||||
* @param iterable<mixed, ArgumentValueResolverInterface|ValueResolverInterface> $argumentValueResolvers
|
||||
*/
|
||||
public function __construct(?ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [], ?ContainerInterface $namedResolvers = null)
|
||||
{
|
||||
$this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory();
|
||||
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
|
||||
$this->namedResolvers = $namedResolvers;
|
||||
}
|
||||
|
||||
public function getArguments(Request $request, callable $controller, ?\ReflectionFunctionAbstract $reflector = null): array
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller, $reflector) as $metadata) {
|
||||
$argumentValueResolvers = $this->argumentValueResolvers;
|
||||
$disabledResolvers = [];
|
||||
|
||||
if ($this->namedResolvers && $attributes = $metadata->getAttributesOfType(ValueResolver::class, $metadata::IS_INSTANCEOF)) {
|
||||
$resolverName = null;
|
||||
foreach ($attributes as $attribute) {
|
||||
if ($attribute->disabled) {
|
||||
$disabledResolvers[$attribute->resolver] = true;
|
||||
} elseif ($resolverName) {
|
||||
throw new \LogicException(sprintf('You can only pin one resolver per argument, but argument "$%s" of "%s()" has more.', $metadata->getName(), $this->getPrettyName($controller)));
|
||||
} else {
|
||||
$resolverName = $attribute->resolver;
|
||||
}
|
||||
}
|
||||
|
||||
if ($resolverName) {
|
||||
if (!$this->namedResolvers->has($resolverName)) {
|
||||
throw new ResolverNotFoundException($resolverName, $this->namedResolvers instanceof ServiceProviderInterface ? array_keys($this->namedResolvers->getProvidedServices()) : []);
|
||||
}
|
||||
|
||||
$argumentValueResolvers = [
|
||||
$this->namedResolvers->get($resolverName),
|
||||
new RequestAttributeValueResolver(),
|
||||
new DefaultValueResolver(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($argumentValueResolvers as $name => $resolver) {
|
||||
if ((!$resolver instanceof ValueResolverInterface || $resolver instanceof TraceableValueResolver) && !$resolver->supports($request, $metadata)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($disabledResolvers[\is_int($name) ? $resolver::class : $name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($resolver->resolve($request, $metadata) as $argument) {
|
||||
++$count;
|
||||
$arguments[] = $argument;
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
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 there is a non-optional argument after this one.', $this->getPrettyName($controller), $metadata->getName()));
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<int, ArgumentValueResolverInterface>
|
||||
*/
|
||||
public static function getDefaultArgumentValueResolvers(): iterable
|
||||
{
|
||||
return [
|
||||
new RequestAttributeValueResolver(),
|
||||
new RequestValueResolver(),
|
||||
new SessionValueResolver(),
|
||||
new DefaultValueResolver(),
|
||||
new VariadicValueResolver(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getPrettyName($controller): string
|
||||
{
|
||||
if (\is_array($controller)) {
|
||||
if (\is_object($controller[0])) {
|
||||
$controller[0] = get_debug_type($controller[0]);
|
||||
}
|
||||
|
||||
return $controller[0].'::'.$controller[1];
|
||||
}
|
||||
|
||||
if (\is_object($controller)) {
|
||||
return get_debug_type($controller);
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
}
|
93
vendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php
vendored
Normal file
93
vendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php
vendored
Normal 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|\TypeError $e) {
|
||||
throw new NotFoundHttpException(sprintf('Could not resolve the "%s $%s" controller argument: ', $argument->getType(), $argument->getName()).$e->getMessage(), $e);
|
||||
}
|
||||
}
|
||||
}
|
98
vendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php
vendored
Normal file
98
vendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Psr\Clock\ClockInterface;
|
||||
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
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ?ClockInterface $clock = null,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
if ($argument->isNullable()) {
|
||||
return [null];
|
||||
}
|
||||
if (!$this->clock) {
|
||||
return [new $class()];
|
||||
}
|
||||
$value = $this->clock->now();
|
||||
}
|
||||
|
||||
if ($value instanceof \DateTimeInterface) {
|
||||
return [$value instanceof $class ? $value : $class::createFromInterface($value)];
|
||||
}
|
||||
|
||||
$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, $this->clock?->now()->getTimeZone());
|
||||
|
||||
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, $this->clock?->now()->getTimeZone());
|
||||
} catch (\Exception) {
|
||||
$date = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$date) {
|
||||
throw new NotFoundHttpException(sprintf('Invalid date given for parameter "%s".', $argument->getName()));
|
||||
}
|
||||
|
||||
return [$date];
|
||||
}
|
||||
}
|
48
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
48
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields the default value defined in the action signature when no value has been given.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class DefaultValueResolver implements ArgumentValueResolverInterface, 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->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic());
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
if ($argument->hasDefaultValue()) {
|
||||
return [$argument->getDefaultValue()];
|
||||
}
|
||||
|
||||
if (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()) {
|
||||
return [null];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
90
vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php
vendored
Normal file
90
vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\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;
|
||||
|
||||
/**
|
||||
* Provides an intuitive error message when controller fails because it is not registered as a service.
|
||||
*
|
||||
* @author Simeon Kolev <simeon.kolev9@gmail.com>
|
||||
*/
|
||||
final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
|
||||
{
|
||||
private ContainerInterface $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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])) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
} elseif (!\is_string($controller) || '' === $controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('\\' === $controller[0]) {
|
||||
$controller = ltrim($controller, '\\');
|
||||
}
|
||||
|
||||
if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) {
|
||||
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
|
||||
}
|
||||
|
||||
return false === $this->container->has($controller);
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
$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)) {
|
||||
$controller = (false !== $i = strrpos($controller, ':'))
|
||||
? substr($controller, 0, $i).strtolower(substr($controller, $i))
|
||||
: $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);
|
||||
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
125
vendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php
vendored
Normal file
125
vendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
<?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\MapQueryParameter;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Resolve arguments of type: array, string, int, float, bool, \BackedEnum from query parameters.
|
||||
*
|
||||
* @author Ruud Kamphuis <ruud@ticketswap.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @author Mateusz Anders <anders_mateusz@outlook.com>
|
||||
*/
|
||||
final class QueryParameterValueResolver implements ValueResolverInterface
|
||||
{
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
if (!$attribute = $argument->getAttributesOfType(MapQueryParameter::class)[0] ?? null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$name = $attribute->name ?? $argument->getName();
|
||||
if (!$request->query->has($name)) {
|
||||
if ($argument->isNullable() || $argument->hasDefaultValue()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException(sprintf('Missing query parameter "%s".', $name));
|
||||
}
|
||||
|
||||
$value = $request->query->all()[$name];
|
||||
$type = $argument->getType();
|
||||
|
||||
if (null === $attribute->filter && 'array' === $type) {
|
||||
if (!$argument->isVariadic()) {
|
||||
return [(array) $value];
|
||||
}
|
||||
|
||||
$filtered = array_values(array_filter((array) $value, \is_array(...)));
|
||||
|
||||
if ($filtered !== $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
|
||||
throw new NotFoundHttpException(sprintf('Invalid query parameter "%s".', $name));
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'flags' => $attribute->flags | \FILTER_NULL_ON_FAILURE,
|
||||
'options' => $attribute->options,
|
||||
];
|
||||
|
||||
if ('array' === $type || $argument->isVariadic()) {
|
||||
$value = (array) $value;
|
||||
$options['flags'] |= \FILTER_REQUIRE_ARRAY;
|
||||
} else {
|
||||
$options['flags'] |= \FILTER_REQUIRE_SCALAR;
|
||||
}
|
||||
|
||||
$enumType = null;
|
||||
$filter = match ($type) {
|
||||
'array' => \FILTER_DEFAULT,
|
||||
'string' => \FILTER_DEFAULT,
|
||||
'int' => \FILTER_VALIDATE_INT,
|
||||
'float' => \FILTER_VALIDATE_FLOAT,
|
||||
'bool' => \FILTER_VALIDATE_BOOL,
|
||||
default => match ($enumType = is_subclass_of($type, \BackedEnum::class) ? (new \ReflectionEnum($type))->getBackingType()->getName() : null) {
|
||||
'int' => \FILTER_VALIDATE_INT,
|
||||
'string' => \FILTER_DEFAULT,
|
||||
default => throw new \LogicException(sprintf('#[MapQueryParameter] cannot be used on controller argument "%s$%s" of type "%s"; one of array, string, int, float, bool or \BackedEnum should be used.', $argument->isVariadic() ? '...' : '', $argument->getName(), $type ?? 'mixed')),
|
||||
}
|
||||
};
|
||||
|
||||
$value = filter_var($value, $attribute->filter ?? $filter, $options);
|
||||
|
||||
if (null !== $enumType && null !== $value) {
|
||||
$enumFrom = static function ($value) use ($type) {
|
||||
if (!\is_string($value) && !\is_int($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return $type::from($value);
|
||||
} catch (\ValueError) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$value = \is_array($value) ? array_map($enumFrom, $value) : $enumFrom($value);
|
||||
}
|
||||
|
||||
if (null === $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
|
||||
throw new NotFoundHttpException(sprintf('Invalid query parameter "%s".', $name));
|
||||
}
|
||||
|
||||
if (!\is_array($value)) {
|
||||
return [$value];
|
||||
}
|
||||
|
||||
$filtered = array_filter($value, static fn ($v) => null !== $v);
|
||||
|
||||
if ($argument->isVariadic()) {
|
||||
$filtered = array_values($filtered);
|
||||
}
|
||||
|
||||
if ($filtered !== $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
|
||||
throw new NotFoundHttpException(sprintf('Invalid query parameter "%s".', $name));
|
||||
}
|
||||
|
||||
return $argument->isVariadic() ? $filtered : [$filtered];
|
||||
}
|
||||
}
|
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields a non-variadic argument's value from the request attributes.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class RequestAttributeValueResolver implements ArgumentValueResolverInterface, 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() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
return !$argument->isVariadic() && $request->attributes->has($argument->getName()) ? [$request->attributes->get($argument->getName())] : [];
|
||||
}
|
||||
}
|
201
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php
vendored
Normal file
201
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
<?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\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapQueryString;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
|
||||
use Symfony\Component\Serializer\Exception\UnsupportedFormatException;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\Exception\ValidationFailedException;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Konstantin Myakshin <molodchick@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @see \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT
|
||||
* @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
|
||||
*/
|
||||
private const CONTEXT_DENORMALIZE = [
|
||||
'disable_type_enforcement' => true,
|
||||
'collect_denormalization_errors' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
|
||||
*/
|
||||
private const CONTEXT_DESERIALIZE = [
|
||||
'collect_denormalization_errors' => true,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private readonly SerializerInterface&DenormalizerInterface $serializer,
|
||||
private readonly ?ValidatorInterface $validator = null,
|
||||
private readonly ?TranslatorInterface $translator = null,
|
||||
) {
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
$attribute = $argument->getAttributesOfType(MapQueryString::class, ArgumentMetadata::IS_INSTANCEOF)[0]
|
||||
?? $argument->getAttributesOfType(MapRequestPayload::class, ArgumentMetadata::IS_INSTANCEOF)[0]
|
||||
?? null;
|
||||
|
||||
if (!$attribute) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($argument->isVariadic()) {
|
||||
throw new \LogicException(sprintf('Mapping variadic argument "$%s" is not supported.', $argument->getName()));
|
||||
}
|
||||
|
||||
$attribute->metadata = $argument;
|
||||
|
||||
return [$attribute];
|
||||
}
|
||||
|
||||
public function onKernelControllerArguments(ControllerArgumentsEvent $event): void
|
||||
{
|
||||
$arguments = $event->getArguments();
|
||||
|
||||
foreach ($arguments as $i => $argument) {
|
||||
if ($argument instanceof MapQueryString) {
|
||||
$payloadMapper = 'mapQueryString';
|
||||
$validationFailedCode = $argument->validationFailedStatusCode;
|
||||
} elseif ($argument instanceof MapRequestPayload) {
|
||||
$payloadMapper = 'mapRequestPayload';
|
||||
$validationFailedCode = $argument->validationFailedStatusCode;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$type = $argument->metadata->getType()) {
|
||||
throw new \LogicException(sprintf('Could not resolve the "$%s" controller argument: argument should be typed.', $argument->metadata->getName()));
|
||||
}
|
||||
|
||||
if ($this->validator) {
|
||||
$violations = new ConstraintViolationList();
|
||||
try {
|
||||
$payload = $this->$payloadMapper($request, $type, $argument);
|
||||
} catch (PartialDenormalizationException $e) {
|
||||
$trans = $this->translator ? $this->translator->trans(...) : fn ($m, $p) => strtr($m, $p);
|
||||
foreach ($e->getErrors() as $error) {
|
||||
$parameters = [];
|
||||
$template = 'This value was of an unexpected type.';
|
||||
if ($expectedTypes = $error->getExpectedTypes()) {
|
||||
$template = 'This value should be of type {{ type }}.';
|
||||
$parameters['{{ type }}'] = implode('|', $expectedTypes);
|
||||
}
|
||||
if ($error->canUseMessageForUser()) {
|
||||
$parameters['hint'] = $error->getMessage();
|
||||
}
|
||||
$message = $trans($template, $parameters, 'validators');
|
||||
$violations->add(new ConstraintViolation($message, $template, $parameters, null, $error->getPath(), null));
|
||||
}
|
||||
$payload = $e->getData();
|
||||
}
|
||||
|
||||
if (null !== $payload && !\count($violations)) {
|
||||
$violations->addAll($this->validator->validate($payload, null, $argument->validationGroups ?? null));
|
||||
}
|
||||
|
||||
if (\count($violations)) {
|
||||
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($payload, $violations));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$payload = $this->$payloadMapper($request, $type, $argument);
|
||||
} catch (PartialDenormalizationException $e) {
|
||||
throw new HttpException($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), $e->getErrors())), $e);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $payload) {
|
||||
$payload = match (true) {
|
||||
$argument->metadata->hasDefaultValue() => $argument->metadata->getDefaultValue(),
|
||||
$argument->metadata->isNullable() => null,
|
||||
default => throw new HttpException($validationFailedCode)
|
||||
};
|
||||
}
|
||||
|
||||
$arguments[$i] = $payload;
|
||||
}
|
||||
|
||||
$event->setArguments($arguments);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::CONTROLLER_ARGUMENTS => 'onKernelControllerArguments',
|
||||
];
|
||||
}
|
||||
|
||||
private function mapQueryString(Request $request, string $type, MapQueryString $attribute): ?object
|
||||
{
|
||||
if (!$data = $request->query->all()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
|
||||
}
|
||||
|
||||
private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object
|
||||
{
|
||||
if (null === $format = $request->getContentTypeFormat()) {
|
||||
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, 'Unsupported format.');
|
||||
}
|
||||
|
||||
if ($attribute->acceptFormat && !\in_array($format, (array) $attribute->acceptFormat, true)) {
|
||||
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', (array) $attribute->acceptFormat), $format));
|
||||
}
|
||||
|
||||
if ($data = $request->request->all()) {
|
||||
return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
|
||||
}
|
||||
|
||||
if ('' === $data = $request->getContent()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ('form' === $format) {
|
||||
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Request payload contains invalid "form" data.');
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->serializer->deserialize($data, $type, $format, self::CONTEXT_DESERIALIZE + $attribute->serializationContext);
|
||||
} catch (UnsupportedFormatException $e) {
|
||||
throw new HttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE, sprintf('Unsupported format: "%s".', $format), $e);
|
||||
} catch (NotEncodableValueException $e) {
|
||||
throw new HttpException(Response::HTTP_BAD_REQUEST, sprintf('Request payload contains invalid "%s" data.', $format), $e);
|
||||
}
|
||||
}
|
||||
}
|
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
40
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Yields the same instance as the request object passed along.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class RequestValueResolver implements ArgumentValueResolverInterface, 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 Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class) ? [$request] : [];
|
||||
}
|
||||
}
|
99
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
99
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\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;
|
||||
|
||||
/**
|
||||
* Yields a service keyed by _controller and argument name.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class ServiceValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
|
||||
{
|
||||
private ContainerInterface $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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])) {
|
||||
$controller = $controller[0].'::'.$controller[1];
|
||||
} elseif (!\is_string($controller) || '' === $controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('\\' === $controller[0]) {
|
||||
$controller = ltrim($controller, '\\');
|
||||
}
|
||||
|
||||
if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) {
|
||||
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
|
||||
}
|
||||
|
||||
return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
$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) && 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 {
|
||||
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());
|
||||
|
||||
if ($e->getMessage() === $message) {
|
||||
$message = sprintf('Cannot resolve %s: %s', $what, $message);
|
||||
}
|
||||
|
||||
$r = new \ReflectionProperty($e, 'message');
|
||||
$r->setValue($e, $message);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
59
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
59
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\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;
|
||||
|
||||
/**
|
||||
* Yields the Session.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class SessionValueResolver 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 (!$request->hasSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = $argument->getType();
|
||||
if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $request->getSession() instanceof $type;
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
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()] : [];
|
||||
}
|
||||
}
|
64
vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php
vendored
Normal file
64
vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?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\Stopwatch\Stopwatch;
|
||||
|
||||
/**
|
||||
* Provides timing information via the stopwatch.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class TraceableValueResolver implements ArgumentValueResolverInterface, ValueResolverInterface
|
||||
{
|
||||
private ArgumentValueResolverInterface|ValueResolverInterface $inner;
|
||||
private Stopwatch $stopwatch;
|
||||
|
||||
public function __construct(ArgumentValueResolverInterface|ValueResolverInterface $inner, Stopwatch $stopwatch)
|
||||
{
|
||||
$this->inner = $inner;
|
||||
$this->stopwatch = $stopwatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 6.2, use resolve() instead
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool
|
||||
{
|
||||
if ($this->inner instanceof ValueResolverInterface) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$method = $this->inner::class.'::'.__FUNCTION__;
|
||||
$this->stopwatch->start($method, 'controller.argument_value_resolver');
|
||||
|
||||
$return = $this->inner->supports($request, $argument);
|
||||
|
||||
$this->stopwatch->stop($method);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable
|
||||
{
|
||||
$method = $this->inner::class.'::'.__FUNCTION__;
|
||||
$this->stopwatch->start($method, 'controller.argument_value_resolver');
|
||||
|
||||
yield from $this->inner->resolve($request, $argument);
|
||||
|
||||
$this->stopwatch->stop($method);
|
||||
}
|
||||
}
|
52
vendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php
vendored
Normal file
52
vendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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($uidClass, AbstractUid::class, true)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
return [$uidClass::fromString($value)];
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new NotFoundHttpException(sprintf('The uid for the "%s" parameter is invalid.', $argument->getName()), $e);
|
||||
}
|
||||
}
|
||||
}
|
50
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
50
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Yields a variadic argument's values from the request attributes.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class VariadicValueResolver 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() && $request->attributes->has($argument->getName());
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
32
vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php
vendored
Normal file
32
vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* An ArgumentResolverInterface instance knows how to determine the
|
||||
* arguments for a specific action.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ArgumentResolverInterface
|
||||
{
|
||||
/**
|
||||
* Returns the arguments to pass to the controller.
|
||||
*
|
||||
* @param \ReflectionFunctionAbstract|null $reflector
|
||||
*
|
||||
* @throws \RuntimeException When no value could be provided for a required argument
|
||||
*/
|
||||
public function getArguments(Request $request, callable $controller/* , \ReflectionFunctionAbstract $reflector = null */): array;
|
||||
}
|
35
vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php
vendored
Normal file
35
vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
|
||||
/**
|
||||
* Responsible for resolving the value of an argument based on its metadata.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*
|
||||
* @deprecated since Symfony 6.2, implement ValueResolverInterface instead
|
||||
*/
|
||||
interface ArgumentValueResolverInterface
|
||||
{
|
||||
/**
|
||||
* Whether this resolver can resolve the value for the given ArgumentMetadata.
|
||||
*/
|
||||
public function supports(Request $request, ArgumentMetadata $argument): bool;
|
||||
|
||||
/**
|
||||
* Returns the possible value(s).
|
||||
*/
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): iterable;
|
||||
}
|
63
vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php
vendored
Normal file
63
vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
|
||||
/**
|
||||
* A controller resolver searching for a controller in a psr-11 container when using the "service::method" notation.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class ContainerControllerResolver extends ControllerResolver
|
||||
{
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container, ?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
parent::__construct($logger);
|
||||
}
|
||||
|
||||
protected function instantiateController(string $class): object
|
||||
{
|
||||
$class = ltrim($class, '\\');
|
||||
|
||||
if ($this->container->has($class)) {
|
||||
return $this->container->get($class);
|
||||
}
|
||||
|
||||
try {
|
||||
return parent::instantiateController($class);
|
||||
} catch (\Error $e) {
|
||||
}
|
||||
|
||||
$this->throwExceptionIfControllerWasRemoved($class, $e);
|
||||
|
||||
if ($e instanceof \ArgumentCountError) {
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e);
|
||||
}
|
||||
|
||||
private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous): void
|
||||
{
|
||||
if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
44
vendor/symfony/http-kernel/Controller/ControllerReference.php
vendored
Normal file
44
vendor/symfony/http-kernel/Controller/ControllerReference.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
|
||||
|
||||
/**
|
||||
* Acts as a marker and a data holder for a Controller.
|
||||
*
|
||||
* Some methods in Symfony accept both a URI (as a string) or a controller as
|
||||
* an argument. In the latter case, instead of passing an array representing
|
||||
* the controller, you can use an instance of this class.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @see FragmentRendererInterface
|
||||
*/
|
||||
class ControllerReference
|
||||
{
|
||||
public $controller;
|
||||
public $attributes = [];
|
||||
public $query = [];
|
||||
|
||||
/**
|
||||
* @param string $controller The controller name
|
||||
* @param array $attributes An array of parameters to add to the Request attributes
|
||||
* @param array $query An array of parameters to add to the Request query string
|
||||
*/
|
||||
public function __construct(string $controller, array $attributes = [], array $query = [])
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->attributes = $attributes;
|
||||
$this->query = $query;
|
||||
}
|
||||
}
|
279
vendor/symfony/http-kernel/Controller/ControllerResolver.php
vendored
Normal file
279
vendor/symfony/http-kernel/Controller/ControllerResolver.php
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
|
||||
/**
|
||||
* This implementation uses the '_controller' request attribute to determine
|
||||
* the controller to execute.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*/
|
||||
class ControllerResolver implements ControllerResolverInterface
|
||||
{
|
||||
private ?LoggerInterface $logger;
|
||||
private array $allowedControllerTypes = [];
|
||||
private array $allowedControllerAttributes = [AsController::class => AsController::class];
|
||||
|
||||
public function __construct(?LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<class-string> $types
|
||||
* @param array<class-string> $attributes
|
||||
*/
|
||||
public function allowControllers(array $types = [], array $attributes = []): void
|
||||
{
|
||||
foreach ($types as $type) {
|
||||
$this->allowedControllerTypes[$type] = $type;
|
||||
}
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$this->allowedControllerAttributes[$attribute] = $attribute;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws BadRequestException when the request has attribute "_check_controller_is_allowed" set to true and the controller is not allowed
|
||||
*/
|
||||
public function getController(Request $request): callable|false
|
||||
{
|
||||
if (!$controller = $request->attributes->get('_controller')) {
|
||||
$this->logger?->warning('Unable to look for the controller as the "_controller" parameter is missing.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (\is_callable($controller)) {
|
||||
return $this->checkController($request, $controller);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $this->checkController($request, $controller);
|
||||
}
|
||||
|
||||
if (\is_object($controller)) {
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $this->checkController($request, $controller);
|
||||
}
|
||||
|
||||
if (\function_exists($controller)) {
|
||||
return $this->checkController($request, $controller);
|
||||
}
|
||||
|
||||
try {
|
||||
$callable = $this->createController($controller);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if (!\is_callable($callable)) {
|
||||
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($callable));
|
||||
}
|
||||
|
||||
return $this->checkController($request, $callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a callable for the given controller.
|
||||
*
|
||||
* @throws \InvalidArgumentException When the controller cannot be created
|
||||
*/
|
||||
protected function createController(string $controller): callable
|
||||
{
|
||||
if (!str_contains($controller, '::')) {
|
||||
$controller = $this->instantiateController($controller);
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException($this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
[$class, $method] = explode('::', $controller, 2);
|
||||
|
||||
try {
|
||||
$controller = [$this->instantiateController($class), $method];
|
||||
} catch (\Error|\LogicException $e) {
|
||||
try {
|
||||
if ((new \ReflectionMethod($class, $method))->isStatic()) {
|
||||
return $class.'::'.$method;
|
||||
}
|
||||
} catch (\ReflectionException) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (!\is_callable($controller)) {
|
||||
throw new \InvalidArgumentException($this->getControllerError($controller));
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instantiated controller.
|
||||
*/
|
||||
protected function instantiateController(string $class): object
|
||||
{
|
||||
return new $class();
|
||||
}
|
||||
|
||||
private function getControllerError(mixed $callable): string
|
||||
{
|
||||
if (\is_string($callable)) {
|
||||
if (str_contains($callable, '::')) {
|
||||
$callable = explode('::', $callable, 2);
|
||||
} else {
|
||||
return sprintf('Function "%s" does not exist.', $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_debug_type($callable), $alternativeMsg);
|
||||
}
|
||||
|
||||
if (!\is_array($callable)) {
|
||||
return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', get_debug_type($callable));
|
||||
}
|
||||
|
||||
if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) {
|
||||
return 'Invalid array callable, expected [controller, method].';
|
||||
}
|
||||
|
||||
[$controller, $method] = $callable;
|
||||
|
||||
if (\is_string($controller) && !class_exists($controller)) {
|
||||
return sprintf('Class "%s" does not exist.', $controller);
|
||||
}
|
||||
|
||||
$className = \is_object($controller) ? get_debug_type($controller) : $controller;
|
||||
|
||||
if (method_exists($controller, $method)) {
|
||||
return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className);
|
||||
}
|
||||
|
||||
$collection = $this->getClassMethodsWithoutMagicMethods($controller);
|
||||
|
||||
$alternatives = [];
|
||||
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($method, $item);
|
||||
|
||||
if ($lev <= \strlen($method) / 3 || str_contains($item, $method)) {
|
||||
$alternatives[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
asort($alternatives);
|
||||
|
||||
$message = sprintf('Expected method "%s" on class "%s"', $method, $className);
|
||||
|
||||
if (\count($alternatives) > 0) {
|
||||
$message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives));
|
||||
} else {
|
||||
$message .= sprintf('. Available methods: "%s".', implode('", "', $collection));
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
private function getClassMethodsWithoutMagicMethods($classOrObject): array
|
||||
{
|
||||
$methods = get_class_methods($classOrObject);
|
||||
|
||||
return array_filter($methods, fn (string $method) => 0 !== strncmp($method, '__', 2));
|
||||
}
|
||||
|
||||
private function checkController(Request $request, callable $controller): callable
|
||||
{
|
||||
if (!$request->attributes->get('_check_controller_is_allowed', false)) {
|
||||
return $controller;
|
||||
}
|
||||
|
||||
$r = null;
|
||||
|
||||
if (\is_array($controller)) {
|
||||
[$class, $name] = $controller;
|
||||
$name = (\is_string($class) ? $class : $class::class).'::'.$name;
|
||||
} elseif (\is_object($controller) && !$controller instanceof \Closure) {
|
||||
$class = $controller;
|
||||
$name = $class::class.'::__invoke';
|
||||
} else {
|
||||
$r = new \ReflectionFunction($controller);
|
||||
$name = $r->name;
|
||||
|
||||
if (str_contains($name, '{closure}')) {
|
||||
$name = $class = \Closure::class;
|
||||
} elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
|
||||
$class = $class->name;
|
||||
$name = $class.'::'.$name;
|
||||
}
|
||||
}
|
||||
|
||||
if ($class) {
|
||||
foreach ($this->allowedControllerTypes as $type) {
|
||||
if (is_a($class, $type, true)) {
|
||||
return $controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$r ??= new \ReflectionClass($class);
|
||||
|
||||
foreach ($r->getAttributes() as $attribute) {
|
||||
if (isset($this->allowedControllerAttributes[$attribute->getName()])) {
|
||||
return $controller;
|
||||
}
|
||||
}
|
||||
|
||||
if (str_contains($name, '@anonymous')) {
|
||||
$name = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $name);
|
||||
}
|
||||
|
||||
if (-1 === $request->attributes->get('_check_controller_is_allowed')) {
|
||||
trigger_deprecation('symfony/http-kernel', '6.4', 'Callable "%s()" is not allowed as a controller. Did you miss tagging it with "#[AsController]" or registering its type with "%s::allowControllers()"?', $name, self::class);
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
throw new BadRequestException(sprintf('Callable "%s()" is not allowed as a controller. Did you miss tagging it with "#[AsController]" or registering its type with "%s::allowControllers()"?', $name, self::class));
|
||||
}
|
||||
}
|
41
vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php
vendored
Normal file
41
vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* A ControllerResolverInterface implementation knows how to determine the
|
||||
* controller to execute based on a Request object.
|
||||
*
|
||||
* A Controller can be any valid PHP callable.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ControllerResolverInterface
|
||||
{
|
||||
/**
|
||||
* Returns the Controller instance associated with a Request.
|
||||
*
|
||||
* As several resolvers can exist for a single application, a resolver must
|
||||
* return false when it is not able to determine the controller.
|
||||
*
|
||||
* The resolver must only throw an exception when it should be able to load a
|
||||
* controller but cannot because of some errors made by the developer.
|
||||
*
|
||||
* @return callable|false A PHP callable representing the Controller,
|
||||
* or false if this resolver is not able to determine the controller
|
||||
*
|
||||
* @throws \LogicException If a controller was found based on the request but it is not callable
|
||||
*/
|
||||
public function getController(Request $request): callable|false;
|
||||
}
|
62
vendor/symfony/http-kernel/Controller/ErrorController.php
vendored
Normal file
62
vendor/symfony/http-kernel/Controller/ErrorController.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Renders error or exception pages from a given FlattenException.
|
||||
*
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
* @author Matthias Pigulla <mp@webfactory.de>
|
||||
*/
|
||||
class ErrorController
|
||||
{
|
||||
private HttpKernelInterface $kernel;
|
||||
private string|object|array|null $controller;
|
||||
private ErrorRendererInterface $errorRenderer;
|
||||
|
||||
public function __construct(HttpKernelInterface $kernel, string|object|array|null $controller, ErrorRendererInterface $errorRenderer)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
$this->controller = $controller;
|
||||
$this->errorRenderer = $errorRenderer;
|
||||
}
|
||||
|
||||
public function __invoke(\Throwable $exception): Response
|
||||
{
|
||||
$exception = $this->errorRenderer->render($exception);
|
||||
|
||||
return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders());
|
||||
}
|
||||
|
||||
public function preview(Request $request, int $code): Response
|
||||
{
|
||||
/*
|
||||
* This Request mimics the parameters set by
|
||||
* \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with
|
||||
* the additional "showException" flag.
|
||||
*/
|
||||
$subRequest = $request->duplicate(null, null, [
|
||||
'_controller' => $this->controller,
|
||||
'exception' => new HttpException($code, 'This is a sample exception.'),
|
||||
'logger' => null,
|
||||
'showException' => false,
|
||||
]);
|
||||
|
||||
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
|
||||
}
|
||||
}
|
45
vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php
vendored
Normal file
45
vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TraceableArgumentResolver implements ArgumentResolverInterface
|
||||
{
|
||||
private ArgumentResolverInterface $resolver;
|
||||
private Stopwatch $stopwatch;
|
||||
|
||||
public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch)
|
||||
{
|
||||
$this->resolver = $resolver;
|
||||
$this->stopwatch = $stopwatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ReflectionFunctionAbstract|null $reflector
|
||||
*/
|
||||
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');
|
||||
|
||||
try {
|
||||
return $this->resolver->getArguments($request, $controller, $reflector);
|
||||
} finally {
|
||||
$e->stop();
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php
vendored
Normal file
41
vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TraceableControllerResolver implements ControllerResolverInterface
|
||||
{
|
||||
private ControllerResolverInterface $resolver;
|
||||
private Stopwatch $stopwatch;
|
||||
|
||||
public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch)
|
||||
{
|
||||
$this->resolver = $resolver;
|
||||
$this->stopwatch = $stopwatch;
|
||||
}
|
||||
|
||||
public function getController(Request $request): callable|false
|
||||
{
|
||||
$e = $this->stopwatch->start('controller.get_callable');
|
||||
|
||||
try {
|
||||
return $this->resolver->getController($request);
|
||||
} finally {
|
||||
$e->stop();
|
||||
}
|
||||
}
|
||||
}
|
28
vendor/symfony/http-kernel/Controller/ValueResolverInterface.php
vendored
Normal file
28
vendor/symfony/http-kernel/Controller/ValueResolverInterface.php
vendored
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user