source: spip-zone/_plugins_/iterateurs/iterateurs_fonctions.php @ 82868

Last change on this file since 82868 was 82868, checked in by marcimat@…, 7 years ago

Critère SI pour la boucle condition qui surcharge celle de spip bonux, sinon ça plante depuis r82600

File size: 8.6 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) return;
4
5include_spip('public/iterateur');
6
7// filtre table_valeur
8// permet de recuperer la valeur d'un tableau pour une cle donnee
9// prend en entree un tableau serialise ou non (ce qui permet d'enchainer le filtre)
10// ou un objet
11// Si la cle est de la forme a.b, on renvoie $table[a][b]
12function Iterateurs_table_valeur($table,$cle,$defaut=''){
13        foreach (explode('/', $cle) as $k) if ($k !== "") {
14                $table= is_string($table) ? unserialize($table) : $table;
15
16                if (is_object($table))
17                        $table = isset($table->$k) ? $table->$k : $default;
18                else if (is_array($table))
19                        $table = isset($table[$k]) ? $table[$k] : $defaut;
20                else
21                        $table = $default;
22        }
23        return $table;
24}
25
26
27// {source mode, "xxxxxx", arg, arg, arg}
28function critere_source($idb, &$boucles, $crit) {
29        $boucle = &$boucles[$idb];
30
31        $args = array();
32        foreach ($crit->param as &$param)
33                array_push($args,
34                calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent));
35
36        $boucle->hash .= '
37        $command[\'sourcemode\'] = '. array_shift($args). ";\n";
38
39        $boucle->hash .= '
40        $command[\'source\'] = array('. join(', ', $args). ");\n";
41
42}
43
44
45// {datasource "xxxxxx", mode}  <= deprecated
46function critere_datasource($idb, &$boucles, $crit) {
47        $boucle = &$boucles[$idb];
48        $boucle->hash .= '
49        $command[\'source\'] = array('.calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent).');
50        $command[\'sourcemode\'] = '.calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent).';';
51}
52
53function critere_datacache($idb, &$boucles, $crit) {
54        $boucle = &$boucles[$idb];
55        $boucle->hash .= '
56        $command[\'datacache\'] = '.calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent).';';
57}
58
59// {tableau #XX} pour compatibilite ascendante boucle POUR
60// ... preferer la notation {datasource #XX,table}
61function critere_tableau($idb, &$boucles, $crit) {
62        $boucle = &$boucles[$idb];
63        $boucle->hash .= '
64        $command[\'source\'] = array('.calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent).');
65        $command[\'sourcemode\'] = \'table\';';
66}
67
68
69/*
70 * Pour passer des arguments a un iterateur non-spip
71 * (php:xxxIterator){args argument1, argument2, argument3}
72 */
73function critere_args($idb, &$boucles, $crit) {
74        $boucle = &$boucles[$idb];
75        $boucle->hash .= '$command[\'args\']=array();';
76        foreach($crit->param as $param) {
77                $boucle->hash .= '
78                        $command[\'args\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).';';
79        }
80}
81
82/*
83 * Passer une liste de donnees a l'iterateur DATA
84 * (DATA){liste X1, X2, X3}
85 */
86function critere_liste($idb, &$boucles, $crit) {
87        $boucle = &$boucles[$idb];
88        $boucle->hash .= "\n\t".'$command[\'liste\'] = array();'."\n";
89        foreach($crit->param as $param) {
90                $boucle->hash .= "\t".'$command[\'liste\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).";\n";
91        }
92}
93
94/*
95 * Extraire un chemin d'un tableau de donnees
96 * (DATA){datapath query.results}
97 */
98function critere_datapath($idb, &$boucles, $crit) {
99        $boucle = &$boucles[$idb];
100        foreach($crit->param as $param) {
101                $boucle->hash .= '
102                        $command[\'datapath\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).';';
103        }
104}
105
106/* le critere {si ...} applicable a toutes les boucles
107 * Doit passer par dessus spip-bonux-2 depuis r82600
108 */
109function critere_CONDITION_si($idb, &$boucles, $crit) {
110        return critere_si($idb, $boucles, $crit);
111}
112
113/* le critere {si ...} applicable a toutes les boucles */
114function critere_si($idb, &$boucles, $crit) {
115        $boucle = &$boucles[$idb];
116        // il faut initialiser 1 fois le tableau a chaque appel de la boucle
117        // (par exemple lorsque notre boucle est appelee dans une autre boucle)
118        // mais ne pas l'initialiser n fois si il y a n criteres {si } dans la boucle !
119        $boucle->hash .= "\n\tif (!isset(\$si_init)) { \$command['si'] = array(); \$si_init = true; }\n";
120        if ($crit->param) {
121                foreach($crit->param as $param) {
122                        $boucle->hash .= "\t\$command['si'][] = "
123                                        . calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent) . ";\n";
124                }
125        // interdire {si 0} aussi !
126        } else {
127                        $boucle->hash .= '$command[\'si\'][] = 0;';
128        }
129}
130
131
132// {pagination}
133// {pagination 20}
134// {pagination #ENV{pages,5}} etc
135// {pagination 20 #ENV{truc,chose}} pour utiliser la variable debut_#ENV{truc,chose}
136// http://www.spip.net/@pagination
137// http://doc.spip.org/@critere_pagination
138function critere_pagination($idb, &$boucles, $crit) {
139
140        $boucle = &$boucles[$idb];
141        // definition de la taille de la page
142        $pas = !isset($crit->param[0][0]) ? "''" : calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent);
143
144        if (!preg_match(_CODE_QUOTE, $pas, $r)) {
145                $pas = "((\$a = intval($pas)) ? \$a : 10)";
146        } else {
147                $r = intval($r[2]);
148                $pas = strval($r ? $r : 10);
149        }
150        $type = !isset($crit->param[0][1]) ? "'$idb'" : calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucle->id_parent);
151        $debut = ($type[0]!=="'") ? "'debut'.$type"
152          : ("'debut" .substr($type,1));
153
154        $boucle->modificateur['debut_nom'] = $type;
155        $partie =
156                 // tester si le numero de page demande est de la forme '@yyy'
157                 'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n"
158                ."\tif(substr(\$debut_boucle,0,1)=='@'){\n"
159                ."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = Iterateurs_quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$iter);'."\n"
160                ."\t\t".'$iter->seek(0);'."\n"
161                ."\t}\n"
162                ."\t".'$debut_boucle = intval($debut_boucle)';
163
164
165        $boucle->total_parties = $pas;
166        calculer_parties($boucles, $idb, $partie, 'p+');
167        // ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id
168        // sauf si pas de primaire, ou si primaire composee
169        // dans ce cas, on ne sait pas gerer une pagination indirecte
170        $t = $boucle->id_table . '.' . $boucle->primary;
171        if ($boucle->primary
172                AND !preg_match('/[,\s]/',$boucle->primary)
173                AND !in_array($t, $boucle->select))
174          $boucle->select[]= $t;
175}
176
177
178
179###### BALISES
180/**
181 * #LISTE{a,b,c,d,e} cree un #ARRAY avec les valeurs, sans preciser les cles
182 *
183 * @param <type> $p
184 * @return <type>
185 */
186function balise_LISTE($p) {
187        $_code = array();
188        $n=1;
189        while ($_val = interprete_argument_balise($n++,$p))
190                $_code[] = $_val;
191        $p->code = 'array(' . join(', ',$_code).')';
192        $p->interdire_scripts = false;
193        return $p;
194}
195
196
197/**
198 * #SAUTER{n} permet de sauter en avant n resultats dans une boucle
199 * La balise modifie le compteur courant de la boucle, mais pas les autres
200 * champs qui restent les valeurs de la boucle avant le saut. Il est donc
201 * preferable d'utiliser la balise juste avant la fermeture </BOUCLE>
202 *
203 * L'argument n doit etre superieur a zero sinon la balise ne fait rien
204 *
205 * @param <type> $p
206 * @return <type>
207 */
208function balise_SAUTER($p){
209        $id_boucle = $p->id_boucle;
210        $boucle = $p->boucles[$id_boucle];
211
212        if (!$boucle) {
213                $msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER'));
214                erreur_squelette($msg, $p);
215        }
216        else {
217                $_saut = interprete_argument_balise(1,$p);
218                $_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
219                $_total = "\$Numrows['$id_boucle']['total']";
220
221                $p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
222        }
223        $p->interdire_scripts = false;
224        return $p;
225}
226
227// #VALEUR renvoie le champ valeur
228// #VALEUR{x} renvoie #VALEUR|Iterateurs_table_valeur{x}
229// #VALEUR{a/b} renvoie #VALEUR|Iterateurs_table_valeur{a/b}
230function balise_VALEUR($p) {
231        $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
232        $p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);;
233        if (($v = interprete_argument_balise(1,$p))!==NULL){
234                $p->code = 'Iterateurs_table_valeur('.$p->code.', '.$v.')';
235        }
236        $p->interdire_scripts = true;
237        return $p;
238}
239
240
241function Iterateurs_quete_debut_pagination($primary,$valeur,$pas,$iter){
242        // on ne devrait pas arriver ici si la cle primaire est inexistante
243        // ou composee, mais verifions
244        if (!$primary OR preg_match('/[,\s]/',$primary))
245                return 0;
246
247        $pos = 0;
248        while ($row = $iter->fetch() AND $row[$primary]!=$valeur){
249                $pos++;
250        }
251        // si on a pas trouve
252        if ($row[$primary]!=$valeur)
253                return 0;
254
255        // sinon, calculer le bon numero de page
256        return floor($pos/$pas)*$pas;
257}
258
259// afficher proprement n'importe quoi
260// en cas de table profonde, l'option $join ne s'applique qu'au plus haut niveau
261// c'est VOULU !  Exemple : [(#VALEUR|print{<hr />})] va afficher de gros blocs
262// separes par des lignes, avec a l'interieur des trucs separes par des virgules
263function filtre_print($u, $join=', ') {
264        if (is_string($u))
265                return typo($u);
266
267        if (is_array($u))
268                return join($join, array_map('filtre_print', $u));
269
270        if (is_object($u))
271                return join($join, array_map('filtre_print', (array) $u));
272
273        return $u;
274}
275
Note: See TracBrowser for help on using the repository browser.