<?php
namespace Core\Controller\Traits;
use App\Entity\PageGeneral;
use Core\Entity\Configuration;
use Core\Entity\CookieConfiguration;
use Core\Entity\Design;
use Core\Entity\DesignThemeType;
use Core\Entity\HistoryMessageType;
use Core\Entity\Image;
use Core\Entity\Language;
use Core\Entity\Page;
use Core\Entity\Redirection;
use Core\Entity\RedirectionType;
use Core\Entity\Text;
use Core\Service\History\HistoryMessage;
use Core\Service\Session\Session;
use ReflectionClass;
use Shopping\Entity\Product;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\Constraints\DateTime;
use User\Entity\AuthorizationGroup;
use User\Entity\AuthorizationType;
use User\Entity\User;
use User\Entity\UserGroup;
use User\Service\UserManager;
trait BaseController
{
/**
* @var array - Tableau de variables utilisé pours les templates
*/
protected $vars = [];
/**
* @var Session - Gère l'enregistrement en Session (Session - Database - File) des données
*/
protected $session;
/**
* @var User - Utilisation courant
*/
protected $user;
/**
* @var array UserAuthorization - Authorization de l'utilisateur courant
*/
protected $user_authorizations;
/**
* Constructeur
*/
public function __construct(Session $session)
{
$this->session = $session;
}
/**
* Initialisation du controller
*/
public function initializeController(Request $request)
{
// Désactivation des logs de Doctrine
if ($_ENV['APP_LOG_DOCTRINE'] == 0) {
$this->getDoctrine()->getEntityManager()->getConnection()->getConfiguration()->setSQLLogger(null);
}
// Configuration générale de l'application
$this->vars['configuration'] = $this->getDoctrine()->getRepository(Configuration::class)->find(1);
// Attributions des différentes langues de l'application
$request = $this->setLanguages($request);
// Initialisation de la configuration utilisateur
$this->setUserSettings($request);
// Définitions du controller à utiliser
$this->vars['controller'] = $this->findRoute($request);
return $request;
}
/**
* Initialisation des variables de controller
*/
public function initializeVariableController(Request $request)
{
$this->vars = $request->attributes->get('vars');
}
public function resetPageController(Request $request)
{
if ($request->attributes->get('vars') != null)
$this->vars['pages'] = $request->attributes->get('vars')['pages'];
}
/**
* Initialisation des paramètres de langues
*/
public function setLanguages(Request $request)
{
$use_language = 'fr'; // Langue à utiliser par défault
$locale = 'fr'; // locale à utiliser per défault
// On récupère les différentes langues actives
$this->vars['languages']['list'] = $this->getDoctrine()->getRepository(Language::class)->findBy([
'is_enabled' => 1
]);
// Définition des URLs
$this->vars['uri']['host'] = $host = $request->headers->get('host');
$this->vars['uri']['protocol'] = 'http://';
if ($_ENV['APP_SSL'] == 1) {
$this->vars['uri']['protocol'] = 'https://';
}
$this->vars['uri']['relative'] = $uri = $request->attributes->get('controller');
$this->vars['uri']['full'] = $this->vars['uri']['protocol'] . $host . $request->getRequestUri();
// Gestion des paramètres
$parameters = explode('?', $request->getRequestUri());
$parametersArray = [];
if (count($parameters) > 1) {
$results = explode('&', $parameters[1]);
foreach ($results as $result) {
$object = explode('=', $result);
if (count($object) > 1) {
$parametersArray[$object[0]] = trim(urldecode($object[1]));
}
}
}
$this->vars['uri']['parameters'] = $parametersArray;
// Définition de la langue via le navigateur || langue par default
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$use_language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}
// Surcharge - Langue via la session
if ($this->session->has('_locale')) {
$use_language = $this->session->get('_locale');
}
// Surcharge - Langue via l'URL
if (preg_match('#^/[a-z]{2}/#', '/' . $uri, $matches) || preg_match('#^/[a-z]{2}$#', '/' . $uri, $matches)) {
$use_language = trim($matches[0], '/');
}
// Langues disponibles via le code ISO
foreach ($this->vars['languages']['list'] as $language) {
if ($language->getIsoCode() == $use_language) {
$locale = $use_language;
break;
}
}
// Sauvegarde des variables de langues
$this->session->set('_locale', $locale); // Sauvegarde en session
$request->setLocale($locale); // Sauvegarde en request
$this->vars['languages']['locale'] = $request->getLocale(); // Sauvegarde en variable
return $request;
}
/**
* Gestion de la configuration utilisateur
*/
public function setUserSettings(Request $request)
{
// Manager d'utilisateur
$entity = new UserManager($this->getDoctrine());
// Création d'un utilisateur guest
$this->user = new User();
// Récupération de l'utilisateur en session
$session_content = $this->session->get('user');
// Session en mémoire
if ($session_content != null) {
// Format du contenu
$this->user->unserialize($session_content);
// Vérification en base de donnée de l'existance de l'utilisateur
$this->user = $this->getDoctrine()->getRepository(User::class)->findByUser($this->user);
}
// Sinon création d'un visiteur si echec de récupération de l'utilisateur
if ($session_content == null || $this->user == null || !$entity->checkUser($this->user)) {
$this->user = $entity->createUser();
}
// Autorisations de l'utilisateurs par groupe
foreach ($this->user->getUserGroups()->toArray() as $group) {
// On récupère les authorizations du groupe
$authorizations = $this->getDoctrine()->getRepository(AuthorizationGroup::class)->findBy([
'team' => $group->getId()
]);
// Attribution des authorisations par clés
foreach ($authorizations as $authorization) {
$this->user_authorizations[$authorization->getAuthorization()->getDevKey()][] = $authorization;
}
if ($this->checkAuthorization($request, [
'authorization' => 'administration',
'type' => 0
])) {
$this->vars['account']['admin'] = true;
}
}
// Définitions de la variable utilisateur
$this->vars['account']['user'] = $this->user;
}
/**
* Vérification de l'autorisation de connexion à l'application
*/
public function checkAuthorization(Request $request, $params = null)
{
// Connexion autorisé par compte
if ($params != null && array_key_exists('authorization', $params) && array_key_exists('type', $params)) {
// Abscence de la clé d'authorization des authorizations
if (!is_array($this->user_authorizations) || !array_key_exists($params['authorization'], $this->user_authorizations)) {
// TODO Supprimer cette condition pour accroite la sécurité lors de la création de groupe
// Vérification absente - Accès authorisé
return false;
}
// On récupère la clé d'authorization à vérifier
$groups = $this->user_authorizations[$params['authorization']];
// Vérification des authorization pour cette clé
foreach ($groups as $group) {
if (($params['type'] == AuthorizationType::VIEW && $group->getEnableView()) ||
($params['type'] == AuthorizationType::EDIT && $group->getEnableEdit()) ||
($params['type'] == AuthorizationType::NEW && $group->getEnableAdd()) ||
($params['type'] == AuthorizationType::FORM && ($group->getEnableAdd() || $group->getEnableEdit())) ||
($params['type'] == AuthorizationType::REMOVE && $group->getEnableDelete())) {
// Vérification réussie - Accès authorisé
return true;
}
}
}
// Accès refusé
return false;
}
/**
* Redirige vers le controller adéquate
*/
public function findRoute(Request $request)
{
$this->vars['redirection']['isRedirection'] = false;
// Redirection s'il y a un '/' en fin d'URL et ce n'est pas la page d'accueil
if (strlen($this->vars['uri']['relative']) > 4 && substr($this->vars['uri']['relative'], -1) == '/') {
$this->vars['redirection']['url'] = $this->vars['uri']['protocol'] . $this->vars['uri']['host'] . '/' . $this->vars['languages']['locale'] . '/' . rtrim($this->vars['uri']['relative'], '/');
$this->vars['redirection']['status'] = 301;
$this->vars['redirection']['isRedirection'] = true;
return false;
}
// Redirection s'il y a pas de '/' en fin d'URL et c'est la page d'accueil avec une langue
if (count($this->vars['languages']['list']) > 1 && strlen($this->vars['uri']['relative']) == 2) {
$this->vars['redirection']['url'] = $this->vars['uri']['protocol'] . $this->vars['uri']['host'] . '/' . $this->vars['languages']['locale'] . '/';
$this->vars['redirection']['status'] = 301;
$this->vars['redirection']['isRedirection'] = true;
return false;
}
// URL de redirection depuis l'administration
$redirection = $this->findRedirection();
if ($redirection['find']) {
$this->vars['redirection']['url'] = $redirection['uri'];
$this->vars['redirection']['status'] = $redirection['code'];
$this->vars['redirection']['isRedirection'] = true;
return false;
}
// Redirection s'il manque la langue dans l'URL et que plusieurs langues sont disponibles
if (count($this->vars['languages']['list']) > 1) {
if (!preg_match('#^/[a-z]{2}/#', '/' . $this->vars['uri']['relative'], $matches) && !preg_match('#^/[a-z]{2}$#', '/' . $this->vars['uri']['relative'], $matches)) {
$this->vars['redirection']['url'] = $this->vars['uri']['protocol'] . $this->vars['uri']['host'] . '/' . $this->vars['languages']['locale'] . '/' . $this->vars['uri']['relative'];
$this->vars['redirection']['status'] = 301;
$this->vars['redirection']['isRedirection'] = true;
return false;
}
}
// Récupération de la liste des pages
$object = $this->setPages();
// Attribution de l'URL spécifique à chaque page avec la langue utilisée
$router = [];
foreach ($object['pages'] as $key => $page) {
if ($page['page'] != null) {
$element = [
'core_page' => $page['core_page'],
'page' => $page['page'],
'controller_uri' => $page['page']->translate($this->vars['languages']['locale'])->getUri(),
'controller_module' => $object['pages_list'][$key]->getControllerModule(),
'controller_entity' => $object['pages_list'][$key]->getControllerEntity(),
'controller_action' => $object['pages_list'][$key]->getControllerPage(),
'controller' => $object['pages_list'][$key]->getController(),
];
$element['controller_namespace'] = $element['controller_module'] . '\Controller\\' . $element['controller'];
if ($element['controller_namespace'] == 'PageDefault') {
$element['controller_namespace'] = 'App\Controller\\' . $element['controller'];
}
$router[] = $element;
} else {
throw new \Exception('La configuration de la page ' . $object['pages_list'][$key]->getControllerEntity() . ' n\'a pas été générée');
}
}
// dump('allo');
// dump($router);
// die;
// Parcours des différentes routes pour trouver une correspondance
foreach ($router as $key => $route) {
// Retourne la chaine sans les parametres '?parameter=value
$controller_uri = strstr($route['controller_uri'], '?', true);
if (!$controller_uri) {
$controller_uri = $route['controller_uri'];
}
// Sauvegarde du controller à utiliser si la route match avec la langue
if (preg_match('#^\/[a-z]{2}' . $controller_uri . '$#', '/' . $this->vars['uri']['relative'])) {
$this->vars['pages']['active'] = $route['page']; // Mémorisation de la page active
return $route;
}
// Sauvegarde du controller à utiliser si la route match sans la langue
if (preg_match('#^' . $controller_uri . '$#', '/' . $this->vars['uri']['relative'])) {
$this->vars['pages']['active'] = $route['page']; // Mémorisation de la page active
return $route;
}
}
// Recherche d'une URL personnalisée
return null;
}
/**
* Recherche d'une URL de redirection depuis la table "Redirection"
*/
private function findRedirection()
{
$redirection_find = false;
$redirection_code = -1;
$redirection_uri = '';
// Recherche d'une correspondance dans le tableau des redirections
$this->vars['uri']['redirection'] = $redirection = $this->getDoctrine()->getRepository(Redirection::class)->findOneBy([
'uri_from' => '/' . $this->vars['uri']['relative']
]);
if ($redirection != null) {
// Redirection détectée
$redirection_find = true;
// URL de redirection
$redirection_uri = $this->vars['redirection']->getUriTo();
// Attribution du type de redirection
switch ($redirection->getType()) {
case RedirectionType::TEMPORARY_REDIRECT:
$redirection_code = 302;
break;
case RedirectionType::PERMANENT_REDIRECT:
$redirection_code = 301;
break;
case RedirectionType::NO_REDIRECTION:
default:
$redirection_code = 404;
$redirection_uri = $this->vars['pages']['error404']->translate($this->vars['locale']);
break;
}
}
return [
'find' => $redirection_find,
'code' => $redirection_code,
'uri' => $redirection_uri
];
}
/**
* Attribution de la liste des pages disponibles
*/
public function setPages()
{
// On récupère la liste des pages actives accessibles
$pages_list = $this->getDoctrine()->getRepository(Page::class)->findBy([
'is_enabled' => 1
]);
// On récupère la configuration spécifique de chaque page
$pages = [];
foreach ($pages_list as $page) {
$class = $page->getControllerModule() . '\Entity\\' . $page->getControllerEntity();
if ($page->getControllerEntity() == 'PageDefault') {
$class = 'App\Entity\\' . $page->getControllerEntity();
}
$pages[] = [
'core_page' => $page,
'page' => $this->getDoctrine()->getRepository($class)->find($page->getControllerId())
];
}
// Passage des pages à la vue
foreach ($pages as $key => $page) {
$this->vars['pages']['list'][$pages_list[$key]->getControllerPage()] = $page['page'];
$this->vars['pages']['core'][$pages_list[$key]->getControllerPage()] = $page['core_page'];
}
return [
'pages_list' => $pages_list, // Liste de toutes les pages actives 'Core/Pages'
'pages' => $pages // Liste de toutes les pages actives 'App/PageHome, App/PageContact, ..'
];
}
/**
* Gestion de la configuration de la page active
*/
public function setPageSettings(Request $request, $page_name)
{
$page = $this->vars['pages']['active'];
$general = $this->vars['pages']['list']['general'];
// Liste des URL par langue
$uris = [];
foreach ($this->vars['languages']['list'] as $language) {
$uris = array_merge($uris, [
$language->getIsoCode() => '/' . $language->getIsoCode() . $page->translate($language->getIsoCode())->getUri()
]);
}
$this->vars['uri']['alternate'] = $uris;
// Paramètre spécifique à la page
$seo_title = $page->getSeoTitle();
$seo_description = $page->getSeoDescription();
$seo_keywords = $page->getSeoKeywords();
$sn_title = $page->getSnTitle();
$sn_description = $page->getSnDescription();
$sn_image_twitter = $page->getTwitter();
$sn_image_social_networks = $page->getFacebook();
// Recoupement avec les paramètres par defaut de l'application
if ($seo_title == null) $seo_title = $general->getSeoTitle();
if ($seo_description == null) $seo_description = $general->getSeoDescription();
if ($seo_keywords == null) $seo_keywords = $general->getSeoKeywords();
if ($sn_title == null) $sn_title = $general->getSnTitle();
if ($sn_description == null) $sn_description = $general->getSnDescription();
if ($sn_image_twitter == null) $sn_image_twitter = $general->getTwitter();
if ($sn_image_social_networks == null) $sn_image_social_networks = $general->getFacebook();
// Restitution des paramètres à la vue
$this->vars['seo']['title'] = $seo_title;
$this->vars['seo']['description'] = $seo_description;
$this->vars['seo']['keywords'] = $seo_keywords;
$this->vars['sn']['title'] = $sn_title;
$this->vars['sn']['description'] = $sn_description;
$this->vars['sn']['image_twitter'] = $sn_image_twitter;
$this->vars['sn']['image_social_networks'] = $sn_image_social_networks;
$this->vars['website']['domain'] = $this->vars['configuration']->getDomain();
$this->vars['website']['name'] = $this->vars['configuration']->getSitename();
}
/**
* Retourne le template adequate
*/
public function generateTemplate($path, $vars = [], $json = false)
{
// Ajoute l'extension si elle n'existe pas
if (!strpos($path, '.html.twig')) {
$path = $path . '.html.twig';
}
if (!$json) {
// On récupère le chemin complet du potentielle template
$file = $this->getParameter('file_templates') . str_replace('@', '', $path);
// Si le fichier de redéfinition n'existe pas "list" / "form" / "view" utilise le fichier par default (Ex: entity_list.html.twig)
if (!file_exists($file)) {
$theme = '@core/admin';
if (preg_match("#(.)+_list.html.twig#", $path)) {
$path = $theme . '/entity_list.html.twig';
} else if (preg_match("#(.)+_form.html.twig#", $path)) {
$path = $theme . '/entity_form.html.twig';
} else if (preg_match("#(.)+_view.html.twig#", $path)) {
$path = $theme . '/entity_view.html.twig';
}
}
// Retourne le template généré
return $this->render($path, array_merge($this->vars, $vars));
} else {
// Retourne le template pouvant être rendu en json
return $this->renderView($path, array_merge($this->vars, $vars));
}
}
/**
* Page d'exception - Erreur 404 - Ressource introuvable
*/
public function redirectNotFoundException($request)
{
// Définition de la page active
$this->vars['pages']['active'] = $this->vars['pages']['list']['page_default_5fc8fb6f41b02'];
// Configuration de la page
$this->setPageSettings($request, 'page_default_5fc8fb6f41b02');
$template = $this->vars['pages']['core']['page_default_5fc8fb6f41b02']->getTemplate();
$response = $this->generateTemplate('@' . $template->getModule() . '/' . $template->getName());
$response->setStatusCode(Response::HTTP_NOT_FOUND);
return $response;
}
/**
* Page d'exception - Erreur 403 - Accès refusé
*/
public function redirectConnexionRequiredException($request)
{
// Définition de la page active
$this->vars['pages']['active'] = $this->vars['pages']['list']['page_default_5fc8fcc13ab1b'];
// Configuration de la page
$this->setPageSettings($request, 'page_default_5fc8fcc13ab1b');
$template = $this->vars['pages']['core']['page_default_5fc8fcc13ab1b']->getTemplate();
$response = $this->generateTemplate('@' . $template->getModule() . '/' . $template->getName());
$response->setStatusCode(Response::HTTP_FORBIDDEN);
return $response;
}
/**
* Page d'exception - Erreur quelconque
*/
public function redirectUnknownException($request)
{
// Définition de la page active
$this->vars['pages']['active'] = $this->vars['pages']['list']['page_default_5fc8fda129a38'];
// Configuration de la page
$this->setPageSettings($request, 'page_default_5fc8fda129a38');
$template = $this->vars['pages']['core']['page_default_5fc8fda129a38']->getTemplate();
$response = $this->generateTemplate('@' . $template->getModule() . '/' . $template->getName());
$response->setStatusCode(Response::HTTP_NOT_FOUND);
return $response;
}
/**
* Permet de recupérer des morceaux de l'URL de la $request
*/
public function getCurrentPageSlug($request, $position = 1)
{
// Récupération du slug
$slug = trim($request->getRequestUri(), '/');
if (preg_match('#^(.){2}/(.)+$#', $slug, $matches)) {
$slug = substr($slug, 3);
}
$slug = explode('/', $slug)[$position];
$result = strstr($slug, '?', true);
if ($result != false) {
$slug = $result;
}
return $slug;
}
/**
* Retourne null ou un object de la $class ayant pour URL le $slug
*/
public function getEntityBySlug($slug, $class)
{
preg_match('/^([0-9]+)-(.)+/', $slug, $matches, PREG_OFFSET_CAPTURE);
if (count($matches) < 1) {
return null;
}
$object = $this->getDoctrine()->getRepository($class)->find($matches[1][0]);
if ($object == null) {
return null;
}
if ($object->getSlug() != '/' . $slug) {
return null;
}
return $object;
}
public function getEntitiesRandom($class, $limit = 8)
{
$items = $this->getDoctrine()->getRepository($class)
->findEntityActive();
shuffle($items);
$results = [];
for ($i = 0; $i < $limit; $i++) {
if(array_key_exists($i, $items)) {
$results[] = $this->getDoctrine()->getRepository($class)
->find($items[$i]['id']);
}
}
if ($class == Product::class) {
$list = [];
foreach ($results as $object) {
$item = new \Shopping\Service\Product\Product($this->getDoctrine(), $this->vars['account']['user']);
$item->createProduct($object->getId());
$list[] = $item;
}
$results = $list;
}
return $results;
}
public function getEntitiesPerPagination($class, $pagination = 1, $filters = [], $productPaginationNumber = 50, $useProductService = true, $constraintes = [])
{
$results = [];
// Recherche des produits de la catégorie trouvée
$results['pagination']['product_per_page'] = $productPaginationNumber;
$results['pagination']['current_page'] = $pagination;
$reflection = new $class();
$reflects = (new ReflectionClass($reflection))->getProperties();
$properties = [];
foreach ($reflects as $item){
$properties[] = (string)$item->getName();
}
$results['list'] = $this->getDoctrine()->getRepository($class)
->findEntityPerPagination($pagination, $productPaginationNumber, $filters, $constraintes, $properties);
$results['count'] = $this->getDoctrine()->getRepository($class)
->countEntityPerPagination($constraintes, $properties);
$results['pagination']['count'] = ceil($results['count'] / $productPaginationNumber);
$start = $pagination * $productPaginationNumber - $productPaginationNumber;
if ($start <= 0) {
$start = 0;
}
$end = $start + $productPaginationNumber;
if ($end > $results['count']) {
$end = $results['count'];
}
$results['pagination']['start'] = $start + 1;
$results['pagination']['end'] = $end;
$results['pagination']['total'] = $results['count'];
if ($class == Product::class && $useProductService) {
$list = [];
foreach ($results['list'] as $object) {
$item = new \Shopping\Service\Product\Product($this->getDoctrine(), $this->vars['account']['user']);
$item->createProduct($object->getId());
$list[] = $item;
}
$results['list'] = $list;
}
return $results;
}
public function getProductsListPagination($categories_list, $pagination, $filters, $products_per_pagination, $contraintes)
{
$results = [];
$products = $this->getDoctrine()->getRepository(Product::class)->findProductsChildrenPerPagination($filters, [
'is_enabled' => true,
'categories' => $categories_list,
]);
foreach ($products as $product) {
if (!in_array($product->getParent()->getId(), $results)) {
$results[] = $product->getParent()->getId();
}
}
$products = $this->getDoctrine()->getRepository(Product::class)->findProductsParentPerPagination($filters, [
'is_enabled' => true,
'categories' => $categories_list,
]);
foreach ($products as $product) {
if (!in_array($product->getId(), $results)) {
$results[] = $product->getId();
}
}
$start = $pagination * $products_per_pagination - $products_per_pagination;
$end = $pagination * $products_per_pagination;
$product_per_page = $products_per_pagination;
$current_page = $pagination;
if (count($results) > 0) {
$count = ceil(count($results) / $products_per_pagination);
} else {
$count = 1;
}
if ($end > $count * $products_per_pagination) {
$end = $count;
}
$list = [];
foreach ($results as $key => $object) {
if ($start <= $key && $key < $end) {
$product = $this->getDoctrine()->getRepository(Product::class)->find($object);
$item = new \Shopping\Service\Product\Product($this->getDoctrine(), $this->vars['account']['user']);
$item->createProduct($product->getId());
$list[] = $item;
}
}
$results['list'] = $list;
$results['pagination']['current_page'] = $current_page;
$results['pagination']['product_per_page'] = $product_per_page;
$results['pagination']['start'] = $start;
$results['pagination']['end'] = $end;
$results['pagination']['count'] = $count;
$results['pagination']['total'] = count($results);
$this->vars['products'] = $results;
return $results;
}
}