[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / spip-bonux / public / spip_bonux_criteres.php
1 <?php
2 /**
3 * Plugin Spip-Bonux
4 * Le plugin qui lave plus SPIP que SPIP
5 * (c) 2008 Mathieu Marcillaud, Cedric Morin, Romy Tetue
6 * Licence GPL
7 *
8 */
9
10 if (!defined("_ECRIRE_INC_VERSION")) return;
11
12 $GLOBALS['exception_des_connect'][] = 'pour';
13 $GLOBALS['exception_des_connect'][] = 'condition';
14
15 /* le critere {tableau ...} des boucles pour:POUR */
16 function critere_POUR_tableau_dist($idb, &$boucles, $crit) {
17 $boucle = &$boucles[$idb];
18 if (isset($crit->param[0])){
19 $table = calculer_liste($crit->param[0], array(), $boucles, $boucle->id_parent);
20 $boucle->having[]=array("'tableau'",$table);
21 }
22 }
23
24 /* le critere {si ...} des boucles condition:CONDITION */
25 function critere_CONDITION_si_dist($idb, &$boucles, $crit) {
26 $boucle = &$boucles[$idb];
27 if (isset($crit->param[0])){
28 $si = calculer_liste($crit->param[0], array(), $boucles, $boucle->id_parent);
29 $boucle->having[]='($test='.$si.')?array(\'tableau\',\'1:1\'):\'\'';
30 }
31 }
32
33 /**
34 * http://www.spip-contrib.net/Classer-les-articles-par-nombre-de#forum409210
35 * Permet de faire un comptage par table liee
36 * exemple
37 * <BOUCLE1(AUTEURS){compteur articles}{par compteur_articles}>
38 * #ID_AUTEUR : #COMPTEUR{articles}
39 * </BOUCLE1>
40 * pour avoir les auteurs classes par articles et le nombre d'article de chacun
41 *
42 * @param unknown_type $idb
43 * @param unknown_type $boucles
44 * @param unknown_type $crit
45 */
46 function critere_compteur($idb, &$boucles, $crit, $left=false){
47 $boucle = &$boucles[$idb];
48
49 $_fusion = calculer_liste($crit->param[1], array(), $boucles, $boucle->id_parent);
50 $params = $crit->param;
51 $table = reset($params);
52 $table = $table[0]->texte;
53 $op = false;
54 if(preg_match(',^(\w+)([<>=])([0-9]+)$,',$table,$r)){
55 $table=$r[1];
56 if (count($r)>=3) $op=$r[2];
57 if (count($r)>=4) $op_val=$r[3];
58 }
59 $type = objet_type($table);
60 $type_id = id_table_objet($type);
61 $table_sql = table_objet_sql($type);
62
63
64 $trouver_table = charger_fonction('trouver_table','base');
65 $arrivee = array($table, $trouver_table($table, $boucle->sql_serveur));
66 $depart = array($boucle->id_table,$trouver_table($boucle->id_table, $boucle->sql_serveur));
67
68 // noter les jointures deja installees
69 $joins = array_keys($boucle->from);
70 if ($compt = calculer_jointure($boucle,$depart,$arrivee)){
71 if ($_fusion!="''"){
72 // en cas de jointure, on ne veut pas du group_by sur la cle primaire !
73 // cela casse le compteur !
74 foreach($boucle->group as $k=>$group)
75 if ($group == $boucle->id_table.'.'.$boucle->primary)
76 unset($boucle->group[$k]);
77 $boucle->group[] = '".($gb='.$_fusion.')."';
78 }
79
80 $boucle->select[]= "COUNT($compt.$type_id) AS compteur_$table";
81 if ($op)
82 $boucle->having[]= array("'".$op."'", "'compteur_".$table."'",$op_val);
83 if ($left){
84 foreach($boucle->from as $k=>$val){
85 if (!in_array($k, $joins)){
86 $boucle->from_type[$k] = 'left';
87 }
88 }
89 }
90 }
91 }
92
93 /**
94 * {compteur_left xxx} permet de faire la meme chose que {compteur xxx}
95 * mais avec un LEFT JOIN pour ne pas ignorer ceux qui ont un compteur nul
96 * @param <type> $idb
97 * @param <type> $boucles
98 * @param <type> $crit
99 */
100 function critere_compteur_left($idb, &$boucles, $crit){
101 critere_compteur($idb, $boucles, $crit, true);
102 }
103
104 /** Critere {somme champ} #SOMME{champ} */
105 function critere_somme($idb, &$boucles, $crit){
106 calcul_critere_fonctions(array('SUM'=>'somme'), $idb, $boucles, $crit);
107 }
108
109 /** Critere {compte champ} #COMPTE{champ} */
110 function critere_compte($idb, &$boucles, $crit){
111 calcul_critere_fonctions(array('COUNT'=>'compte'), $idb, $boucles, $crit);
112 }
113
114 /** Critere {moyenne champ} #MOYENNE{champ} */
115 function critere_moyenne($idb, &$boucles, $crit){
116 calcul_critere_fonctions(array('AVG'=>'moyenne'), $idb, $boucles, $crit);
117 }
118
119 /** Critere {minimum champ} #MINIMUM{champ} */
120 function critere_minimum($idb, &$boucles, $crit){
121 calcul_critere_fonctions(array('MIN'=>'minimum'), $idb, $boucles, $crit);
122 }
123
124 /** Critere {maximum champ} #MAXIMUM{champ} */
125 function critere_maximum($idb, &$boucles, $crit){
126 calcul_critere_fonctions(array('MAX'=>'maximum'), $idb, $boucles, $crit);
127 }
128
129 /** Critere {stats champ} calcul la totale : somme, compte, minimum, moyenne, maximum */
130 function critere_stats($idb, &$boucles, $crit){
131 calcul_critere_fonctions(array(
132 'SUM'=>'somme',
133 'COUNT'=>'compte',
134 'AVG'=>'moyenne',
135 'MIN'=>'minimum',
136 'MAX'=>'maximum',
137 ), $idb, $boucles, $crit);
138 }
139
140 /* $func : array(FUNC => balise) */
141 function calcul_critere_fonctions($func, $idb, &$boucles, $crit) {
142 $boucle = &$boucles[$idb];
143 $_fusion = calculer_liste($crit->param[1], array(), $boucles, $boucle->id_parent);
144
145 $params = $crit->param;
146 $champ = reset($params);
147 $champ = $champ[0]->texte;
148
149 // option DISTINCT {compte DISTINCT(id_article) }
150 $filter="";
151 if (preg_match('/^([a-zA-Z]+)\(\s*([a-zA-Z_]+)\s*\)$/', trim($champ), $r)) {
152 $filter = $r[1]; // DISTINCT
153 $champ = $r[2]; // id_article
154 }
155
156 $sel = $filter ? "$filter($champ)" : $champ;
157 foreach ($func as $f => $as) {
158 $boucle->select[]= "$f($sel) AS $as" . "_$champ";
159 }
160 }
161
162 /**
163 * {tri [champ_par_defaut][,sens_par_defaut][,nom_variable]}
164 * champ_par_defaut : un champ de la table sql
165 * sens_par_defaut : -1 ou inverse pour decroissant, 1 ou direct pour croissant
166 * nom_variable : nom de la variable utilisee (par defaut tri_nomboucle)
167 *
168 * {tri titre}
169 * {tri titre,inverse}
170 * {tri titre,-1}
171 * {tri titre,-1,truc}
172 *
173 * @param unknown_type $idb
174 * @param unknown_type $boucles
175 * @param unknown_type $crit
176 */
177 function critere_tri_dist($idb, &$boucles, $crit) {
178 $boucle = &$boucles[$idb];
179 $id_table = $boucle->id_table;
180
181 // definition du champ par defaut
182 $_champ_defaut = !isset($crit->param[0][0]) ? "''" : calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent);
183 $_sens_defaut = !isset($crit->param[1][0]) ? "1" : calculer_liste(array($crit->param[1][0]), array(), $boucles, $boucle->id_parent);
184 $_variable = !isset($crit->param[2][0]) ? "'$idb'" : calculer_liste(array($crit->param[2][0]), array(), $boucles, $boucle->id_parent);
185
186 $_tri = "((\$t=(isset(\$Pile[0]['tri'.$_variable]))?\$Pile[0]['tri'.$_variable]:$_champ_defaut)?tri_protege_champ(\$t):'')";
187
188 $_sens_defaut = "(is_array(\$s=$_sens_defaut)?(isset(\$s[\$st=$_tri])?\$s[\$st]:reset(\$s)):\$s)";
189 $_sens ="((intval(\$t=(isset(\$Pile[0]['sens'.$_variable]))?\$Pile[0]['sens'.$_variable]:$_sens_defaut)==-1 OR \$t=='inverse')?-1:1)";
190
191 $boucle->modificateur['tri_champ'] = $_tri;
192 $boucle->modificateur['tri_sens'] = $_sens;
193 $boucle->modificateur['tri_nom'] = $_variable;
194 // faut il inserer un test sur l'existence de $tri parmi les champs de la table ?
195 // evite des erreurs sql, mais peut empecher des tri sur jointure ...
196 $boucle->hash .= "
197 \$senstri = '';
198 \$tri = $_tri;
199 if (\$tri){
200 \$senstri = $_sens;
201 \$senstri = (\$senstri<0)?' DESC':'';
202 };
203 ";
204 $field = serialize(array_keys($boucle->show['field']));
205 $boucle->select[] = "\".tri_champ_select(\$tri).\"";
206 $boucle->order[] = "tri_champ_order(\$tri,'$id_table','$field').\$senstri";
207 }
208
209 /**
210 * Trouver toutes les objets qui ont des enfants (les noeuds de l'arbre)
211 * {noeud}
212 * {!noeud} retourne les feuilles
213 *
214 * @global array $exceptions_des_tables
215 * @param string $idb
216 * @param array $boucles
217 * @param <type> $crit
218 */
219 function critere_noeud_dist($idb, &$boucles, $crit) {
220 global $exceptions_des_tables;
221 $not = $crit->not;
222 $boucle = &$boucles[$idb];
223 $primary = $boucle->primary;
224
225 if (!$primary OR strpos($primary,',')) {
226 erreur_squelette(_T('zbug_doublon_sur_table_sans_cle_primaire'), "BOUCLE$idb");
227 return;
228 }
229 $table = $boucle->type_requete;
230 $table_sql = table_objet_sql(objet_type($table));
231
232 $id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ?
233 $exceptions_des_tables[$boucle->id_table]['id_parent'] :
234 'id_parent';
235
236 $in = "IN";
237 $where= array("'IN'", "'$boucle->id_table." . "$primary'","'('.sql_get_select('$id_parent', '$table_sql').')'");
238 if ($not)
239 $where = array("'NOT'",$where);
240
241 $boucle->where[]= $where;
242 }
243
244 /**
245 * Trouver toutes les objets qui n'ont pas d'enfants (les feuilles de l'arbre)
246 * {feuille}
247 * {!feuille} retourne les noeuds
248 *
249 * @global array $exceptions_des_tables
250 * @param string $idb
251 * @param array $boucles
252 * @param <type> $crit
253 */
254 function critere_feuille_dist($idb, &$boucles, $crit) {
255 $not = $crit->not;
256 $crit->not = $not ? false:true;
257 critere_noeud_dist($idb,$boucles,$crit);
258 $crit->not = $not;
259 }
260
261 ?>