|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/***************************************************************************\ |
|
4
|
|
|
* SPIP, Systeme de publication pour l'internet * |
|
5
|
|
|
* * |
|
6
|
|
|
* Copyright (c) 2001-2016 * |
|
7
|
|
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|
8
|
|
|
* * |
|
9
|
|
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. * |
|
10
|
|
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * |
|
11
|
|
|
\***************************************************************************/ |
|
12
|
|
|
|
|
13
|
|
|
// |
|
14
|
|
|
// Definition des {criteres} d'une boucle |
|
15
|
|
|
// |
|
16
|
|
|
|
|
17
|
|
|
// Une Regexp reperant une chaine produite par le compilateur, |
|
18
|
|
|
// souvent utilisee pour faire de la concatenation lors de la compilation |
|
19
|
|
|
// plutot qu'a l'execution, i.e. pour remplacer 'x'.'y' par 'xy' |
|
20
|
|
|
|
|
21
|
|
|
define('_CODE_QUOTE', ",^(\n//[^\n]*\n)? *'(.*)' *$,"); |
|
22
|
|
|
|
|
23
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) return; |
|
24
|
|
|
|
|
25
|
|
|
// {racine} |
|
26
|
|
|
// http://www.spip.net/@racine |
|
27
|
|
|
// http://doc.spip.org/@critere_racine_dist |
|
28
|
|
|
function critere_racine_dist($idb, &$boucles, $crit) { |
|
29
|
|
|
global $exceptions_des_tables; |
|
30
|
|
|
$not = $crit->not; |
|
31
|
|
|
$boucle = &$boucles[$idb]; |
|
32
|
|
|
$id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ? |
|
33
|
|
|
$exceptions_des_tables[$boucle->id_table]['id_parent'] : |
|
34
|
|
|
'id_parent'; |
|
35
|
|
|
|
|
36
|
|
|
if ($not) |
|
37
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $not . $crit->op))); |
|
38
|
|
|
|
|
39
|
|
|
$boucle->where[]= array("'='", "'$boucle->id_table." . "$id_parent'", 0); |
|
40
|
|
|
} |
|
41
|
|
|
|
|
42
|
|
|
// {exclus} |
|
43
|
|
|
// http://www.spip.net/@exclus |
|
44
|
|
|
// http://doc.spip.org/@critere_exclus_dist |
|
45
|
|
|
function critere_exclus_dist($idb, &$boucles, $crit) { |
|
46
|
|
|
$not = $crit->not; |
|
47
|
|
|
$boucle = &$boucles[$idb]; |
|
48
|
|
|
$id = $boucle->primary; |
|
49
|
|
|
|
|
50
|
|
View Code Duplication |
if ($not OR !$id) |
|
|
|
|
|
|
51
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $not . $crit->op))); |
|
52
|
|
|
$arg = kwote(calculer_argument_precedent($idb, $id, $boucles)); |
|
53
|
|
|
$boucle->where[]= array("'!='", "'$boucle->id_table." . "$id'", $arg); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
// {doublons} ou {unique} |
|
57
|
|
|
// http://www.spip.net/@doublons |
|
58
|
|
|
// attention: boucle->doublons designe une variable qu'on affecte |
|
59
|
|
|
// http://doc.spip.org/@critere_doublons_dist |
|
60
|
|
|
function critere_doublons_dist($idb, &$boucles, $crit) { |
|
61
|
|
|
$boucle = &$boucles[$idb]; |
|
62
|
|
|
$primary = $boucle->primary; |
|
63
|
|
|
$type = $boucle->type_requete; |
|
64
|
|
|
// Dans le cas NOT, la table du doublon peut etre indiquee |
|
65
|
|
|
// si la table courante a un champ homonyme de sa cle primaire. |
|
66
|
|
|
// Tres utile pour la table des forums. |
|
67
|
|
|
if (isset($crit->param[1])) { |
|
68
|
|
|
$primary = ''; |
|
69
|
|
|
$x = !$crit->not ? '' : calculer_liste($crit->param[1], array(), $boucles, $boucle->id_parent); |
|
70
|
|
|
# attention au commentaire "// x signes" qui precede |
|
71
|
|
|
if (preg_match(",^(?:\s*//[^\n]*\n)?'([^']+)'*$,ms", $x, $m)) { |
|
72
|
|
|
$x = id_table_objet($type = $m[1]); |
|
73
|
|
|
if (isset($boucle->show['field'][$x])) |
|
74
|
|
|
$primary = $x; // sinon erreur declenchee ci-dessous |
|
75
|
|
|
} |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
if (!$primary OR strpos($primary,',')) { |
|
79
|
|
|
return (array('zbug_doublon_sur_table_sans_cle_primaire')); |
|
80
|
|
|
} |
|
81
|
|
|
$not = ($crit->not ? '' : 'NOT'); |
|
82
|
|
|
$nom = !isset($crit->param[0]) ? "''" : calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent); |
|
83
|
|
|
// mettre un tableau pour que ce ne soit pas vu comme une constante |
|
84
|
|
|
|
|
85
|
|
|
$nom = "'" . $type . "'" . ($nom == "''" ? '' : " . $nom"); |
|
86
|
|
|
|
|
87
|
|
|
$debutdoub = '$doublons[' |
|
88
|
|
|
. (!$not ? '' : ($boucle->doublons . "[]= ")); |
|
89
|
|
|
|
|
90
|
|
|
$findoub = "($nom)]"; |
|
91
|
|
|
|
|
92
|
|
|
$debin = "sql_in('" . $boucle->id_table . '.' . $primary . "', "; |
|
93
|
|
|
|
|
94
|
|
|
$suitin = $debin . $debutdoub; |
|
95
|
|
|
|
|
96
|
|
|
// si autre critere doublon, fusionner pour avoir un seul In |
|
97
|
|
|
foreach ($boucle->where as $k => $w) { |
|
98
|
|
|
if (strpos($w[0], $suitin) ===0) { |
|
99
|
|
|
$boucle->where[$k][0] = $debin . $debutdoub . $findoub . ' . ' . substr($w[0],strlen($debin)); |
|
100
|
|
|
return; |
|
101
|
|
|
} |
|
102
|
|
|
} |
|
103
|
|
|
$boucle->where[]= array($suitin . $findoub . ", '" . $not . "')"); |
|
104
|
|
|
|
|
105
|
|
|
# la ligne suivante avait l'intention d'eviter une collecte deja faite |
|
106
|
|
|
# mais elle fait planter une boucle a 2 critere doublons: |
|
107
|
|
|
# {!doublons A}{doublons B} |
|
108
|
|
|
# (de http://article.gmane.org/gmane.comp.web.spip.devel/31034) |
|
109
|
|
|
# if ($crit->not) $boucle->doublons = ""; |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
// {lang_select} |
|
113
|
|
|
// http://www.spip.net/@lang_select |
|
114
|
|
|
// http://doc.spip.org/@critere_lang_select_dist |
|
115
|
|
|
function critere_lang_select_dist($idb, &$boucles, $crit) { |
|
116
|
|
|
if (!($param = $crit->param[1][0]->texte)) $param = 'oui'; |
|
117
|
|
|
if ($crit->not) $param = ($param=='oui') ? 'non' : 'oui'; |
|
118
|
|
|
$boucle = &$boucles[$idb]; |
|
119
|
|
|
$boucle->lang_select = $param; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
// {debut_xxx} |
|
123
|
|
|
// http://www.spip.net/@debut_ |
|
124
|
|
|
// http://doc.spip.org/@critere_debut_dist |
|
125
|
|
|
function critere_debut_dist($idb, &$boucles, $crit) { |
|
126
|
|
|
list($un, $deux) = $crit->param; |
|
127
|
|
|
$un = $un[0]->texte; |
|
128
|
|
|
$deux = $deux[0]->texte; |
|
129
|
|
|
if ($deux) { |
|
130
|
|
|
$boucles[$idb]->limit = 'intval($Pile[0]["debut' . |
|
131
|
|
|
$un . |
|
132
|
|
|
'"]) . ",' . |
|
133
|
|
|
$deux . |
|
134
|
|
|
'"' ; |
|
135
|
|
|
} else calculer_critere_DEFAUT_dist($idb, $boucles, $crit); |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
// {pagination} |
|
139
|
|
|
// {pagination 20} |
|
140
|
|
|
// {pagination #ENV{pages,5}} etc |
|
141
|
|
|
// {pagination 20 #ENV{truc,chose}} pour utiliser la variable debut_#ENV{truc,chose} |
|
142
|
|
|
// http://www.spip.net/@pagination |
|
143
|
|
|
// http://doc.spip.org/@critere_pagination_dist |
|
144
|
|
|
function critere_pagination_dist($idb, &$boucles, $crit) { |
|
145
|
|
|
|
|
146
|
|
|
$boucle = &$boucles[$idb]; |
|
147
|
|
|
// definition de la taille de la page |
|
148
|
|
|
$pas = !isset($crit->param[0][0]) ? "''" : calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucle->id_parent); |
|
149
|
|
|
|
|
150
|
|
|
if (!preg_match(_CODE_QUOTE, $pas, $r)) { |
|
151
|
|
|
$pas = "((\$a = intval($pas)) ? \$a : 10)"; |
|
152
|
|
|
} else { |
|
153
|
|
|
$r = intval($r[2]); |
|
154
|
|
|
$pas = strval($r ? $r : 10); |
|
155
|
|
|
} |
|
156
|
|
|
$type = !isset($crit->param[0][1]) ? "'$idb'" : calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucle->id_parent); |
|
157
|
|
|
$debut = ($type[0]!=="'") ? "'debut'.$type" |
|
158
|
|
|
: ("'debut" .substr($type,1)); |
|
159
|
|
|
|
|
160
|
|
|
$boucle->modificateur['debut_nom'] = $type; |
|
161
|
|
|
$partie = |
|
162
|
|
|
// tester si le numero de page demande est de la forme '@yyy' |
|
163
|
|
|
'isset($Pile[0]['.$debut.']) ? $Pile[0]['.$debut.'] : _request('.$debut.");\n" |
|
164
|
|
|
."\tif(substr(\$debut_boucle,0,1)=='@'){\n" |
|
165
|
|
|
."\t\t".'$debut_boucle = $Pile[0]['. $debut.'] = quete_debut_pagination(\''.$boucle->primary.'\',$Pile[0][\'@'.$boucle->primary.'\'] = substr($debut_boucle,1),'.$pas.',$result,'._q($boucle->sql_serveur).');'."\n" |
|
166
|
|
|
."\t\t".'if (!sql_seek($result,0,'._q($boucle->sql_serveur).")){\n" |
|
167
|
|
|
."\t\t\t".'@sql_free($result,'._q($boucle->sql_serveur).");\n" |
|
168
|
|
|
."\t\t\t".'$result = calculer_select($select, $from, $type, $where, $join, $groupby, $orderby, $limit, $having, $table, $id, $connect);'."\n" |
|
169
|
|
|
."\t\t}\n" |
|
170
|
|
|
."\t}\n" |
|
171
|
|
|
."\t".'$debut_boucle = intval($debut_boucle)'; |
|
172
|
|
|
|
|
173
|
|
|
|
|
174
|
|
|
$boucle->total_parties = $pas; |
|
175
|
|
|
calculer_parties($boucles, $idb, $partie, 'p+'); |
|
176
|
|
|
// ajouter la cle primaire dans le select pour pouvoir gerer la pagination referencee par @id |
|
177
|
|
|
// sauf si pas de primaire, ou si primaire composee |
|
178
|
|
|
// dans ce cas, on ne sait pas gerer une pagination indirecte |
|
179
|
|
|
$t = $boucle->id_table . '.' . $boucle->primary; |
|
180
|
|
|
if ($boucle->primary |
|
181
|
|
|
AND !preg_match('/[,\s]/',$boucle->primary) |
|
182
|
|
|
AND !in_array($t, $boucle->select)) |
|
183
|
|
|
$boucle->select[]= $t; |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
|
|
187
|
|
|
// {recherche} ou {recherche susan} |
|
188
|
|
|
// http://www.spip.net/@recherche |
|
189
|
|
|
// http://doc.spip.org/@critere_recherche_dist |
|
190
|
|
|
function critere_recherche_dist($idb, &$boucles, $crit) { |
|
191
|
|
|
|
|
192
|
|
|
$boucle = &$boucles[$idb]; |
|
193
|
|
|
|
|
194
|
|
View Code Duplication |
if (isset($crit->param[0])) |
|
|
|
|
|
|
195
|
|
|
$quoi = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent); |
|
196
|
|
|
else |
|
197
|
|
|
$quoi = '@$Pile[0]["recherche"]'; |
|
198
|
|
|
|
|
199
|
|
|
// indiquer si l'on est dans une boucle forum avec le critère {plat} ou {tout} |
|
200
|
|
|
$plat = "false" ; |
|
201
|
|
|
if (isset($boucle->modificateur['tout']) OR isset($boucle->modificateur['plat'])) { |
|
202
|
|
|
$plat = "true" ; |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
$boucle->hash .= ' |
|
206
|
|
|
// RECHERCHE |
|
207
|
|
|
$prepare_recherche = charger_fonction(\'prepare_recherche\', \'inc\'); |
|
208
|
|
|
list($rech_select, $rech_where) = $prepare_recherche('.$quoi.', "'.$boucle->id_table.'", "'.$crit->cond.'","' . $boucle->sql_serveur . '", "'.$plat.'"); |
|
209
|
|
|
'; |
|
210
|
|
|
|
|
211
|
|
|
$t = $boucle->id_table . '.' . $boucle->primary; |
|
212
|
|
|
if (!in_array($t, $boucles[$idb]->select)) |
|
213
|
|
|
$boucle->select[]= $t; # pour postgres, neuneu ici |
|
214
|
|
|
$boucle->join['resultats']=array("'".$boucle->id_table."'","'id'","'".$boucle->primary."'"); |
|
215
|
|
|
$boucle->from['resultats']='spip_resultats'; |
|
216
|
|
|
$boucle->select[]= '$rech_select'; |
|
217
|
|
|
//$boucle->where[]= "\$rech_where?'resultats.id=".$boucle->id_table.".".$boucle->primary."':''"; |
|
218
|
|
|
|
|
219
|
|
|
// et la recherche trouve |
|
220
|
|
|
$boucle->where[]= '$rech_where?$rech_where:\'\''; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
// {traduction} |
|
224
|
|
|
// http://www.spip.net/@traduction |
|
225
|
|
|
// (id_trad>0 AND id_trad=id_trad(precedent)) |
|
226
|
|
|
// OR id_article=id_article(precedent) |
|
227
|
|
|
// http://doc.spip.org/@critere_traduction_dist |
|
228
|
|
|
function critere_traduction_dist($idb, &$boucles, $crit) { |
|
|
|
|
|
|
229
|
|
|
$boucle = &$boucles[$idb]; |
|
230
|
|
|
$prim = $boucle->primary; |
|
231
|
|
|
$table = $boucle->id_table; |
|
232
|
|
|
$arg = kwote(calculer_argument_precedent($idb, 'id_trad', $boucles)); |
|
233
|
|
|
$dprim = kwote(calculer_argument_precedent($idb, $prim, $boucles)); |
|
234
|
|
|
$boucle->where[]= |
|
235
|
|
|
array("'OR'", |
|
236
|
|
|
array("'AND'", |
|
237
|
|
|
array("'='", "'$table.id_trad'", 0), |
|
238
|
|
|
array("'='", "'$table.$prim'", $dprim) |
|
239
|
|
|
), |
|
240
|
|
|
array("'AND'", |
|
241
|
|
|
array("'>'", "'$table.id_trad'", 0), |
|
242
|
|
|
array("'='", "'$table.id_trad'", $arg) |
|
243
|
|
|
) |
|
244
|
|
|
); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
// {origine_traduction} |
|
248
|
|
|
// (id_trad>0 AND id_article=id_trad) OR (id_trad=0) |
|
249
|
|
|
// http://www.spip.net/@origine_traduction |
|
250
|
|
|
// http://doc.spip.org/@critere_origine_traduction_dist |
|
251
|
|
|
function critere_origine_traduction_dist($idb, &$boucles, $crit) { |
|
252
|
|
|
$boucle = &$boucles[$idb]; |
|
253
|
|
|
$prim = $boucle->primary; |
|
254
|
|
|
$table = $boucle->id_table; |
|
255
|
|
|
|
|
256
|
|
|
$c = |
|
257
|
|
|
array("'OR'", |
|
258
|
|
|
array("'='", "'$table." . "id_trad'", "'$table.$prim'"), |
|
259
|
|
|
array("'='", "'$table.id_trad'", "'0'") |
|
260
|
|
|
); |
|
261
|
|
|
$boucle->where[]= ($crit->not ? array("'NOT'", $c) : $c); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
// {meme_parent} |
|
265
|
|
|
// http://www.spip.net/@meme_parent |
|
266
|
|
|
// http://doc.spip.org/@critere_meme_parent_dist |
|
267
|
|
|
function critere_meme_parent_dist($idb, &$boucles, $crit) { |
|
|
|
|
|
|
268
|
|
|
global $exceptions_des_tables; |
|
269
|
|
|
$boucle = &$boucles[$idb]; |
|
270
|
|
|
$arg = kwote(calculer_argument_precedent($idb, 'id_parent', $boucles)); |
|
271
|
|
|
$id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ? |
|
272
|
|
|
$exceptions_des_tables[$boucle->id_table]['id_parent'] : |
|
273
|
|
|
'id_parent'; |
|
274
|
|
|
$mparent = $boucle->id_table . '.' . $id_parent; |
|
275
|
|
|
|
|
276
|
|
|
if ($boucle->type_requete == 'rubriques' OR isset($exceptions_des_tables[$boucle->id_table]['id_parent'])) { |
|
277
|
|
|
$boucle->where[]= array("'='", "'$mparent'", $arg); |
|
278
|
|
|
|
|
279
|
|
|
} else if ($boucle->type_requete == 'forums') { |
|
280
|
|
|
$boucle->where[]= array("'='", "'$mparent'", $arg); |
|
281
|
|
|
$boucle->where[]= array("'>'", "'$mparent'", 0); |
|
282
|
|
|
$boucle->modificateur['plat'] = true; |
|
283
|
|
|
} else erreur_squelette(_T('zbug_info_erreur_squelette'), "{meme_parent} BOUCLE$idb"); |
|
284
|
|
|
} |
|
285
|
|
|
|
|
286
|
|
|
// {branche ?} |
|
287
|
|
|
// http://www.spip.net/@branche |
|
288
|
|
|
// http://doc.spip.org/@critere_branche_dist |
|
289
|
|
|
function critere_branche_dist($idb, &$boucles, $crit) { |
|
290
|
|
|
|
|
291
|
|
|
$not = $crit->not; |
|
292
|
|
|
$boucle = &$boucles[$idb]; |
|
293
|
|
|
$arg = calculer_argument_precedent($idb, 'id_rubrique', $boucles); |
|
294
|
|
|
|
|
295
|
|
|
//Trouver une jointure |
|
296
|
|
|
$desc = $boucle->show; |
|
297
|
|
|
//Seulement si necessaire |
|
298
|
|
|
if (!array_key_exists('id_rubrique', $desc['field'])) { |
|
299
|
|
|
$cle = trouver_jointure_champ('id_rubrique', $boucle); |
|
300
|
|
|
} else $cle = $boucle->id_table; |
|
301
|
|
|
|
|
302
|
|
|
$c = "sql_in('$cle" . ".id_rubrique', calcul_branche_in($arg)" |
|
303
|
|
|
. ($not ? ", 'NOT'" : '') . ")"; |
|
304
|
|
|
$boucle->where[]= !$crit->cond ? $c : |
|
305
|
|
|
("($arg ? $c : " . ($not ? "'0=1'" : "'1=1'") .')'); |
|
306
|
|
|
} |
|
307
|
|
|
|
|
308
|
|
|
// {logo} liste les objets qui ont un logo |
|
309
|
|
|
// http://doc.spip.org/@critere_logo_dist |
|
310
|
|
|
function critere_logo_dist($idb, &$boucles, $crit) { |
|
311
|
|
|
|
|
312
|
|
|
$not = $crit->not; |
|
313
|
|
|
$boucle = &$boucles[$idb]; |
|
314
|
|
|
|
|
315
|
|
|
$c = "sql_in('" . |
|
316
|
|
|
$boucle->id_table . '.' . $boucle->primary |
|
317
|
|
|
. "', lister_objets_avec_logos('". $boucle->primary ."'), '')"; |
|
318
|
|
|
if ($crit->cond) $c = "($arg ? $c : 1)"; |
|
|
|
|
|
|
319
|
|
|
|
|
320
|
|
|
if ($not) |
|
321
|
|
|
$boucle->where[]= array("'NOT'", $c); |
|
322
|
|
|
else |
|
323
|
|
|
$boucle->where[]= $c; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
// c'est la commande SQL "GROUP BY" |
|
327
|
|
|
// par exemple <boucle(articles){fusion lang}> |
|
328
|
|
|
// http://doc.spip.org/@critere_fusion_dist |
|
329
|
|
|
function critere_fusion_dist($idb,&$boucles, $crit) { |
|
330
|
|
|
if ($t = isset($crit->param[0])) { |
|
331
|
|
|
$t = $crit->param[0]; |
|
332
|
|
|
if ($t[0]->type == 'texte') { |
|
333
|
|
|
$t = $t[0]->texte; |
|
334
|
|
View Code Duplication |
if (preg_match("/^(.*)\.(.*)$/", $t, $r)) { |
|
|
|
|
|
|
335
|
|
|
$t = table_objet_sql($r[1]); |
|
336
|
|
|
$t = array_search($t, $boucles[$idb]->from); |
|
337
|
|
|
if ($t) $t .= '.' . $r[2]; |
|
338
|
|
|
} |
|
339
|
|
|
} else { $t = '".' |
|
340
|
|
|
. calculer_critere_arg_dynamique($idb, $boucles, $t) |
|
341
|
|
|
. '."'; |
|
342
|
|
|
} |
|
343
|
|
|
} |
|
344
|
|
|
if ($t) { |
|
345
|
|
|
$boucles[$idb]->group[] = $t; |
|
346
|
|
View Code Duplication |
if (!in_array($t, $boucles[$idb]->select)) |
|
|
|
|
|
|
347
|
|
|
$boucles[$idb]->select[] = $t; |
|
348
|
|
|
} else |
|
349
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . ' ?'))); |
|
350
|
|
|
} |
|
351
|
|
|
|
|
352
|
|
|
// c'est la commande SQL "COLLATE" |
|
353
|
|
|
// qui peut etre appliquee sur les order by, group by, where like ... |
|
354
|
|
|
// http://doc.spip.org/@critere_collecte_dist |
|
355
|
|
|
function critere_collecte_dist($idb,&$boucles, $crit) { |
|
356
|
|
|
if (isset($crit->param[0])) { |
|
357
|
|
|
$_coll = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent); |
|
358
|
|
|
$boucle = $boucles[$idb]; |
|
359
|
|
|
$boucle->modificateur['collate'] = "($_coll ?' COLLATE '.$_coll:'')"; |
|
360
|
|
|
$n = count($boucle->order); |
|
361
|
|
|
if ($n && (strpos($boucle->order[$n-1],'COLLATE')===false)) |
|
362
|
|
|
$boucle->order[$n-1] .= " . " . $boucle->modificateur['collate']; |
|
363
|
|
|
} else |
|
364
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . " $n"))); |
|
|
|
|
|
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
// http://doc.spip.org/@calculer_critere_arg_dynamique |
|
368
|
|
|
function calculer_critere_arg_dynamique($idb, &$boucles, $crit, $suffix='') |
|
369
|
|
|
{ |
|
370
|
|
|
$boucle = $boucles[$idb]; |
|
371
|
|
|
$alt = "('" . $boucle->id_table . '.\' . $x' . $suffix . ')'; |
|
372
|
|
|
$var = '$champs_' . $idb; |
|
373
|
|
|
$desc = (strpos($boucle->in, "static $var =") !== false); |
|
374
|
|
|
if (!$desc) { |
|
375
|
|
|
$desc = $boucle->show['field']; |
|
376
|
|
|
$desc = implode(',',array_map('_q',array_keys($desc))); |
|
377
|
|
|
$boucles[$idb]->in .= "\n\tstatic $var = array(" . $desc .");"; |
|
378
|
|
|
} |
|
379
|
|
|
if ($desc) $alt = "(in_array(\$x, $var) ? $alt :(\$x$suffix))"; |
|
380
|
|
|
$arg = calculer_liste($crit, array(), $boucles, $boucle->id_parent); |
|
381
|
|
|
return "((\$x = preg_replace(\"/\\W/\",'', $arg)) ? $alt : '')"; |
|
382
|
|
|
} |
|
383
|
|
|
// Tri : {par xxxx} |
|
384
|
|
|
// http://www.spip.net/@par |
|
385
|
|
|
// http://doc.spip.org/@critere_par_dist |
|
386
|
|
|
function critere_par_dist($idb, &$boucles, $crit) { |
|
387
|
|
|
return critere_parinverse($idb, $boucles, $crit) ; |
|
388
|
|
|
} |
|
389
|
|
|
|
|
390
|
|
|
// http://doc.spip.org/@critere_parinverse |
|
391
|
|
|
function critere_parinverse($idb, &$boucles, $crit, $sens='') { |
|
392
|
|
|
global $exceptions_des_jointures; |
|
393
|
|
|
$boucle = &$boucles[$idb]; |
|
394
|
|
|
if ($crit->not) $sens = $sens ? "" : " . ' DESC'"; |
|
395
|
|
|
$collecte = (isset($boucle->modificateur['collecte']))?" . ".$boucle->modificateur['collecte']:""; |
|
396
|
|
|
|
|
397
|
|
|
foreach ($crit->param as $tri) { |
|
398
|
|
|
|
|
399
|
|
|
$order = $fct = ""; // en cas de fonction SQL |
|
|
|
|
|
|
400
|
|
|
// tris specifies dynamiquement |
|
401
|
|
|
if ($tri[0]->type != 'texte') { |
|
402
|
|
|
// calculer le order dynamique qui verifie les champs |
|
403
|
|
|
$order = calculer_critere_arg_dynamique($idb, $boucles, $tri, $sens); |
|
404
|
|
|
// et si ce n'est fait, ajouter un champ 'hasard' |
|
405
|
|
|
// pour supporter 'hasard' comme tri dynamique |
|
406
|
|
|
$par = "rand()"; |
|
407
|
|
|
$parha = $par . " AS hasard"; |
|
408
|
|
|
if (!in_array($parha, $boucle->select)) |
|
409
|
|
|
$boucle->select[]= $parha; |
|
410
|
|
|
} else { |
|
411
|
|
|
$par = array_shift($tri); |
|
412
|
|
|
$par = $par->texte; |
|
413
|
|
|
// par multi champ |
|
414
|
|
|
if (preg_match(",^multi[\s]*(.*)$,",$par, $m)) { |
|
415
|
|
|
$texte = $boucle->id_table . '.' . trim($m[1]); |
|
416
|
|
|
$boucle->select[] = "\".sql_multi('".$texte."', \$GLOBALS['spip_lang']).\"" ; |
|
417
|
|
|
$order = "'multi'"; |
|
418
|
|
|
// par num champ(, suite) |
|
419
|
|
|
} else if (preg_match(",^num (.*)$,m",$par, $m)) { |
|
420
|
|
|
$texte = '0+' . $boucle->id_table . '.' . trim($m[1]); |
|
421
|
|
|
$suite = calculer_liste($tri, array(), $boucles, $boucle->id_parent); |
|
422
|
|
|
if ($suite !== "''") |
|
423
|
|
|
$texte = "\" . ((\$x = $suite) ? ('$texte' . \$x) : '0')" . " . \""; |
|
424
|
|
|
$as = 'num' .($boucle->order ? count($boucle->order) : ""); |
|
425
|
|
|
$boucle->select[] = $texte . " AS $as"; |
|
426
|
|
|
$order = "'$as'"; |
|
427
|
|
|
} else { |
|
428
|
|
|
if (!preg_match(",^" . CHAMP_SQL_PLUS_FONC . '$,is', $par, $match)) { |
|
429
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . " $par"))); |
|
430
|
|
|
} else { |
|
431
|
|
|
if (count($match)>2) { $par = substr($match[2],1,-1); $fct = $match[1]; } |
|
432
|
|
|
// par hasard |
|
433
|
|
|
if ($par == 'hasard') { |
|
434
|
|
|
$par = "rand()"; |
|
435
|
|
|
$boucle->select[]= $par . " AS alea"; |
|
436
|
|
|
$order = "'alea'"; |
|
437
|
|
|
} |
|
438
|
|
|
// par titre_mot ou type_mot voire d'autres |
|
439
|
|
|
else if (isset($exceptions_des_jointures[$par])) { |
|
440
|
|
|
list($table, $champ) = $exceptions_des_jointures[$par]; |
|
441
|
|
|
$order = critere_par_joint($table, $champ, $boucle, $idb); |
|
442
|
|
View Code Duplication |
if (!$order) |
|
|
|
|
|
|
443
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . " $par"))); |
|
444
|
|
|
} |
|
445
|
|
|
else if ($par == 'date' |
|
446
|
|
|
AND isset($GLOBALS['table_date'][$boucle->type_requete])) { |
|
447
|
|
|
$m = $GLOBALS['table_date'][$boucle->type_requete]; |
|
448
|
|
|
$order = "'".$boucle->id_table ."." . $m . "'"; |
|
449
|
|
|
} |
|
450
|
|
|
// par champ. Verifier qu'ils sont presents. |
|
451
|
|
|
elseif (preg_match("/^([^,]*)\.(.*)$/", $par, $r)) { |
|
452
|
|
|
// cas du tri sur champ de jointure explicite |
|
453
|
|
|
$t = array_search($r[1], $boucle->from); |
|
454
|
|
|
if (!$t) { |
|
455
|
|
|
$t = trouver_champ_exterieur($r[2], array($r[1]), $boucle); |
|
456
|
|
|
$t = array_search(@$t[0], $boucle->from); |
|
457
|
|
|
} |
|
458
|
|
|
if (!$t) { |
|
459
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . " $par"))); |
|
460
|
|
|
} else $order = "'" . $t . '.' . $r[2] . "'"; |
|
461
|
|
|
} else { |
|
462
|
|
|
$desc = $boucle->show; |
|
463
|
|
|
if ($desc['field'][$par]) |
|
464
|
|
|
$par = $boucle->id_table.".".$par; |
|
465
|
|
|
// sinon tant pis, ca doit etre un champ synthetise (cf points) |
|
466
|
|
|
$order = "'$par'"; |
|
467
|
|
|
} |
|
468
|
|
|
} |
|
469
|
|
|
} |
|
470
|
|
|
} |
|
471
|
|
View Code Duplication |
if (preg_match('/^\'([^"]*)\'$/', $order, $m)) { |
|
|
|
|
|
|
472
|
|
|
$t = $m[1]; |
|
473
|
|
|
if (strpos($t,'.') AND !in_array($t, $boucle->select)) { |
|
474
|
|
|
$boucle->select[] = $t; |
|
475
|
|
|
} |
|
476
|
|
|
} else $sens =''; |
|
477
|
|
|
|
|
478
|
|
View Code Duplication |
if ($fct) { |
|
|
|
|
|
|
479
|
|
|
if (preg_match("/^\s*'(.*)'\s*$/", $order, $r)) |
|
480
|
|
|
$order = "'$fct(" . $r[1] . ")'"; |
|
481
|
|
|
else $order = "'$fct(' . $order . ')'"; |
|
482
|
|
|
} |
|
483
|
|
|
$t = $order . $collecte . $sens; |
|
484
|
|
|
if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) |
|
485
|
|
|
$t = $r[1] . $r[2]; |
|
486
|
|
|
$boucle->order[] = $t; |
|
487
|
|
|
} |
|
488
|
|
|
} |
|
489
|
|
|
|
|
490
|
|
|
// http://doc.spip.org/@critere_par_joint |
|
491
|
|
|
function critere_par_joint($table, $champ, &$boucle, $idb) |
|
|
|
|
|
|
492
|
|
|
{ |
|
493
|
|
|
$t = array_search($table, $boucle->from); |
|
494
|
|
|
if (!$t) $t = trouver_jointure_champ($champ, $boucle); |
|
495
|
|
|
return !$t ? '' : ("'" . $t . '.' . $champ . "'"); |
|
496
|
|
|
} |
|
497
|
|
|
|
|
498
|
|
|
// {inverse} |
|
499
|
|
|
// http://www.spip.net/@inverse |
|
500
|
|
|
|
|
501
|
|
|
// http://doc.spip.org/@critere_inverse_dist |
|
502
|
|
|
function critere_inverse_dist($idb, &$boucles, $crit) { |
|
503
|
|
|
|
|
504
|
|
|
$boucle = &$boucles[$idb]; |
|
505
|
|
|
// Classement par ordre inverse |
|
506
|
|
|
if ($crit->not) |
|
507
|
|
|
critere_parinverse($idb, $boucles, $crit); |
|
508
|
|
|
else |
|
509
|
|
|
{ |
|
510
|
|
|
$order = "' DESC'"; |
|
511
|
|
|
// Classement par ordre inverse fonction eventuelle de #ENV{...} |
|
512
|
|
View Code Duplication |
if (isset($crit->param[0])){ |
|
|
|
|
|
|
513
|
|
|
$critere = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent); |
|
514
|
|
|
$order = "(($critere)?' DESC':'')"; |
|
515
|
|
|
} |
|
516
|
|
|
|
|
517
|
|
|
$n = count($boucle->order); |
|
518
|
|
|
if (!$n) { |
|
519
|
|
|
if (isset($boucle->default_order[0])) |
|
520
|
|
|
$boucle->default_order[0] .= ' . " DESC"'; |
|
521
|
|
|
else |
|
522
|
|
|
$boucle->default_order[] = ' DESC'; |
|
523
|
|
|
} |
|
524
|
|
|
else { |
|
525
|
|
|
$t = $boucle->order[$n-1] . " . $order"; |
|
526
|
|
|
if (preg_match("/^(.*)'\s*\.\s*'([^']*')$/", $t, $r)) |
|
527
|
|
|
$t = $r[1] . $r[2]; |
|
528
|
|
|
$boucle->order[$n-1] = $t; |
|
529
|
|
|
} |
|
530
|
|
|
} |
|
531
|
|
|
} |
|
532
|
|
|
|
|
533
|
|
|
// http://doc.spip.org/@critere_agenda_dist |
|
534
|
|
|
function critere_agenda_dist($idb, &$boucles, $crit) |
|
535
|
|
|
{ |
|
536
|
|
|
$params = $crit->param; |
|
537
|
|
|
|
|
538
|
|
|
if (count($params) < 1) |
|
539
|
|
|
return array('zbug_critere_inconnu', array('critere' => $crit->op . " ?")); |
|
540
|
|
|
|
|
541
|
|
|
$boucle = &$boucles[$idb]; |
|
542
|
|
|
$parent = $boucle->id_parent; |
|
543
|
|
|
$fields = $boucle->show['field']; |
|
544
|
|
|
|
|
545
|
|
|
$date = array_shift($params); |
|
546
|
|
|
$type = array_shift($params); |
|
547
|
|
|
|
|
548
|
|
|
// la valeur $type doit etre connue a la compilation |
|
549
|
|
|
// donc etre forcement reduite a un litteral unique dans le source |
|
550
|
|
|
|
|
551
|
|
|
$type = $type[0]->texte; |
|
552
|
|
|
|
|
553
|
|
|
// La valeur date doit designer un champ de la table SQL. |
|
554
|
|
|
// Si c'est un litteral unique dans le source, verifier a la compil, |
|
555
|
|
|
// sinon synthetiser le test de verif pour execution ulterieure |
|
556
|
|
|
// On prendra arbitrairement le premier champ si test negatif. |
|
557
|
|
|
|
|
558
|
|
|
if ((count($date) == 1) AND ($date[0]->type == 'texte')) { |
|
559
|
|
|
$date = $date[0]->texte; |
|
560
|
|
|
if (!isset($fields[$date])) |
|
561
|
|
|
return array('zbug_critere_inconnu', array('critere' => $crit->op . " " . $date)); |
|
562
|
|
|
} else { |
|
563
|
|
|
$a = calculer_liste($date, array(), $boucles, $parent); |
|
564
|
|
|
$noms = array_keys($fields); |
|
565
|
|
|
$defaut = $noms[0]; |
|
566
|
|
|
$noms = join(" ", $noms); |
|
567
|
|
|
# bien laisser 2 espaces avant $nom pour que strpos<>0 |
|
568
|
|
|
$cond = "(\$a=strval($a))AND\nstrpos(\" $noms \",\" \$a \")"; |
|
569
|
|
|
$date = "'.(($cond)\n?\$a:\"$defaut\").'"; |
|
570
|
|
|
} |
|
571
|
|
|
$annee = $params ? array_shift($params) : ""; |
|
572
|
|
|
$annee = "\n" . 'sprintf("%04d", ($x = ' . |
|
573
|
|
|
calculer_liste($annee, array(), $boucles, $parent) . |
|
574
|
|
|
') ? $x : date("Y"))'; |
|
575
|
|
|
|
|
576
|
|
|
$mois = $params ? array_shift($params) : ""; |
|
577
|
|
|
$mois = "\n" . 'sprintf("%02d", ($x = ' . |
|
578
|
|
|
calculer_liste($mois, array(), $boucles, $parent) . |
|
579
|
|
|
') ? $x : date("m"))'; |
|
580
|
|
|
|
|
581
|
|
|
$jour = $params ? array_shift($params) : ""; |
|
582
|
|
|
$jour = "\n" . 'sprintf("%02d", ($x = ' . |
|
583
|
|
|
calculer_liste($jour, array(), $boucles, $parent) . |
|
584
|
|
|
') ? $x : date("d"))'; |
|
585
|
|
|
|
|
586
|
|
|
$annee2 = $params ? array_shift($params) : ""; |
|
587
|
|
|
$annee2 = "\n" . 'sprintf("%04d", ($x = ' . |
|
588
|
|
|
calculer_liste($annee2, array(), $boucles, $parent) . |
|
589
|
|
|
') ? $x : date("Y"))'; |
|
590
|
|
|
|
|
591
|
|
|
$mois2 = $params ? array_shift($params) : ""; |
|
592
|
|
|
$mois2 = "\n" . 'sprintf("%02d", ($x = ' . |
|
593
|
|
|
calculer_liste($mois2, array(), $boucles, $parent) . |
|
594
|
|
|
') ? $x : date("m"))'; |
|
595
|
|
|
|
|
596
|
|
|
$jour2 = $params ? array_shift($params) : ""; |
|
597
|
|
|
$jour2 = "\n" . 'sprintf("%02d", ($x = ' . |
|
598
|
|
|
calculer_liste($jour2, array(), $boucles, $parent) . |
|
599
|
|
|
') ? $x : date("d"))'; |
|
600
|
|
|
|
|
601
|
|
|
$date = $boucle->id_table . ".$date"; |
|
602
|
|
|
|
|
603
|
|
|
if ($type == 'jour') |
|
604
|
|
|
$boucle->where[]= array("'='", "'DATE_FORMAT($date, \'%Y%m%d\')'", |
|
605
|
|
|
("$annee . $mois . $jour")); |
|
606
|
|
|
elseif ($type == 'mois') |
|
607
|
|
|
$boucle->where[]= array("'='", "'DATE_FORMAT($date, \'%Y%m\')'", |
|
608
|
|
|
("$annee . $mois")); |
|
609
|
|
View Code Duplication |
elseif ($type == 'semaine') |
|
|
|
|
|
|
610
|
|
|
$boucle->where[]= array("'AND'", |
|
611
|
|
|
array("'>='", |
|
612
|
|
|
"'DATE_FORMAT($date, \'%Y%m%d\')'", |
|
613
|
|
|
("date_debut_semaine($annee, $mois, $jour)")), |
|
614
|
|
|
array("'<='", |
|
615
|
|
|
"'DATE_FORMAT($date, \'%Y%m%d\')'", |
|
616
|
|
|
("date_fin_semaine($annee, $mois, $jour)"))); |
|
617
|
|
View Code Duplication |
elseif (count($crit->param) > 2) |
|
|
|
|
|
|
618
|
|
|
$boucle->where[]= array("'AND'", |
|
619
|
|
|
array("'>='", |
|
620
|
|
|
"'DATE_FORMAT($date, \'%Y%m%d\')'", |
|
621
|
|
|
("$annee . $mois . $jour")), |
|
622
|
|
|
array("'<='", "'DATE_FORMAT($date, \'%Y%m%d\')'", ("$annee2 . $mois2 . $jour2"))); |
|
623
|
|
|
// sinon on prend tout |
|
624
|
|
|
} |
|
625
|
|
|
|
|
626
|
|
|
// http://doc.spip.org/@calculer_critere_parties |
|
627
|
|
|
function calculer_critere_parties($idb, &$boucles, $crit) { |
|
628
|
|
|
$boucle = &$boucles[$idb]; |
|
629
|
|
|
$a1 = $crit->param[0]; |
|
630
|
|
|
$a2 = $crit->param[1]; |
|
631
|
|
|
$op = $crit->op; |
|
632
|
|
|
|
|
633
|
|
|
list($a11,$a12) = calculer_critere_parties_aux($idb, $boucles, $a1); |
|
634
|
|
|
list($a21,$a22) = calculer_critere_parties_aux($idb, $boucles, $a2); |
|
635
|
|
|
if (($op== ',')&&(is_numeric($a11) && (is_numeric($a21)))) |
|
636
|
|
|
$boucle->limit = $a11 .',' . $a21; |
|
637
|
|
|
else { |
|
638
|
|
|
$boucle->total_parties = ($a21 != 'n') ? $a21 : $a22; |
|
639
|
|
|
$partie = ($a11 != 'n') ? $a11 : $a12; |
|
640
|
|
|
$mode = (($op == '/') ? '/' : |
|
641
|
|
|
(($a11=='n') ? '-' : '+').(($a21=='n') ? '-' : '+')); |
|
642
|
|
|
calculer_parties($boucles, $idb, $partie, $mode); |
|
643
|
|
|
} |
|
644
|
|
|
} |
|
645
|
|
|
|
|
646
|
|
|
// |
|
647
|
|
|
// Code specifique aux criteres {pagination}, {1,n} {n/m} etc |
|
648
|
|
|
// |
|
649
|
|
|
|
|
650
|
|
|
function calculer_parties(&$boucles, $id_boucle, $debut, $mode) { |
|
651
|
|
|
|
|
652
|
|
|
$total_parties = $boucles[$id_boucle]->total_parties; |
|
653
|
|
|
preg_match(",([+-/p])([+-/])?,", $mode, $regs); |
|
654
|
|
|
list(,$op1,$op2) = $regs; |
|
655
|
|
|
$nombre_boucle = "\$Numrows['$id_boucle']['total']"; |
|
656
|
|
|
// {1/3} |
|
657
|
|
|
if ($op1 == '/') { |
|
658
|
|
|
$pmoins1 = is_numeric($debut) ? ($debut-1) : "($debut-1)"; |
|
659
|
|
|
$totpos = is_numeric($total_parties) ? ($total_parties) : |
|
660
|
|
|
"($total_parties ? $total_parties : 1)"; |
|
661
|
|
|
$fin = "ceil(($nombre_boucle * $debut )/$totpos) - 1"; |
|
662
|
|
|
$debut = !$pmoins1 ? 0 : "ceil(($nombre_boucle * $pmoins1)/$totpos);"; |
|
663
|
|
|
} else { |
|
664
|
|
|
// cas {n-1,x} |
|
665
|
|
|
if ($op1 == '-') $debut = "$nombre_boucle - $debut;"; |
|
666
|
|
|
|
|
667
|
|
|
// cas {x,n-1} |
|
668
|
|
|
if ($op2 == '-') { |
|
669
|
|
|
$fin = '$debut_boucle + '.$nombre_boucle.' - ' |
|
670
|
|
|
. (is_numeric($total_parties) ? ($total_parties+1) : |
|
671
|
|
|
($total_parties . ' - 1')); |
|
672
|
|
|
} else { |
|
673
|
|
|
// {x,1} ou {pagination} |
|
674
|
|
|
$fin = '$debut_boucle' |
|
675
|
|
|
. (is_numeric($total_parties) ? |
|
676
|
|
|
(($total_parties==1) ? "" :(' + ' . ($total_parties-1))): |
|
677
|
|
|
('+' . $total_parties . ' - 1')); |
|
678
|
|
|
} |
|
679
|
|
|
|
|
680
|
|
|
// {pagination}, gerer le debut_xx=-1 pour tout voir |
|
681
|
|
|
if ($op1 == 'p') { |
|
682
|
|
|
$debut .= ";\n \$debut_boucle = ((\$tout=(\$debut_boucle == -1))?0:(\$debut_boucle))"; |
|
683
|
|
|
$debut .= ";\n \$debut_boucle = max(0,min(\$debut_boucle,floor(($nombre_boucle-1)/($total_parties))*($total_parties)))"; |
|
684
|
|
|
$fin = "(\$tout ? $nombre_boucle : $fin)"; |
|
685
|
|
|
} |
|
686
|
|
|
} |
|
687
|
|
|
|
|
688
|
|
|
// Notes : |
|
689
|
|
|
// $debut_boucle et $fin_boucle sont les indices SQL du premier |
|
690
|
|
|
// et du dernier demandes dans la boucle : 0 pour le premier, |
|
691
|
|
|
// n-1 pour le dernier ; donc total_boucle = 1 + debut - fin |
|
692
|
|
|
// Utiliser min pour rabattre $fin_boucle sur total_boucle. |
|
693
|
|
|
|
|
694
|
|
|
$boucles[$id_boucle]->mode_partie = "\n\t" |
|
695
|
|
|
. '$debut_boucle = ' . $debut . ";\n " |
|
696
|
|
|
. '$fin_boucle = min(' . $fin . ", \$Numrows['$id_boucle']['total'] - 1);\n " |
|
697
|
|
|
. '$Numrows[\''.$id_boucle. "']['grand_total'] = \$Numrows['$id_boucle']['total'];\n " |
|
698
|
|
|
. '$Numrows[\''.$id_boucle.'\']["total"] = max(0,$fin_boucle - $debut_boucle + 1);' |
|
699
|
|
|
. "\n\tif (\$debut_boucle>0 AND \$debut_boucle < \$Numrows['$id_boucle']['grand_total'] AND sql_seek(\$result,\$debut_boucle,"._q($boucles[$id_boucle]->sql_serveur).",'continue'))\n\t\t\$Numrows['$id_boucle']['compteur_boucle'] = \$debut_boucle;\n\t"; |
|
700
|
|
|
|
|
701
|
|
|
$boucles[$id_boucle]->partie = " |
|
702
|
|
|
if (\$Numrows['$id_boucle']['compteur_boucle'] <= \$debut_boucle) continue; |
|
703
|
|
|
if (\$Numrows['$id_boucle']['compteur_boucle']-1 > \$fin_boucle) break;"; |
|
704
|
|
|
} |
|
705
|
|
|
|
|
706
|
|
|
// http://doc.spip.org/@calculer_critere_parties_aux |
|
707
|
|
|
function calculer_critere_parties_aux($idb, &$boucles, $param) { |
|
708
|
|
|
if ($param[0]->type != 'texte') |
|
709
|
|
|
{ |
|
710
|
|
|
$a1 = calculer_liste(array($param[0]), array('id_mere' => $idb), $boucles, $boucles[$idb]->id_parent); |
|
711
|
|
|
preg_match(',^ *(-([0-9]+))? *$,', $param[1]->texte, $m); |
|
712
|
|
|
return array("intval($a1)", ($m[2] ? $m[2] : 0)); |
|
713
|
|
|
} else { |
|
714
|
|
|
preg_match(',^ *(([0-9]+)|n) *(- *([0-9]+)? *)?$,', $param[0]->texte, $m); |
|
715
|
|
|
$a1 = $m[1]; |
|
716
|
|
|
if (!@$m[3]) |
|
717
|
|
|
return array($a1, 0); |
|
718
|
|
|
elseif ($m[4]) |
|
719
|
|
|
return array($a1, $m[4]); |
|
720
|
|
|
else return array($a1, |
|
721
|
|
|
calculer_liste(array($param[1]), array(), $boucles[$idb]->id_parent, $boucles)); |
|
722
|
|
|
} |
|
723
|
|
|
} |
|
724
|
|
|
|
|
725
|
|
|
// |
|
726
|
|
|
// La fonction d'aiguillage sur le nom du critere dans leur liste |
|
727
|
|
|
// Si l'une au moins des fonctions associees retourne une erreur |
|
728
|
|
|
// (i.e. un tableau), on propage l'information |
|
729
|
|
|
// Sinon, ne retourne rien (affectation directe dans l'arbre) |
|
730
|
|
|
|
|
731
|
|
|
// http://doc.spip.org/@calculer_criteres |
|
732
|
|
|
function calculer_criteres ($idb, &$boucles) |
|
733
|
|
|
{ |
|
734
|
|
|
$msg = ''; |
|
735
|
|
|
$boucle = $boucles[$idb]; |
|
736
|
|
|
$table = strtoupper($boucle->id_table); |
|
737
|
|
|
$defaut = charger_fonction('DEFAUT', 'calculer_critere'); |
|
738
|
|
|
// s'il y avait une erreur de syntaxe, propager cette info |
|
739
|
|
|
if (!is_array($boucle->criteres)) return array(); |
|
740
|
|
|
foreach($boucle->criteres as $crit) { |
|
741
|
|
|
$critere = $crit->op; |
|
742
|
|
|
// critere personnalise ? |
|
743
|
|
|
if ((!function_exists($f="critere_".$table."_".$critere)) |
|
744
|
|
|
AND (!function_exists($f=$f."_dist")) |
|
745
|
|
|
AND (!function_exists($f="critere_".$critere)) |
|
746
|
|
|
AND (!function_exists($f=$f."_dist")) ) { |
|
747
|
|
|
// fonction critere standard |
|
748
|
|
|
$f = $defaut; |
|
749
|
|
|
} |
|
750
|
|
|
// compile le critere |
|
751
|
|
|
$res = $f($idb, $boucles, $crit); |
|
752
|
|
|
|
|
753
|
|
|
// Gestion centralisee des erreurs pour pouvoir propager |
|
754
|
|
|
if (is_array($res)) { |
|
755
|
|
|
$msg = $res; |
|
756
|
|
|
erreur_squelette($msg, $boucle); |
|
757
|
|
|
} |
|
758
|
|
|
} |
|
759
|
|
|
return $msg; |
|
760
|
|
|
} |
|
761
|
|
|
|
|
762
|
|
|
// Madeleine de Proust, revision MIT-1958 sqq, revision CERN-1989 |
|
763
|
|
|
// hum, c'est kwoi cette fonxion ? |
|
764
|
|
|
// http://doc.spip.org/@kwote |
|
765
|
|
|
function kwote($lisp) |
|
766
|
|
|
{ |
|
767
|
|
|
if (preg_match(_CODE_QUOTE, $lisp, $r)) |
|
768
|
|
|
return $r[1] . "\"" . sql_quote(str_replace(array("\\'","\\\\"),array("'","\\"),$r[2])) . "\"" ; |
|
769
|
|
|
else |
|
770
|
|
|
return "sql_quote($lisp)"; |
|
771
|
|
|
} |
|
772
|
|
|
|
|
773
|
|
|
// Si on a une liste de valeurs dans #ENV{x}, utiliser la double etoile |
|
774
|
|
|
// pour faire par exemple {id_article IN #ENV**{liste_articles}} |
|
775
|
|
|
// http://doc.spip.org/@critere_IN_dist |
|
776
|
|
|
function critere_IN_dist ($idb, &$boucles, $crit) |
|
777
|
|
|
{ |
|
778
|
|
|
$r = calculer_critere_infixe($idb, $boucles, $crit); |
|
779
|
|
|
if (!$r) { |
|
780
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op . " ?"))); |
|
781
|
|
|
} |
|
782
|
|
|
list($arg, $op, $val, $col, $where_complement) = $r; |
|
783
|
|
|
|
|
784
|
|
|
$in = critere_IN_cas($idb, $boucles, $crit->not ? 'NOT' : ($crit->exclus? 'exclus' : ''), $arg, $op, $val, $col); |
|
785
|
|
|
// inserer la condition; exemple: {id_mot ?IN (66, 62, 64)} |
|
786
|
|
|
$where = $in; |
|
787
|
|
|
if ($crit->cond) { |
|
788
|
|
|
$pred = calculer_argument_precedent($idb, $col, $boucles); |
|
789
|
|
|
$where = array("'?'",$pred, $where,"''"); |
|
790
|
|
|
if ($where_complement) // condition annexe du type "AND (objet='article')" |
|
791
|
|
|
$where_complement = array("'?'",$pred, $where_complement,"''"); |
|
792
|
|
|
} |
|
793
|
|
View Code Duplication |
if ($crit->exclus) |
|
|
|
|
|
|
794
|
|
|
if (!preg_match(",^L[0-9]+[.],",$arg)) |
|
795
|
|
|
$where = array("'NOT'", $where); |
|
796
|
|
|
else |
|
797
|
|
|
// un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete |
|
798
|
|
|
$where = array("'NOT'",array("'IN'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'" ,array("'SELF'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'",$where))); |
|
799
|
|
|
|
|
800
|
|
|
$boucles[$idb]->where[] = $where; |
|
801
|
|
|
if ($where_complement) // condition annexe du type "AND (objet='article')" |
|
802
|
|
|
$boucles[$idb]->where[]= $where_complement; |
|
803
|
|
|
} |
|
804
|
|
|
|
|
805
|
|
|
// http://doc.spip.org/@critere_IN_cas |
|
806
|
|
|
function critere_IN_cas ($idb, &$boucles, $crit2, $arg, $op, $val, $col) |
|
|
|
|
|
|
807
|
|
|
{ |
|
808
|
|
|
static $num = array(); |
|
809
|
|
|
$descr = $boucles[$idb]->descr; |
|
810
|
|
|
$cpt = &$num[$descr['nom']][$descr['gram']][$idb]; |
|
811
|
|
|
|
|
812
|
|
|
$var = '$in' . $cpt++; |
|
813
|
|
|
$x= "\n\t$var = array();"; |
|
814
|
|
|
foreach ($val as $k => $v) { |
|
815
|
|
|
if (preg_match(",^(\n//.*\n)?'(.*)'$,", $v, $r)) { |
|
816
|
|
|
// optimiser le traitement des constantes |
|
817
|
|
|
if (is_numeric($r[2])) |
|
818
|
|
|
$x .= "\n\t$var" . "[]= $r[2];"; |
|
819
|
|
|
else |
|
820
|
|
|
$x .= "\n\t$var" . "[]= " . sql_quote($r[2]) . ";"; |
|
821
|
|
|
} else { |
|
822
|
|
|
// Pour permettre de passer des tableaux de valeurs |
|
823
|
|
|
// on repere l'utilisation brute de #ENV**{X}, |
|
824
|
|
|
// c'est-a-dire sa traduction en ($PILE[0][X]). |
|
825
|
|
|
// et on deballe mais en rajoutant l'anti XSS |
|
826
|
|
|
$x .= "\n\tif (!(is_array(\$a = ($v))))\n\t\t$var" ."[]= \$a;\n\telse $var = array_merge($var, \$a);"; |
|
827
|
|
|
} |
|
828
|
|
|
} |
|
829
|
|
|
|
|
830
|
|
|
$boucles[$idb]->in .= $x; |
|
831
|
|
|
|
|
832
|
|
|
// inserer le tri par defaut selon les ordres du IN ... |
|
833
|
|
|
// avec une ecriture de type FIELD qui degrade les performances (du meme ordre qu'un rexgexp) |
|
834
|
|
|
// et que l'on limite donc strictement aux cas necessaires : |
|
835
|
|
|
// si ce n'est pas un !IN, et si il n'y a pas d'autre order dans la boucle |
|
836
|
|
|
if (!$crit2){ |
|
837
|
|
|
$boucles[$idb]->default_order[] = "((!sql_quote($var) OR sql_quote($var)===\"''\") ? 0 : ('FIELD($arg,' . sql_quote($var) . ')'))"; |
|
838
|
|
|
} |
|
839
|
|
|
|
|
840
|
|
|
return "sql_in('$arg',sql_quote($var)".($crit2=='NOT'?",'NOT'":"").")"; |
|
841
|
|
|
} |
|
842
|
|
|
|
|
843
|
|
|
# Criteres de comparaison |
|
844
|
|
|
|
|
845
|
|
|
// http://doc.spip.org/@calculer_critere_DEFAUT |
|
846
|
|
|
function calculer_critere_DEFAUT_dist($idb, &$boucles, $crit) |
|
847
|
|
|
{ |
|
848
|
|
|
// double cas particulier {0,1} et {1/2} repere a l'analyse lexicale |
|
849
|
|
|
if (($crit->op == ",") OR ($crit->op == '/')) |
|
850
|
|
|
return calculer_critere_parties($idb, $boucles, $crit); |
|
851
|
|
|
|
|
852
|
|
|
$r = calculer_critere_infixe($idb, $boucles, $crit); |
|
853
|
|
|
|
|
854
|
|
|
if (!$r) { |
|
855
|
|
|
return (array('zbug_critere_inconnu', array('critere' => $crit->op ))); |
|
856
|
|
|
} else calculer_critere_DEFAUT_args($idb, $boucles, $crit, $r); |
|
857
|
|
|
} |
|
858
|
|
|
|
|
859
|
|
|
function calculer_critere_DEFAUT_args($idb, &$boucles, $crit, $args) |
|
860
|
|
|
{ |
|
861
|
|
|
list($arg, $op, $val, $col, $where_complement) = $args; |
|
862
|
|
|
|
|
863
|
|
|
$where = array("'$op'", "'$arg'", $val[0]); |
|
864
|
|
|
|
|
865
|
|
|
// inserer la negation (cf !...) |
|
866
|
|
|
|
|
867
|
|
|
if ($crit->not) $where = array("'NOT'", $where); |
|
868
|
|
View Code Duplication |
if ($crit->exclus) |
|
|
|
|
|
|
869
|
|
|
if (!preg_match(",^L[0-9]+[.],",$arg)) |
|
870
|
|
|
$where = array("'NOT'", $where); |
|
871
|
|
|
else |
|
872
|
|
|
// un not sur un critere de jointure se traduit comme un NOT IN avec une sous requete |
|
873
|
|
|
$where = array("'NOT'",array("'IN'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'" ,array("'SELF'","'".$boucles[$idb]->id_table.".".$boucles[$idb]->primary."'",$where))); |
|
874
|
|
|
|
|
875
|
|
|
// inserer la condition (cf {lang?}) |
|
876
|
|
|
// traiter a part la date, elle est mise d'office par SPIP, |
|
877
|
|
|
if ($crit->cond) { |
|
878
|
|
|
$pred = calculer_argument_precedent($idb, $col, $boucles); |
|
879
|
|
View Code Duplication |
if ($col == "date" OR $col == "date_redac") { |
|
|
|
|
|
|
880
|
|
|
if($pred == "\$Pile[0]['".$col."']") { |
|
881
|
|
|
$pred = "(\$Pile[0]['{$col}_default']?'':$pred)"; |
|
882
|
|
|
} |
|
883
|
|
|
} |
|
884
|
|
|
|
|
885
|
|
|
if ($op == '=' AND !$crit->not) |
|
886
|
|
|
$where = array("'?'", "(is_array($pred))", |
|
887
|
|
|
critere_IN_cas ($idb, $boucles, 'COND', $arg, $op, array($pred), $col), |
|
888
|
|
|
$where); |
|
889
|
|
|
$where = array("'?'", "!(is_array($pred)?count($pred):strlen($pred))","''", $where); |
|
890
|
|
|
if ($where_complement) // condition annexe du type "AND (objet='article')" |
|
891
|
|
|
$where_complement = array("'?'", "!$pred","''", $where_complement); |
|
892
|
|
|
} |
|
893
|
|
|
|
|
894
|
|
|
$boucles[$idb]->where[]= $where; |
|
895
|
|
|
if ($where_complement) // condition annexe du type "AND (objet='article')" |
|
896
|
|
|
$boucles[$idb]->where[]= $where_complement; |
|
897
|
|
|
} |
|
898
|
|
|
|
|
899
|
|
|
// http://doc.spip.org/@calculer_critere_infixe |
|
900
|
|
|
function calculer_critere_infixe($idb, &$boucles, $crit) { |
|
901
|
|
|
|
|
902
|
|
|
global $table_criteres_infixes; |
|
903
|
|
|
global $exceptions_des_jointures, $exceptions_des_tables; |
|
904
|
|
|
|
|
905
|
|
|
$boucle = &$boucles[$idb]; |
|
906
|
|
|
$type = $boucle->type_requete; |
|
907
|
|
|
$table = $boucle->id_table; |
|
908
|
|
|
$desc = $boucle->show; |
|
909
|
|
|
$date = array(); |
|
910
|
|
|
|
|
911
|
|
|
list($fct, $col, $op, $val, $args_sql) = |
|
912
|
|
|
calculer_critere_infixe_ops($idb, $boucles, $crit); |
|
913
|
|
|
|
|
914
|
|
|
$col_alias = $col; |
|
915
|
|
|
$where_complement =false; |
|
916
|
|
|
|
|
917
|
|
|
// Cas particulier : id_enfant => utiliser la colonne id_objet |
|
918
|
|
|
if ($col == 'id_enfant') |
|
919
|
|
|
$col = $boucle->primary; |
|
920
|
|
|
|
|
921
|
|
|
// Cas particulier : id_parent => verifier les exceptions de tables |
|
922
|
|
|
if ($col == 'id_parent') |
|
923
|
|
|
$col = isset($exceptions_des_tables[$table]['id_parent']) ? |
|
924
|
|
|
$exceptions_des_tables[$table]['id_parent'] : |
|
925
|
|
|
'id_parent'; |
|
926
|
|
|
|
|
927
|
|
|
// Cas particulier : id_secteur pour certaines tables |
|
928
|
|
|
else if (($col == 'id_secteur')&&($type == 'breves')) { |
|
929
|
|
|
$col = 'id_rubrique'; |
|
930
|
|
|
} |
|
931
|
|
|
// et possibilite de gerer un critere secteur sur des tables de plugins (ie forums) |
|
932
|
|
|
else if (($col == 'id_secteur') AND ($critere_secteur = charger_fonction("critere_secteur_$type","public",true))) { |
|
933
|
|
|
$table = $critere_secteur($idb, $boucles, $val, $crit); |
|
934
|
|
|
} |
|
935
|
|
|
|
|
936
|
|
|
// cas id_article=xx qui se mappe en id_objet=xx AND objet=article |
|
937
|
|
|
else if (count(trouver_champs_decomposes($col,$desc))>1){ |
|
938
|
|
|
$e = decompose_champ_id_objet($col); |
|
939
|
|
|
$col = array_shift($e); |
|
940
|
|
|
$where_complement = primary_doublee($e, $table); |
|
941
|
|
|
|
|
942
|
|
|
} |
|
943
|
|
|
// Cas particulier : expressions de date |
|
944
|
|
|
else if ($date = tester_param_date($boucle->type_requete, $col)) { |
|
945
|
|
|
$col = calculer_critere_infixe_date($idb, $boucles, $date); |
|
946
|
|
|
$table = ''; |
|
947
|
|
|
} |
|
948
|
|
|
else if (preg_match('/^(.*)\.(.*)$/', $col, $r)) { |
|
949
|
|
|
list(,$table, $col) = $r; |
|
950
|
|
|
$col_alias = $col; |
|
951
|
|
|
$table = calculer_critere_externe_init($boucle, array($table), $col, $desc, ($crit->cond OR $op !='='), true); |
|
952
|
|
|
if (!$table) return ''; |
|
953
|
|
|
} |
|
954
|
|
|
elseif (@!array_key_exists($col, $desc['field'])) { |
|
955
|
|
|
$r = calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table); |
|
956
|
|
|
if (!$r) return ''; |
|
957
|
|
|
list($col, $col_alias, $table, $where_complement) = $r; |
|
958
|
|
|
} |
|
959
|
|
|
// Si la colonne SQL est numerique ou le critere est une date relative |
|
960
|
|
|
// virer les guillemets eventuels qui sont refuses par certains SQL |
|
961
|
|
|
// Ne pas utiliser intval, PHP tronquant les Bigint de SQL |
|
962
|
|
|
|
|
963
|
|
|
if (($op == '=' OR in_array($op, $table_criteres_infixes)) |
|
964
|
|
|
AND (($desc AND isset($desc['field'][$col]) AND sql_test_int($desc['field'][$col])) |
|
965
|
|
|
OR ($date AND strpos($date[0], '_relatif')))) { |
|
966
|
|
|
if (preg_match("/^\"'(-?\d+)'\"$/", $val[0], $r)) |
|
967
|
|
|
$val[0] = $r[1]; |
|
968
|
|
|
elseif (preg_match('/^sql_quote[(](.*?)(,[^)]*)?[)]\s*$/', $val[0], $r)) { |
|
969
|
|
|
$r = $r[1] . ($r[2] ? $r[2] : ",''") . ",'int'"; |
|
970
|
|
|
$val[0] = "sql_quote($r)"; |
|
971
|
|
|
} |
|
972
|
|
|
} |
|
973
|
|
|
// Indicateur pour permettre aux fonctionx boucle_X de modifier |
|
974
|
|
|
// leurs requetes par defaut, notamment le champ statut |
|
975
|
|
|
// Ne pas confondre champs de la table principale et des jointures |
|
976
|
|
|
if ($table === $boucle->id_table) { |
|
977
|
|
|
$boucles[$idb]->modificateur['criteres'][$col] = true; |
|
978
|
|
|
if ($col_alias!=$col) |
|
979
|
|
|
$boucles[$idb]->modificateur['criteres'][$col_alias] = true; |
|
980
|
|
|
} |
|
981
|
|
|
|
|
982
|
|
|
// ajout pour le cas special d'une condition sur le champ statut: |
|
983
|
|
|
// il faut alors interdire a la fonction de boucle |
|
984
|
|
|
// de mettre ses propres criteres de statut |
|
985
|
|
|
// http://www.spip.net/@statut (a documenter) |
|
986
|
|
|
// garde pour compatibilite avec code des plugins anterieurs, mais redondant avec la ligne precedente |
|
987
|
|
|
if ($col == 'statut') $boucles[$idb]->statut = true; |
|
988
|
|
|
|
|
989
|
|
|
// ajout pour le cas special des forums |
|
990
|
|
|
// il faut alors interdire a la fonction de boucle sur forum |
|
991
|
|
|
// de selectionner uniquement les forums sans pere |
|
992
|
|
|
|
|
993
|
|
|
elseif ($boucles[$idb]->type_requete == 'forums' AND |
|
994
|
|
|
($col == 'id_parent' OR $col == 'id_forum')) |
|
995
|
|
|
$boucles[$idb]->modificateur['plat'] = true; |
|
996
|
|
|
// inserer le nom de la table SQL devant le nom du champ |
|
997
|
|
|
if ($table) { |
|
998
|
|
|
if ($col[0] == "`") |
|
999
|
|
|
$arg = "$table." . substr($col,1,-1); |
|
1000
|
|
|
else $arg = "$table.$col"; |
|
1001
|
|
|
} else $arg = $col; |
|
1002
|
|
|
|
|
1003
|
|
|
// inserer la fonction SQL |
|
1004
|
|
|
if ($fct) $arg = "$fct($arg$args_sql)"; |
|
1005
|
|
|
|
|
1006
|
|
|
return array($arg, $op, $val, $col_alias, $where_complement); |
|
1007
|
|
|
} |
|
1008
|
|
|
|
|
1009
|
|
|
function calculer_critere_infixe_externe(&$boucle, $crit, $op, $desc, $col, $col_alias, $table) |
|
1010
|
|
|
{ |
|
1011
|
|
|
global $exceptions_des_jointures; |
|
1012
|
|
|
$where = ''; |
|
1013
|
|
|
|
|
1014
|
|
|
$calculer_critere_externe = 'calculer_critere_externe_init'; |
|
1015
|
|
|
// gestion par les plugins des jointures tordues |
|
1016
|
|
|
// pas automatiques mais necessaires |
|
1017
|
|
|
if (is_array($exceptions_des_jointures[$table])) { |
|
1018
|
|
|
|
|
1019
|
|
|
$t = $exceptions_des_jointures[$table]; |
|
1020
|
|
|
$index = isset($t[$col]) |
|
1021
|
|
|
? $t[$col] : (isset($t['']) ? $t[''] : array()); |
|
1022
|
|
|
|
|
1023
|
|
|
if (count($index)==3) |
|
1024
|
|
|
list($t, $col, $calculer_critere_externe) = $index; |
|
1025
|
|
|
elseif (count($index)==2) |
|
1026
|
|
|
list($t, $col) = $t[$col]; |
|
1027
|
|
|
elseif (count($index)==1){ |
|
1028
|
|
|
list($calculer_critere_externe) = $index; |
|
1029
|
|
|
$t = $table; |
|
1030
|
|
|
} |
|
1031
|
|
|
else |
|
1032
|
|
|
$t=''; // jointure non declaree. La trouver. |
|
1033
|
|
|
} |
|
1034
|
|
|
elseif (isset($exceptions_des_jointures[$col])) |
|
1035
|
|
|
list($t, $col) = $exceptions_des_jointures[$col]; |
|
1036
|
|
|
else $t =''; // jointure non declaree. La trouver. |
|
1037
|
|
|
|
|
1038
|
|
|
$table = $calculer_critere_externe($boucle, $boucle->jointures, $col, $desc, ($crit->cond OR $op !='='), $t); |
|
1039
|
|
|
|
|
1040
|
|
|
if (!$table) return ''; |
|
1041
|
|
|
|
|
1042
|
|
|
list($nom, $desc) = trouver_champ_exterieur($col, $boucle->jointures, $boucle); |
|
|
|
|
|
|
1043
|
|
|
if (count(trouver_champs_decomposes($col,$desc))>1){ |
|
1044
|
|
|
$col_alias = $col; // id_article devient juste le nom d'origine |
|
1045
|
|
|
$e = decompose_champ_id_objet($col); |
|
1046
|
|
|
$col = array_shift($e); |
|
1047
|
|
|
$where = primary_doublee($e, $table); |
|
1048
|
|
|
} |
|
1049
|
|
|
|
|
1050
|
|
|
return array($col, $col_alias, $table, $where); |
|
1051
|
|
|
} |
|
1052
|
|
|
|
|
1053
|
|
|
// Ne pas appliquer sql_quote lors de la compilation, |
|
1054
|
|
|
// car on ne connait pas le serveur SQL, donc s'il faut \' ou '' |
|
1055
|
|
|
|
|
1056
|
|
|
// http://doc.spip.org/@primary_doublee |
|
1057
|
|
|
function primary_doublee($decompose, $table) |
|
1058
|
|
|
{ |
|
1059
|
|
|
$e1 = reset($decompose); |
|
1060
|
|
|
$e2 = "sql_quote('" . end($decompose) ."')"; |
|
1061
|
|
|
return array("'='","'$table.". $e1 ."'",$e2); |
|
1062
|
|
|
} |
|
1063
|
|
|
|
|
1064
|
|
|
// Faute de copie du champ id_secteur dans la table des forums, |
|
1065
|
|
|
// faut le retrouver par jointure |
|
1066
|
|
|
// Pour chaque Row il faudrait tester si le forum est |
|
1067
|
|
|
// d'article, de breve, de rubrique, ou de syndication. |
|
1068
|
|
|
// Pour le moment on ne traite que les articles, |
|
1069
|
|
|
// les 3 autres cas ne marcheront donc pas: ca ferait 4 jointures |
|
1070
|
|
|
// qu'il faut traiter optimalement ou alors pas du tout. |
|
1071
|
|
|
|
|
1072
|
|
|
// http://doc.spip.org/@critere_secteur_forum |
|
1073
|
|
|
function critere_secteur_forum($idb, &$boucles, $val, $crit) |
|
|
|
|
|
|
1074
|
|
|
{ |
|
1075
|
|
|
static $trouver_table; |
|
1076
|
|
|
if (!$trouver_table) |
|
1077
|
|
|
$trouver_table = charger_fonction('trouver_table', 'base'); |
|
1078
|
|
|
|
|
1079
|
|
|
$desc = $trouver_table('articles', $boucles[$idb]->sql_serveur); |
|
1080
|
|
|
return calculer_critere_externe_init($boucles[$idb], array($desc['table']), 'id_secteur', $desc, $crit->cond, true); |
|
1081
|
|
|
} |
|
1082
|
|
|
|
|
1083
|
|
|
// Champ hors table, ca ne peut etre qu'une jointure. |
|
1084
|
|
|
// On cherche la table du champ et on regarde si elle est deja jointe |
|
1085
|
|
|
// Si oui et qu'on y cherche un champ nouveau, pas de jointure supplementaire |
|
1086
|
|
|
// Exemple: criteres {titre_mot=...}{type_mot=...} |
|
1087
|
|
|
// Dans les 2 autres cas ==> jointure |
|
1088
|
|
|
// (Exemple: criteres {type_mot=...}{type_mot=...} donne 2 jointures |
|
1089
|
|
|
// pour selectioner ce qui a exactement ces 2 mots-cles. |
|
1090
|
|
|
|
|
1091
|
|
|
// http://doc.spip.org/@calculer_critere_externe_init |
|
1092
|
|
|
function calculer_critere_externe_init(&$boucle, $joints, $col, $desc, $eg, $checkarrivee = false) |
|
1093
|
|
|
{ |
|
1094
|
|
|
$cle = trouver_champ_exterieur($col, $joints, $boucle, $checkarrivee); |
|
1095
|
|
|
if (!$cle) return ''; |
|
1096
|
|
|
$t = array_search($cle[0], $boucle->from); |
|
1097
|
|
|
// transformer eventuellement id_xx en (id_objet,objet) |
|
1098
|
|
|
$cols = trouver_champs_decomposes($col,$cle[1]); |
|
1099
|
|
|
if ($t) { |
|
1100
|
|
|
$joindre = false; |
|
1101
|
|
|
foreach($cols as $col){ |
|
1102
|
|
|
$c = '/\b' . $t . ".$col" . '\b/'; |
|
1103
|
|
|
if (trouver_champ($c, $boucle->where)) $joindre = true; |
|
1104
|
|
|
else { |
|
1105
|
|
|
// mais ca peut etre dans le FIELD pour le Having |
|
1106
|
|
|
$c = "/FIELD.$t" .".$col,/"; |
|
1107
|
|
|
if (trouver_champ($c, $boucle->select)) $joindre = true; |
|
1108
|
|
|
} |
|
1109
|
|
|
} |
|
1110
|
|
|
if (!$joindre) return $t; |
|
1111
|
|
|
} |
|
1112
|
|
|
return calculer_jointure($boucle, array($boucle->id_table, $desc), $cle, $cols, $eg); |
|
1113
|
|
|
|
|
1114
|
|
|
} |
|
1115
|
|
|
|
|
1116
|
|
|
// http://doc.spip.org/@trouver_champ |
|
1117
|
|
|
function trouver_champ($champ, $where) |
|
1118
|
|
|
{ |
|
1119
|
|
|
if (!is_array($where)) |
|
1120
|
|
|
return preg_match($champ,$where); |
|
1121
|
|
|
else { |
|
1122
|
|
|
foreach ($where as $clause) { |
|
1123
|
|
|
if (trouver_champ($champ, $clause)) return true; |
|
1124
|
|
|
} |
|
1125
|
|
|
return false; |
|
1126
|
|
|
} |
|
1127
|
|
|
} |
|
1128
|
|
|
|
|
1129
|
|
|
|
|
1130
|
|
|
// determine l'operateur et les operandes |
|
1131
|
|
|
|
|
1132
|
|
|
// http://doc.spip.org/@calculer_critere_infixe_ops |
|
1133
|
|
|
function calculer_critere_infixe_ops($idb, &$boucles, $crit) |
|
1134
|
|
|
{ |
|
1135
|
|
|
// cas d'une valeur comparee a elle-meme ou son referent |
|
1136
|
|
|
if (count($crit->param) == 0) |
|
1137
|
|
|
{ $op = '='; |
|
1138
|
|
|
$col = $val = $crit->op; |
|
1139
|
|
|
if (preg_match('/^(.*)\.(.*)$/', $col, $r)) $val = $r[2]; |
|
1140
|
|
|
// Cas special {lang} : aller chercher $GLOBALS['spip_lang'] |
|
1141
|
|
|
if ($val == 'lang') |
|
1142
|
|
|
$val = array(kwote('$GLOBALS[\'spip_lang\']')); |
|
1143
|
|
|
else { |
|
1144
|
|
|
// Si id_parent, comparer l'id_parent avec l'id_objet |
|
1145
|
|
|
// de la boucle superieure.... faudrait verifier qu'il existe |
|
1146
|
|
|
// pour eviter l'erreur SQL |
|
1147
|
|
|
if ($val == 'id_parent') |
|
1148
|
|
|
$val = $boucles[$idb]->primary; |
|
1149
|
|
|
// Si id_enfant, comparer l'id_objet avec l'id_parent |
|
1150
|
|
|
// de la boucle superieure |
|
1151
|
|
|
else if ($val == 'id_enfant') |
|
1152
|
|
|
$val = 'id_parent'; |
|
1153
|
|
|
// un critere conditionnel sur date est traite a part |
|
1154
|
|
|
// car la date est mise d'office par SPIP, |
|
1155
|
|
|
$val = calculer_argument_precedent($idb, $val, $boucles); |
|
1156
|
|
View Code Duplication |
if ($crit->cond AND ($col == "date" OR $col == "date_redac")) { |
|
|
|
|
|
|
1157
|
|
|
if($val == "\$Pile[0]['".$col."']") { |
|
1158
|
|
|
$val = "(\$Pile[0]['{$col}_default']?'':$val)"; |
|
1159
|
|
|
} |
|
1160
|
|
|
} |
|
1161
|
|
|
$val = array(kwote($val)); |
|
1162
|
|
|
} |
|
1163
|
|
|
} else { |
|
1164
|
|
|
// comparaison explicite |
|
1165
|
|
|
// le phraseur impose que le premier param soit du texte |
|
1166
|
|
|
$params = $crit->param; |
|
1167
|
|
|
$op = $crit->op; |
|
1168
|
|
|
if ($op == '==') $op = 'REGEXP'; |
|
1169
|
|
|
$col = array_shift($params); |
|
1170
|
|
|
$col = $col[0]->texte; |
|
1171
|
|
|
|
|
1172
|
|
|
$val = array(); |
|
1173
|
|
|
$desc = array('id_mere' => $idb); |
|
1174
|
|
|
$parent = $boucles[$idb]->id_parent; |
|
1175
|
|
|
|
|
1176
|
|
|
// Dans le cas {x=='#DATE'} etc, defaire le travail du phraseur, |
|
1177
|
|
|
// celui ne sachant pas ce qu'est un critere infixe |
|
1178
|
|
|
// et a fortiori son 2e operande qu'entoure " ou ' |
|
1179
|
|
|
if (count($params)==1 |
|
1180
|
|
|
AND count($params[0]==3) |
|
1181
|
|
|
AND $params[0][0]->type == 'texte' |
|
1182
|
|
|
AND @$params[0][2]->type == 'texte' |
|
1183
|
|
|
AND ($p=$params[0][0]->texte) == $params[0][2]->texte |
|
1184
|
|
|
AND (($p == "'") OR ($p == '"')) |
|
1185
|
|
|
AND $params[0][1]->type == 'champ' ) { |
|
1186
|
|
|
$val[]= "$p\\$p#" . $params[0][1]->nom_champ . "\\$p$p"; |
|
1187
|
|
|
} else |
|
1188
|
|
|
foreach ((($op != 'IN') ? $params : calculer_vieux_in($params)) as $p) { |
|
1189
|
|
|
$a = calculer_liste($p, $desc, $boucles, $parent); |
|
1190
|
|
|
if ($op == 'IN') $val[]= $a; |
|
1191
|
|
|
else $val[]=kwote($a); |
|
1192
|
|
|
} |
|
1193
|
|
|
} |
|
1194
|
|
|
|
|
1195
|
|
|
$fct = $args_sql = ''; |
|
1196
|
|
|
// fonction SQL ? |
|
1197
|
|
|
if (preg_match('/^(.*)' . SQL_ARGS . '$/', $col, $m)) { |
|
1198
|
|
|
$fct = $m[1]; |
|
1199
|
|
|
preg_match('/^\(([^,]*)(.*)\)$/', $m[2], $a); |
|
1200
|
|
|
$col = $a[1]; |
|
1201
|
|
|
if (preg_match('/^(\S*)(\s+AS\s+.*)$/i', $col, $m)) { |
|
1202
|
|
|
$col=$m[1]; |
|
1203
|
|
|
$args_sql = $m[2]; |
|
1204
|
|
|
} |
|
1205
|
|
|
$args_sql .= $a[2];; |
|
1206
|
|
|
} |
|
1207
|
|
|
|
|
1208
|
|
|
return array($fct, $col, $op, $val, $args_sql); |
|
1209
|
|
|
} |
|
1210
|
|
|
|
|
1211
|
|
|
// compatibilite ancienne version |
|
1212
|
|
|
|
|
1213
|
|
|
// http://doc.spip.org/@calculer_vieux_in |
|
1214
|
|
|
function calculer_vieux_in($params) |
|
1215
|
|
|
{ |
|
1216
|
|
|
$deb = $params[0][0]; |
|
1217
|
|
|
$k = count($params)-1; |
|
1218
|
|
|
$last = $params[$k]; |
|
1219
|
|
|
$j = count($last)-1; |
|
1220
|
|
|
$last = $last[$j]; |
|
1221
|
|
|
$n = strlen($last->texte); |
|
1222
|
|
|
|
|
1223
|
|
|
if (!(($deb->texte[0] == '(') && ($last->texte[$n-1] == ')'))) |
|
1224
|
|
|
return $params; |
|
1225
|
|
|
$params[0][0]->texte = substr($deb->texte,1); |
|
1226
|
|
|
// attention, on peut avoir k=0,j=0 ==> recalculer |
|
1227
|
|
|
$last = $params[$k][$j]; |
|
1228
|
|
|
$n = strlen($last->texte); |
|
1229
|
|
|
$params[$k][$j]->texte = substr($last->texte,0,$n-1); |
|
1230
|
|
|
$newp = array(); |
|
1231
|
|
|
foreach($params as $v) { |
|
1232
|
|
|
if ($v[0]->type != 'texte') |
|
1233
|
|
|
$newp[] = $v; |
|
1234
|
|
|
else { |
|
1235
|
|
|
foreach(explode(',', $v[0]->texte) as $x) { |
|
1236
|
|
|
$t = new Texte; |
|
1237
|
|
|
$t->texte = $x; |
|
1238
|
|
|
$newp[] = array($t); |
|
1239
|
|
|
} |
|
1240
|
|
|
} |
|
1241
|
|
|
} |
|
1242
|
|
|
return $newp; |
|
1243
|
|
|
} |
|
1244
|
|
|
|
|
1245
|
|
|
// http://doc.spip.org/@calculer_critere_infixe_date |
|
1246
|
|
|
function calculer_critere_infixe_date($idb, &$boucles, $regs) |
|
1247
|
|
|
{ |
|
1248
|
|
|
global $table_date; |
|
1249
|
|
|
$boucle = $boucles[$idb]; |
|
1250
|
|
|
$col = $regs[1]; |
|
1251
|
|
|
$date_orig = $pred = isset($table_date[$boucle->type_requete])?$table_date[$boucle->type_requete]:'date'; |
|
1252
|
|
|
if (isset($regs[3]) AND $suite=$regs[3]) { |
|
1253
|
|
|
# Recherche de l'existence du champ date_xxxx, |
|
1254
|
|
|
# si oui choisir ce champ, sinon choisir xxxx |
|
1255
|
|
|
$t = $boucle->show; |
|
1256
|
|
|
if ($t['field']["date$suite"]) |
|
1257
|
|
|
$date_orig = 'date'.$suite; |
|
1258
|
|
|
else |
|
1259
|
|
|
$date_orig = substr($suite, 1); |
|
1260
|
|
|
$pred = $date_orig; |
|
1261
|
|
|
} |
|
1262
|
|
|
else |
|
1263
|
|
|
if (isset($regs[2]) AND $rel=$regs[2]) $pred = 'date'; |
|
1264
|
|
|
|
|
1265
|
|
|
$date_compare = "\"' . normaliser_date(" . |
|
1266
|
|
|
calculer_argument_precedent($idb, $pred, $boucles) . |
|
1267
|
|
|
") . '\""; |
|
1268
|
|
|
$date_orig = $boucle->id_table . '.' . $date_orig; |
|
1269
|
|
|
|
|
1270
|
|
|
switch ($col) { |
|
1271
|
|
|
case 'date': |
|
1272
|
|
|
$col = $date_orig; |
|
1273
|
|
|
break; |
|
1274
|
|
|
case 'jour': |
|
1275
|
|
|
$col = "DAYOFMONTH($date_orig)"; |
|
1276
|
|
|
break; |
|
1277
|
|
|
case 'mois': |
|
1278
|
|
|
$col = "MONTH($date_orig)"; |
|
1279
|
|
|
break; |
|
1280
|
|
|
case 'annee': |
|
1281
|
|
|
$col = "YEAR($date_orig)"; |
|
1282
|
|
|
break; |
|
1283
|
|
|
case 'heure': |
|
1284
|
|
|
$col = "DATE_FORMAT($date_orig, '%H:%i')"; |
|
1285
|
|
|
break; |
|
1286
|
|
|
case 'age': |
|
1287
|
|
|
$col = calculer_param_date("NOW()", $date_orig); |
|
1288
|
|
|
break; |
|
1289
|
|
|
case 'age_relatif': |
|
1290
|
|
|
$col = calculer_param_date($date_compare, $date_orig); |
|
1291
|
|
|
break; |
|
1292
|
|
|
case 'jour_relatif': |
|
1293
|
|
|
$col = "LEAST(TO_DAYS(" .$date_compare . ")-TO_DAYS(" . |
|
1294
|
|
|
$date_orig . "), DAYOFMONTH(" . $date_compare . |
|
1295
|
|
|
")-DAYOFMONTH(" . $date_orig . ")+30.4368*(MONTH(" . |
|
1296
|
|
|
$date_compare . ")-MONTH(" . $date_orig . |
|
1297
|
|
|
"))+365.2422*(YEAR(" . $date_compare . ")-YEAR(" . |
|
1298
|
|
|
$date_orig . ")))"; |
|
1299
|
|
|
break; |
|
1300
|
|
|
case 'mois_relatif': |
|
1301
|
|
|
$col = "MONTH(" . $date_compare . ")-MONTH(" . |
|
1302
|
|
|
$date_orig . ")+12*(YEAR(" . $date_compare . |
|
1303
|
|
|
")-YEAR(" . $date_orig . "))"; |
|
1304
|
|
|
break; |
|
1305
|
|
|
case 'annee_relatif': |
|
1306
|
|
|
$col = "YEAR(" . $date_compare . ")-YEAR(" . |
|
1307
|
|
|
$date_orig . ")"; |
|
1308
|
|
|
break; |
|
1309
|
|
|
} |
|
1310
|
|
|
return $col; |
|
1311
|
|
|
} |
|
1312
|
|
|
|
|
1313
|
|
|
// http://doc.spip.org/@calculer_param_date |
|
1314
|
|
|
function calculer_param_date($date_compare, $date_orig) { |
|
1315
|
|
|
if (preg_match(",'\" *\.(.*)\. *\"',", $date_compare, $r)) { |
|
1316
|
|
|
$init = "'\" . (\$x = $r[1]) . \"'"; |
|
1317
|
|
|
$date_compare = '\'$x\''; |
|
1318
|
|
|
} |
|
1319
|
|
|
else |
|
1320
|
|
|
$init = $date_compare; |
|
1321
|
|
|
|
|
1322
|
|
|
return |
|
1323
|
|
|
"LEAST((UNIX_TIMESTAMP(" . |
|
1324
|
|
|
$init . |
|
1325
|
|
|
")-UNIX_TIMESTAMP(" . |
|
1326
|
|
|
$date_orig . |
|
1327
|
|
|
"))/86400,\n\tTO_DAYS(" . |
|
1328
|
|
|
$date_compare . |
|
1329
|
|
|
")-TO_DAYS(" . |
|
1330
|
|
|
$date_orig . |
|
1331
|
|
|
"),\n\tDAYOFMONTH(" . |
|
1332
|
|
|
$date_compare . |
|
1333
|
|
|
")-DAYOFMONTH(" . |
|
1334
|
|
|
$date_orig . |
|
1335
|
|
|
")+30.4368*(MONTH(" . |
|
1336
|
|
|
$date_compare . |
|
1337
|
|
|
")-MONTH(" . |
|
1338
|
|
|
$date_orig . |
|
1339
|
|
|
"))+365.2422*(YEAR(" . |
|
1340
|
|
|
$date_compare . |
|
1341
|
|
|
")-YEAR(" . |
|
1342
|
|
|
$date_orig . |
|
1343
|
|
|
")))"; |
|
1344
|
|
|
} |
|
1345
|
|
|
|
|
1346
|
|
|
// http://doc.spip.org/@tester_param_date |
|
1347
|
|
|
function tester_param_date($type, $col) |
|
1348
|
|
|
{ |
|
1349
|
|
|
global $table_date; |
|
1350
|
|
|
if (isset($table_date[$type]) |
|
1351
|
|
|
AND preg_match(",^((age|jour|mois|annee)_relatif|date|mois|annee|jour|heure|age)(_[a-z]+)?$,", $col, $regs)) |
|
1352
|
|
|
return $regs; |
|
1353
|
|
|
else return false; |
|
1354
|
|
|
} |
|
1355
|
|
|
|
|
1356
|
|
|
?> |
|
|
|
|
|
|
1357
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.