-
-
Save tcharlss/ff8d7de690dbcf5ab3e8eb48ef86b423 to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Calcul du critère `initiale` | |
* | |
* NE FONCTIONNE QU'AVEC MYSQL | |
* | |
* Extrait l'initiale d'un champ ou d'une expression. | |
* Ajoute l'alias `initiale` dans la boucle, ce qui permet de faire un GROUP BY `{fusion initiale}` ou un ORDER BY `{par initiale}` | |
* Voir aussi le pipeline pre_boucle à ce sujet. | |
* | |
* @example | |
* ``` | |
* {initiale} | |
* {initiale?} | |
* {initiale a} | |
* {initiale a, prenom} | |
* {initiale a, CONCAT(prenom,nom)} | |
* {initiale, CONCAT(prenom,nom)} | |
* ``` | |
* | |
* @critere | |
* | |
* @param string $idb Identifiant de la boucle | |
* @param array $boucles AST du squelette | |
* @param Critere $crit Paramètres du critère dans cette boucle | |
* @return void | |
*/ | |
function critere_initiale_dist($idb, &$boucles, $crit) { | |
$boucle = &$boucles[$idb]; | |
$id_table = $boucle->id_table; | |
$_id_table = "'$id_table'"; | |
$not = ($crit->not ? 'NOT ' : ''); | |
$condition = $crit->cond; | |
// Initiale : celle passée en param, sinon celle dans l'env si opérateur conditionnel | |
if (isset($crit->param[0])) { | |
$_initiale = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent); | |
} else { | |
$_initiale = ($condition ? "(isset(\$Pile[0]['initiale']) ? \$Pile[0]['initiale'] : '')" : "''"); | |
} | |
// Nom du ou des champs d'où extraire l'initiale : celui passé en param, sinon `nom` | |
// Possible de mettre `CONCAT(prenom,nom)` si on veut | |
if (isset($crit->param[1])) { | |
$_champ = calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent); | |
} else { | |
$_champ = "'nom'"; | |
} | |
// SELECT : ajout de l'alias `initiale` pour permettre de trier ou de grouper dessus | |
$boucle->hash .= '$champ_initiale = ' . $_champ . ';'; | |
$boucle->select[] = '" . calculer_sql_initiale($champ_initiale, ' . $_id_table . ') . " AS initiale" . "'; | |
// WHERE : kamoulox | |
$boucle->where[] = "(($_initiale) ? '$not' . '(' . calculer_sql_initiale($_champ, $_id_table) . ' = ' . sql_quote(" . $_initiale . ") . ')' : '')"; | |
} | |
/** | |
* Retourne l'expression SQL qui permet d'extraire une initiale | |
* | |
* @param string $champ | |
* Nom ou expression où extraire l'initiale : | |
* - nom | |
* - CONCAT(prenom,nom) | |
* - etc. | |
* @param string $id_table | |
* Nom de la table dans la requête | |
*/ | |
function calculer_sql_initiale(string $champ, ? string $id_table = null) { | |
// Injecter le nom de la table | |
if ($id_table) { | |
$champ = preg_replace('/([^\.])(prenom|nom)/', "$1$id_table.$2", $champ); | |
} | |
// La formule : 1ère lettre du 1er mot trouvé (ce qui exclut les tirets, les points, les apostrophes, etc) | |
$sql = "REGEXP_SUBSTR(LOWER($champ), '[:word:]')"; | |
return $sql; | |
} | |
/** | |
* Calcul de la balise #INITIALE | |
* | |
* @balise | |
* | |
* @param unknown_type $p | |
*/ | |
function balise_INITIALE_dist($p) { | |
return rindex_pile($p, 'initiale', 'initiale'); | |
} | |
/** | |
* Modifier les boucles | |
* | |
* Éviter une erreur sql en supprimant le champ `initiale` inexistant dans le select. | |
* Il est ajouté automatiquement en présence des critères {par initiale} ou {fusion initiale}. | |
* | |
* @pipeline pre_boucle | |
* @param [type] $boucle | |
* @return void | |
*/ | |
function plugin_pre_boucle($boucle) { | |
foreach ($boucle->criteres as $critere) { | |
if ( | |
// il y le critère {initiale} | |
$critere->type === 'critere' | |
and $critere->op === 'initiale' | |
// et il y a 'initiale' dans le select (à cause de {par initiale} ou {fusion initiale}) | |
and ($k = array_search('initiale', $boucle->select)) !== false | |
) { | |
unset($boucle->select[$k]); | |
} | |
} | |
return $boucle; | |
} |
mais calculer_sql_initiale limite sa regexp à prenom ou nom et donc le critère aussi en l'état.
Ah oui en effet, cette partie n'était pas finie. Il faudrait récupérer la liste des champs de la table de l'objet.
Au passage je pige pas ce que fait ce replace : avec $1 il transforme un préfixe de champ xxx_nom ou xxx_prénom en préfixe SPIP de table genre xxx_profils ??
Ça ajoute l'alias de la table pour éviter les ambiguités en cas de jointure : titre → articles.titre
wè mais et le ([^\.])
qui précède ?
On ne veut pas préfixer les champs déjà préfixés : articles.titre → articles.articles.titre
Aaaah ok merci :-) ... et ça marche car il y a une quote dans le cas contraire (ici ça serait plus simple d'exiger une quote direct, mais faudra voir dans le cas général...)
Chouette, mais j'ai un doute
C'est présenté comme polyvalent alors qu'il y a
prenom
etnom
en dur dans le code.Dans
critere_initiale_dist
c'est seulement une valeur par défaut (donc pas bloquant, juste ça pourrait être documenté)mais
calculer_sql_initiale
limite sa regexp àprenom
ounom
et donc le critère aussi en l'état.Non ?
Au passage je pige pas ce que fait ce replace : avec
$1
il transforme un préfixe de champxxx_nom
ouxxx_prénom
en préfixe SPIP de table genrexxx_profils
??