<?php
namespace WebBundle\Controller;
use Exception;
use FlexApp\Service\ParametersGenerator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManager;
use WebBundle\Helper\App;
use WebBundle\Helper\LocaleHelper;
use WebBundle\Helper\RequestHelper;
/*
* class: ExtendedController
* -----------------------------------------------------
* Класс для наследования, в нем реализованы базовые общие методы
* @package WebBundle\Controller
*/
class ExtendedController extends AbstractController
{
/** @var $oSession */
private $oSession;
/** @var $oRequest */
private $oRequest;
/** текущая локаль юзера */
private $sLocale;
/**
* ExtendedController constructor.
* @throws Exception
*/
public function __construct()
{
if (RequestHelper::isAjax()) {
if (!$this->isValidToken()) {
// тут должен быть abort операции
return $this->error('Token не валиден');
}
}
return true;
}
public function render(string $view, array $parameters = [], Response $response = null): Response
{
$response = parent::render($view, $parameters, $response); // TODO: Change the autogenerated stub
$response->headers->set('Cache-Control','no-store');
return $response;
}
/**
* Отдача контента
* @param null $val
* @param bool $jsonOnly
* @return null|JsonResponse
*/
protected function ok($val = null, $jsonOnly = false)
{
if (RequestHelper::isAjax() or $jsonOnly) {
$res['content'] = $val;
$res['status'] = 'success';
$res = new JsonResponse($res);
} else {
if ($val instanceof Response) {
$res = $val;
} else {
if (is_array($val)) {
$res = new JsonResponse($val);
} else {
$res = new Response($val);
}
}
}
return $res;
}
/**
* Отдача контента ОШИБКИ
* @param null $val
* @param int|string $code
* @param bool $jsonOnly
* @return null|JsonResponse
*/
protected function error($val = null, $code = 500, $jsonOnly = false)
{
if (RequestHelper::isAjax() or $jsonOnly) {
$res['content'] = $val;
$res['status'] = 'error';
$res = new JsonResponse($res);
} else {
switch ($code) {
case 403:
throw $this->createAccessDeniedException($val);
case 404:
throw $this->createNotFoundException($val);
default:
$res = $val;
}
}
return $res;
}
/**
* Валидация по CSRF токену
* @param null $xCSRFToken
* @param null $xCSRFTokenKey
* @return bool
* @throws Exception
*/
public function isValidToken($xCSRFToken = null, $xCSRFTokenKey = null): bool
{
if (!is_object($this->container)) {
return true;//TODO Возможно стоит проверять валидность токена не в конструкторе контроллера, а в лиссенере по событию kernel.request: https://symfony.com/doc/current/reference/events.html#kernel-request
// throw new \Exception('$this->container не является объектом.');
}
/** @var CsrfTokenManager $csrfManager */
$csrfManager = $this->get('security.csrf.token_manager');
$xCSRFToken = $xCSRFToken ? $xCSRFToken : RequestHelper::getToken();
$xCSRFTokenKey = $xCSRFTokenKey ? $xCSRFTokenKey : $this->oSession()->getId();
if (!$xCSRFToken) {
//static::abort('Токен не найден', 403);
return false;
}
if (!$xCSRFTokenKey) {
//static::abort('ID сессии не найден', 403);
return false;
}
$oCsrfToken = new CsrfToken($xCSRFTokenKey, $xCSRFToken);
if (!$csrfManager->isTokenValid($oCsrfToken)) {
//static::abort('Токен не валиден', 403);
return false;
}
return true;
}
/**
* Текущая локаль юзера
* @param bool $full
* @return string
*/
public function getCurLocale($full = false)
{
if (!$this->sLocale) {
$this->sLocale = $this->oRequest()->getLocale() ? $this->oRequest()->getLocale() : LocaleHelper::getDefault();
}
return $full ? $this->sLocale : explode('-', $this->sLocale)[0];
}
/**
* @return Request
*/
protected function oRequest()
{
if (!$this->oRequest) {
$this->oRequest = RequestHelper::syRequest();
}
return $this->oRequest;
}
/**
* @return Session
*/
protected function oSession()
{
if (!$this->oSession) {
$this->oSession = $this->get('session');
}
return $this->oSession;
}
// public function get($id)
// {
// // алтернативная реализация получения контейнера, используется прия AJAx запросах
// if (!$this->container) {
// $this->setContainer(WebBundle::getContainer());
// }
//
// return $this->container->get($id);
// }
/**
* translator
* @param $val
* @param array $parameters
* @param null $domain
* @param null $locale
* @return string
*/
public function translate($val, $locale = null, array $parameters = [], $domain = null): string
{
$oTtranslator = $this->get('translator');
return $oTtranslator->trans($val, $parameters, $domain, $locale);
}
/**
* Generates a URL from the given parameters.
* @param string $route The name of the route
* @param mixed $parameters An array of parameters
* @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
* @return string The generated URL
* @see UrlGeneratorInterface
*/
// public function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string
// {
// return urldecode($this->container->get('router')->generate($route, $parameters, $referenceType));
// }
/**
* Добавляет к initialState общие данные по header и footer блокам
* @param string $template
* @param array $params
* @return Response
* @throws Exception
*/
public function renderReact(string $template, $params = []): Response
{
/** @var ParametersGenerator $parametersGenerator */
$parametersGenerator = App::getContainer()->get(ParametersGenerator::class);
$params = $parametersGenerator->generate($params);
$oLeftService = App::getContainer()->get('app.service.leftmenu');
$params['initialState']['liteMenu'] = $oLeftService->getDataMenuLite();
return $this->render($template, $params);
}
}