Files
kupshop/bundles/KupShop/KupShopBundle/Util/System/ControllerUtil.php
2025-08-02 16:30:27 +02:00

99 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\KupShopBundle\Util\System;
use KupShop\KupShopBundle\Event\EarlyDynamicRouteEvent;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
class ControllerUtil
{
public function __construct(
#[Autowire(service: 'argument_resolver')] private readonly ArgumentResolverInterface $argumentResolver,
#[Autowire(service: 'controller_resolver')] private readonly ControllerResolverInterface $controllerResolver,
private readonly EventDispatcherInterface $dispatcher,
private readonly HttpKernelInterface $kernel,
private readonly RouterInterface $router,
) {
}
/**
* Returns controller info for given request (for request uri in request) and assign attributes to request if controller was found.
*
* @return array{
* path: string,
* _controller: string,
* _route: string,
* _route_params?: array
* }|null
*/
public function getControllerByRequest(Request $request): ?array
{
$path = $request->getPathInfo();
// try to get controller from EarlyDynamicRouteEvent first
$this->dispatcher->dispatch(new EarlyDynamicRouteEvent($request));
// if controller was set by event we return it
if ($request->attributes->get('_controller')) {
return [
'path' => $request->attributes->get('path'),
'_controller' => $request->attributes->get('_controller'),
'_route' => $request->attributes->get('_route'),
'_route_params' => $request->attributes->get('_route_params'),
];
}
// event does not set controller so try to use router match
if ($result = $this->router->match($path)) {
$result['_route_params'] = array_filter(array_filter($result, fn ($x) => !in_array($x, ['_controller', '_route']), ARRAY_FILTER_USE_KEY));
// assign controller attributes to request
foreach ($result as $key => $value) {
$request->attributes->set($key, $value);
}
return $result;
}
return null;
}
public function callController(Request $request, callable $controller, int $requestType = HttpKernelInterface::SUB_REQUEST): mixed
{
// the reflector gets created inside ArgumentMetadataFactory
$arguments = $this->argumentResolver->getArguments($request, $controller);
$event = new ControllerArgumentsEvent(
kernel: $this->kernel,
controller: $controller,
arguments: $arguments,
request: $request,
requestType: $requestType,
);
$this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS);
$controller = $event->getController();
$arguments = $event->getArguments();
return $controller(...$arguments);
}
public function instantiateController(string $controller): false|callable
{
$request = new Request();
$request->attributes->set('_controller', $controller);
return $this->controllerResolver->getController($request);
}
}