<?php
namespace App\Service;
use App\Entity\CfgBlocs;
use App\Entity\CfgClient;
use App\Entity\CfgClientAddresses;
use App\Entity\CfgConstants;
use App\Entity\CfgLangues;
use App\Entity\CfgSite;
use App\Entity\CfgTranslations;
use App\Form\RappelsType;
use App\Kernel;
use App\Modules\Pages\Entity\Pages;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Twig\Environment;
class BootService extends AbstractController
{
public EntityManagerInterface $entityManager;
public $container;
public FormFactoryInterface $formFactory;
public RouterInterface $router;
public Environment $twig;
private static array $params = [
"modules"=>[],
"lang_dir"=>"/languages/"
];
public static array $ressources = [];
protected array $css = [];
protected array $js = [];
public static array $bc = [];
public function __construct(Kernel $kernel, FormFactoryInterface $formFactory, EntityManagerInterface $entityManager, Environment $twig, RouterInterface $router)
{
/*if(defined("API_IS_ACTIVE") && API_IS_ACTIVE === true){
$response = new Response();
$response->setContent('Accès non autorisé');
$response->setStatusCode(401);
$response->send();
}*/
$this->formFactory = $formFactory;
$this->container = $kernel->getContainer();
$this->twig = $twig;
$this->entityManager = $entityManager;
$this->router = $router;
$informations=$this->getConfigurationSite();
if($informations->site instanceof CfgSite && PROTOCOL."://".$_SERVER['HTTP_HOST']<>$informations->site->getUrl() && LOCALHOST === false){
header("Status: 301 Moved Permanently", false, 301);
header("location:".$informations->site->getUrl());
}
if($this->getPageTemporaire($informations->site) === false){
echo $this->twig->render('templates/offline/index.html.twig', [
"site_offline"=>$informations
]);exit;
}
$this->setContentCfgConstants();
$this->setContentCfgTranslations();
$this->loadTwigVars();
$this->setContentLangues();
$this->getParamMod();
if(defined('TARTEAUCITRON_ACTIVE') && TARTEAUCITRON_ACTIVE===true && TARTEAUCITRON_SERVICES['recaptcha']===true){
$this->AddJS("https://www.google.com/recaptcha/api.js");
}
if(defined("TARTEAUCITRON_ACTIVE") && TARTEAUCITRON_ACTIVE===true){
$this->AddJS("/lib/tarteaucitron.js-1.9.0/tarteaucitron.js");
}
$this->loadTwigVars("scripts");
$this->loadTwigVars("styles");
}
public function getPageTemporaire(CfgSite $cfgSite):bool
{
if(str_contains($cfgSite->getIpsAuth(), $_SERVER["REMOTE_ADDR"])){
return true;
}
if($cfgSite->isIsActive() === true){
return true;
}
return false;
}
public static function getParamMod()
{
$containerBuilder = new ContainerBuilder();
$containerBuilder->register('boot', 'App\Service\BootService');
}
public static function returnMessage(array|string $data,int $status=200,bool $errorCode=true):array
{
if($errorCode === true){
return [
"status"=>$status,
"data"=>[
"error"=>$data
]
];
}
return [
"status"=>$status,
"data"=>$data
];
}
public function getRessourceCoreTwig(string $ressource, array $params=[]):string
{
if($ressource === "content_all"){
if(CONTROLEUR_DEFAUT === "pages"){
return $this->forward("App\Modules\Pages\Controller\PagesController::indexPagesRoot")->getContent();
}
}
return $this->renderView("/templates/core/".$ressource.".html.twig", $params);
}
public static function getParamsRoot(string $hook, string $sshook=null):string
{
if($sshook !== null){
return "src/Modules/".ucfirst($hook)."/Hooks/".ucfirst($sshook)."/";
}
return "src/Modules/".ucfirst($hook)."/Templates/";
}
/*public static function getParamsEntity(string $module=null, string $hook=null):string
{
if($hook !== null){
return "App\Modules\\".ucfirst($module)."\\Hooks\\".ucfirst($hook)."\\Entity\\";
} elseif($module !== null){
return "App\Modules\\".ucfirst($module)."\\Entity\\";
}
return "App\Entity\\";
}*/
public function getConfigurationSite():object
{
$data = (object)[
"site"=>[
"fetch"=>$this->entityManager->getRepository(CfgSite::class)->find(1),
"instance"=>CfgSite::class
],
"client"=>[
"fetch"=>$this->entityManager->getRepository(CfgClient::class)->find(1),
"instance"=>CfgClient::class
],
"addresses"=>[
"fetch"=>$this->entityManager->getRepository(CfgClientAddresses::class)->findBy(["isActive"=>true]),
]
];
foreach($data as $config=>$params){
if(isset($params["instance"]) && !$params["fetch"] instanceof $params["instance"]){
echo "<h1>Une erreur est parvenue lors de la configuration du {$config}.</h1>";exit;
}
$data->{$config} = $params["fetch"];
}
return $data;
}
public function loadTwigVars(string $reloadRessource = null):void
{
switch($reloadRessource){
case "styles":
$this->assign($reloadRessource, $this->css);
break;
case "scripts":
$this->assign($reloadRessource, $this->js);
break;
default:
if(!defined("LANGUE_DEFAULT")){
$this->assign('langue', "fr");
} else{
$this->assign('langue', LANGUE_DEFAUT);
}
$this->assign('styles', $this->css);
$this->assign('scripts', $this->js);
$configSite = $this->getConfigurationSite();
$this->assign('config', $configSite);
$this->assign("device", MobileDetectService::getDevice(["twig"=>$this->twig,"site"=>$configSite]));
$this->assign("rappelForm", $this->formFactory->create(RappelsType::class)->createView());
$this->assign("sentences", $this->entityManager->getRepository(CfgBlocs::class)->findBy(["isActive"=>true],["rank"=>"ASC"]));
$this->assign("pag_contact", $this->entityManager->getRepository(Pages::class)->findOneBy(["id"=>$_ENV["pag_contact"],"isActive"=>1]));
$this->assign("pag_avis", $this->entityManager->getRepository(Pages::class)->findOneBy(["id"=>$_ENV["pag_avis"],"isActive"=>1]));
$this->loadDefaultModules();
break;
}
}
private function loadDefaultModules():void
{
$this->assign('mod_social', $this->getModule("Socials"));
$this->assign('mod_shortcuts', $this->getModule("Shortcuts"));
$this->assign('mod_shortcuts_projects', $this->getModule("Shortcuts", "ShortcutsProjects"));
$this->assign('mod_shortcuts_facts', $this->getModule("Shortcuts", "ShortcutsFacts"));
$this->assign('mod_newsletter', $this->getModule("Newsletter", null, ["id"=>1]));
if(MODE_INTRANET === false){
$this->assign('menu_haut', $this->getModule("CfgMenus","Menus", ["tag"=>"menu_haut", "origin"=>"includeContentDynamicalMenu"]));
$this->assign('menu_bas', $this->getModule("CfgMenus","Menus", [
"menus"=>[
"menu_bas_gauche",
"menu_bas_milieu",
"menu_bas_droite",
"menu_copyrights"
]
], "loadMenuFooter"));
}
}
private function setContentCfgConstants():bool
{
$constants = $this->entityManager->getRepository(CfgConstants::class)->findBy(["isActive"=>true]);
if(empty($constants)){
return false;
}
foreach($constants as $constant){
if(!defined($constant->getName())){
define($constant->getName(),$constant->getValue());
}
}
return true;
}
private function setContentCfgTranslations():bool
{
$translations = $this->entityManager->getRepository(CfgTranslations::class)->findAll();
if(empty($translations)){
return false;
}
foreach($translations as $translation){
if(!defined($translation->getName())){
define($translation->getName(),$translation->getValue());
}
}
return true;
}
private function setContentLangues():void
{
try{
// On récupère les valeurs des fichiers de langue
$langueDirectory = scandir(ROOT.self::$params["lang_dir"]);
foreach($langueDirectory as $valeur){
if($valeur !== "." && $valeur !== ".." && strpos($valeur, "json")){
$lang_file = json_decode(file_get_contents(ROOT.self::$params["lang_dir"].$valeur),true);
foreach($lang_file as $key=>$tab){
$this->assign($key,$tab[LANGUE]);
}
}
}
}
catch(\Exception $e){
echo $e->getMessage();
}
}
public function assign(string $var, $value):void
{
if (!array_key_exists($var, $this->twig->getGlobals())) {
$this->twig->addGlobal($var, $value);
self::$ressources[$var] = $value;
}
}
public function checkURL(string $ct, string $itemTitle, int $itemId, string $requestUri, string $itemUrlRw, bool $champs_redirection=false):string
{
$langDefault = $this->entityManager->getRepository(CfgLangues::class)->findOneBy(["isDefault"=>1,"isActive"=>1]);
if(!$langDefault instanceof CfgLangues){
$ct = LANGUE_DEFAUT."/".$ct;
}
$urlReceived = $requestUri;
$urlValid = URL."/".$ct."/".ReecritureService::reecrire($itemTitle)."-".$itemId.".html";
if($itemUrlRw){
$urlValid = URL."/".$ct."/".ReecritureService::reecrire($itemUrlRw)."-".$itemId.".html";
}
if($urlValid !== $urlReceived){
header("HTTP/1.1 301 Moved Permanently");
header("location:".$urlValid);
header("Connection: close");exit;
}
return $urlValid;
}
public function getBBCode(string $content):string
{
preg_match_all('#\[\[(.*)\]\]#',$content,$modules);
if(!empty($modules[1])){
foreach($modules[1] as $module){
$param = [];
$ss_module = null;
$explode = explode("|",$module);
$explode = explode("-",$explode[0]);
if(!empty($explode[1])){
$param = ["id"=>$explode[1]];
}
$explode = explode("/",$explode[0]);
if(!empty($explode[1])){
$ss_module = $explode[1];
}
$lemodule = $explode[0];
$module_preg = preg_quote($module, '/');
$content = preg_replace('#\[\['.$module_preg.'\]\]#',$this->getModule($lemodule,$ss_module,$param),$content,1);
}
}
return $content;
}
private function getModuleFormsConfig(array $data):array
{
return array_merge([
"bootService"=>$this
], $data);
}
private function getModuleNewsletterConfig(array $data):array
{
return array_merge([
"formFactory"=>$this->formFactory
], $data);
}
private function getModuleJobsConfig(array $data):array
{
return array_merge([
"formFactory"=>$this->formFactory
], $data);
}
public function loadConfigurationHook(array $data=[]):array
{
return array_merge([
"container"=>$this->container,
"twig"=>$this->twig,
"router"=>$this->router,
"entityManager"=>$this->entityManager,
], $data);
}
private static function checkRegisteredModule($mod):bool
{
if(array_key_exists($mod, self::$params["modules"])){
return false;
}
return true;
}
// Chargement d'un module
public function getModule(string $module,string $ss_module=null,array $param=[],string $action="loadConfigHook"):string|array
{
$modLoad = base64_encode($module.$ss_module.json_encode($param).$action);
if(self::checkRegisteredModule($modLoad) === false){
return self::$params["modules"][$modLoad];
}
if($ss_module===null){
$ss_module = ucfirst($module);
} else{
$ss_module = ucfirst($ss_module);
}
$module = ucfirst($module);
$servicesMod = "App\Modules\\".$module."\Hooks\\".$ss_module."\\".$ss_module."Hook";
if(!class_exists($servicesMod)) {
return '<div class="alert alert-danger">Erreur de chargement de la classe '.$servicesMod.'</div>';
}
if(!method_exists($servicesMod,$action)) {
return '<div class="alert alert-danger">Erreur de chargement de la méthode '.$servicesMod.'\\'.$action.'</div>';
}
if(isset($param["default"])){
$data = $param["default"];
} else{
$data = [
"param"=>$param,
"hookRep"=>"src/Modules/".$module."/Hooks/"
];
}
if(method_exists("App\Service\BootService", "getModule".$module."Config")){
$data = $this->{"getModule".$module."Config"}($data);
}
$modServiceInst = new $servicesMod($this->loadConfigurationHook($data));
$contentHook = $modServiceInst->$action();
if(!is_string($contentHook) && !is_array($contentHook)) {
switch ($contentHook->getStatusCode()) {
case 500:
$content = '<div class="alert alert-danger">Le module n\'a pas pu être récupéré : Erreur ' . $contentHook->getStatusCode() . '</div>';
break;
default:
$content = $contentHook->getContent();
break;
}
} else{
$content = $contentHook;
}
self::$params["modules"][$modLoad] = $content;
return $content;
}
public static function addBC($name,$url):void
{
self::$bc[]=array(
"name"=>$name,
"url"=>$url
);
}
public function Error($description="Page introuvable",$code=404):Response
{
return $this->render('/templates/error.html.twig', ['error' => [
'code'=>$code,
'description'=>$description
]]);
}
public function AddJS($url, $index=null):void
{
if(!in_array($url, $this->js)){
if(is_null($index) || $index===false){
$k = 100 + count($this->js);
}
else{
$k = $index;
}
while(array_key_exists($k, $this->js)){
$k++;
}
$this->js[$k]=$url;
ksort($this->js);
}
}
public function AddCSS($url, $index=null):void
{
if(!in_array($url, $this->css)){
if(is_null($index) || $index===false){
$k = 100 + count($this->css);
}
else{
$k = $index;
}
while(array_key_exists($k, $this->css)){
$k++;
}
$this->css[$k]=$url;
ksort($this->css);
}
}
public static function sendCurlBasic(string $endpoint, array $endpointConfig=[], string $endpointType="GET"):string|array
{
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if(!empty($endpointConfig)){
if(isset($endpointConfig["auth"]) && isset($endpointConfig["auth"]["type"]) && !empty($endpointConfig["auth"]["type"])){
switch($endpointConfig["auth"]["type"]){
case "bearer":
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer '.$endpointConfig["auth"]["token"]
]);
break;
}
}
if(isset($endpointConfig["data"])){
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($endpointConfig["data"]));
}
}
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)');
$result = curl_exec($ch);
//dd($ch);
if(mb_strtoupper($endpointType) === "GET"){
// 3 try si timeout dépassé
$retry = 0;
while(curl_errno($ch) == 28 && $retry < 3){
$result = curl_exec($ch);
$retry++;
}
// Dernier try avec timeout plus long
if(curl_errno($ch) == 28){
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$result = curl_exec($ch);
}
}
curl_close($ch);
return json_decode($result, true);
}
}