[SPIP] v3.2.1-->v3.2.2
[lhc/web/www.git] / www / ecrire / public / decompiler.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2019 *
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 if (!defined('_ECRIRE_INC_VERSION')) {
14 return;
15 }
16
17 // Decompilation de l'arbre de syntaxe abstraite d'un squelette SPIP
18
19 function decompiler_boucle($struct, $fmt = '', $prof = 0) {
20 $nom = $struct->id_boucle;
21 $avant = decompiler_($struct->avant, $fmt, $prof);
22 $apres = decompiler_($struct->apres, $fmt, $prof);
23 $altern = decompiler_($struct->altern, $fmt, $prof);
24 $milieu = decompiler_($struct->milieu, $fmt, $prof);
25
26 $type = $struct->sql_serveur ? "$struct->sql_serveur:" : '';
27 $type .= ($struct->type_requete ? $struct->type_requete :
28 $struct->table_optionnelle);
29
30 if ($struct->jointures_explicites) {
31 $type .= " " . $struct->jointures_explicites;
32 }
33 if ($struct->table_optionnelle) {
34 $type .= "?";
35 }
36 // Revoir le cas de la boucle recursive
37
38 $crit = $struct->param;
39 if ($crit and !is_array($crit[0])) {
40 $type = strtolower($type) . array_shift($crit);
41 }
42 $crit = decompiler_criteres($struct, $fmt, $prof);
43
44 $f = 'format_boucle_' . $fmt;
45
46 return $f($avant, $nom, $type, $crit, $milieu, $apres, $altern, $prof);
47 }
48
49 function decompiler_include($struct, $fmt = '', $prof = 0) {
50 $res = array();
51 foreach ($struct->param ? $struct->param : array() as $couple) {
52 array_shift($couple);
53 foreach ($couple as $v) {
54 $res[] = decompiler_($v, $fmt, $prof);
55 }
56 }
57 $file = is_string($struct->texte) ? $struct->texte :
58 decompiler_($struct->texte, $fmt, $prof);
59 $f = 'format_inclure_' . $fmt;
60
61 return $f($file, $res, $prof);
62 }
63
64 function decompiler_texte($struct, $fmt = '', $prof = 0) {
65 $f = 'format_texte_' . $fmt;
66
67 return strlen($struct->texte) ? $f($struct->texte, $prof) : '';
68 }
69
70 function decompiler_polyglotte($struct, $fmt = '', $prof = 0) {
71 $f = 'format_polyglotte_' . $fmt;
72
73 return $f($struct->traductions, $prof);
74 }
75
76 function decompiler_idiome($struct, $fmt = '', $prof = 0) {
77 $args = array();
78 foreach ($struct->arg as $k => $v) {
79 $args[$k] = public_decompiler($v, $fmt, $prof);
80 }
81
82 $filtres = decompiler_liste($struct->param, $fmt, $prof);
83
84 $f = 'format_idiome_' . $fmt;
85
86 return $f($struct->nom_champ, $struct->module, $args, $filtres, $prof);
87 }
88
89 function decompiler_champ($struct, $fmt = '', $prof = 0) {
90 $avant = decompiler_($struct->avant, $fmt, $prof);
91 $apres = decompiler_($struct->apres, $fmt, $prof);
92 $args = $filtres = '';
93 if ($p = $struct->param) {
94 if ($p[0][0] === '') {
95 $args = decompiler_liste(array(array_shift($p)), $fmt, $prof);
96 }
97 $filtres = decompiler_liste($p, $fmt, $prof);
98 }
99 $f = 'format_champ_' . $fmt;
100
101 return $f($struct->nom_champ, $struct->nom_boucle, $struct->etoile, $avant, $apres, $args, $filtres, $prof);
102 }
103
104 function decompiler_liste($sources, $fmt = '', $prof = 0) {
105 if (!is_array($sources)) {
106 return '';
107 }
108 $f = 'format_liste_' . $fmt;
109 $res = '';
110 foreach ($sources as $arg) {
111 if (!is_array($arg)) {
112 continue; // ne devrait pas arriver.
113 } else {
114 $r = array_shift($arg);
115 }
116 $args = array();
117 foreach ($arg as $v) {
118 // cas des arguments entoures de ' ou "
119 if ((count($v) == 1)
120 and $v[0]->type == 'texte'
121 and (strlen($v[0]->apres) == 1)
122 and $v[0]->apres == $v[0]->avant
123 ) {
124 $args[] = $v[0]->avant . $v[0]->texte . $v[0]->apres;
125 } else {
126 $args[] = decompiler_($v, $fmt, 0 - $prof);
127 }
128 }
129 if (($r !== '') or $args) {
130 $res .= $f($r, $args, $prof);
131 }
132 }
133
134 return $res;
135 }
136
137 // Decompilation des criteres: on triche et on deroge:
138 // - le phraseur fournit un bout du source en plus de la compil
139 // - le champ apres signale le critere {"separateur"} ou {'separateur'}
140 // - les champs sont implicitement etendus (crochets implicites mais interdits)
141 function decompiler_criteres($boucle, $fmt = '', $prof = 0) {
142 $sources = $boucle->param;
143 if (!is_array($sources)) {
144 return '';
145 }
146 $res = '';
147 $f = 'format_critere_' . $fmt;
148 foreach ($sources as $crit) {
149 if (!is_array($crit)) {
150 continue;
151 } // boucle recursive
152 array_shift($crit);
153 $args = array();
154 foreach ($crit as $i => $v) {
155 if ((count($v) == 1)
156 and $v[0]->type == 'texte'
157 and $v[0]->apres
158 ) {
159 $args[] = array(array('texte', ($v[0]->apres . $v[0]->texte . $v[0]->apres)));
160 } else {
161 $res2 = array();
162 foreach ($v as $k => $p) {
163 if (isset($p->type)
164 and function_exists($d = 'decompiler_' . $p->type)
165 ) {
166 $r = $d($p, $fmt, (0 - $prof), @$v[$k + 1]);
167 $res2[] = array($p->type, $r);
168 } else {
169 spip_log("critere $i / $k mal forme");
170 }
171 }
172 $args[] = $res2;
173 }
174 }
175 $res .= $f($args);
176 }
177
178 return $res;
179 }
180
181
182 function decompiler_($liste, $fmt = '', $prof = 0) {
183 if (!is_array($liste)) {
184 return '';
185 }
186 $prof2 = ($prof < 0) ? ($prof - 1) : ($prof + 1);
187 $contenu = array();
188 foreach ($liste as $k => $p) {
189 if (!isset($p->type)) {
190 continue;
191 } #??????
192 $d = 'decompiler_' . $p->type;
193 $next = isset($liste[$k + 1]) ? $liste[$k + 1] : false;
194 // Forcer le champ etendu si son source (pas les reecritures)
195 // contenait des args et s'il est suivi d'espaces,
196 // le champ simple les eliminant est un bug helas perenne.
197
198 if ($next
199 and ($next->type == 'texte')
200 and $p->type == 'champ'
201 and !$p->apres
202 and !$p->avant
203 and $p->fonctions
204 ) {
205 $n = strlen($next->texte) - strlen(ltrim($next->texte));
206 if ($n) {
207 $champ = new Texte;
208 $champ->texte = substr($next->texte, 0, $n);
209 $champ->ligne = $p->ligne;
210 $p->apres = array($champ);
211 $next->texte = substr($next->texte, $n);
212 }
213 }
214 $contenu[] = array($d($p, $fmt, $prof2), $p->type);
215
216 }
217 $f = 'format_suite_' . $fmt;
218
219 return $f($contenu);
220 }
221
222 function public_decompiler($liste, $fmt = '', $prof = 0, $quoi = '') {
223 if (!include_spip('public/format_' . $fmt)) {
224 return "'$fmt'?";
225 }
226 $f = 'decompiler_' . $quoi;
227
228 return $f($liste, $fmt, $prof);
229 }