99 lines
3.6 KiB
PHP
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);
|
|
}
|
|
}
|