Initial Drupal 11 with DDEV setup
This commit is contained in:
68
vendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php
vendored
Normal file
68
vendor/symfony/http-kernel/Controller/ArgumentResolver/BackedEnumValueResolver.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?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\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 class BackedEnumValueResolver implements ValueResolverInterface
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
87
vendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php
vendored
Normal file
87
vendor/symfony/http-kernel/Controller/ArgumentResolver/DateTimeValueResolver.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?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\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 ValueResolverInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ?ClockInterface $clock = null,
|
||||
) {
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
37
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
37
vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
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 ValueResolverInterface
|
||||
{
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
61
vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php
vendored
Normal file
61
vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?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\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 ValueResolverInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ContainerInterface $container,
|
||||
) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
140
vendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php
vendored
Normal file
140
vendor/symfony/http-kernel/Controller/ArgumentResolver/QueryParameterValueResolver.php
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
<?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\HttpException;
|
||||
use Symfony\Component\Uid\AbstractUid;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* @author Ionut Enache <i.ovidiuenache@yahoo.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();
|
||||
$validationFailedCode = $attribute->validationFailedStatusCode;
|
||||
|
||||
if (!$request->query->has($name)) {
|
||||
if ($argument->isNullable() || $argument->hasDefaultValue()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
throw HttpException::fromStatusCode($validationFailedCode, \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 HttpException::fromStatusCode($validationFailedCode, \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;
|
||||
}
|
||||
|
||||
$uidType = null;
|
||||
if (is_subclass_of($type, AbstractUid::class)) {
|
||||
$uidType = $type;
|
||||
$type = 'uid';
|
||||
}
|
||||
|
||||
$enumType = null;
|
||||
$filter = match ($type) {
|
||||
'array' => \FILTER_DEFAULT,
|
||||
'string' => isset($attribute->options['regexp']) ? \FILTER_VALIDATE_REGEXP : \FILTER_DEFAULT,
|
||||
'int' => \FILTER_VALIDATE_INT,
|
||||
'float' => \FILTER_VALIDATE_FLOAT,
|
||||
'bool' => \FILTER_VALIDATE_BOOL,
|
||||
'uid' => \FILTER_DEFAULT,
|
||||
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, uid 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 !== $uidType) {
|
||||
$value = \is_array($value) ? array_map([$uidType, 'fromString'], $value) : $uidType::fromString($value);
|
||||
}
|
||||
|
||||
if (null === $value && !($attribute->flags & \FILTER_NULL_ON_FAILURE)) {
|
||||
throw HttpException::fromStatusCode($validationFailedCode, \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 HttpException::fromStatusCode($validationFailedCode, \sprintf('Invalid query parameter "%s".', $name));
|
||||
}
|
||||
|
||||
return $argument->isVariadic() ? $filtered : [$filtered];
|
||||
}
|
||||
}
|
||||
29
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
29
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?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\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 ValueResolverInterface
|
||||
{
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
return !$argument->isVariadic() && $request->attributes->has($argument->getName()) ? [$request->attributes->get($argument->getName())] : [];
|
||||
}
|
||||
}
|
||||
241
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php
vendored
Normal file
241
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
<?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\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapQueryString;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
||||
use Symfony\Component\HttpKernel\Attribute\MapUploadedFile;
|
||||
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NearMissValueResolverException;
|
||||
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
|
||||
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedPropertyException;
|
||||
use Symfony\Component\Serializer\Exception\UnsupportedFormatException;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
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 DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
|
||||
*/
|
||||
private const CONTEXT_DENORMALIZE = [
|
||||
'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,
|
||||
private string $translationDomain = 'validators',
|
||||
) {
|
||||
}
|
||||
|
||||
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]
|
||||
?? $argument->getAttributesOfType(MapUploadedFile::class, ArgumentMetadata::IS_INSTANCEOF)[0]
|
||||
?? null;
|
||||
|
||||
if (!$attribute) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!$attribute instanceof MapUploadedFile && $argument->isVariadic()) {
|
||||
throw new \LogicException(\sprintf('Mapping variadic argument "$%s" is not supported.', $argument->getName()));
|
||||
}
|
||||
|
||||
if ($attribute instanceof MapRequestPayload) {
|
||||
if ('array' === $argument->getType()) {
|
||||
if (!$attribute->type) {
|
||||
throw new NearMissValueResolverException(\sprintf('Please set the $type argument of the #[%s] attribute to the type of the objects in the expected array.', MapRequestPayload::class));
|
||||
}
|
||||
} elseif ($attribute->type) {
|
||||
throw new NearMissValueResolverException(\sprintf('Please set its type to "array" when using argument $type of #[%s].', MapRequestPayload::class));
|
||||
}
|
||||
}
|
||||
|
||||
$attribute->metadata = $argument;
|
||||
|
||||
return [$attribute];
|
||||
}
|
||||
|
||||
public function onKernelControllerArguments(ControllerArgumentsEvent $event): void
|
||||
{
|
||||
$arguments = $event->getArguments();
|
||||
|
||||
foreach ($arguments as $i => $argument) {
|
||||
if ($argument instanceof MapQueryString) {
|
||||
$payloadMapper = $this->mapQueryString(...);
|
||||
$validationFailedCode = $argument->validationFailedStatusCode;
|
||||
} elseif ($argument instanceof MapRequestPayload) {
|
||||
$payloadMapper = $this->mapRequestPayload(...);
|
||||
$validationFailedCode = $argument->validationFailedStatusCode;
|
||||
} elseif ($argument instanceof MapUploadedFile) {
|
||||
$payloadMapper = $this->mapUploadedFile(...);
|
||||
$validationFailedCode = $argument->validationFailedStatusCode;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$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 = $payloadMapper($request, $argument->metadata, $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, $this->translationDomain);
|
||||
$violations->add(new ConstraintViolation($message, $template, $parameters, null, $error->getPath(), null));
|
||||
}
|
||||
$payload = $e->getData();
|
||||
}
|
||||
|
||||
if (null !== $payload && !\count($violations)) {
|
||||
$constraints = $argument->constraints ?? null;
|
||||
if (\is_array($payload) && !empty($constraints) && !$constraints instanceof Assert\All) {
|
||||
$constraints = new Assert\All($constraints);
|
||||
}
|
||||
$violations->addAll($this->validator->validate($payload, $constraints, $argument->validationGroups ?? null));
|
||||
}
|
||||
|
||||
if (\count($violations)) {
|
||||
throw HttpException::fromStatusCode($validationFailedCode, implode("\n", array_map(static fn ($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($payload, $violations));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$payload = $payloadMapper($request, $argument->metadata, $argument);
|
||||
} catch (PartialDenormalizationException $e) {
|
||||
throw HttpException::fromStatusCode($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 HttpException::fromStatusCode($validationFailedCode),
|
||||
};
|
||||
}
|
||||
|
||||
$arguments[$i] = $payload;
|
||||
}
|
||||
|
||||
$event->setArguments($arguments);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::CONTROLLER_ARGUMENTS => 'onKernelControllerArguments',
|
||||
];
|
||||
}
|
||||
|
||||
private function mapQueryString(Request $request, ArgumentMetadata $argument, MapQueryString $attribute): ?object
|
||||
{
|
||||
if (!($data = $request->query->all($attribute->key)) && ($argument->isNullable() || $argument->hasDefaultValue())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->serializer->denormalize($data, $argument->getType(), 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ['filter_bool' => true]);
|
||||
}
|
||||
|
||||
private function mapRequestPayload(Request $request, ArgumentMetadata $argument, MapRequestPayload $attribute): object|array|null
|
||||
{
|
||||
if (null === $format = $request->getContentTypeFormat()) {
|
||||
throw new UnsupportedMediaTypeHttpException('Unsupported format.');
|
||||
}
|
||||
|
||||
if ($attribute->acceptFormat && !\in_array($format, (array) $attribute->acceptFormat, true)) {
|
||||
throw new UnsupportedMediaTypeHttpException(\sprintf('Unsupported format, expects "%s", but "%s" given.', implode('", "', (array) $attribute->acceptFormat), $format));
|
||||
}
|
||||
|
||||
if ('array' === $argument->getType() && null !== $attribute->type) {
|
||||
$type = $attribute->type.'[]';
|
||||
} else {
|
||||
$type = $argument->getType();
|
||||
}
|
||||
|
||||
if ($data = $request->request->all()) {
|
||||
return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ('form' === $format ? ['filter_bool' => true] : []));
|
||||
}
|
||||
|
||||
if ('' === ($data = $request->getContent()) && ($argument->isNullable() || $argument->hasDefaultValue())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ('form' === $format) {
|
||||
throw new BadRequestHttpException('Request payload contains invalid "form" data.');
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->serializer->deserialize($data, $type, $format, self::CONTEXT_DESERIALIZE + $attribute->serializationContext);
|
||||
} catch (UnsupportedFormatException $e) {
|
||||
throw new UnsupportedMediaTypeHttpException(\sprintf('Unsupported format: "%s".', $format), $e);
|
||||
} catch (NotEncodableValueException $e) {
|
||||
throw new BadRequestHttpException(\sprintf('Request payload contains invalid "%s" data.', $format), $e);
|
||||
} catch (UnexpectedPropertyException $e) {
|
||||
throw new BadRequestHttpException(\sprintf('Request payload contains invalid "%s" property.', $e->property), $e);
|
||||
}
|
||||
}
|
||||
|
||||
private function mapUploadedFile(Request $request, ArgumentMetadata $argument, MapUploadedFile $attribute): UploadedFile|array|null
|
||||
{
|
||||
if (!($files = $request->files->get($attribute->name ?? $argument->getName())) && ($argument->isNullable() || $argument->hasDefaultValue())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $files ?? ('array' === $argument->getType() ? [] : null);
|
||||
}
|
||||
}
|
||||
38
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
38
vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?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\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Exception\NearMissValueResolverException;
|
||||
|
||||
/**
|
||||
* Yields the same instance as the request object passed along.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
final class RequestValueResolver implements ValueResolverInterface
|
||||
{
|
||||
public function resolve(Request $request, ArgumentMetadata $argument): array
|
||||
{
|
||||
if (Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class)) {
|
||||
return [$request];
|
||||
}
|
||||
|
||||
if (str_ends_with($argument->getType() ?? '', '\\Request')) {
|
||||
throw new NearMissValueResolverException(\sprintf('Looks like you required a Request object with the wrong class name "%s". Did you mean to use "%s" instead?', $argument->getType(), Request::class));
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
70
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
70
vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?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\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Exception\NearMissValueResolverException;
|
||||
|
||||
/**
|
||||
* Yields a service keyed by _controller and argument name.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class ServiceValueResolver implements ValueResolverInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ContainerInterface $container,
|
||||
) {
|
||||
}
|
||||
|
||||
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 = 'argument $'.$argument->getName();
|
||||
$message = str_replace(\sprintf('service "%s"', $argument->getName()), $what, $e->getMessage());
|
||||
$what .= \sprintf(' of "%s()"', $controller);
|
||||
$message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $message);
|
||||
|
||||
if ($e->getMessage() === $message) {
|
||||
$message = \sprintf('Cannot resolve %s: %s', $what, $message);
|
||||
}
|
||||
|
||||
throw new NearMissValueResolverException($message, $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
39
vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
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 ValueResolverInterface
|
||||
{
|
||||
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()] : [];
|
||||
}
|
||||
}
|
||||
41
vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php
vendored
Normal file
41
vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.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\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
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 ValueResolverInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ValueResolverInterface $inner,
|
||||
private Stopwatch $stopwatch,
|
||||
) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
38
vendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php
vendored
Normal file
38
vendor/symfony/http-kernel/Controller/ArgumentResolver/UidValueResolver.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?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\ValueResolverInterface;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Uid\AbstractUid;
|
||||
|
||||
final class UidValueResolver implements ValueResolverInterface
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
39
vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
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 ValueResolverInterface
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user