4 * Le plugin qui lave plus SPIP que SPIP
5 * (c) 2008 Mathieu Marcillaud, Cedric Morin, Tetue
10 if (!defined('_ECRIRE_INC_VERSION')) return;
13 * Permet de faire un comptage par table liee
15 * @syntaxe `{compteur table[, champ]}`
16 * @link http://www.spip-contrib.net/Classer-les-articles-par-nombre-de#forum409210
19 * Pour avoir les auteurs classes par articles et
20 * le nombre d'article de chacun :
23 * <BOUCLE1(AUTEURS){compteur articles}{par compteur_articles}>
24 * #ID_AUTEUR : #COMPTEUR{articles}
29 * Avec un seul argument {compteur autre_table} le groupby est fait
30 * implicitement sur la cle primaire de la boucle en cours.
31 * Avec un second argument {compteur autre_table,champ_fusion}
32 * le groupby est fait sur le champ_fusion"
35 * Identifiant de la boucle
36 * @param Boucle[] $boucles
38 * @param Critere $crit
39 * Paramètres du critère dans cette boucle
41 * true pour utiliser un left join plutôt qu'un inner join.
44 function critere_compteur($idb, &$boucles, $crit, $left=false){
45 $boucle = &$boucles[$idb];
47 if (isset($crit->param
[1])) {
48 $_fusion = calculer_liste($crit->param
[1], array(), $boucles, $boucle->id_parent
);
52 $params = $crit->param
;
53 $table = reset($params);
54 $table = $table[0]->texte
;
56 if (preg_match(',^(\w+)([<>=])([0-9]+)$,',$table,$r)){
58 if (count($r)>=3) $op=$r[2];
59 if (count($r)>=4) $op_val=$r[3];
61 $type = objet_type($table);
62 $type_id = id_table_objet($type);
65 * Si la clé primaire est une clé multiple, on prend la première partie
66 * Utile pour compter les versions de spip_versions par exemple
68 if (count($types = explode(',',$type_id)) > 1)
70 $table_sql = table_objet_sql($type);
72 $trouver_table = charger_fonction('trouver_table','base');
73 $arrivee = array($table, $trouver_table($table, $boucle->sql_serveur
));
74 $depart = array($boucle->id_table
,$trouver_table($boucle->id_table
, $boucle->sql_serveur
));
76 // noter les jointures deja installees
77 $joins = array_keys($boucle->from
);
78 if ($compt = calculer_jointure($boucle,$depart,$arrivee)){
80 // en cas de jointure, on ne veut pas du group_by sur la cle primaire !
81 // cela casse le compteur !
82 foreach($boucle->group
as $k=>$group)
83 if ($group == $boucle->id_table
.'.'.$boucle->primary
)
84 unset($boucle->group
[$k]);
85 $boucle->group
[] = '".($gb='.$_fusion.')."';
88 $boucle->select
[]= "COUNT($compt.$type_id) AS compteur_$table";
90 $boucle->having
[]= array("'".$op."'", "'compteur_".$table."'",$op_val);
92 foreach($boucle->from
as $k=>$val){
93 if (!in_array($k, $joins)){
94 $boucle->from_type
[$k] = 'left';
102 * {compteur_left xxx} permet de faire la meme chose que {compteur xxx}
103 * mais avec un LEFT JOIN pour ne pas ignorer ceux qui ont un compteur nul
105 * @param <type> $boucles
106 * @param <type> $crit
108 function critere_compteur_left($idb, &$boucles, $crit){
109 critere_compteur($idb, $boucles, $crit, true);
112 /** Critere {somme champ} #SOMME{champ} */
113 function critere_somme($idb, &$boucles, $crit){
114 calcul_critere_fonctions(array('SUM'=>'somme'), $idb, $boucles, $crit);
117 /** Critere {compte champ} #COMPTE{champ} */
118 function critere_compte($idb, &$boucles, $crit){
119 calcul_critere_fonctions(array('COUNT'=>'compte'), $idb, $boucles, $crit);
122 /** Critere {moyenne champ} #MOYENNE{champ} */
123 function critere_moyenne($idb, &$boucles, $crit){
124 calcul_critere_fonctions(array('AVG'=>'moyenne'), $idb, $boucles, $crit);
127 /** Critere {minimum champ} #MINIMUM{champ} */
128 function critere_minimum($idb, &$boucles, $crit){
129 calcul_critere_fonctions(array('MIN'=>'minimum'), $idb, $boucles, $crit);
132 /** Critere {maximum champ} #MAXIMUM{champ} */
133 function critere_maximum($idb, &$boucles, $crit){
134 calcul_critere_fonctions(array('MAX'=>'maximum'), $idb, $boucles, $crit);
137 /** Critere {stats champ} calcul la totale : somme, compte, minimum, moyenne, maximum */
138 function critere_stats($idb, &$boucles, $crit){
139 calcul_critere_fonctions(array(
145 ), $idb, $boucles, $crit);
148 /* $func : array(FUNC => balise) */
149 function calcul_critere_fonctions($func, $idb, &$boucles, $crit) {
150 $boucle = &$boucles[$idb];
152 $params = $crit->param
;
153 $champ = reset($params);
154 $champ = $champ[0]->texte
;
156 // option DISTINCT {compte DISTINCT(id_article) }
158 if (preg_match('/^([a-zA-Z]+)\(\s*([a-zA-Z_]+)\s*\)$/', trim($champ), $r)) {
159 $filter = $r[1]; // DISTINCT
160 $champ = $r[2]; // id_article
163 $sel = $filter ?
"$filter($champ)" : $champ;
164 foreach ($func as $f => $as) {
165 $boucle->select
[]= "$f($sel) AS $as" . "_$champ";