4 * Le plugin qui lave plus SPIP que SPIP
5 * (c) 2008 Mathieu Marcillaud, Cedric Morin, Tetue
10 if (!defined('_ECRIRE_INC_VERSION')) {
15 * Permet de faire un comptage par table liee
17 * @syntaxe `{compteur table[, champ]}`
18 * @link http://www.spip-contrib.net/Classer-les-articles-par-nombre-de#forum409210
21 * Pour avoir les auteurs classes par articles et
22 * le nombre d'article de chacun :
25 * <BOUCLE1(AUTEURS){compteur articles}{par compteur_articles}>
26 * #ID_AUTEUR : #COMPTEUR{articles}
31 * Avec un seul argument {compteur autre_table} le groupby est fait
32 * implicitement sur la cle primaire de la boucle en cours.
33 * Avec un second argument {compteur autre_table,champ_fusion}
34 * le groupby est fait sur le champ_fusion"
37 * Identifiant de la boucle
38 * @param Boucle[] $boucles
40 * @param Critere $crit
41 * Paramètres du critère dans cette boucle
43 * true pour utiliser un left join plutôt qu'un inner join.
46 function critere_compteur($idb, &$boucles, $crit, $left = false) {
47 $boucle = &$boucles[$idb];
49 if (isset($crit->param
[1])) {
50 $_fusion = calculer_liste($crit->param
[1], array(), $boucles, $boucle->id_parent
);
54 $params = $crit->param
;
55 $table = reset($params);
56 $table = $table[0]->texte
;
58 if (preg_match(',^(\w+)([<>=])([0-9]+)$,', $table, $r)) {
67 $type = objet_type($table);
68 $type_id = id_table_objet($type);
71 * Si la clé primaire est une clé multiple, on prend la première partie
72 * Utile pour compter les versions de spip_versions par exemple
74 if (count($types = explode(',', $type_id)) > 1) {
77 $table_sql = table_objet_sql($type);
79 $trouver_table = charger_fonction('trouver_table', 'base');
80 $arrivee = array($table, $trouver_table($table, $boucle->sql_serveur
));
81 $depart = array($boucle->id_table
,$trouver_table($boucle->id_table
, $boucle->sql_serveur
));
83 // noter les jointures deja installees
84 $joins = array_keys($boucle->from
);
85 if ($compt = calculer_jointure($boucle, $depart, $arrivee)) {
87 // en cas de jointure, on ne veut pas du group_by sur la cle primaire !
88 // cela casse le compteur !
89 foreach ($boucle->group
as $k => $group) {
90 if ($group == $boucle->id_table
.'.'.$boucle->primary
) {
91 unset($boucle->group
[$k]);
94 $boucle->group
[] = '".($gb='.$_fusion.')."';
97 $boucle->select
[]= "COUNT($compt.$type_id) AS compteur_$table";
99 $boucle->having
[]= array("'".$op."'", "'compteur_".$table."'",$op_val);
102 foreach ($boucle->from
as $k => $val) {
103 if (!in_array($k, $joins)) {
104 $boucle->from_type
[$k] = 'left';
112 * {compteur_left xxx} permet de faire la meme chose que {compteur xxx}
113 * mais avec un LEFT JOIN pour ne pas ignorer ceux qui ont un compteur nul
115 * @param <type> $boucles
116 * @param <type> $crit
118 function critere_compteur_left($idb, &$boucles, $crit) {
119 critere_compteur($idb, $boucles, $crit, true);
122 /** Critere {somme champ} #SOMME{champ} */
123 function critere_somme($idb, &$boucles, $crit) {
124 calcul_critere_fonctions(array('SUM'=>'somme'), $idb, $boucles, $crit);
127 /** Critere {compte champ} #COMPTE{champ} */
128 function critere_compte($idb, &$boucles, $crit) {
129 calcul_critere_fonctions(array('COUNT'=>'compte'), $idb, $boucles, $crit);
132 /** Critere {moyenne champ} #MOYENNE{champ} */
133 function critere_moyenne($idb, &$boucles, $crit) {
134 calcul_critere_fonctions(array('AVG'=>'moyenne'), $idb, $boucles, $crit);
137 /** Critere {minimum champ} #MINIMUM{champ} */
138 function critere_minimum($idb, &$boucles, $crit) {
139 calcul_critere_fonctions(array('MIN'=>'minimum'), $idb, $boucles, $crit);
142 /** Critere {maximum champ} #MAXIMUM{champ} */
143 function critere_maximum($idb, &$boucles, $crit) {
144 calcul_critere_fonctions(array('MAX'=>'maximum'), $idb, $boucles, $crit);
147 /** Critere {stats champ} calcul la totale : somme, compte, minimum, moyenne, maximum */
148 function critere_stats($idb, &$boucles, $crit) {
149 calcul_critere_fonctions(array(
155 ), $idb, $boucles, $crit);
158 /* $func : array(FUNC => balise) */
159 function calcul_critere_fonctions($func, $idb, &$boucles, $crit) {
160 $boucle = &$boucles[$idb];
162 $params = $crit->param
;
163 $champ = reset($params);
164 $champ = $champ[0]->texte
;
166 // option DISTINCT {compte DISTINCT(id_article) }
168 if (preg_match('/^([a-zA-Z]+)\(\s*([a-zA-Z_]+)\s*\)$/', trim($champ), $r)) {
169 $filter = $r[1]; // DISTINCT
170 $champ = $r[2]; // id_article
173 $sel = $filter ?
"$filter($champ)" : $champ;
174 foreach ($func as $f => $as) {
175 $boucle->select
[]= "$f($sel) AS $as" . "_$champ";
179 function critere_fusion_supprimer_dist($idb, &$boucles, $crit){
180 $boucles[$idb]->group
= array();