<?php
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\DBAL\Connection;
use App\Repository\TableauRepository;
use App\Repository\TableauFiltreRepository;
use App\Repository\TableauColonneRepository;
class TableauService
{
private $repo_tablo;
private $repo_colonne;
private $repo_filtre;
private $entityManager;
private $conn;
public function __construct(Connection $connection, FormulaireService $service_form, EntityManagerInterface $entityManager, TableauRepository $repo_tablo, TableauFiltreRepository $repo_filtre, TableauColonneRepository $repo_colonne) {
$this->conn = $connection;
$this->entityManager = $entityManager;
$this->repo_tablo = $repo_tablo;
$this->repo_colonne = $repo_colonne;
$this->repo_filtre = $repo_filtre;
$this->service_form = $service_form;
}
/**
* Retourne tous les tableaux créés ordonnés par libellé croissant
* @return App\Entity\Tableau[]
*/
public function fetchAllAssociative() {
$tabAll = $this->repo_tablo->findBy([], ["libelle" => "ASC"]);
return $tabAll;
}
/**
* Retourne en chaine de caractères le champ d'une colonne d'un tableau
* @param integer $colonne_id TableauColonne ID
* @return string
*/
public function getColumnChamp($colonne_id) {
$colonne = $this->repo_colonne->find($colonne_id);
if(!is_null($colonne->getTableau()->getEntite())) { // cas d'un tableau lié à une entité custom : on retourne le libellé du champ
return $colonne->getChamp()->getLibelle();
}
else { // cas d'un tableau requête SQL
return $colonne->getSqlColumn();
}
}
/**
* Savoir si un champ fait partie des colonnes
* @param integer $champ_id FormChamp ID
* @param App\Entity\Tableau $tableau
* @return boolean
*/
public function isChampInTableau($champ_id, $tableau) {
foreach ($tableau->getColonnes() as $key => $colonne) {
if(!is_null($colonne->getChamp()) && $colonne->getChamp()->getId() == $champ_id) {
return true;
}
}
return false;
}
/**
* Connaitre les colonnes possibles d'un tableau en fonction d'une requête SQL
* @param string $strProcedure Requête MySQL
* @return array
*/
public function getProcedureColumns($strProcedure){
$res = $this->conn->fetchAllAssociative($strProcedure);
if(count($res) > 0) {
return array_keys($res[0]);
}
else {
return false;
}
}
/**
* Retourne les lignes d'un tableau
* @param App\Entity\Tableau $tableau
* @return array
*/
public function getContent($tableau){
// CAS D'UN TABLEAU "ENTITE"
if(!is_null($tableau->getEntite())) {
$className = "App\\Entity\\".$tableau->getEntite()->getName();
if(class_exists($className)) {
$repo = $this->entityManager->getRepository($className);
$filtres = $this->repo_filtre->findBy(["parent" => null, "tableau" => $tableau->getId()], ["champ" => "ASC"]);
// Construction de la requete SQL avec prise en compte des filtres (on a juste besoin des ids)
$sql = 'SELECT id FROM `'.$tableau->getEntite()->getSqlTable().'` entite WHERE 1=1';
foreach ($filtres as $filtre) {
if(!is_null($filtre->getChamp()) && !is_null($filtre->getOperateur()) && !is_null($filtre->getValeur())) {
$field = $this->getFieldForFiltre($filtre);
// Pour des filtres de champs à choix multiples
if($filtre->getOperateur()->getMultiple()) {
if(count($filtre->getEnfants()) > 0) {
$sql .= ' AND COALESCE((
SELECT COUNT(*)
FROM form_valeur
WHERE entite_nom = "'.$tableau->getEntite()->getName().'"
AND entite_id = entite.id
AND champ_id = '.$filtre->getChamp()->getId().'
AND value_text IN ("'.$filtre->getValeur().'" , ';
foreach ($filtre->getEnfants() as $child) {
$sql .= '"'.$child->getValeur().'",';
}
$sql = substr($sql, 0, -1);
$sql .= ') ) , 0)';
$sql .= ' '.$filtre->getOperateur()->getSqlQuery();
}
else {
$sql .= ' AND COALESCE((SELECT COUNT(*) FROM form_valeur WHERE entite_nom = "'.$tableau->getEntite()->getName().'" AND entite_id = entite.id AND champ_id = '.$filtre->getChamp()->getId().' AND value_text = "'.$filtre->getValeur().'"), 0)';
$sql .= ' '.$filtre->getOperateur()->getSqlQuery();
}
}
// Pour des filtres classiques
else {
if(count($filtre->getEnfants()) > 0) {
$sql .= ' AND ( COALESCE((SELECT '.$field.' FROM form_valeur WHERE entite_nom = "'.$tableau->getEntite()->getName().'" AND entite_id = entite.id AND champ_id = '.$filtre->getChamp()->getId().'), "")';
$sql .= ' '.str_replace("{value}", $filtre->getValeur(), $filtre->getOperateur()->getSqlQuery()).' ';
foreach ($filtre->getEnfants() as $child) {
$field2 = $this->getFieldForFiltre($child);
$sql .= ' OR COALESCE((SELECT '.$field2.' FROM form_valeur WHERE entite_nom = "'.$tableau->getEntite()->getName().'" AND entite_id = entite.id AND champ_id = '.$child->getChamp()->getId().'), "")';
$sql .= ' '.str_replace("{value}", $child->getValeur(), $child->getOperateur()->getSqlQuery()).' ';
}
$sql .= ' ) ';
}
else {
$sql .= ' AND COALESCE((SELECT '.$field.' FROM form_valeur WHERE entite_nom = "'.$tableau->getEntite()->getName().'" AND entite_id = entite.id AND champ_id = '.$filtre->getChamp()->getId().'), "")';
$sql .= ' '.str_replace("{value}", $filtre->getValeur(), $filtre->getOperateur()->getSqlQuery());
}
}
}
}
$sql = $this->replaceVariablesInQuery($sql);
// dump($sql);die();
// Résultats de la requête
$rows = $this->conn->fetchAllAssociative($sql);
// Pour chaque ligne le FormulaireService va récupérer toutes les données en fonction des valeurs de formulaires
$allLignes = [];
foreach ($rows as $row) {
$allLignes[] = $this->service_form->getAllData($tableau->getEntite(), $row["id"]);
}
}
else {
throw new \Exception("Erreur lors du chargement du tableau.");
}
}
// CAS D'UN TABLEAU "SQL CLASSIQUE"
else {
$allLignes = $this->conn->fetchAllAssociative($tableau->getSqlConfig());
}
// On retourne seulement les data à afficher dans le tableau
$lignes = [];
foreach ($allLignes as $data) {
$newLigneData = [];
foreach ($data as $code => $value) {
foreach ($tableau->getColonnes() as $colonne) {
if($colonne->getSqlColumn() == $code || (!is_null($colonne->getChamp()) && $colonne->getChamp()->getCode() == $code)) {
$newLigneData[$code] = $value;
}
}
}
$lignes[] = $newLigneData;
}
return $lignes;
}
/**
* Construction d'une requete avec filtres : remplacement des valeurs dynamiques (notamment pour les dates)
* @param string $sql
* @return string
*/
public function replaceVariablesInQuery($sql){
// Maintenant
$sql = str_replace("#NOW#", date("Y-m-d H:i:s"), $sql);
// Date du jour
$sql = str_replace("#TODAY#", date("Y-m-d"), $sql);
// Premier jour du mois en cours
$sql = str_replace("#M_1#", date("Y-m")."-01", $sql);
// Premier jour de l'année en cours
$sql = str_replace("#Y_1#", date("Y")."-01-01", $sql);
return $sql;
}
/**
* Connaitre la colonne à vérifier en fonction du type de champ du filtre
* @param App\Entity\TableauFiltre $filtre
* @return string
*/
public function getFieldForFiltre($filtre){
switch($filtre->getChamp()->getType()->getCode()) {
case "TXT":
case "TXTAREA":
case "TXTEMAIL":
case "LIST":
case "LISTSQL":
case "CHOICE":
$field = "value_text";
break;
case "DATE":
case "DATETIME":
$field = "value_date";
break;
case "INT":
case "BOOL":
$field = "value_int";
break;
case "DEC":
$field = "value_dec";
break;
default:
$field = "value_text";
break;
}
return $field;
}
}
?>