<?php
namespace App\Event\Http;
use App\Controller\ApiPluginController;
use App\Entity\ApiPluginCalls;
use App\Service\Utils\CommonUtils;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class ApiPluginControllerCall implements EventSubscriberInterface
{
/**
* @var EntityManagerInterface
*/
private $em;
const PARAM_KEY = 'plugin_api_call_flaged';
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
if (is_array($controller)) {
$controller = $controller[0];
}
if ($controller instanceof ApiPluginController) {
$event->getRequest()->attributes->set(self::PARAM_KEY, 'new');
// $token = $event->getRequest()->query->get('token');
// if (!in_array($token, $this->tokens)) {
// throw new AccessDeniedHttpException('This action needs a valid token!');
// }
}
}
public function onKernelResponse(ResponseEvent $event)
{
if (!$token = $event->getRequest()->attributes->get(self::PARAM_KEY)) {
return;
}
if ($token !== 'new'){
return;
}
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
// check to see if onKernelController marked this as a token "auth'ed" request
$request = $event->getRequest();
$response = $event->getResponse();
try {
if ($response->getStatusCode() != 200 && ($request->getMethod() === 'POST' || $request->getMethod() === 'GET')) {
// file_put_contents('/tmp/dropped_data.log',json_encode([
// 'request'=>$request->getContent(),
// 'response'=>$response->getContent()
// ]));
$ip = CommonUtils::getClientIP($request);
$droppedCall = (new ApiPluginCalls())
->setRequest(
[
'url' => $request->getUri(),
'method' => $request->getMethod(),
'data' => $request->getContent(),
'ip' => $ip,
'headers' => $request->headers,
]
)
->setResponse(
[
'status' => $response->getStatusCode(),
'content' => $response->getContent()
]
);
$this->em->persist($droppedCall);
$this->em->flush();
$event->getRequest()->attributes->set(self::PARAM_KEY, $droppedCall->getId());
}
} catch (\Exception $e) {
file_put_contents('/tmp/dropped_data.log', PHP_EOL . $e->getMessage(), FILE_APPEND);
}
}
public function onKernelRequestException(ExceptionEvent $event){
if (!$token = $event->getRequest()->attributes->get(self::PARAM_KEY)) {
return;
}
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
// check to see if onKernelController marked this as a token "auth'ed" request
$request = $event->getRequest();
$response = $event->getResponse();
try {
$ip = CommonUtils::getClientIP($request);
$droppedCall = (new ApiPluginCalls())
->setRequest(
[
'url' => $request->getUri(),
'method' => $request->getMethod(),
'data' => $request->getContent(),
'ip' => $ip,
'headers' => $request->headers,
]
);
$resp_data = [];
if ($response && $response->getStatusCode() != 200 && ($request->getMethod() === 'POST' || $request->getMethod() === 'GET')) {
$resp_data =
[
'status' => $response->getStatusCode(),
];
}
$resp_data['exception']=$event->getThrowable()->getMessage().PHP_EOL.
"File {$event->getThrowable()->getFile()} Line {$event->getThrowable()->getLine()}".PHP_EOL.
$event->getThrowable()->getTraceAsString();
$droppedCall->setResponse($resp_data);
$this->em->persist($droppedCall);
$this->em->flush();
$event->getRequest()->attributes->set(self::PARAM_KEY, $droppedCall->getId());
} catch (\Exception $e) {
file_put_contents('/tmp/dropped_data.log', PHP_EOL . $e->getMessage(), FILE_APPEND);
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
KernelEvents::RESPONSE => 'onKernelResponse',
KernelEvents::EXCEPTION => 'onKernelRequestException',
];
}
}