<?php

namespace App\EventListener;

use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

/**
 * Symfony AccessDenied fixer
 * When and "AccessDeniedException" is throw by symfony (ex: is granted)
 * the throw happen before getting users informations, and so make tempalting full bugged
 * and also as no user, security access_control look user as visitor (no access)
 * so, intercepting those, to repalce with "AccessDeniedHttpException" work better
 */
class AccessDeniedListener implements EventSubscriberInterface
{
    private $Security;

    public function __construct(Security $Security)
    {
        $this->Security = $Security;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            // the priority must be greater than the Security HTTP
            // ExceptionListener, to make sure it's called before
            // the default exception listener
            KernelEvents::EXCEPTION => ['onKernelException', 2],
        ];
    }

    public function onKernelException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();


        //if no user, don't replace "AccessDeniedException"
        //this will just lock access_control out
        if (!$this->Security->getUser()) {
            return;
        }

        if (!$exception instanceof AccessDeniedException) {
            return;
        }

        throw new AccessDeniedHttpException($exception->getMessage());
    }
}
