src/App/Controller/AbstractController.php line 434

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Component\ViewLayer\Views\DocHtmlView;
  4. use App\Component\ViewLayer\Views\AjaxHtmlView;
  5. use App\Component\ViewLayer\Views\JsonView;
  6. use App\Component\ViewLayer\Views\TwimlView;
  7. use App\Contracts\Service\CustomServiceSubscriberTrait;
  8. use App\Util\Permissions;
  9. use App\Security\Core\Authorization\AuthorizationTester;
  10. use Cms\CoreBundle\Model\Contexts\GlobalContext;
  11. use Cms\CoreBundle\Service\ContextManager;
  12. use Cms\CoreBundle\Service\LocaleManager;
  13. use Cms\CoreBundle\Util\Doctrine\EntityManager;
  14. use Cms\LogBundle\Service\LoggingService;
  15. use Cms\TenantBundle\Entity\Tenant;
  16. use Doctrine\ORM\EntityRepository;
  17. use Doctrine\Persistence\ManagerRegistry;
  18. use SessionHandlerInterface;
  19. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
  20. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  21. use Symfony\Component\Form\Extension\Core\Type\FormType;
  22. use Symfony\Component\Form\FormBuilderInterface;
  23. use Symfony\Component\Form\FormFactoryInterface;
  24. use Symfony\Component\Form\FormInterface;
  25. use Symfony\Component\HttpFoundation\RedirectResponse;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\RequestStack;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  30. use Symfony\Component\HttpKernel\HttpKernelInterface;
  31. use Symfony\Component\HttpKernel\Profiler\Profiler;
  32. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  33. use Symfony\Component\Routing\RouterInterface;
  34. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  35. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  36. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  37. use Symfony\Component\Serializer\SerializerInterface;
  38. use Symfony\Contracts\Translation\TranslatorInterface;
  39. use Twig\Environment;
  40. use Twilio\TwiML\TwiML;
  41. /**
  42.  * Class AbstractController
  43.  * @package App\Controller
  44.  */
  45. abstract class AbstractController extends SymfonyAbstractController
  46. {
  47.     use CustomServiceSubscriberTrait {
  48.         CustomServiceSubscriberTrait::getSubscribedServices as resolveSubscribedServices;
  49.     }
  50.     /**
  51.      * When working with a request, will do the work necessary to process the incoming form data and validate the form.
  52.      * Returns whether the form is properly submitted and if it is valid.
  53.      *
  54.      * @param string|array<string> $attributes
  55.      * @return bool
  56.      */
  57.     protected function maybeGranted($attributes): bool
  58.     {
  59.         return $this->container->get(AuthorizationTester::class)->maybeGranted($attributes);
  60.     }
  61.     /**
  62.      * @param string|array<string> $attributes
  63.      * @param string $message
  64.      * @return void
  65.      */
  66.     protected function denyAccessUnlessMaybeGranted($attributesstring $message 'Access Denied.'): void
  67.     {
  68.         if (!$this->maybeGranted($attributes)) {
  69.             $exception $this->createAccessDeniedException($message);
  70.             $exception->setAttributes($attributes);
  71.             throw $exception;
  72.         }
  73.     }
  74.     /**
  75.      * @param FormInterface $form
  76.      * @param Request|null $request
  77.      * @return bool
  78.      */
  79.     protected function handleForm(
  80.         FormInterface $form,
  81.         ?Request $request null
  82.     ): bool {
  83.         $form->handleRequest($request ?? $this->getRequest());
  84.         return ($form->isSubmitted() && $form->isValid());
  85.     }
  86.     /**
  87.      * When working with raw form data (not in a request), will do the work of processing the form against that data.
  88.      *
  89.      * @param FormInterface $form
  90.      * @param array $data
  91.      * @return bool
  92.      */
  93.     protected function submitForm(
  94.         FormInterface $form,
  95.         array $data = []
  96.     ): bool {
  97.         $form->submit($data);
  98.         return ($form->isSubmitted() && $form->isValid());
  99.     }
  100.     /**
  101.      * Determines whether the request is an AJAX request based on headers.
  102.      *
  103.      * @param Request|null $request
  104.      * @return bool
  105.      */
  106.     protected function isAjax(?Request $request null): bool
  107.     {
  108.         return ($request ?? $this->getRequest())->isXmlHttpRequest();
  109.     }
  110.     /**
  111.      * @param Request|null $request
  112.      * @return void
  113.      */
  114.     protected function enforceAjax(?Request $request null): void
  115.     {
  116.         if (!$this->isAjax($request)) {
  117.             throw $this->createNotFoundException();
  118.         }
  119.     }
  120.     /**
  121.      * @param FormInterface $form
  122.      * @param Request|null $request
  123.      * @return bool
  124.      */
  125.     protected function handleSearch(
  126.         FormInterface $form,
  127.         ?Request $request null
  128.     ): bool {
  129.         if (!$request) {
  130.             $request $this->getRequest();
  131.         }
  132.         $data array_filter(
  133.             ($form->getName())
  134.                 ? $request->query->get(
  135.                 $form->getName(),
  136.                 []
  137.             )
  138.                 : $request->query->all()
  139.         );
  140.         if ($data) {
  141.             $form->submit(
  142.                 $data,
  143.                 false
  144.             );
  145.         }
  146.         return ($form->isSubmitted() && $form->isValid());
  147.     }
  148.     /**
  149.      * @return LoggingService|object
  150.      */
  151.     protected function getLoggingService(): LoggingService
  152.     {
  153.         return $this->get(__METHOD__);
  154.     }
  155.     /**
  156.      * @return LocaleManager|object
  157.      */
  158.     protected function getLocaleManager(): LocaleManager
  159.     {
  160.         return $this->get(__METHOD__);
  161.     }
  162.     /**
  163.      * @return SessionInterface|object
  164.      */
  165.     protected function getSession(): SessionInterface
  166.     {
  167.         return $this->get(__METHOD__);
  168.     }
  169.     /**
  170.      * @return Request
  171.      */
  172.     public function getRequest(): Request
  173.     {
  174.         return $this->getRequestStack()->getCurrentRequest();
  175.     }
  176.     /**
  177.      * @return RequestStack|object
  178.      */
  179.     protected function getRequestStack(): RequestStack
  180.     {
  181.         return $this->get(RequestStack::class);
  182.     }
  183.     /**
  184.      * @return EntityManager|object
  185.      */
  186.     protected function getEntityManager(): EntityManager
  187.     {
  188.         // TODO: need to figure out how to get this into the doctrine registry...
  189.         return $this->get(EntityManager::class);
  190.     }
  191.     /**
  192.      * @param object|string $class
  193.      * @return EntityRepository
  194.      */
  195.     protected function getRepository($class): EntityRepository
  196.     {
  197.         if (is_object($class)) {
  198.             $class get_class($class);
  199.         }
  200.         return $this->getEntityManager()->getRepository($class);
  201.     }
  202.     /**
  203.      * @return string
  204.      */
  205.     protected function getEnvironment(): string
  206.     {
  207.         return $this->getParameter('kernel.environment');
  208.     }
  209.     /**
  210.      * @return ContextManager|object
  211.      */
  212.     protected function getContextManager(): ContextManager
  213.     {
  214.         return $this->get(ContextManager::class);
  215.     }
  216.     /**
  217.      * @return GlobalContext
  218.      */
  219.     protected function getGlobalContext(): GlobalContext
  220.     {
  221.         return $this->getContextManager()->getGlobalContext();
  222.     }
  223.     /**
  224.      * @return Tenant|null
  225.      */
  226.     protected function getTenant(): ?Tenant
  227.     {
  228.         return $this->getGlobalContext()->getTenant();
  229.     }
  230.     /**
  231.      * @return Environment
  232.      */
  233.     protected function getTwig(): Environment
  234.     {
  235.         return $this->get(Environment::class);
  236.     }
  237.     /**
  238.      * @return FormFactoryInterface
  239.      */
  240.     protected function getFormFactory(): FormFactoryInterface
  241.     {
  242.         return $this->get(FormFactoryInterface::class);
  243.     }
  244.     /**
  245.      * @return RouterInterface
  246.      */
  247.     protected function getRouter(): RouterInterface
  248.     {
  249.         return $this->get(RouterInterface::class);
  250.     }
  251.     /**
  252.      * @return TranslatorInterface
  253.      */
  254.     protected function getTranslator(): TranslatorInterface
  255.     {
  256.         return $this->get(TranslatorInterface::class);
  257.     }
  258.     /**
  259.      * @param int $status
  260.      * @return Response
  261.      */
  262.     protected function resp(int $status Response::HTTP_OK): Response
  263.     {
  264.         return new Response($status);
  265.     }
  266.     /**
  267.      * @param array $parameters
  268.      * @param string|null $template
  269.      * @return DocHtmlView
  270.      */
  271.     protected function html(array $parameters = [], ?string $template null): DocHtmlView
  272.     {
  273.         return new DocHtmlView($parameters$template);
  274.     }
  275.     /**
  276.      * @param array $parameters
  277.      * @param string|null $template
  278.      * @return AjaxHtmlView
  279.      */
  280.     protected function ajax(array $parameters = [], ?string $template null): AjaxHtmlView
  281.     {
  282.         return new AjaxHtmlView($parameters$template);
  283.     }
  284.     /**
  285.      * @param TwiML $twiml
  286.      * @return TwimlView
  287.      */
  288.     protected function twiml(TwiML $twiml): TwimlView
  289.     {
  290.         return new TwimlView($twiml);
  291.     }
  292.     /**
  293.      * @param mixed $data
  294.      * @param int $status
  295.      * @param array $headers
  296.      * @return JsonView
  297.      */
  298.     protected function jsonView($dataint $status 200, array $headers = []): JsonView
  299.     {
  300.         $view = new JsonView($data);
  301.         $view->getResponse()->setStatusCode($status);
  302.         if ($headers) {
  303.             $view->getResponse()->headers->replace($headers);
  304.         }
  305.         return $view;
  306.     }
  307.     /**
  308.      * @param string $name
  309.      * @param mixed $data
  310.      * @param array $options
  311.      * @return FormBuilderInterface
  312.      */
  313.     public function createNamedBuilder(string $name$data null, array $options = []): FormBuilderInterface
  314.     {
  315.         return $this->getFormFactory()->createNamedBuilder($name ?? ''FormType::class, $data$options);
  316.     }
  317.     /**
  318.      * @param string|null $name
  319.      * @param mixed $type
  320.      * @param mixed $data
  321.      * @param array $options
  322.      * @return FormInterface
  323.      */
  324.     public function createNamed(?string $name$type$data null, array $options = []): FormInterface
  325.     {
  326.         return $this->getFormFactory()->createNamed($name$type$data$options);
  327.     }
  328.     /**
  329.      * @param RedirectResponse $redirect
  330.      * @param Request|null $request
  331.      * @return RedirectResponse
  332.      */
  333.     public function jumpOrRedirect(RedirectResponse $redirect, ?Request $request null): RedirectResponse
  334.     {
  335.         if ( ! $request) {
  336.             $request $this->getRequest();
  337.         }
  338.         if ($request->query->has('jump')) {
  339.             return new RedirectResponse($request->query->get('jump'));
  340.         }
  341.         return $redirect;
  342.     }
  343.     /**
  344.      * @param string $route
  345.      * @param array $parameters
  346.      * @param int $status
  347.      * @return RedirectResponse
  348.      */
  349.     public function jumpOrRedirectToRoute(string $route, array $parameters = [], int $status Response::HTTP_FOUND): RedirectResponse
  350.     {
  351.         return $this->jumpOrRedirect($this->redirectToRoute(
  352.             $route,
  353.             $parameters,
  354.             $status
  355.         ));
  356.     }
  357.     /**
  358.      * @param string $route
  359.      * @param array $parameters
  360.      * @return string
  361.      */
  362.     public function generateAbsoluteUrl(string $route, array $parameters = []): string
  363.     {
  364.         return $this->generateUrl($route$parametersUrlGeneratorInterface::ABSOLUTE_URL);
  365.     }
  366.     /**
  367.      * @param string $route
  368.      * @param array $parameters
  369.      * @return Request
  370.      */
  371.     public function subrequest(string $route, array $parameters = []): Request
  372.     {
  373.         $request Request::create($this->generateAbsoluteUrl($route$parameters));
  374.         $params $this->getRouter()->matchRequest($request);
  375.         $request->attributes->add($params);
  376.         unset($params['_route'], $params['_controller']);
  377.         $request->attributes->set('_route_params'$params);
  378.         return $request;
  379.     }
  380.     /**
  381.      * @return void
  382.      */
  383.     protected function disableProfiling(): void
  384.     {
  385.         if ($this->has('profiler')) {
  386.             $this->get('profiler')->disable();
  387.         }
  388.     }
  389.     /**
  390.      * @return void
  391.      */
  392.     protected function closeSession(): void
  393.     {
  394.         // speed some things up by closing the session
  395.         // symfony will block concurrency when a session is opened
  396.         // public-facing pages should not need to use a session
  397.         // so, closing it when needed should speed up the system a bit in certain places
  398.         $this->get('session.handler')->close();
  399.     }
  400.     /**
  401.      * @param string $name
  402.      * @return string
  403.      */
  404.     protected function locateResource(string $name): string
  405.     {
  406.         return $this->get('kernel')->locateResource($name);
  407.     }
  408.     /**
  409.      * {@inheritDoc}
  410.      */
  411.     protected function isGranted($attribute$subject null): bool
  412.     {
  413.         return parent::isGranted(
  414.             Permissions::attributesExpression($attribute),
  415.             $subject,
  416.         );
  417.     }
  418.     /**
  419.      * {@inheritDoc}
  420.      */
  421.     public static function getSubscribedServices(): array
  422.     {
  423.         return array_merge(
  424.             parent::getSubscribedServices(),
  425.             [
  426.                 'kernel' => '?kernel',
  427.                 'profiler' => '?profiler',
  428.                 'translator' => '?'.TranslatorInterface::class,
  429.                 'session.handler' => '?'.SessionHandlerInterface::class,
  430.             ],
  431.             // TODO: doing this to alias the core stuff being brought in, probably not needed in later versions
  432.             [
  433.                 RouterInterface::class => '?'.RouterInterface::class,
  434.                 RequestStack::class => '?'.RequestStack::class,
  435.                 HttpKernelInterface::class => '?'.HttpKernelInterface::class,
  436.                 SerializerInterface::class => '?'.SerializerInterface::class,
  437.                 SessionInterface::class => '?'.SessionInterface::class,
  438.                 AuthorizationCheckerInterface::class => '?'.AuthorizationCheckerInterface::class,
  439.                 Environment::class => '?'.Environment::class,
  440.                 ManagerRegistry::class => '?'.ManagerRegistry::class,
  441.                 FormFactoryInterface::class => '?'.FormFactoryInterface::class,
  442.                 TokenStorageInterface::class => '?'.TokenStorageInterface::class,
  443.                 CsrfTokenManagerInterface::class => '?'.CsrfTokenManagerInterface::class,
  444.                 ParameterBagInterface::class => '?'.ParameterBagInterface::class,
  445.                 TranslatorInterface::class => '?'.TranslatorInterface::class,
  446.             ],
  447.             // injecting things we use commonly
  448.             [
  449.                 EntityManager::class => EntityManager::class,
  450.                 ContextManager::class => ContextManager::class,
  451.                 LoggingService::class => LoggingService::class,
  452.                 AuthorizationTester::class => AuthorizationTester::class,
  453.             ],
  454.             // inject things found in the controllers methods
  455.             self::resolveSubscribedServices(),
  456.         );
  457.     }
  458. }