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

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

Report de http://core.spip.org/projects/spip/repository/revisions/19098 : pouvoir mettre plusieurs critères {si x} sans écraser le précédent

File size: 8.1 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
107/* le critere {si ...} applicable a toutes les boucles */
108function critere_si($idb, &$boucles, $crit) {
109        $boucle = &$boucles[$idb];
110        $boucle->hash .= 'if (!isset($command[\'si\'])) $command[\'si\'] = array();'."\n";
111        if ($crit->param) {
112                foreach($crit->param as $param) {
113                        $boucle->hash .= '
114                                $command[\'si\'][] = '.calculer_liste($param, array(), $boucles, $boucles[$idb]->id_parent).';';
115                }
116        // interdire {si 0} aussi !
117        } else {
118                        $boucle->hash .= '$command[\'si\'][] = 0;';
119        }
120}
121
122
123// {pagination}
124// {pagination 20}
125// {pagination #ENV{pages,5}} etc
126// {pagination 20 #ENV{truc,chose}} pour utiliser la variable debut_#ENV{truc,chose}
127// http://www.spip.net/@pagination
128// http://doc.spip.org/@critere_pagination
129function critere_pagination($idb, &$boucles, $crit) {
130
131        $boucle = &$boucles[$idb];
132        // definition de la taille de la page
133        $pas = !isset($crit->param[0][0]) ? "''" : calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent);
134
135        if (!preg_match(_CODE_QUOTE, $pas, $r)) {
136                $pas = "((\$a = intval($pas)) ? \$a : 10)";
137        } else {
138                $r = intval($r[2]);
139                $pas = strval($r ? $r : 10);
140        }
141        $type = !isset($crit->param[0][1]) ? "'$idb'" : calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucle->id_parent);
142        $debut = ($type[0]!=="'") ? "'debut'.$type" 
143          : ("'debut" .substr($type,1));
144
145        $boucle->modificateur['debut_nom'] = $type;
146        $partie =
147                 // tester si le numero de page demande est de la forme '@yyy'
148                 'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n"
149                ."\tif(substr(\$debut_boucle,0,1)=='@'){\n"
150                ."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = Iterateurs_quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$iter);'."\n"
151                ."\t\t".'$iter->seek(0);'."\n"
152                ."\t}\n"
153                ."\t".'$debut_boucle = intval($debut_boucle)';
154
155
156        $boucle->total_parties = $pas;
157        calculer_parties($boucles, $idb, $partie, 'p+');
158        // ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id
159        // sauf si pas de primaire, ou si primaire composee
160        // dans ce cas, on ne sait pas gerer une pagination indirecte
161        $t = $boucle->id_table . '.' . $boucle->primary;
162        if ($boucle->primary
163                AND !preg_match('/[,\s]/',$boucle->primary)
164                AND !in_array($t, $boucle->select))
165          $boucle->select[]= $t;
166}
167
168
169
170###### BALISES
171/**
172 * #LISTE{a,b,c,d,e} cree un #ARRAY avec les valeurs, sans preciser les cles
173 *
174 * @param <type> $p
175 * @return <type>
176 */
177function balise_LISTE($p) {
178        $_code = array();
179        $n=1;
180        while ($_val = interprete_argument_balise($n++,$p))
181                $_code[] = $_val;
182        $p->code = 'array(' . join(', ',$_code).')';
183        $p->interdire_scripts = false;
184        return $p;
185}
186
187
188/**
189 * #SAUTER{n} permet de sauter en avant n resultats dans une boucle
190 * La balise modifie le compteur courant de la boucle, mais pas les autres
191 * champs qui restent les valeurs de la boucle avant le saut. Il est donc
192 * preferable d'utiliser la balise juste avant la fermeture </BOUCLE>
193 *
194 * L'argument n doit etre superieur a zero sinon la balise ne fait rien
195 *
196 * @param <type> $p
197 * @return <type>
198 */
199function balise_SAUTER($p){
200        $id_boucle = $p->id_boucle;
201        $boucle = $p->boucles[$id_boucle];
202
203        if (!$boucle) {
204                $msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER'));
205                erreur_squelette($msg, $p);
206        }
207        else {
208                $_saut = interprete_argument_balise(1,$p);
209                $_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
210                $_total = "\$Numrows['$id_boucle']['total']";
211
212                $p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
213        }
214        $p->interdire_scripts = false;
215        return $p;
216}
217
218// #VALEUR renvoie le champ valeur
219// #VALEUR{x} renvoie #VALEUR|Iterateurs_table_valeur{x}
220// #VALEUR{a/b} renvoie #VALEUR|Iterateurs_table_valeur{a/b}
221function balise_VALEUR($p) {
222        $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
223        $p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);;
224        if (($v = interprete_argument_balise(1,$p))!==NULL){
225                $p->code = 'Iterateurs_table_valeur('.$p->code.', '.$v.')';
226        }
227        $p->interdire_scripts = true;
228        return $p;
229}
230
231
232function Iterateurs_quete_debut_pagination($primary,$valeur,$pas,$iter){
233        // on ne devrait pas arriver ici si la cle primaire est inexistante
234        // ou composee, mais verifions
235        if (!$primary OR preg_match('/[,\s]/',$primary))
236                return 0;
237
238        $pos = 0;
239        while ($row = $iter->fetch() AND $row[$primary]!=$valeur){
240                $pos++;
241        }
242        // si on a pas trouve
243        if ($row[$primary]!=$valeur)
244                return 0;
245
246        // sinon, calculer le bon numero de page
247        return floor($pos/$pas)*$pas;
248}
249
250// afficher proprement n'importe quoi
251// en cas de table profonde, l'option $join ne s'applique qu'au plus haut niveau
252// c'est VOULU !  Exemple : [(#VALEUR|print{<hr />})] va afficher de gros blocs
253// separes par des lignes, avec a l'interieur des trucs separes par des virgules
254function filtre_print($u, $join=', ') {
255        if (is_string($u))
256                return typo($u);
257
258        if (is_array($u))
259                return join($join, array_map('filtre_print', $u));
260
261        if (is_object($u))
262                return join($join, array_map('filtre_print', (array) $u));
263
264        return $u;
265}
266
Note: See TracBrowser for help on using the repository browser.