mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-13 03:31:31 +00:00
Import latest app updates from streamline
An updated set of source files and initialization was provided by streamline to address issues observed during initial testing. These files have been updated in order to generate a new set of app images.
This commit is contained in:
-146
@@ -1,146 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,201 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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);
|
||||
}
|
||||
}
|
||||
Vendored
-52
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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;
|
||||
}
|
||||
Vendored
-35
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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;
|
||||
}
|
||||
Vendored
-63
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,279 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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));
|
||||
}
|
||||
}
|
||||
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpKernel\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