<?php
namespace Sq\Service\EventSubscriber;
use Sq\Event\Kernel\InitialiseContainerEvent;
use Sq\Service\Profiler\ProfilerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\KernelEvents;
class MainRequestProfileSubscriber implements EventSubscriberInterface
{
/** @var \Sq\Service\Profiler\ProfilerInterface */
private $profiler;
/** @var \Sq\Entity\Profiler\ProfileInterface */
private $mainProfile;
/**
* @param \Sq\Service\Profiler\ProfilerInterface $profiler
*/
public function __construct(ProfilerInterface $profiler)
{
$this->profiler = $profiler;
}
/** @inheritDoc */
public static function getSubscribedEvents()
{
return [
InitialiseContainerEvent::class => ['onInitializeContainer'],
// For the request and controller events, set the priority really low so that they are executed after the
// route and controller information has been calculated by first-party Symfony event listeners/subscribers.
KernelEvents::REQUEST => ['onRequest', -64],
KernelEvents::CONTROLLER => ['onController', -64],
KernelEvents::TERMINATE => ['onTerminate'],
];
}
/**
* Start profiling the "main" application as soon as the container has been initialized.
*
* @param \Sq\Event\Kernel\InitialiseContainerEvent $event
*/
public function onInitializeContainer(InitialiseContainerEvent $event): void
{
$this->mainProfile = $this->profiler->start('main');
}
/**
* When the route has been determined, add that and information about the request to the main profile.
*
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
*/
public function onRequest(Event\RequestEvent $event): void
{
if ($this->mainProfile !== null)
{
$request = $event->getRequest();
$this->mainProfile->addDataField('request_method', $request->getMethod());
$this->mainProfile->addDataField('request_uri', $request->getPathInfo());
$this->mainProfile->addDataField('query_string', $request->getQueryString() ?? "");
$this->mainProfile->addDataField('route_name', $request->attributes->get('_route', ''));
$this->mainProfile->addDataField('route_params', json_encode($request->attributes->get('_route_params', [])));
}
}
/**
* When the controller has been determined, add that information to the main profile.
*
* @param \Symfony\Component\HttpKernel\Event\ControllerEvent $event
*/
public function onController(Event\ControllerEvent $event): void
{
if ($this->mainProfile !== null)
{
$request = $event->getRequest();
$this->mainProfile->addDataField('controller', $request->attributes->get('_controller', ''));
}
}
/**
* Stop profiling when the kernel terminates, instead of when the PHP script ends, for accuracy.
*
* @param \Symfony\Component\HttpKernel\Event\TerminateEvent $event
*/
public function onTerminate(Event\TerminateEvent $event): void
{
if ($this->mainProfile !== null)
{
$this->mainProfile->stop();
}
}
}