X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fecrire%2Fpublic%2Fcompiler.php;h=a99fd9554f9d478fa158d5661050d9bb99a3e798;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=362000afd29b1b6d4adfb549a513b5b4995f42a4;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/ecrire/public/compiler.php b/www/ecrire/public/compiler.php index 362000af..a99fd955 100644 --- a/www/ecrire/public/compiler.php +++ b/www/ecrire/public/compiler.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2017 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -14,10 +14,12 @@ /** * Fichier principal du compilateur de squelettes * - * @package SPIP\Compilateur\Compilation -**/ + * @package SPIP\Core\Compilateur\Compilation + **/ -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} /** Repérer un code ne calculant rien, meme avec commentaire */ define('CODE_MONOTONE', ",^(\n//[^\n]*\n)?\(?'([^'])*'\)?$,"); @@ -56,62 +58,91 @@ include_spip('public/jointures'); // mais pas pour dont le fond est defini explicitement. -// http://doc.spip.org/@argumenter_inclure -function argumenter_inclure($params, $rejet_filtres, $p, &$boucles, $id_boucle, $echap=true, $lang = '', $fond1=false){ +// http://code.spip.net/@argumenter_inclure +function argumenter_inclure( + $params, + $rejet_filtres, + $p, + &$boucles, + $id_boucle, + $echap = true, + $lang = '', + $fond1 = false +) { $l = array(); $erreur_p_i_i = ''; - if (!is_array($params)) return $l; - foreach($params as $k => $couple) { - // la liste d'arguments d'inclusion peut se terminer par un filtre + if (!is_array($params)) { + return $l; + } + foreach ($params as $k => $couple) { + // la liste d'arguments d'inclusion peut se terminer par un filtre $filtre = array_shift($couple); - if ($filtre) break; - foreach($couple as $n => $val) { + if ($filtre) { + break; + } + foreach ($couple as $n => $val) { $var = $val[0]; if ($var->type != 'texte') { - if ($n OR $k OR $fond1) { - $erreur_p_i_i = array('zbug_parametres_inclus_incorrects', - array('param' => $var->nom_champ)); - erreur_squelette($erreur_p_i_i, $p); - break; - } - else $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle); + if ($n or $k or $fond1) { + $erreur_p_i_i = array( + 'zbug_parametres_inclus_incorrects', + array('param' => $var->nom_champ) + ); + erreur_squelette($erreur_p_i_i, $p); + break; + } else { + $l[1] = calculer_liste($val, $p->descr, $boucles, $id_boucle); + } } else { - preg_match(",^([^=]*)(=?)(.*)$,m", $var->texte,$m); + preg_match(",^([^=]*)(=?)(.*)$,m", $var->texte, $m); + $m = array_pad($m, 3, null); $var = $m[1]; $auto = false;; if ($m[2]) { - $v = $m[3]; - if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) $v = $m[1]; - $val[0] = new Texte; - $val[0]->texte = $v; - } elseif ($k OR $n OR $fond1) { - $auto = true; - } else $var = 1; + $v = $m[3]; + if (preg_match(',^[\'"](.*)[\'"]$,', $v, $m)) { + $v = $m[1]; + } + $val[0] = new Texte; + $val[0]->texte = $v; + } elseif ($k or $n or $fond1) { + $auto = true; + } else { + $var = 1; + } if ($var == 'lang') { - $lang = !$auto - ? calculer_liste($val, $p->descr, $boucles, $id_boucle) - : '$GLOBALS["spip_lang"]'; + $lang = !$auto + ? calculer_liste($val, $p->descr, $boucles, $id_boucle) + : '$GLOBALS["spip_lang"]'; } else { - $val = $auto - ? index_pile($id_boucle, $var, $boucles) - : calculer_liste($val, $p->descr, $boucles, $id_boucle); - if ($var !== 1) - $val = ($echap?"\'$var\' => ' . argumenter_squelette(":"'$var' => ") - . $val . ($echap? ") . '":" "); - else $val = $echap ? "'.$val.'" : $val; - $l[$var] = $val; + $val = $auto + ? index_pile($id_boucle, $var, $boucles) + : calculer_liste($val, $p->descr, $boucles, $id_boucle); + if ($var !== 1) { + $val = ($echap ? "\'$var\' => ' . argumenter_squelette(" : "'$var' => ") + . $val . ($echap ? ") . '" : " "); + } else { + $val = $echap ? "'.$val.'" : $val; + } + $l[$var] = $val; } } } } - if ($erreur_p_i_i) return false; + if ($erreur_p_i_i) { + return false; + } // Cas particulier de la langue : si {lang=xx} est definie, on // la passe, sinon on passe la langue courante au moment du calcul // sauf si on n'en veut pas - if ($lang === false) return $l; - if (!$lang) $lang = '$GLOBALS["spip_lang"]'; - $l['lang'] = ($echap?"\'lang\' => ' . argumenter_squelette(":"'lang' => ") . $lang . ($echap?") . '":" "); + if ($lang === false) { + return $l; + } + if (!$lang) { + $lang = '$GLOBALS["spip_lang"]'; + } + $l['lang'] = ($echap ? "\'lang\' => ' . argumenter_squelette(" : "'lang' => ") . $lang . ($echap ? ") . '" : " "); return $l; } @@ -134,7 +165,7 @@ define('CODE_RECUPERER_FOND', 'recuperer_fond(%s, %s, array(%s), %s)'); * Identifiant de la boucle contenant l'inclure * @return string * Code PHP appelant l'inclusion -**/ + **/ function calculer_inclure($p, &$boucles, $id_boucle) { $_contexte = argumenter_inclure($p->param, false, $p, $boucles, $id_boucle, true, '', true); @@ -144,21 +175,26 @@ function calculer_inclure($p, &$boucles, $id_boucle) { } else { $code = calculer_liste($p->texte, $p->descr, $boucles, $id_boucle); - if ($code AND preg_match("/^'([^']*)'/s", $code, $r)) + if ($code and preg_match("/^'([^']*)'/s", $code, $r)) { $fichier = $r[1]; - else $fichier = ''; + } else { + $fichier = ''; + } } - if (!$code OR $code === '""') { - $erreur_p_i_i = array('zbug_parametres_inclus_incorrects', - array('param' => $code)); + if (!$code or $code === '""') { + $erreur_p_i_i = array( + 'zbug_parametres_inclus_incorrects', + array('param' => $code) + ); erreur_squelette($erreur_p_i_i, $p); + return false; } $compil = texte_script(memoriser_contexte_compil($p)); if (is_array($_contexte)) { // Critere d'inclusion {env} (et {self} pour compatibilite ascendante) - if ($env = (isset($_contexte['env'])|| isset($_contexte['self']))) { + if ($env = (isset($_contexte['env']) || isset($_contexte['self']))) { unset($_contexte['env']); } @@ -167,17 +203,17 @@ function calculer_inclure($p, &$boucles, $id_boucle) { $_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'"; } - if ($ajax = isset($_contexte['ajax'])){ - $ajax = preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']); + if ($ajax = isset($_contexte['ajax'])) { + $ajax = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']); unset($_contexte['ajax']); } $_contexte = join(",\n\t", $_contexte); - } - else - return false; // j'aurais voulu toucher le fond ... - - $contexte = 'array(' . $_contexte .')'; + } else { + return false; + } // j'aurais voulu toucher le fond ... + + $contexte = 'array(' . $_contexte . ')'; if ($env) { $contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)"; @@ -186,15 +222,17 @@ function calculer_inclure($p, &$boucles, $id_boucle) { // s'il y a une extension .php, ce n'est pas un squelette if ($fichier and preg_match('/^.+[.]php$/s', $fichier)) { $code = sandbox_composer_inclure_php($fichier, $p, $contexte); - } else { + } else { $_options[] = "\"compil\"=>array($compil)"; - if ($ajax) + if ($ajax) { $_options[] = $ajax; - $code = " ' . argumenter_squelette($code) . '"; - $code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',',$_options), "_request(\"connect\")") . ';'; + } + $code = " ' . argumenter_squelette($code) . '"; + $code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',', $_options), + "_request(\"connect\")") . ';'; } - return "\n'<'.'". "?php ". $code . "\n?'." . "'>'"; + return "\n'<'.'" . "?php " . $code . "\n?'." . "'>'"; } @@ -211,7 +249,7 @@ function calculer_inclure($p, &$boucles, $id_boucle) { * @param bool $ignore_previsu * true pour ne tester que le cas publie et ignorer l'eventuel var_mode=preview de la page */ -function instituer_boucle(&$boucle, $echapper=true, $ignore_previsu=false){ +function instituer_boucle(&$boucle, $echapper = true, $ignore_previsu = false) { /* $show['statut'][] = array( 'champ'=>'statut', // champ de la table sur lequel porte le filtrage par le statut @@ -238,13 +276,13 @@ function instituer_boucle(&$boucle, $echapper=true, $ignore_previsu=false){ */ $id_table = $boucle->id_table; $show = $boucle->show; - if (isset($show['statut']) AND $show['statut']){ - foreach($show['statut'] as $k=>$s){ + if (isset($show['statut']) and $show['statut']) { + foreach ($show['statut'] as $k => $s) { // Restreindre aux elements publies si pas de {statut} ou autre dans les criteres $filtrer = true; if (isset($s['exception'])) { - foreach(is_array($s['exception'])?$s['exception']:array($s['exception']) as $m) { - if (isset($boucle->modificateur[$m]) OR isset($boucle->modificateur['criteres'][$m])) { + foreach (is_array($s['exception']) ? $s['exception'] : array($s['exception']) as $m) { + if (isset($boucle->modificateur[$m]) or isset($boucle->modificateur['criteres'][$m])) { $filtrer = false; break; } @@ -252,51 +290,51 @@ function instituer_boucle(&$boucle, $echapper=true, $ignore_previsu=false){ } if ($filtrer) { - if (is_array($s['champ'])){ - $statut = preg_replace(',\W,','',array_pop($s['champ'])); // securite + if (is_array($s['champ'])) { + $statut = preg_replace(',\W,', '', array_pop($s['champ'])); // securite $jointures = array(); // indiquer la description de chaque table dans le tableau de jointures, // ce qui permet d'eviter certains GROUP BY inutiles. $trouver_table = charger_fonction('trouver_table', 'base'); - foreach($s['champ'] as $j) { + foreach ($s['champ'] as $j) { $id = reset($j); $def = $trouver_table($id); - $jointures[] = array('',array($id,$def),end($j)); + $jointures[] = array('', array($id, $def), end($j)); } $jointures[0][0] = $id_table; - if (!array_search($id, $boucle->from)){ + if (!array_search($id, $boucle->from)) { include_spip('public/jointures'); fabrique_jointures($boucle, $jointures, true, $boucle->show, $id_table, '', $echapper); } // trouver l'alias de la table d'arrivee qui porte le statut $id = array_search($id, $boucle->from); - } - else { + } else { $id = $id_table; - $statut = preg_replace(',\W,','',$s['champ']); // securite + $statut = preg_replace(',\W,', '', $s['champ']); // securite } - $mstatut = $id .'.'.$statut; + $mstatut = $id . '.' . $statut; - $arg_ignore_previsu=($ignore_previsu?",true":''); + $arg_ignore_previsu = ($ignore_previsu ? ",true" : ''); include_spip('public/quete'); - if (isset($s['post_date']) AND $s['post_date'] - AND $GLOBALS['meta']["post_dates"] == 'non'){ - $date = $id.'.'.preg_replace(',\W,','',$s['post_date']); // securite + if (isset($s['post_date']) and $s['post_date'] + and $GLOBALS['meta']["post_dates"] == 'non' + ) { + $date = $id . '.' . preg_replace(',\W,', '', $s['post_date']); // securite array_unshift($boucle->where, $echapper ? - "\nquete_condition_postdates('$date',"._q($boucle->sql_serveur)."$arg_ignore_previsu)" - : - quete_condition_postdates($date,$boucle->sql_serveur,$ignore_previsu) + "\nquete_condition_postdates('$date'," . _q($boucle->sql_serveur) . "$arg_ignore_previsu)" + : + quete_condition_postdates($date, $boucle->sql_serveur, $ignore_previsu) ); } array_unshift($boucle->where, $echapper ? "\nquete_condition_statut('$mstatut'," - . _q($s['previsu'])."," - ._q($s['publie'])."," - ._q($boucle->sql_serveur)."$arg_ignore_previsu)" - : - quete_condition_statut($mstatut,$s['previsu'],$s['publie'],$boucle->sql_serveur,$ignore_previsu) + . _q($s['previsu']) . "," + . _q($s['publie']) . "," + . _q($boucle->sql_serveur) . "$arg_ignore_previsu)" + : + quete_condition_statut($mstatut, $s['previsu'], $s['publie'], $boucle->sql_serveur, $ignore_previsu) ); } } @@ -305,17 +343,17 @@ function instituer_boucle(&$boucle, $echapper=true, $ignore_previsu=false){ /** * Produit le corps PHP d'une boucle Spip. - * + * * Ce corps remplit une variable $t0 retournée en valeur. * Ici on distingue boucles recursives et boucle à requête SQL * et on insère le code d'envoi au debusqueur du resultat de la fonction. * * @param string $id_boucle - * Identifiant de la boucle + * Identifiant de la boucle * @param array $boucles - * AST du squelette + * AST du squelette * @return string - * Code PHP compilé de la boucle + * Code PHP compilé de la boucle */ function calculer_boucle($id_boucle, &$boucles) { @@ -325,63 +363,66 @@ function calculer_boucle($id_boucle, &$boucles) { // en mode debug memoriser les premiers passages dans la boucle, // mais pas tous, sinon ca pete. - if (_request('var_mode_affiche') != 'resultat') + if (_request('var_mode_affiche') != 'resultat') { $trace = ''; - else { + } else { $trace = $boucles[$id_boucle]->descr['nom'] . $id_boucle; $trace = "if (count(@\$GLOBALS['debug_objets']['resultat']['$trace'])<3) \$GLOBALS['debug_objets']['resultat']['$trace'][] = \$t0;"; } + return ($boucles[$id_boucle]->type_requete == TYPE_RECURSIF) - ? calculer_boucle_rec($id_boucle, $boucles, $trace) - : calculer_boucle_nonrec($id_boucle, $boucles, $trace); + ? calculer_boucle_rec($id_boucle, $boucles, $trace) + : calculer_boucle_nonrec($id_boucle, $boucles, $trace); } /** - * Compilation d'une boucle recursive. + * Compilation d'une boucle recursive. * * @internal - * Il suffit (ET IL FAUT) sauvegarder les valeurs des arguments passes par - * reference, car par definition un tel passage ne les sauvegarde pas - * + * Il suffit (ET IL FAUT) sauvegarder les valeurs des arguments passes par + * reference, car par definition un tel passage ne les sauvegarde pas + * * @param string $id_boucle - * Identifiant de la boucle + * Identifiant de la boucle * @param array $boucles - * AST du squelette + * AST du squelette * @param string $trace - * Code PHP (en mode debug uniquement) servant à conserver une - * trace des premières valeurs de la boucle afin de pouvoir - * les afficher dans le débugueur ultérieurement + * Code PHP (en mode debug uniquement) servant à conserver une + * trace des premières valeurs de la boucle afin de pouvoir + * les afficher dans le débugueur ultérieurement * @return string - * Code PHP compilé de la boucle récursive -**/ + * Code PHP compilé de la boucle récursive + **/ function calculer_boucle_rec($id_boucle, &$boucles, $trace) { $nom = $boucles[$id_boucle]->param[0]; + return - // Numrows[$nom] peut ne pas être encore defini - "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());" - . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";" - . "\n\t\$Numrows['$nom'] = (\$save_numrows);" - . $trace - . "\n\treturn \$t0;"; + // Numrows[$nom] peut ne pas être encore defini + "\n\t\$save_numrows = (isset(\$Numrows['$nom']) ? \$Numrows['$nom'] : array());" + . "\n\t\$t0 = " . $boucles[$id_boucle]->return . ";" + . "\n\t\$Numrows['$nom'] = (\$save_numrows);" + . $trace + . "\n\treturn \$t0;"; } /** * Compilation d'une boucle non recursive. - * + * * La constante donne le cadre systématique du code: - * %s1: initialisation des arguments de calculer_select - * %s2: appel de calculer_select en donnant un contexte pour les cas d'erreur - * %s3: initialisation du sous-tableau Numrows[id_boucle] - * %s4: sauvegarde de la langue et calcul des invariants de boucle sur elle - * %s5: boucle while sql_fetch ou str_repeat si corps monotone - * %s6: restauration de la langue - * %s7: liberation de la ressource, en tenant compte du serveur SQL - * %s8: code de trace eventuel avant le retour -**/ + * + * - %s1: initialisation des arguments de calculer_select + * - %s2: appel de calculer_select en donnant un contexte pour les cas d'erreur + * - %s3: initialisation du sous-tableau Numrows[id_boucle] + * - %s4: sauvegarde de la langue et calcul des invariants de boucle sur elle + * - %s5: boucle while sql_fetch ou str_repeat si corps monotone + * - %s6: restauration de la langue + * - %s7: liberation de la ressource, en tenant compte du serveur SQL + * - %s8: code de trace eventuel avant le retour + **/ define('CODE_CORPS_BOUCLE', '%s - if (defined("_BOUCLE_PROFILER")) $timer = time()+microtime(); + if (defined("_BOUCLE_PROFILER")) $timer = time()+(float)microtime(); $t0 = ""; // REQUETE $iter = IterFactory::create( @@ -396,50 +437,54 @@ define('CODE_CORPS_BOUCLE', '%s %s$iter->free(); }%s if (defined("_BOUCLE_PROFILER") - AND 1000*($timer = (time()+microtime())-$timer) > _BOUCLE_PROFILER) + AND 1000*($timer = (time()+(float)microtime())-$timer) > _BOUCLE_PROFILER) spip_log(intval(1000*$timer)."ms %s","profiler"._LOG_AVERTISSEMENT); return $t0;' ); /** - * Compilation d'une boucle (non recursive). + * Compilation d'une boucle (non recursive). * * @param string $id_boucle - * Identifiant de la boucle + * Identifiant de la boucle * @param array $boucles - * AST du squelette + * AST du squelette * @param string $trace - * Code PHP (en mode debug uniquement) servant à conserver une - * trace des premières valeurs de la boucle afin de pouvoir - * les afficher dans le débugueur ultérieurement + * Code PHP (en mode debug uniquement) servant à conserver une + * trace des premières valeurs de la boucle afin de pouvoir + * les afficher dans le débugueur ultérieurement * @return string - * Code PHP compilé de la boucle récursive -**/ + * Code PHP compilé de la boucle récursive + **/ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) { $boucle = &$boucles[$id_boucle]; $return = $boucle->return; $type_boucle = $boucle->type_requete; $primary = $boucle->primary; - $constant = preg_match(CODE_MONOTONE, str_replace("\\'",'', $return)); - $flag_cpt = $boucle->mode_partie ||$boucle->cptrows; + $constant = preg_match(CODE_MONOTONE, str_replace("\\'", '', $return)); + $flag_cpt = $boucle->mode_partie || $boucle->cptrows; $corps = ''; // faudrait expanser le foreach a la compil, car y en a souvent qu'un // et puis faire un [] plutot qu'un "','." - if ($boucle->doublons) + if ($boucle->doublons) { $corps .= "\n\t\t\tforeach(" . $boucle->doublons . ' as $k) $doublons[$k] .= "," . ' . - index_pile($id_boucle, $primary, $boucles) - . "; // doublons\n"; + index_pile($id_boucle, $primary, $boucles) + . "; // doublons\n"; + } // La boucle doit-elle selectionner la langue ? // - par defaut, les boucles suivantes le font // (sauf si forcer_lang==true ou si le titre contient ). // - a moins d'une demande explicite via {!lang_select} if (!$constant && $boucle->lang_select != 'non' && - (($boucle->lang_select == 'oui') || - in_array($type_boucle, array( - 'articles', 'rubriques', 'hierarchie', 'breves' + (($boucle->lang_select == 'oui') || + in_array($type_boucle, array( + 'articles', + 'rubriques', + 'hierarchie', + 'breves' ))) ) { // Memoriser la langue avant la boucle et la restituer apres @@ -448,24 +493,27 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) { $fin_lang = "lang_select();\n\t"; $fin_lang_select_public = "\n\t\tlang_select();"; - $corps .= + $corps .= "\n\t\tlang_select_public(" . index_pile($id_boucle, 'lang', $boucles) - . ", '".$boucle->lang_select."'" + . ", '" . $boucle->lang_select . "'" . (in_array($type_boucle, array( - 'articles', 'rubriques', 'hierarchie', 'breves' - )) ? ', '.index_pile($id_boucle, 'titre', $boucles) : '') + 'articles', + 'rubriques', + 'hierarchie', + 'breves' + )) ? ', ' . index_pile($id_boucle, 'titre', $boucles) : '') . ');'; - } - else { + } else { $init_lang = ''; $fin_lang = ''; $fin_lang_select_public = ''; // sortir les appels au traducteur (invariants de boucle) if (strpos($return, '?php') === false - AND preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r)) { + and preg_match_all("/\W(_T[(]'[^']*'[)])/", $return, $r) + ) { $i = 1; - foreach($r[1] as $t) { + foreach ($r[1] as $t) { $init_lang .= "\n\t\$l$i = $t;"; $return = str_replace($t, "\$l$i", $return); $i++; @@ -474,79 +522,89 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) { } // gestion optimale des separateurs et des boucles constantes - if (count($boucle->separateur)) - $code_sep = ("'" . str_replace("'","\'",join('',$boucle->separateur)) . "'"); + if (count($boucle->separateur)) { + $code_sep = ("'" . str_replace("'", "\'", join('', $boucle->separateur)) . "'"); + } - $corps .= - ((!$boucle->separateur) ? + $corps .= + ((!$boucle->separateur) ? (($constant && !$corps && !$flag_cpt) ? $return : - (($return==="''") ? '' : - ("\n\t\t" . '$t0 .= ' . $return . ";"))) : - ("\n\t\t\$t1 " . - ((strpos($return, '$t1.') === 0) ? - (".=" . substr($return,4)) : - ('= ' . $return)) . - ";\n\t\t" . - '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;")); - + (($return === "''") ? '' : + ("\n\t\t" . '$t0 .= ' . $return . ";"))) : + ("\n\t\t\$t1 " . + ((strpos($return, '$t1.') === 0) ? + (".=" . substr($return, 4)) : + ('= ' . $return)) . + ";\n\t\t" . + '$t0 .= ((strlen($t1) && strlen($t0)) ? ' . $code_sep . " : '') . \$t1;")); + // Calculer les invalideurs si c'est une boucle non constante et si on // souhaite invalider ces elements - if (!$constant AND $primary) { + if (!$constant and $primary) { include_spip('inc/invalideur'); - if (function_exists($i = 'calcul_invalideurs')) + if (function_exists($i = 'calcul_invalideurs')) { $corps = $i($corps, $primary, $boucles, $id_boucle); + } } // gerer le compteur de boucle // avec ou sans son utilisation par les criteres {1/3} {1,4} {n-2,1}... - if ($boucle->partie OR $boucle->cptrows) + if ($boucle->partie or $boucle->cptrows) { $corps = "\n\t\t\$Numrows['$id_boucle']['compteur_boucle']++;" - . $boucle->partie - . $corps; + . $boucle->partie + . $corps; + } // depiler la lang de la boucle si besoin $corps .= $fin_lang_select_public; // si le corps est une constante, ne pas appeler le serveur N fois! - if (preg_match(CODE_MONOTONE,str_replace("\\'",'',$corps), $r)) { - if (!isset($r[2]) OR (!$r[2])) { - if (!$boucle->numrows) + if (preg_match(CODE_MONOTONE, str_replace("\\'", '', $corps), $r)) { + if (!isset($r[2]) or (!$r[2])) { + if (!$boucle->numrows) { return "\n\t\$t0 = '';"; - else + } else { $corps = ""; + } } else { $boucle->numrows = true; $corps = "\n\t\$t0 = str_repeat($corps, \$Numrows['$id_boucle']['total']);"; } - } else $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n }"; + } else { + $corps = "while (\$Pile[\$SP]=\$iter->fetch()) {\n$corps\n }"; + } $count = ''; if (!$boucle->select) { - if (!$boucle->numrows OR $boucle->limit OR $boucle->mode_partie OR $boucle->group) + if (!$boucle->numrows or $boucle->limit or $boucle->mode_partie or $boucle->group) { $count = '1'; - else $count = 'count(*)'; - $boucles[$id_boucle]->select[]= $count; + } else { + $count = 'count(*)'; + } + $boucles[$id_boucle]->select[] = $count; } - if ($flag_cpt) + if ($flag_cpt) { $nums = "\n\t// COMPTEUR\n\t" - . "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t"; - else $nums = ''; + . "\$Numrows['$id_boucle']['compteur_boucle'] = 0;\n\t"; + } else { + $nums = ''; + } - if ($boucle->numrows OR $boucle->mode_partie) { + if ($boucle->numrows or $boucle->mode_partie) { $nums .= "\$Numrows['$id_boucle']['total'] = @intval(\$iter->count());" - . $boucle->mode_partie - . "\n\t"; + . $boucle->mode_partie + . "\n\t"; } // Ne calculer la requete que maintenant // car ce qui precede appelle index_pile qui influe dessus $init = (($init = $boucles[$id_boucle]->doublons) - ? ("\n\t$init = array();") : '') - . calculer_requete_sql($boucles[$id_boucle]); + ? ("\n\t$init = array();") : '') + . calculer_requete_sql($boucles[$id_boucle]); $contexte = memoriser_contexte_compil($boucle); @@ -560,7 +618,7 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) { $corps, $fin_lang, $trace, - 'BOUCLE'.$id_boucle .' @ '.($boucle->descr['sourcefile']) + 'BOUCLE' . $id_boucle . ' @ ' . ($boucle->descr['sourcefile']) ); # var_dump($a);exit; @@ -572,47 +630,51 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) { * Calcule le code PHP d'une boucle contenant les informations qui produiront une requête SQL * * Le code produit est un tableau associatif $command contenant les informations - * pour que la boucle produise ensuite sa requête, tel que $command['from'] = 'spip_articles'; + * pour que la boucle produise ensuite sa requête, tel que `$command['from'] = 'spip_articles';` * * @param Boucle $boucle - * AST de la boucle + * AST de la boucle * @return string - * Code PHP compilé définissant les informations de requête -**/ -function calculer_requete_sql($boucle) -{ + * Code PHP compilé définissant les informations de requête + **/ +function calculer_requete_sql($boucle) { $init = array(); - $init[] = calculer_dec('table', "'" . $boucle->id_table ."'"); - $init[] = calculer_dec('id', "'" . $boucle->id_boucle ."'"); + $init[] = calculer_dec('table', "'" . $boucle->id_table . "'"); + $init[] = calculer_dec('id', "'" . $boucle->id_boucle . "'"); # En absence de champ c'est un decompte : - $init[] = calculer_dec('from', calculer_from($boucle)); + $init[] = calculer_dec('from', calculer_from($boucle)); $init[] = calculer_dec('type', calculer_from_type($boucle)); - $init[] = calculer_dec('groupby', 'array(' . (($g=join("\",\n\t\t\"",$boucle->group))?'"'.$g.'"':'') . ")"); - $init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select). "\")"); - $init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ")"); + $init[] = calculer_dec('groupby', + 'array(' . (($g = join("\",\n\t\t\"", $boucle->group)) ? '"' . $g . '"' : '') . ")"); + $init[] = calculer_dec('select', 'array("' . join("\",\n\t\t\"", $boucle->select) . "\")"); + $init[] = calculer_dec('orderby', 'array(' . calculer_order($boucle) . ")"); $init[] = calculer_dec('where', calculer_dump_array($boucle->where)); $init[] = calculer_dec('join', calculer_dump_join($boucle->join)); $init[] = calculer_dec('limit', - (strpos($boucle->limit, 'intval') === false ? - "'".$boucle->limit."'" - : - $boucle->limit)); + (strpos($boucle->limit, 'intval') === false ? + "'" . $boucle->limit . "'" + : + $boucle->limit)); $init[] = calculer_dec('having', calculer_dump_array($boucle->having)); $s = $d = ""; - foreach ($init as $i){ - if (reset($i)) - $s .= "\n\t\t".end($i); - else - $d .= "\n\t".end($i); + // l'index 0 de $i indique si l'affectation est statique (contenu) + // ou recalculée à chaque passage (vide) + foreach ($init as $i) { + if (reset($i)) { + $s .= "\n\t\t" . end($i); + } # statique + else { + $d .= "\n\t" . end($i); + } # dynamique } return ($boucle->hierarchie ? "\n\t$boucle->hierarchie" : '') - . $boucle->in - . $boucle->hash - . "\n\t".'if (!isset($command[\'table\'])) {' - . $s - . "\n\t}" - . $d; + . $boucle->in + . $boucle->hash + . "\n\t" . 'if (!isset($command[\'table\'])) {' + . $s + . "\n\t}" + . $d; } /** @@ -622,52 +684,77 @@ function calculer_requete_sql($boucle) * de l'élément dans une chaîne. * * @see reconstruire_contexte_compil() - * + * * @param Object $p * Objet de l'AST dont on mémorise le contexte * @return string * Informations du contexte séparés par des virgules, * qui peut être utilisé pour la production d'un tableau array() -**/ + **/ function memoriser_contexte_compil($p) { return join(',', array( - _q($p->descr['sourcefile']), - _q($p->descr['nom']), - @_q($p->id_boucle), + _q(isset($p->descr['sourcefile']) ? $p->descr['sourcefile'] : ''), + _q(isset($p->descr['nom']) ? $p->descr['nom'] : ''), + _q(isset($p->id_boucle) ? $p->id_boucle : null), intval($p->ligne), - '$GLOBALS[\'spip_lang\']')); + '$GLOBALS[\'spip_lang\']' + )); } /** - * Reconstruit un contexte de compilation + * Reconstruit un contexte de compilation * * Pour un tableau d'information de contexte donné, * retourne un objet Contexte (objet générique de l'AST) * avec ces informations * * @see memoriser_contexte_compil() - * + * * @param array $context_compil * Tableau des informations du contexte * @return Contexte * Objet Contexte -**/ -function reconstruire_contexte_compil($context_compil) -{ - if (!is_array($context_compil)) return $context_compil; + **/ +function reconstruire_contexte_compil($context_compil) { + if (!is_array($context_compil)) { + return $context_compil; + } $p = new Contexte; - $p->descr = array('sourcefile' => $context_compil[0], - 'nom' => $context_compil[1]); + $p->descr = array( + 'sourcefile' => $context_compil[0], + 'nom' => $context_compil[1] + ); $p->id_boucle = $context_compil[2]; $p->ligne = $context_compil[3]; $p->lang = $context_compil[4]; + return $p; } -// http://doc.spip.org/@calculer_dec -function calculer_dec($nom, $val) -{ - $static = 'if (!isset($command[\''.$nom.'\'])) '; +/** + * Calcule le code d'affectation d'une valeur à une commande de boucle + * + * Décrit le code qui complète le tableau $command qui servira entre autres + * à l'itérateur. Pour un nom de commande donnée et un code PHP décrivant + * ou récupérant une valeur, on retourne le code PHP qui fait l'affectation. + * + * L'index 0 du tableau retourné indique, lorsqu'il n'est pas vide, que l'affectation + * de la variable pourra être statique (c'est à dire qu'il ne dépend + * pas d'une quelconque variable PHP), et donc attribué une fois pour toutes + * quelque soit le nombre d'appels de la boucle. + * + * @param string $nom + * Nom de la commande + * @param string $val + * Code PHP décrivant la valeur à affecter + * @return array + * + * - index 0 : Code pour une affectation statique. Si non rempli, la propriété devra + * être ré-affectée à chaque appel de la boucle. + * - index 1 : Code de l'affectation + **/ +function calculer_dec($nom, $val) { + $static = 'if (!isset($command[\'' . $nom . '\'])) '; // si une variable apparait dans le calcul de la clause // il faut la re-evaluer a chaque passage if ( @@ -680,59 +767,100 @@ function calculer_dec($nom, $val) AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes )*/ - ) + ) { $static = ""; + } - return array($static,'$command[\''.$nom.'\'] = ' . $val . ';'); + return array($static, '$command[\'' . $nom . '\'] = ' . $val . ';'); } -// http://doc.spip.org/@calculer_dump_array -function calculer_dump_array($a) -{ - if (!is_array($a)) return $a ; - $res = ""; - if ($a AND $a[0] == "'?'") - return ("(" . calculer_dump_array($a[1]) . - " ? " . calculer_dump_array($a[2]) . - " : " . calculer_dump_array($a[3]) . - ")"); - else { - foreach($a as $v) $res .= ", " . calculer_dump_array($v); - return "\n\t\t\tarray(" . substr($res,2) . ')'; - } +/** + * Calcule l'expression PHP décrivant un tableau complexe (ou une chaîne) + * + * Lorsqu'un tableau est transmis, reconstruit de quoi créer le tableau + * en code PHP (une sorte de var_export) en appelant pour chaque valeur + * cette fonction de manière récursive. + * + * Si le premier index (0) du tableau est "'?'", retourne un code + * de test entre les 3 autres valeurs (v1 ? v2 : v3). Les valeurs + * pouvant être des tableaux aussi. + * + * @param mixed $a + * Les données dont on veut construire un équivalent de var_export + * @return string + * Expression PHP décrivant un texte ou un tableau + **/ +function calculer_dump_array($a) { + if (!is_array($a)) { + return $a; + } + $res = ""; + if ($a and $a[0] == "'?'") { + return ("(" . calculer_dump_array($a[1]) . + " ? " . calculer_dump_array($a[2]) . + " : " . calculer_dump_array($a[3]) . + ")"); + } else { + foreach ($a as $v) { + $res .= ", " . calculer_dump_array($v); + } + + return "\n\t\t\tarray(" . substr($res, 2) . ')'; + } } -// http://doc.spip.org/@calculer_dump_join -function calculer_dump_join($a) -{ - $res = ""; - foreach($a as $k => $v) - $res .= ", '$k' => array(".implode(',',$v).")"; - return 'array(' . substr($res,2) . ')'; +// http://code.spip.net/@calculer_dump_join +function calculer_dump_join($a) { + $res = ""; + foreach ($a as $k => $v) { + $res .= ", '$k' => array(" . implode(',', $v) . ")"; + } + + return 'array(' . substr($res, 2) . ')'; } -// http://doc.spip.org/@calculer_from -function calculer_from(&$boucle) -{ - $res = ""; - foreach($boucle->from as $k => $v) $res .= ",'$k' => '$v'"; - return 'array(' . substr($res,1) . ')'; +/** + * Calcule l'expression PHP décrivant les informations FROM d'une boucle + * + * @param Boucle $boucle + * Description de la boucle + * @return string + * Code PHP construisant un tableau des alias et noms des tables du FROM + **/ +function calculer_from(&$boucle) { + $res = ""; + foreach ($boucle->from as $k => $v) { + $res .= ",'$k' => '$v'"; + } + + return 'array(' . substr($res, 1) . ')'; } -// http://doc.spip.org/@calculer_from_type -function calculer_from_type(&$boucle) -{ - $res = ""; - foreach($boucle->from_type as $k => $v) $res .= ",'$k' => '$v'"; - return 'array(' . substr($res,1) . ')'; +/** + * Calcule l'expression PHP décrivant des informations de type de jointure + * pour un alias de table connu dans le FROM + * + * @param Boucle $boucle + * Description de la boucle + * @return string + * Code PHP construisant un tableau des alias et type de jointure du FROM + **/ +function calculer_from_type(&$boucle) { + $res = ""; + foreach ($boucle->from_type as $k => $v) { + $res .= ",'$k' => '$v'"; + } + + return 'array(' . substr($res, 1) . ')'; } -// http://doc.spip.org/@calculer_order -function calculer_order(&$boucle) -{ +// http://code.spip.net/@calculer_order +function calculer_order(&$boucle) { if (!$order = $boucle->order - AND !$order = $boucle->default_order) + and !$order = $boucle->default_order + ) { $order = array(); + } /*if (isset($boucle->modificateur['collate'])){ $col = "." . $boucle->modificateur['collate']; @@ -740,6 +868,7 @@ function calculer_order(&$boucle) if (strpos($order[$k],'COLLATE')===false) $order[$k].= $col; }*/ + return join(', ', $order); } @@ -748,47 +877,60 @@ function calculer_order(&$boucle) // Retourne une expression PHP, // (qui sera argument d'un Return ou la partie droite d'une affectation). -// http://doc.spip.org/@calculer_liste -function calculer_liste($tableau, $descr, &$boucles, $id_boucle='') { - if (!$tableau) return "''"; - if (!isset($descr['niv'])) $descr['niv'] = 0; +// http://code.spip.net/@calculer_liste +function calculer_liste($tableau, $descr, &$boucles, $id_boucle = '') { + if (!$tableau) { + return "''"; + } + if (!isset($descr['niv'])) { + $descr['niv'] = 0; + } $codes = compile_cas($tableau, $descr, $boucles, $id_boucle); - if ($codes === false) return false; + if ($codes === false) { + return false; + } $n = count($codes); - if (!$n) return "''"; + if (!$n) { + return "''"; + } $tab = str_repeat("\t", $descr['niv']); if (_request('var_mode_affiche') != 'validation') { - if ($n==1) + if ($n == 1) { return $codes[0]; - else { + } else { $res = ''; - foreach($codes as $code) { + foreach ($codes as $code) { if (!preg_match("/^'[^']*'$/", $code) - OR substr($res,-1,1)!=="'") - $res .= " .\n$tab$code"; - else { - $res = substr($res,0,-1) . substr($code,1); + or substr($res, -1, 1) !== "'" + ) { + $res .= " .\n$tab$code"; + } else { + $res = substr($res, 0, -1) . substr($code, 1); } } - return '(' . substr($res,2+$descr['niv']) . ')'; + + return '(' . substr($res, 2 + $descr['niv']) . ')'; } } else { - $nom = $descr['nom'] . $id_boucle . ($descr['niv']?$descr['niv']:''); - return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(" ,\n$tab", $codes) . ")))"; + $nom = $descr['nom'] . $id_boucle . ($descr['niv'] ? $descr['niv'] : ''); + + return "join('', array_map('array_shift', \$GLOBALS['debug_objets']['sequence']['$nom'] = array(" . join(" ,\n$tab", + $codes) . ")))"; } } -define('_REGEXP_COND_VIDE_NONVIDE',"/^[(](.*)[?]\s*''\s*:\s*('[^']+')\s*[)]$/"); -define('_REGEXP_COND_NONVIDE_VIDE',"/^[(](.*)[?]\s*('[^']+')\s*:\s*''\s*[)]$/"); +define('_REGEXP_COND_VIDE_NONVIDE', "/^[(](.*)[?]\s*''\s*:\s*('[^']+')\s*[)]$/"); +define('_REGEXP_COND_NONVIDE_VIDE', "/^[(](.*)[?]\s*('[^']+')\s*:\s*''\s*[)]$/"); define('_REGEXP_CONCAT_NON_VIDE', "/^(.*)[.]\s*'[^']+'\s*$/"); -// http://doc.spip.org/@compile_cas +// http://code.spip.net/@compile_cas function compile_cas($tableau, $descr, &$boucles, $id_boucle) { - $codes = array(); + $codes = array(); // cas de la boucle recursive - if (is_array($id_boucle)) - $id_boucle = $id_boucle[0]; + if (is_array($id_boucle)) { + $id_boucle = $id_boucle[0]; + } $type = !$id_boucle ? '' : $boucles[$id_boucle]->type_requete; $tab = str_repeat("\t", ++$descr['niv']); $mode = _request('var_mode_affiche'); @@ -797,158 +939,169 @@ function compile_cas($tableau, $descr, &$boucles, $id_boucle) { // par un caractere distinguant le cas, pour exploitation par debug. foreach ($tableau as $p) { - switch($p->type) { - // texte seul - case 'texte': - $code = sandbox_composer_texte($p->texte, $p); - $commentaire= strlen($p->texte) . " signes"; - $avant=''; - $apres=''; - $altern = "''"; - break; - - case 'polyglotte': - $code = ""; - foreach($p->traductions as $k => $v) { - $code .= ",'" . - str_replace(array("\\","'"),array("\\\\","\\'"), $k) . - "' => '" . - str_replace(array("\\","'"),array("\\\\","\\'"), $v) . - "'"; - } - $code = "choisir_traduction(array(" . - substr($code,1) . - "))"; - $commentaire= '&'; - $avant=''; - $apres=''; - $altern = "''"; - break; - - // inclure - case 'include': - $p->descr = $descr; - $code = calculer_inclure($p, $boucles, $id_boucle); - if ($code === false) { - $err_e_c = true; - $code = "''"; - } else { - $commentaire = ''; - $avant=''; - $apres=''; + switch ($p->type) { + // texte seul + case 'texte': + $code = sandbox_composer_texte($p->texte, $p); + $commentaire = strlen($p->texte) . " signes"; + $avant = ''; + $apres = ''; $altern = "''"; - } - break; - - // boucle - case TYPE_RECURSIF: - $nom = $p->id_boucle; - $newdescr = $descr; - $newdescr['id_mere'] = $nom; - $newdescr['niv']++; - $avant = calculer_liste($p->avant, - $newdescr, $boucles, $id_boucle); - $apres = calculer_liste($p->apres, - $newdescr, $boucles, $id_boucle); - $newdescr['niv']--; - $altern = calculer_liste($p->altern, - $newdescr, $boucles, $id_boucle); - if (($avant === false) OR ($apres === false) OR ($altern === false)) { - $err_e_c = true; - $code = "''"; - } else { - $code = 'BOUCLE' . - str_replace("-","_", $nom) . $descr['nom'] . - '($Cache, $Pile, $doublons, $Numrows, $SP)'; - $commentaire= "?$nom"; - if (!$boucles[$nom]->milieu - AND $boucles[$nom]->type_requete <> TYPE_RECURSIF) { - if ($altern != "''") $code .= "\n. $altern"; - if ($avant<>"''" OR $apres<>"''") - spip_log("boucle $nom toujours vide, code superflu dans $id"); - $avant = $apres = $altern = "''"; - } else if ($altern != "''") $altern = "($altern)"; - } - break; - - case 'idiome': - $l = array(); - $code = ''; - foreach ($p->arg as $k => $v) { - $_v = calculer_liste($v, $descr, $boucles, $id_boucle); - if ($k) { - $l[] = _q($k) . ' => ' . $_v; + break; + + case 'polyglotte': + $code = ""; + foreach ($p->traductions as $k => $v) { + $code .= ",'" . + str_replace(array("\\", "'"), array("\\\\", "\\'"), $k) . + "' => '" . + str_replace(array("\\", "'"), array("\\\\", "\\'"), $v) . + "'"; + } + $code = "choisir_traduction(array(" . + substr($code, 1) . + "))"; + $commentaire = '&'; + $avant = ''; + $apres = ''; + $altern = "''"; + break; + + // inclure + case 'include': + $p->descr = $descr; + $code = calculer_inclure($p, $boucles, $id_boucle); + if ($code === false) { + $err_e_c = true; + $code = "''"; } else { - $code = $_v; + $commentaire = ''; + $avant = ''; + $apres = ''; + $altern = "''"; } - } - // Si le module n'est pas fourni, l'expliciter sauf si calculé - if ($p->module) { - $m = $p->module .':'.$p->nom_champ; - } elseif ($p->nom_champ) { - $m = MODULES_IDIOMES .':'.$p->nom_champ; - } else { - $m = ''; - } - $code = (!$code ? "'$m'" : + break; + + // boucle + case TYPE_RECURSIF: + $nom = $p->id_boucle; + $newdescr = $descr; + $newdescr['id_mere'] = $nom; + $newdescr['niv']++; + $avant = calculer_liste($p->avant, + $newdescr, $boucles, $id_boucle); + $apres = calculer_liste($p->apres, + $newdescr, $boucles, $id_boucle); + $newdescr['niv']--; + $altern = calculer_liste($p->altern, + $newdescr, $boucles, $id_boucle); + if (($avant === false) or ($apres === false) or ($altern === false)) { + $err_e_c = true; + $code = "''"; + } else { + $code = 'BOUCLE' . + str_replace("-", "_", $nom) . $descr['nom'] . + '($Cache, $Pile, $doublons, $Numrows, $SP)'; + $commentaire = "?$nom"; + if (!$boucles[$nom]->milieu + and $boucles[$nom]->type_requete <> TYPE_RECURSIF + ) { + if ($altern != "''") { + $code .= "\n. $altern"; + } + if ($avant <> "''" or $apres <> "''") { + spip_log("boucle $nom toujours vide, code superflu dans $descr[sourcefile]"); + } + $avant = $apres = $altern = "''"; + } else { + if ($altern != "''") { + $altern = "($altern)"; + } + } + } + break; + + case 'idiome': + $l = array(); + $code = ''; + foreach ($p->arg as $k => $v) { + $_v = calculer_liste($v, $descr, $boucles, $id_boucle); + if ($k) { + $l[] = _q($k) . ' => ' . $_v; + } else { + $code = $_v; + } + } + // Si le module n'est pas fourni, l'expliciter sauf si calculé + if ($p->module) { + $m = $p->module . ':' . $p->nom_champ; + } elseif ($p->nom_champ) { + $m = MODULES_IDIOMES . ':' . $p->nom_champ; + } else { + $m = ''; + } + + $code = (!$code ? "'$m'" : ($m ? "'$m' . $code" : ("(strpos(\$x=$code, ':') ? \$x : ('" . MODULES_IDIOMES . ":' . \$x))"))) . (!$l ? '' : (", array(" . implode(",\n", $l) . ")")); - $code = "_T($code)"; - if ($p->param) { + $code = "_T($code)"; + if ($p->param) { + $p->id_boucle = $id_boucle; + $p->boucles = &$boucles; + $code = compose_filtres($p, $code); + } + $commentaire = ":"; + $avant = ''; + $apres = ''; + $altern = "''"; + break; + + case 'champ': + + // cette structure pourrait etre completee des le phrase' (a faire) $p->id_boucle = $id_boucle; $p->boucles = &$boucles; - $code = compose_filtres($p, $code); - } - $commentaire = ":"; - $avant=''; - $apres=''; - $altern = "''"; - break; - - case 'champ': - - // cette structure pourrait etre completee des le phrase' (a faire) - $p->id_boucle = $id_boucle; - $p->boucles = &$boucles; - $p->descr = $descr; - #$p->interdire_scripts = true; - $p->type_requete = $type; - - $code = calculer_champ($p); - $commentaire = '#' . $p->nom_champ . $p->etoile; - $avant = calculer_liste($p->avant, - $descr, $boucles, $id_boucle); - $apres = calculer_liste($p->apres, - $descr, $boucles, $id_boucle); - $altern = "''"; - // Si la valeur est destinee a une comparaison a '' - // forcer la conversion en une chaine par strval - // si ca peut etre autre chose qu'une chaine - if (($avant != "''" OR $apres != "''") - AND $code[0]!= "'" + $p->descr = $descr; + #$p->interdire_scripts = true; + $p->type_requete = $type; + + $code = calculer_champ($p); + $commentaire = '#' . $p->nom_champ . $p->etoile; + $avant = calculer_liste($p->avant, + $descr, $boucles, $id_boucle); + $apres = calculer_liste($p->apres, + $descr, $boucles, $id_boucle); + $altern = "''"; + // Si la valeur est destinee a une comparaison a '' + // forcer la conversion en une chaine par strval + // si ca peut etre autre chose qu'une chaine + if (($avant != "''" or $apres != "''") + and $code[0] != "'" # AND (strpos($code,'interdire_scripts') !== 0) - AND !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code) - AND !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code) - AND !preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) - $code = "strval($code)"; - break; + and !preg_match(_REGEXP_COND_VIDE_NONVIDE, $code) + and !preg_match(_REGEXP_COND_NONVIDE_VIDE, $code) + and !preg_match(_REGEXP_CONCAT_NON_VIDE, $code) + ) { + $code = "strval($code)"; + } + break; - default: - // Erreur de construction de l'arbre de syntaxe abstraite - $code = "''"; - $p->descr = $descr; - $err_e_c = _T('zbug_erreur_compilation'); - erreur_squelette($err_e_c, $p); + default: + // Erreur de construction de l'arbre de syntaxe abstraite + $code = "''"; + $p->descr = $descr; + $err_e_c = _T('zbug_erreur_compilation'); + erreur_squelette($err_e_c, $p); } // switch if ($code != "''") { $code = compile_retour($code, $avant, $apres, $altern, $tab, $descr['niv']); - $codes[]= (($mode == 'validation') ? + $codes[] = (($mode == 'validation') ? "array($code, '$commentaire', " . $p->ligne . ")" : (($mode == 'code') ? - "\n// $commentaire\n$code" : - $code)); + "\n// $commentaire\n$code" : + $code)); } } // foreach @@ -959,43 +1112,57 @@ function compile_cas($tableau, $descr, &$boucles, $id_boucle) { // mais si EXP est de la forme (t ? 'C' : '') on produit (t ? (p . C . s) : a) // de meme si EXP est de la forme (t ? '' : 'C') -// http://doc.spip.org/@compile_retour -function compile_retour($code, $avant, $apres, $altern, $tab, $n) -{ - if ($avant == "''") $avant = ''; - if ($apres == "''") $apres = ''; - if (!$avant AND !$apres AND ($altern==="''")) return $code; +// http://code.spip.net/@compile_retour +function compile_retour($code, $avant, $apres, $altern, $tab, $n) { + if ($avant == "''") { + $avant = ''; + } + if ($apres == "''") { + $apres = ''; + } + if (!$avant and !$apres and ($altern === "''")) { + return $code; + } if (preg_match(_REGEXP_CONCAT_NON_VIDE, $code)) { $t = $code; $cond = ''; - } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE,$code, $r)) { - $t = $r[2]; - $cond = '!' . $r[1]; - } else if (preg_match(_REGEXP_COND_NONVIDE_VIDE,$code, $r)) { + } elseif (preg_match(_REGEXP_COND_VIDE_NONVIDE, $code, $r)) { $t = $r[2]; - $cond = $r[1]; + $cond = '!' . $r[1]; } else { - $t = '$t' . $n; - $cond = "($t = $code)!==''"; + if (preg_match(_REGEXP_COND_NONVIDE_VIDE, $code, $r)) { + $t = $r[2]; + $cond = $r[1]; + } else { + $t = '$t' . $n; + $cond = "($t = $code)!==''"; + } } - $res = (!$avant ? "" : "$avant . ") . + $res = (!$avant ? "" : "$avant . ") . $t . (!$apres ? "" : " . $apres"); - if ($res !== $t) $res = "($res)"; + if ($res !== $t) { + $res = "($res)"; + } + return !$cond ? $res : "($cond ?\n\t$tab$res :\n\t$tab$altern)"; } -function compile_inclure_doublons($lexemes) -{ - foreach($lexemes as $v) - if($v->type === 'include' AND $v->param) - foreach($v->param as $r) - if (trim($r[0]) === 'doublons') - return true; +function compile_inclure_doublons($lexemes) { + foreach ($lexemes as $v) { + if ($v->type === 'include' and $v->param) { + foreach ($v->param as $r) { + if (trim($r[0]) === 'doublons') { + return true; + } + } + } + } + return false; } @@ -1014,8 +1181,8 @@ function compile_inclure_doublons($lexemes) // - 'entetes' => tableau des entetes http // En cas d'erreur, elle retournera un tableau des 2 premiers elements seulement -// http://doc.spip.org/@public_compiler_dist -function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect=''){ +// http://code.spip.net/@public_compiler_dist +function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect = '') { // Pre-traitement : reperer le charset du squelette, et le convertir // Bonus : supprime le BOM include_spip('inc/charsets'); @@ -1023,14 +1190,18 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') // rendre inertes les echappements de #[](){}<> $i = 0; - while(false !== strpos($squelette, $inerte = '-INERTE'.$i)) $i++; + while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) { + $i++; + } $squelette = preg_replace_callback(',\\\\([#[()\]{}<>]),', create_function('$a', "return '$inerte-'.ord(\$a[1]).'-';"), $squelette, -1, $esc); - $descr = array('nom' => $nom, - 'gram' => $gram, - 'sourcefile' => $sourcefile, - 'squelette' => $squelette); + $descr = array( + 'nom' => $nom, + 'gram' => $gram, + 'sourcefile' => $sourcefile, + 'squelette' => $squelette + ); // Phraser le squelette, selon sa grammaire @@ -1038,32 +1209,37 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') $f = charger_fonction('phraser_' . $gram, 'public'); $squelette = $f($squelette, '', $boucles, $descr); + $boucles = compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect); // restituer les echappements - if ($esc) - foreach($boucles as $i=>$boucle) { + if ($esc) { + foreach ($boucles as $i => $boucle) { $boucles[$i]->return = preg_replace_callback(",$inerte-(\d+)-,", create_function('$a', 'return chr($a[1]);'), $boucle->return); - $boucles[$i]->descr['squelette'] = preg_replace_callback(",$inerte-(\d+)-,", create_function('$a', 'return "\\\\".chr($a[1]);'), + $boucles[$i]->descr['squelette'] = preg_replace_callback(",$inerte-(\d+)-,", + create_function('$a', 'return "\\\\".chr($a[1]);'), $boucle->descr['squelette']); } - - $debug = ($boucles AND defined('_VAR_MODE') AND _VAR_MODE == 'debug'); + } + + $debug = ($boucles and defined('_VAR_MODE') and _VAR_MODE == 'debug'); if ($debug) { include_spip('public/decompiler'); - foreach($boucles as $id => $boucle) { - if ($id) - $decomp = "\n/* BOUCLE " . - $boucle->type_requete . - " " . - str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) . - " */\n"; - else $decomp = ("\n/*\n" . - str_replace('*/', '* /', public_decompiler($squelette, $gram)) - . "\n*/"); - $boucles[$id]->return = $decomp .$boucle->return; - $GLOBALS['debug_objets']['code'][$nom.$id] = $boucle->return; + foreach ($boucles as $id => $boucle) { + if ($id) { + $decomp = "\n/* BOUCLE " . + $boucle->type_requete . + " " . + str_replace('*/', '* /', public_decompiler($boucle, $gram, 0, 'criteres')) . + " */\n"; + } else { + $decomp = ("\n/*\n" . + str_replace('*/', '* /', public_decompiler($squelette, $gram)) + . "\n*/"); + } + $boucles[$id]->return = $decomp . $boucle->return; + $GLOBALS['debug_objets']['code'][$nom . $id] = $boucle->return; } } @@ -1073,94 +1249,110 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') // Point d'entree pour arbre de syntaxe abstraite fourni en premier argument // Autres specifications comme ci-dessus -function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect=''){ +function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $connect = '') { static $trouver_table; spip_timer('calcul_skel'); - if (defined('_VAR_MODE') AND _VAR_MODE == 'debug') { + if (defined('_VAR_MODE') and _VAR_MODE == 'debug') { $GLOBALS['debug_objets']['squelette'][$nom] = $descr['squelette']; $GLOBALS['debug_objets']['sourcefile'][$nom] = $sourcefile; - if (!isset($GLOBALS['debug_objets']['principal'])) + if (!isset($GLOBALS['debug_objets']['principal'])) { $GLOBALS['debug_objets']['principal'] = $nom; + } } foreach ($boucles as $id => $boucle) { - $GLOBALS['debug_objets']['boucle'][$nom.$id] = $boucle; + $GLOBALS['debug_objets']['boucle'][$nom . $id] = $boucle; } $descr['documents'] = compile_inclure_doublons($squelette); // Demander la description des tables une fois pour toutes - // et reperer si les doublons sont demandes - // pour un inclure ou une boucle document - // c'est utile a la fonction champs_traitements - if (!$trouver_table) + if (!$trouver_table) { $trouver_table = charger_fonction('trouver_table', 'base'); + } - foreach($boucles as $id => $boucle) { - if (!($type = $boucle->type_requete)) continue; - if (!$descr['documents'] AND ( - (($type == 'documents') AND $boucle->doublons) OR - compile_inclure_doublons($boucle->avant) OR - compile_inclure_doublons($boucle->apres) OR - compile_inclure_doublons($boucle->milieu) OR - compile_inclure_doublons($boucle->altern))) - $descr['documents'] = true; + // reperer si les doublons sont demandes + // pour un inclure ou une boucle document + // c'est utile a la fonction champs_traitements + foreach ($boucles as $id => $boucle) { + if (!($type = $boucle->type_requete)) { + continue; + } + if (!$descr['documents'] and ( + (($type == 'documents') and $boucle->doublons) or + compile_inclure_doublons($boucle->avant) or + compile_inclure_doublons($boucle->apres) or + compile_inclure_doublons($boucle->milieu) or + compile_inclure_doublons($boucle->altern)) + ) { + $descr['documents'] = true; + } if ($type != TYPE_RECURSIF) { - if (!$boucles[$id]->sql_serveur AND $connect) + if (!$boucles[$id]->sql_serveur and $connect) { $boucles[$id]->sql_serveur = $connect; + } // chercher dans les iterateurs du repertoire iterateur/ if ($g = charger_fonction( - preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true)) { + preg_replace('/\W/', '_', $boucle->type_requete), 'iterateur', true) + ) { $boucles[$id] = $g($boucle); - // sinon, en cas de requeteur d'un type predefini, - // utiliser les informations donnees par le requeteur - // cas "php:xx" et "data:xx". - } else if ($boucle->sql_serveur AND $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) { - $requeteur($boucles, $boucle, $id); - - // utiliser la description des champs transmis + // sinon, en cas de requeteur d'un type predefini, + // utiliser les informations donnees par le requeteur + // cas "php:xx" et "data:xx". } else { - $show = $trouver_table($type, $boucles[$id]->sql_serveur); - // si la table n'existe pas avec le connecteur par defaut, - // c'est peut etre une table qui necessite son connecteur dedie fourni - // permet une ecriture allegee (GEO) -> (geo:GEO) - if (!$show - AND $show=$trouver_table($type, strtolower($type))) { - $boucles[$id]->sql_serveur = strtolower($type); - } - if ($show) { - $boucles[$id]->show = $show; - // recopie les infos les plus importantes - $boucles[$id]->primary = $show['key']["PRIMARY KEY"]; - $boucles[$id]->id_table = $x = preg_replace(",^spip_,","",$show['id_table']); - $boucles[$id]->from[$x] = $nom_table = $show['table']; - $boucles[$id]->iterateur = 'SQL'; - - $boucles[$id]->descr = &$descr; - if ((!$boucles[$id]->jointures) - AND is_array($show['tables_jointures']) - AND count($x = $show['tables_jointures'])) - $boucles[$id]->jointures = $x; - if ($boucles[$id]->jointures_explicites){ - $jointures = preg_split("/\s+/",$boucles[$id]->jointures_explicites); - while ($j=array_pop($jointures)) - array_unshift($boucles[$id]->jointures,$j); - } + if ($boucle->sql_serveur and $requeteur = charger_fonction($boucle->sql_serveur, 'requeteur', true)) { + $requeteur($boucles, $boucle, $id); + + // utiliser la description des champs transmis } else { - // Pas une erreur si la table est optionnelle - if ($boucles[$id]->table_optionnelle) - $boucles[$id]->type_requete = ''; - else { - $boucles[$id]->type_requete = false; - $boucle = $boucles[$id]; - $x = (!$boucle->sql_serveur ? '' : - ($boucle->sql_serveur . ":")) . - $type; - $msg = array('zbug_table_inconnue', - array('table' => $x)); - erreur_squelette($msg, $boucle); + $show = $trouver_table($type, $boucles[$id]->sql_serveur); + // si la table n'existe pas avec le connecteur par defaut, + // c'est peut etre une table qui necessite son connecteur dedie fourni + // permet une ecriture allegee (GEO) -> (geo:GEO) + if (!$show + and $show = $trouver_table($type, strtolower($type)) + ) { + $boucles[$id]->sql_serveur = strtolower($type); + } + if ($show) { + $boucles[$id]->show = $show; + // recopie les infos les plus importantes + $boucles[$id]->primary = isset($show['key']["PRIMARY KEY"]) ? $show['key']["PRIMARY KEY"] : ''; + $boucles[$id]->id_table = $x = preg_replace(",^spip_,", "", $show['id_table']); + $boucles[$id]->from[$x] = $nom_table = $show['table']; + $boucles[$id]->iterateur = 'SQL'; + + $boucles[$id]->descr = &$descr; + if ((!$boucles[$id]->jointures) + and is_array($show['tables_jointures']) + and count($x = $show['tables_jointures']) + ) { + $boucles[$id]->jointures = $x; + } + if ($boucles[$id]->jointures_explicites) { + $jointures = preg_split("/\s+/", $boucles[$id]->jointures_explicites); + while ($j = array_pop($jointures)) { + array_unshift($boucles[$id]->jointures, $j); + } + } + } else { + // Pas une erreur si la table est optionnelle + if ($boucles[$id]->table_optionnelle) { + $boucles[$id]->type_requete = ''; + } else { + $boucles[$id]->type_requete = false; + $boucle = $boucles[$id]; + $x = (!$boucle->sql_serveur ? '' : + ($boucle->sql_serveur . ":")) . + $type; + $msg = array( + 'zbug_table_inconnue', + array('table' => $x) + ); + erreur_squelette($msg, $boucle); + } } } } @@ -1169,30 +1361,32 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co // Commencer par reperer les boucles appelees explicitement // car elles indexent les arguments de maniere derogatoire - foreach($boucles as $id => $boucle) { - if ($boucle->type_requete == TYPE_RECURSIF AND $boucle->param) { + foreach ($boucles as $id => $boucle) { + if ($boucle->type_requete == TYPE_RECURSIF and $boucle->param) { $boucles[$id]->descr = &$descr; $rec = &$boucles[$boucle->param[0]]; if (!$rec) { - $msg = array('zbug_boucle_recursive_undef', - array('nom' => $boucle->param[0])); + $msg = array( + 'zbug_boucle_recursive_undef', + array('nom' => $boucle->param[0]) + ); erreur_squelette($msg, $boucle); $boucles[$id]->type_requete = false; } else { $rec->externe = $id; $descr['id_mere'] = $id; $boucles[$id]->return = - calculer_liste(array($rec), - $descr, - $boucles, - $boucle->param); + calculer_liste(array($rec), + $descr, + $boucles, + $boucle->param); } } } - foreach($boucles as $id => $boucle) { + foreach ($boucles as $id => $boucle) { $id = strval($id); // attention au type dans index_pile $type = $boucle->type_requete; - if ($type AND $type != TYPE_RECURSIF) { + if ($type and $type != TYPE_RECURSIF) { $res = ''; if ($boucle->param) { // retourne un tableau en cas d'erreur @@ -1200,10 +1394,10 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co } $descr['id_mere'] = $id; $boucles[$id]->return = - calculer_liste($boucle->milieu, - $descr, - $boucles, - $id); + calculer_liste($boucle->milieu, + $descr, + $boucles, + $id); // Si les criteres se sont mal compiles // ne pas tenter d'assembler le code final // (mais compiler le corps pour detection d'erreurs) @@ -1218,14 +1412,16 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co $corps = calculer_liste($squelette, $descr, $boucles); - // Calcul du corps de toutes les fonctions PHP, // en particulier les requetes SQL et TOTAL_BOUCLE // de'terminables seulement maintenant - foreach($boucles as $id => $boucle) { + foreach ($boucles as $id => $boucle) { $boucle = $boucles[$id] = pipeline('pre_boucle', $boucle); - if ($boucle->return === false) {$corps = false; continue;} + if ($boucle->return === false) { + $corps = false; + continue; + } // appeler la fonction de definition de la boucle if ($req = $boucle->type_requete) { @@ -1234,15 +1430,15 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co $serveur = strtolower($boucle->sql_serveur); if ( // fonction de boucle avec serveur & table - (!$serveur OR - ((!function_exists($f = "boucle_".$serveur."_".$table)) - AND (!function_exists($f = $f."_dist")) - ) + (!$serveur or + ((!function_exists($f = "boucle_" . $serveur . "_" . $table)) + and (!function_exists($f = $f . "_dist")) + ) ) // fonction de boucle avec table - AND (!function_exists($f = "boucle_".$table)) - AND (!function_exists($f = $f."_dist")) - ){ + and (!function_exists($f = "boucle_" . $table)) + and (!function_exists($f = $f . "_dist")) + ) { // fonction de boucle standard if (!function_exists($f = 'boucle_DEFAUT')) { $f = 'boucle_DEFAUT_dist'; @@ -1250,15 +1446,17 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co } $req = "\n\n\tstatic \$command = array();\n\t" . - "static \$connect;\n\t" . - "\$command['connect'] = \$connect = " . + "static \$connect;\n\t" . + "\$command['connect'] = \$connect = " . _q($boucle->sql_serveur) . ";" . $f($id, $boucles); - } else $req = ("\n\treturn '';"); + } else { + $req = ("\n\treturn '';"); + } - $boucles[$id]->return = - "\n\nfunction BOUCLE" . strtr($id,"-","_") . $nom . + $boucles[$id]->return = + "\n\nfunction BOUCLE" . strtr($id, "-", "_") . $nom . '(&$Cache, &$Pile, &$doublons, &$Numrows, $SP) {' . $req . "\n}\n"; @@ -1266,25 +1464,27 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co // Au final, si le corps ou un critere au moins s'est mal compile // retourner False, sinon inserer leur decompilation - if (is_bool($corps)) return false; + if (is_bool($corps)) { + return false; + } - $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons=array(), $Numrows=array(), $SP=0) { + $principal = "\nfunction " . $nom . '($Cache, $Pile, $doublons = array(), $Numrows = array(), $SP = 0) { ' - // reporter de maniere securisee les doublons inclus -.' + // reporter de maniere securisee les doublons inclus + . ' if (isset($Pile[0]["doublons"]) AND is_array($Pile[0]["doublons"])) $doublons = nettoyer_env_doublons($Pile[0]["doublons"]); $connect = ' . - _q($connect) . '; + _q($connect) . '; $page = ' . - // ATTENTION, le calcul de l'expression $corps affectera $Cache - // c'est pourquoi on l'affecte a la variable auxiliaire $page. - // avant de referencer $Cache - $corps . "; + // ATTENTION, le calcul de l'expression $corps affectera $Cache + // c'est pourquoi on l'affecte a la variable auxiliaire $page. + // avant de referencer $Cache + $corps . "; - return analyse_resultat_skel(".var_export($nom,true) - .", \$Cache, \$page, ".var_export($sourcefile,true)."); + return analyse_resultat_skel(" . var_export($nom, true) + . ", \$Cache, \$page, " . var_export($sourcefile, true) . "); }"; $secondes = spip_timer('calcul_skel'); @@ -1297,21 +1497,22 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co $code->descr = $descr; $code->return = ' // -// Fonction principale du squelette ' . - $sourcefile . - ($connect ? " pour $connect" : '') . - (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") . - "\n//\n" . - $principal; +// Fonction principale du squelette ' . + $sourcefile . + ($connect ? " pour $connect" : '') . + (!CODE_COMMENTE ? '' : "\n// Temps de compilation total: $secondes") . + "\n//\n" . + $principal; $boucles[''] = $code; + return $boucles; } /** * Requeteur pour les boucles (php:nom_iterateur) - * + * * Analyse si le nom d'iterateur correspond bien a une classe PHP existante * et dans ce cas charge la boucle avec cet iterateur. * Affichera une erreur dans le cas contraire. @@ -1319,8 +1520,8 @@ function compiler_squelette($squelette, $boucles, $nom, $descr, $sourcefile, $co * @param $boucles Liste des boucles * @param $boucle La boucle parcourue * @param $id L'identifiant de la boucle parcourue - * -**/ + * + **/ function requeteur_php_dist(&$boucles, &$boucle, &$id) { if (class_exists($boucle->type_requete)) { $g = charger_fonction('php', 'iterateur'); @@ -1328,8 +1529,10 @@ function requeteur_php_dist(&$boucles, &$boucle, &$id) { } else { $x = $boucle->type_requete; $boucle->type_requete = false; - $msg = array('zbug_iterateur_inconnu', - array('iterateur' => $x)); + $msg = array( + 'zbug_iterateur_inconnu', + array('iterateur' => $x) + ); erreur_squelette($msg, $boucle); } } @@ -1338,7 +1541,7 @@ function requeteur_php_dist(&$boucles, &$boucle, &$id) { /** * Requeteur pour les boucles (data:type de donnee) * note: (DATA) tout court ne passe pas par ici. - * + * * Analyse si le type de donnee peut etre traite * et dans ce cas charge la boucle avec cet iterateur. * Affichera une erreur dans le cas contraire. @@ -1346,26 +1549,26 @@ function requeteur_php_dist(&$boucles, &$boucle, &$id) { * @param $boucles Liste des boucles * @param $boucle La boucle parcourue * @param $id L'identifiant de la boucle parcourue - * -**/ + * + **/ function requeteur_data_dist(&$boucles, &$boucle, &$id) { include_spip('iterateur/data'); - if ($h = charger_fonction($boucle->type_requete . '_to_array' , 'inc', true)) { + if ($h = charger_fonction($boucle->type_requete . '_to_array', 'inc', true)) { $g = charger_fonction('data', 'iterateur'); $boucles[$id] = $g($boucle); // from[0] stocke le type de data (rss, yql, ...) $boucles[$id]->from[] = $boucle->type_requete; - + } else { $x = $boucle->type_requete; $boucle->type_requete = false; - $msg = array('zbug_requeteur_inconnu', - array( + $msg = array( + 'zbug_requeteur_inconnu', + array( 'requeteur' => 'data', 'type' => $x - )); + ) + ); erreur_squelette($msg, $boucle); } } - -?>