param) && (!$p->param[0][0]) && (count($p->param[0]) > $n)) { return calculer_liste($p->param[0][$n], $p->descr, $p->boucles, $p->id_boucle); } else { return null; } } // // Définition des balises // /** * Compile la balise `#NOM_SITE_SPIP` retournant le nom du site * * @balise * @link http://www.spip.net/4622 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_NOM_SITE_SPIP_dist($p) { $p->code = "\$GLOBALS['meta']['nom_site']"; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#EMAIL_WEBMASTER` retournant l'adresse courriel * du webmestre * * @balise * @link http://www.spip.net/4586 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_EMAIL_WEBMASTER_dist($p) { $p->code = "\$GLOBALS['meta']['email_webmaster']"; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#DESCRIPTIF_SITE_SPIP` qui retourne le descriptif * du site ! * * @balise * @link http://www.spip.net/4338 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_DESCRIPTIF_SITE_SPIP_dist($p) { $p->code = "\$GLOBALS['meta']['descriptif_site']"; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#CHARSET` qui retourne le nom du jeu de caractères * utilisé par le site tel que `utf-8` * * @balise * @link http://www.spip.net/4331 * @example * ``` * * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CHARSET_dist($p) { $p->code = "\$GLOBALS['meta']['charset']"; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#LANG_LEFT` retournant 'left' si la langue s'écrit * de gauche à droite, sinon 'right' * * @note * Peut servir à l'écriture de code CSS dans un squelette, mais * pour inclure un fichier css, il vaut mieux utiliser le filtre * `direction_css` si on le souhaite sensible à la langue utilisé. * * @balise * @link http://www.spip.net/4625 * @see lang_dir() * @see balise_LANG_RIGHT_dist() * @see balise_LANG_DIR_dist() * @see direction_css() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_LANG_LEFT_dist($p) { $_lang = champ_sql('lang', $p); $p->code = "lang_dir($_lang, 'left','right')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#LANG_RIGHT` retournant 'right' si la langue s'écrit * de gauche à droite, sinon 'left' * * @balise * @link http://www.spip.net/4625 * @see lang_dir() * @see balise_LANG_LEFT_dist() * @see balise_LANG_DIR_dist() * @see direction_css() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_LANG_RIGHT_dist($p) { $_lang = champ_sql('lang', $p); $p->code = "lang_dir($_lang, 'right','left')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#LANG_DIR` retournant 'ltr' si la langue s'écrit * de gauche à droite, sinon 'rtl' * * @balise * @link http://www.spip.net/4625 * @see lang_dir() * @see balise_LANG_LEFT_dist() * @see balise_LANG_RIGHT_dist() * @example * ``` * * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_LANG_DIR_dist($p) { $_lang = champ_sql('lang', $p); $p->code = "lang_dir($_lang, 'ltr','rtl')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#PUCE` affichant une puce * * @balise * @link http://www.spip.net/4628 * @see definir_puce() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_PUCE_dist($p) { $p->code = "definir_puce()"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#DATE` qui retourne la date de mise en ligne * * Cette balise retourne soit le champ `date` d'une table si elle est * utilisée dans une boucle, sinon la date de calcul du squelette. * * @balise * @link http://www.spip.net/4336 Balise DATE * @link http://www.spip.net/1971 La gestion des dates * @example * ``` * [(#DATE|affdate_jourcourt)] * ``` * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_DATE_dist($p) { $d = champ_sql('date', $p); # if ($d === "@\$Pile[0]['date']") # $d = "isset(\$Pile[0]['date']) ? $d : time()"; $p->code = $d; return $p; } /** * Compile la balise `#DATE_REDAC` qui retourne la date de première publication * * Cette balise retourne le champ `date_redac` d'une table * * @balise * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC * @link http://www.spip.net/1971 La gestion des dates * @see balise_DATE_MODIF_dist() * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_DATE_REDAC_dist($p) { $d = champ_sql('date_redac', $p); # if ($d === "@\$Pile[0]['date_redac']") # $d = "isset(\$Pile[0]['date_redac']) ? $d : time()"; $p->code = $d; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#DATE_MODIF` qui retourne la date de dernière modification * * Cette balise retourne le champ `date_modif` d'une table * * @balise * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC * @link http://www.spip.net/1971 La gestion des dates * @see balise_DATE_REDAC_dist() * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_DATE_MODIF_dist($p) { $p->code = champ_sql('date_modif', $p); $p->interdire_scripts = false; return $p; } /** * Compile la balise `#DATE_NOUVEAUTES` indiquant la date de dernier envoi * du mail de nouveautés * * @balise * @link http://www.spip.net/4337 Balise DATE_NOUVEAUTES * @link http://www.spip.net/1971 La gestion des dates * @see balise_DATE_REDAC_dist() * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_DATE_NOUVEAUTES_dist($p) { $p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui' AND isset(\$GLOBALS['meta']['dernier_envoi_neuf'])) ? \$GLOBALS['meta']['dernier_envoi_neuf'] : \"'0000-00-00'\")"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#DOSSIER_SQUELETTE` retournant le chemin vers le * répertoire de squelettes actuellement utilisé * * @balise * @deprecated Utiliser `#CHEMIN` * @link http://www.spip.net/4627 * @see balise_CHEMIN_dist() * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_DOSSIER_SQUELETTE_dist($p) { $code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE)); $p->code = "_DIR_RACINE . '$code'" . $p->interdire_scripts = false; return $p; } /** * Compile la balise `#SQUELETTE` retournant le chemin du squelette courant * * @balise * @link http://www.spip.net/4027 * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_SQUELETTE_dist($p) { $code = addslashes($p->descr['sourcefile']); $p->code = "'$code'" . $p->interdire_scripts = false; return $p; } /** * Compile la balise `#SPIP_VERSION` qui affiche la version de SPIP * * @balise * @see spip_version() * @example * ``` * [] * ``` * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_SPIP_VERSION_dist($p) { $p->code = "spip_version()"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#NOM_SITE` qui affiche le nom du site. * * Affiche le nom du site ou sinon l'URL ou le titre de l'objet * Utiliser `#NOM_SITE*` pour avoir le nom du site ou rien. * * Cette balise interroge les colonnes `nom_site` ou `url_site` * dans la boucle la plus proche. * * @balise * @see calculer_url() * @example * ``` * #NOM_SITE * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_NOM_SITE_dist($p) { if (!$p->etoile) { $p->code = "supprimer_numero(calculer_url(" . champ_sql('url_site', $p) . "," . champ_sql('nom_site', $p) . ", 'titre', \$connect, false))"; } else { $p->code = champ_sql('nom_site', $p); } $p->interdire_scripts = true; return $p; } /** * Compile la balise `#NOTE` qui affiche les notes de bas de page * * @balise * @link http://www.spip.net/3964 * @see calculer_notes() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_NOTES_dist($p) { // Recuperer les notes $p->code = 'calculer_notes()'; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#RECHERCHE` qui retourne le terme de recherche demandé * * Retourne un terme demandé en recherche, en le prenant dans _request() * sous la clé `recherche`. * * @balise * @example * ``` *

Recherche de : #RECHERCHE

* ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_RECHERCHE_dist($p) { $p->code = 'entites_html(_request("recherche"))'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#COMPTEUR_BOUCLE` qui retourne le numéro de l’itération * actuelle de la boucle * * @balise * @link http://www.spip.net/4333 * @see balise_TOTAL_BOUCLE_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_COMPTEUR_BOUCLE_dist($p) { $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere']; if ($b === '') { $msg = array( 'zbug_champ_hors_boucle', array('champ' => '#COMPTEUR_BOUCLE') ); erreur_squelette($msg, $p); } else { $p->code = "\$Numrows['$b']['compteur_boucle']"; $p->boucles[$b]->cptrows = true; $p->interdire_scripts = false; return $p; } } /** * Compile la balise `#TOTAL_BOUCLE` qui retourne le nombre de résultats * affichés par la boucle * * @balise * @link http://www.spip.net/4334 * @see balise_COMPTEUR_BOUCLE_dist() * @see balise_GRAND_TOTAL_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_TOTAL_BOUCLE_dist($p) { $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere']; if ($b === '' || !isset($p->boucles[$b])) { $msg = array( 'zbug_champ_hors_boucle', array('champ' => "#$b" . 'TOTAL_BOUCLE') ); erreur_squelette($msg, $p); } else { $p->code = "\$Numrows['$b']['total']"; $p->boucles[$b]->numrows = true; $p->interdire_scripts = false; } return $p; } /** * Compile la balise `#POINTS` qui affiche la pertinence des résultats * * Retourne le calcul `points` réalisé par le critère `recherche`. * Cette balise nécessite donc la présence de ce critère. * * @balise * @link http://www.spip.net/903 Boucles et balises de recherche * @see critere_recherche_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_POINTS_dist($p) { return rindex_pile($p, 'points', 'recherche'); } /** * Compile la balise `#POPULARITE_ABSOLUE` qui affiche la popularité absolue * * Cela correspond à la popularité quotidienne de l'article * * @balise * @link http://www.spip.net/1846 La popularité * @see balise_POPULARITE_dist() * @see balise_POPULARITE_MAX_dist() * @see balise_POPULARITE_SITE_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_POPULARITE_ABSOLUE_dist($p) { $p->code = 'ceil(' . champ_sql('popularite', $p) . ')'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#POPULARITE_SITE` qui affiche la popularité du site * * La popularité du site est la somme de toutes les popularités absolues. * * @balise * @link http://www.spip.net/1846 La popularité * @see balise_POPULARITE_ABSOLUE_dist() * @see balise_POPULARITE_dist() * @see balise_POPULARITE_MAX_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_POPULARITE_SITE_dist($p) { $p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#POPULARITE_MAX` qui affiche la popularité maximum * parmis les popularités des articles * * Cela correspond à la popularité quotidienne de l'article * * @balise * @link http://www.spip.net/1846 La popularité * @see balise_POPULARITE_ABSOLUE_dist() * @see balise_POPULARITE_dist() * @see balise_POPULARITE_SITE_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_POPULARITE_MAX_dist($p) { $p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#VALEUR` retournant le champ `valeur` * * Utile dans une boucle DATA pour retourner une valeur. * * @balise * @link http://www.spip.net/5546 #CLE et #VALEUR * @see table_valeur() * @example * ``` * #VALEUR renvoie le champ valeur * #VALEUR{x} renvoie #VALEUR|table_valeur{x}, * équivalent à #X (si X n'est pas une balise spécifique à SPIP) * #VALEUR{a/b} renvoie #VALEUR|table_valeur{a/b} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_VALEUR_dist($p) { $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle; $p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);; if (($v = interprete_argument_balise(1, $p)) !== null) { $p->code = 'table_valeur(' . $p->code . ', ' . $v . ')'; } $p->interdire_scripts = true; return $p; } /** * Compile la balise `#EXPOSE` qui met en évidence l'élément sur lequel * la page se trouve * * Expose dans une boucle l'élément de la page sur laquelle on se trouve, * en retournant `on` si l'élément correspond à la page, une chaîne vide sinon. * * On peut passer les paramètres à faire retourner par la balise. * * @example * ``` * * * * ``` * * @balise * @link http://www.spip.net/2319 Exposer un article * @uses calculer_balise_expose() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_EXPOSE_dist($p) { $on = "'on'"; $off = "''"; if (($v = interprete_argument_balise(1, $p)) !== null) { $on = $v; if (($v = interprete_argument_balise(2, $p)) !== null) { $off = $v; } } return calculer_balise_expose($p, $on, $off); } /** * Calcul de la balise expose * * @see calcul_exposer() * * @param Champ $p * Pile au niveau de la balise * @param string $on * Texte à afficher si l'élément est exposé (code à écrire tel que "'on'") * @param string $off * Texte à afficher si l'élément n'est pas exposé (code à écrire tel que "''") * @return Champ * Pile complétée par le code à générer **/ function calculer_balise_expose($p, $on, $off) { $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle; if (empty($p->boucles[$b]->primary)) { $msg = array('zbug_champ_hors_boucle', array('champ' => '#EXPOSER')); erreur_squelette($msg, $p); } else { $key = $p->boucles[$b]->primary; $type = $p->boucles[$p->id_boucle]->primary; $desc = $p->boucles[$b]->show; $connect = sql_quote($p->boucles[$b]->sql_serveur); // Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite $c = index_pile($p->id_boucle, $type, $p->boucles); if (isset($desc['field']['id_parent'])) { $parent = 0; // pour if (!$parent) dans calculer_expose } elseif (isset($desc['field']['id_rubrique'])) { $parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b); } elseif (isset($desc['field']['id_groupe'])) { $parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b); } else { $parent = "''"; } $p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)"; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#DEBUT_SURLIGNE` qui permettait le surlignage * des mots d'une recherche * * @note * Cette balise n'a plus d'effet depuis r9343 * * @balise * @see balise_FIN_SURLIGNE_dist() * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_DEBUT_SURLIGNE_dist($p) { include_spip('inc/surligne'); $p->code = "''"; return $p; } /** * Compile la balise `#FIN_SURLIGNE` qui arrêtait le surlignage * des mots d'une recherche * * @note * Cette balise n'a plus d'effet depuis r9343 * * @balise * @see balise_DEBUT_SURLIGNE_dist() * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_FIN_SURLIGNE_dist($p) { include_spip('inc/surligne'); $p->code = "''"; return $p; } /** * Compile la balise `#INTRODUCTION` * * Retourne une introduction d'un objet éditorial, c'est à dire les 600 * premiers caractères environ du champ 'texte' de l'objet ou le contenu * indiqué entre `` et `` de ce même champ. * * Pour les articles, l'introduction utilisée est celle du champ `descriptif` * s'il est renseigné, sinon il est pris dans les champs `chapo` et `texte` et * est par défaut limité à 500 caractères. * * Pour les rubriques, l'introduction utilisée est celle du champ `descriptif` * s'il est renseigné, sinon du champ texte. * * La balise accèpte 1 paramètre indiquant la longueur en nombre de caractères * de l'introduction. * * @see filtre_introduction_dist() * @example * ``` * #INTRODUCTION * #INTRODUCTION{300} * ``` * * @balise * @link http://www.spip.net/@introduction * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_INTRODUCTION_dist($p) { $type = $p->type_requete; $_texte = champ_sql('texte', $p); $_descriptif = ($type == 'articles' or $type == 'rubriques') ? champ_sql('descriptif', $p) : "''"; if ($type == 'articles') { $_chapo = champ_sql('chapo', $p); $_texte = "(strlen($_descriptif)) ? '' : $_chapo . \"\\n\\n\" . $_texte"; } // longueur en parametre, ou valeur par defaut $longueur_defaut = objet_info($type, 'introduction_longueur'); if (!$longueur_defaut) { $longueur_defaut = 600; } $_suite = 'null'; $_longueur = $longueur_defaut; if (($v = interprete_argument_balise(1, $p)) !== null) { $_longueur = 'is_numeric(' . $v . ')?intval(' . $v . '):' . $longueur_defaut; $_suite = '!is_numeric(' . $v . ')?' . $v . ':null'; } if (($v2 = interprete_argument_balise(2, $p)) !== null) { $_suite = $v2; } $f = chercher_filtre('introduction'); $p->code = "$f($_descriptif, $_texte, $_longueur, \$connect, $_suite)"; #$p->interdire_scripts = true; $p->etoile = '*'; // propre est deja fait dans le calcul de l'intro return $p; } /** * Compile la balise `#LANG` qui affiche la langue de l'objet (ou d'une boucle supérieure), * et à defaut la langue courante * * La langue courante est celle du site ou celle qui a été passée dans l'URL par le visiteur. * L'étoile `#LANG*` n'affiche rien si aucune langue n'est trouvée dans le SQL ou le contexte. * * @balise * @link http://www.spip.net/3864 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_LANG_dist($p) { $_lang = champ_sql('lang', $p); if (!$p->etoile) { $p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])"; } else { $p->code = "spip_htmlentities($_lang)"; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#LESAUTEURS` chargée d'afficher la liste des auteurs d'un objet * * - Soit le champ `lesauteurs` existe dans la table et à ce moment là, * la balise retourne son contenu, * - soit la balise appelle le modele `lesauteurs.html` en lui passant * le couple `objet` et `id_objet` dans son environnement. * * @balise * @link http://www.spip.net/3966 Description de la balise * @link http://www.spip.net/902 Description de la boucle ARTICLES * @link http://www.spip.net/911 Description de la boucle SYNDIC_ARTICLES * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_LESAUTEURS_dist($p) { // Cherche le champ 'lesauteurs' dans la pile $_lesauteurs = champ_sql('lesauteurs', $p, false); // Si le champ n'existe pas (cas de spip_articles), on applique // le modele lesauteurs.html en passant id_article dans le contexte; // dans le cas contraire on prend le champ 'lesauteurs' // (cf extension sites/) if ($_lesauteurs and $_lesauteurs != '@$Pile[0][\'lesauteurs\']' ) { $p->code = "safehtml($_lesauteurs)"; // $p->interdire_scripts = true; } else { if (!$p->id_boucle) { $connect = ''; $objet = 'article'; $id_table_objet = 'id_article'; } else { $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle; $connect = $p->boucles[$b]->sql_serveur; $type_boucle = $p->boucles[$b]->type_requete; $objet = objet_type($type_boucle); $id_table_objet = id_table_objet($type_boucle); } $c = memoriser_contexte_compil($p); $p->code = sprintf(CODE_RECUPERER_FOND, "'modeles/lesauteurs'", "array('objet'=>'" . $objet . "','id_objet' => " . champ_sql($id_table_objet, $p) . ",'$id_table_objet' => " . champ_sql($id_table_objet, $p) . ($objet == 'article' ? "" : ",'id_article' => " . champ_sql('id_article', $p)) . ")", "'trim'=>true, 'compil'=>array($c)", _q($connect)); $p->interdire_scripts = false; // securite apposee par recuperer_fond() } return $p; } /** * Compile la balise `#RANG` chargée d'afficher le numéro de l'objet * * Affiche le « numero de l'objet ». Soit `1` quand on a un titre `1. Premier article`. * * Ceci est transitoire afin de préparer une migration vers un vrai système de * tri des articles dans une rubrique (et plus si affinités). * La balise permet d'extraire le numero masqué par le filtre `supprimer_numero`. * * La balise recupère le champ declaré dans la définition `table_titre` * de l'objet, ou à defaut du champ `titre` * * Si un champ `rang` existe, il est pris en priorité. * * @balise * @link http://www.spip.net/5495 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_RANG_dist($p) { $b = index_boucle($p); if ($b === '') { $msg = array( 'zbug_champ_hors_boucle', array('champ' => '#RANG') ); erreur_squelette($msg, $p); } else { // chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql) // dans la boucle immediatement englobante uniquement // sinon on compose le champ calcule $_rang = champ_sql('rang', $p, '', false); // si pas trouve de champ sql rang : if (!$_rang or $_rang == "''") { $boucle = &$p->boucles[$b]; $trouver_table = charger_fonction('trouver_table', 'base'); $desc = $trouver_table($boucle->id_table); $_titre = ''; # où extraire le numero ? if (isset($desc['titre'])) { $t = $desc['titre']; if ( // Soit on trouve avec la déclaration de la lang AVANT preg_match(';(?:lang\s*,)\s*(.*?titre)\s*(,|$);', $t, $m) // Soit on prend depuis le début or preg_match(';^(.*?titre)\s*(,|$);', $t, $m) ) { $m = preg_replace(',as\s+titre$,i', '', $m[1]); $m = trim($m); if ($m != "''") { if (!preg_match(",\W,", $m)) { $m = $boucle->id_table . ".$m"; } $m .= " AS titre_rang"; $boucle->select[] = $m; $_titre = '$Pile[$SP][\'titre_rang\']'; } } } // si on n'a rien trouvé, on utilise le champ titre classique if (!$_titre) { $_titre = champ_sql('titre', $p); } $_rang = "recuperer_numero($_titre)"; } $p->code = $_rang; $p->interdire_scripts = false; } return $p; } /** * Compile la balise `#POPULARITE` qui affiche la popularité relative. * * C'est à dire le pourcentage de la fréquentation de l'article * (la popularité absolue) par rapport à la popularité maximum. * * @balise * @link http://www.spip.net/1846 La popularité * @see balise_POPULARITE_ABSOLUE_dist() * @see balise_POPULARITE_MAX_dist() * @see balise_POPULARITE_SITE_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_POPULARITE_dist($p) { $_popularite = champ_sql('popularite', $p); $p->code = "(ceil(min(100, 100 * $_popularite / max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))"; $p->interdire_scripts = false; return $p; } /** * Code de compilation pour la balise `#PAGINATION` * * Le code produit est trompeur, car les modèles ne fournissent pas Pile[0]. * On produit un appel à `_request` si on ne l'a pas, mais c'est inexact: * l'absence peut-être due à une faute de frappe dans le contexte inclus. */ define('CODE_PAGINATION', '%s($Numrows["%s"]["grand_total"], %s, isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)), %5$s, %6$s, %7$s, %8$s, array(%9$s))'); /** * Compile la balise `#PAGINATION` chargée d'afficher une pagination * * Elle charge le modèle `pagination.html` (par défaut), mais un paramètre * permet d'indiquer d'autres modèles. `#PAGINATION{nom}` utilisera le * modèle `pagination_nom.html`. * * Cette balise nécessite le critère `pagination` sur la boucle où elle * est utilisée. * * @balise * @link http://www.spip.net/3367 Le système de pagination * @see filtre_pagination_dist() * @see critere_pagination_dist() * @see balise_ANCRE_PAGINATION_dist() * @example * ``` * [

(#PAGINATION{prive})

] * ``` * * @param Champ $p * Pile au niveau de la balise * @param string $liste * Afficher ou non les liens de pagination (variable de type `string` * car code à faire écrire au compilateur) : * - `true` pour les afficher * - `false` pour afficher uniquement l'ancre. * @return Champ * Pile complétée par le code à générer */ function balise_PAGINATION_dist($p, $liste = 'true') { $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere']; // s'il n'y a pas de nom de boucle, on ne peut pas paginer if ($b === '') { $msg = array( 'zbug_champ_hors_boucle', array('champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION') ); erreur_squelette($msg, $p); return $p; } // s'il n'y a pas de mode_partie, c'est qu'on se trouve // dans un boucle recursive ou qu'on a oublie le critere {pagination} if (!$p->boucles[$b]->mode_partie) { if (!$p->boucles[$b]->table_optionnelle) { $msg = array( 'zbug_pagination_sans_critere', array('champ' => '#PAGINATION') ); erreur_squelette($msg, $p); } return $p; } // a priori true // si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise // si true, les arguments simples (sans truc=chose) vont degager $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false); if (count($_contexte)) { $key = key($_contexte); if (is_numeric($key)) { array_shift($_contexte); $__modele = interprete_argument_balise(1, $p); } } if (count($_contexte)) { $code_contexte = implode(',', $_contexte); } else { $code_contexte = ''; } $connect = $p->boucles[$b]->sql_serveur; $pas = $p->boucles[$b]->total_parties; $f_pagination = chercher_filtre('pagination'); $type = $p->boucles[$b]->modificateur['debut_nom']; $modif = ($type[0] !== "'") ? "'debut'.$type" : ("'debut" . substr($type, 1)); $p->code = sprintf(CODE_PAGINATION, $f_pagination, $b, $type, $modif, $pas, $liste, ((isset($__modele) and $__modele) ? $__modele : "''"), _q($connect), $code_contexte); $p->boucles[$b]->numrows = true; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#ANCRE_PAGINATION` chargée d'afficher l'ancre * de la pagination * * Cette ancre peut ainsi être placée au-dessus la liste des éléments * de la boucle alors qu'on mettra les liens de pagination en-dessous de * cette liste paginée. * * Cette balise nécessite le critère `pagination` sur la boucle où elle * est utilisée. * * @balise * @link http://www.spip.net/3367 Le système de pagination * @link http://www.spip.net/4328 Balise ANCRE_PAGINATION * @see critere_pagination_dist() * @see balise_PAGINATION_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_ANCRE_PAGINATION_dist($p) { if ($f = charger_fonction('PAGINATION', 'balise', true)) { return $f($p, $liste = 'false'); } else { return null; } // ou une erreur ? } /** * Compile la balise `#GRAND_TOTAL` qui retourne le nombre total de résultats * d'une boucle * * Cette balise set équivalente à `#TOTAL_BOUCLE` sauf pour les boucles paginées. * Dans ce cas elle indique le nombre total d'éléments répondant aux critères * hors pagination. * * @balise * @see balise_GRAND_TOTAL_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_GRAND_TOTAL_dist($p) { $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere']; if ($b === '' || !isset($p->boucles[$b])) { $msg = array( 'zbug_champ_hors_boucle', array('champ' => "#$b" . 'TOTAL_BOUCLE') ); erreur_squelette($msg, $p); } else { $p->code = "(isset(\$Numrows['$b']['grand_total']) ? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])"; $p->boucles[$b]->numrows = true; $p->interdire_scripts = false; } return $p; } /** * Compile la balise `#SELF` qui retourne l’URL de la page appelée. * * Cette URL est nettoyée des variables propres à l’exécution de SPIP * tel que `var_mode`. * * @note * Attention dans un `INCLURE()` ou une balise dynamique, on n'a pas le droit de * mettre en cache `#SELF` car il peut correspondre à une autre page (attaque XSS) * (Dans ce cas faire pour différencier les caches.) * * @balise * @link http://www.spip.net/4574 * @example * ``` *
... * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_SELF_dist($p) { $p->code = 'self()'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#CHEMIN` qui cherche un fichier dans les chemins * connus de SPIP et retourne son chemin complet depuis la racine * * Signature : `#CHEMIN{chemin/vers/fichier.ext}` * * Retourne une chaîne vide si le fichier n'est pas trouvé. * * @balise * @link http://www.spip.net/4332 * @see find_in_path() Recherche de chemin * @example * ``` * [] * [] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CHEMIN_dist($p) { $arg = interprete_argument_balise(1, $p); if (!$arg) { $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN')); erreur_squelette($msg, $p); } else { $p->code = 'find_in_path(' . $arg . ')'; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#CHEMIN_IMAGE` qui cherche une image dans le thème * de l'espace privé utilisé par SPIP et retourne son chemin complet depuis * la racine * * Signature : `#CHEMIN_IMAGE{image.png}` * * Retourne une chaîne vide si le fichier n'est pas trouvé. * * @balise * @see chemin_image() * @example * ``` * #CHEMIN_IMAGE{article-24.png} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CHEMIN_IMAGE_dist($p) { $arg = interprete_argument_balise(1, $p); if (!$arg) { $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN_IMAGE')); erreur_squelette($msg, $p); } else { $p->code = 'chemin_image(' . $arg . ')'; } #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#ENV` qui permet de récupérer le contexte d'environnement * transmis à un squelette. * * La syntaxe `#ENV{toto, valeur par defaut}` * renverra `valeur par defaut` si `$toto` est vide. * * La recherche de la clé s'appuyant sur la fonction `table_valeur` * il est possible de demander un sous élément d'un tableau : * `#ENV{toto/sous/element, valeur par defaut}` retournera l'équivalent de * `#ENV{toto}|table_valeur{sous/element}` c'est-à-dire en quelque sorte * `$env['toto']['sous']['element']` s'il existe, sinon la valeur par défaut. * * Si le tableau est vide on renvoie `''` (utile pour `#SESSION`) * * Enfin, la balise utilisée seule `#ENV` retourne le tableau complet * de l'environnement. À noter que ce tableau est retourné sérialisé. * * En standard est appliqué le filtre `entites_html`, mais si l'étoile est * utilisée pour désactiver les filtres par défaut, par exemple avec * `[(#ENV*{toto})]` , il *faut* s'assurer de la sécurité * anti-javascript, par exemple en filtrant avec `safehtml` : `[(#ENV*{toto}|safehtml)]` * * * @param Champ $p * Pile ; arbre de syntaxe abstrait positionné au niveau de la balise. * @param array $src * Tableau dans lequel chercher la clé demandée en paramètre de la balise. * Par defaut prend dans le contexte du squelette. * @return Champ * Pile completée du code PHP d'exécution de la balise **/ function balise_ENV_dist($p, $src = null) { // cle du tableau desiree $_nom = interprete_argument_balise(1, $p); // valeur par defaut $_sinon = interprete_argument_balise(2, $p); // $src est un tableau de donnees sources eventuellement transmis // en absence, on utilise l'environnement du squelette $Pile[0] if (!$_nom) { // cas de #ENV sans argument : on retourne le serialize() du tableau // une belle fonction [(#ENV|affiche_env)] serait pratique if ($src) { $p->code = '(is_array($a = (' . $src . ')) ? serialize($a) : "")'; } else { $p->code = '@serialize($Pile[0])'; } } else { if (!$src) { $src = '@$Pile[0]'; } if ($_sinon) { $p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)"; } else { $p->code = "table_valeur($src, (string)$_nom, null)"; } } #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#CONFIG` qui retourne une valeur de configuration * * Cette balise appelle la fonction `lire_config()` pour obtenir les * configurations du site. * * Par exemple `#CONFIG{gerer_trad}` donne 'oui ou 'non' selon le réglage. * * Le 3ème argument permet de contrôler la sérialisation du résultat * (mais ne sert que pour le dépot `meta`) qui doit parfois désérialiser, * par exemple avec `|in_array{#CONFIG{toto,#ARRAY,1}}`. Ceci n'affecte * pas d'autres dépots et `|in_array{#CONFIG{toto/,#ARRAY}}` sera * équivalent. * * Òn peut appeler d'autres tables que `spip_meta` avec un * `#CONFIG{/infos/champ,defaut}` qui lit la valeur de `champ` * dans une table des meta qui serait `spip_infos` * * @balise * @link http://www.spip.net/4335 * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_CONFIG_dist($p) { if (!$arg = interprete_argument_balise(1, $p)) { $arg = "''"; } $_sinon = interprete_argument_balise(2, $p); $_unserialize = sinon(interprete_argument_balise(3, $p), "false"); $p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' . ($_sinon && $_sinon != "''" ? $_sinon : 'null') . ',' . $_unserialize . "):'')"; return $p; } /** * Compile la balise `#CONNECT` qui retourne le nom du connecteur * de base de données * * Retourne le nom du connecteur de base de données utilisé (le nom * du fichier `config/xx.php` sans l'extension, utilisé pour calculer * les données du squelette). * * Retourne `NULL` si le connecteur utilisé est celui par défaut de SPIP * (connect.php), sinon retourne son nom. * * @balise * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise */ function balise_CONNECT_dist($p) { $p->code = '($connect ? $connect : NULL)'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#SESSION` qui permet d’accéder aux informations * liées au visiteur authentifié et de différencier automatiquement * le cache en fonction du visiteur. * * Cette balise est un tableau des données du visiteur (nom, email etc). * Si elle est invoquée, elle lève un drapeau dans le fichier cache, qui * permet à public/cacher de créer un cache différent par visiteur * * @balise * @link http://www.spip.net/3979 * @see balise_AUTORISER_dist() * @see balise_SESSION_SET_dist() * @example * ``` * #SESSION{nom} * ``` * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise **/ function balise_SESSION_dist($p) { $p->descr['session'] = true; $f = function_exists('balise_ENV') ? 'balise_ENV' : 'balise_ENV_dist'; $p = $f($p, '$GLOBALS["visiteur_session"]'); return $p; } /** * Compile la balise `#SESSION_SET` qui d’insérer dans la session * des données supplémentaires * * @balise * @link http://www.spip.net/3984 * @see balise_AUTORISER_dist() * @see balise_SESSION_SET_dist() * @example * ``` * #SESSION_SET{x,y} ajoute x=y dans la session du visiteur * ``` * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise **/ function balise_SESSION_SET_dist($p) { $_nom = interprete_argument_balise(1, $p); $_val = interprete_argument_balise(2, $p); if (!$_nom or !$_val) { $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SESSION_SET')); erreur_squelette($err_b_s_a, $p); } else { $p->code = '(include_spip("inc/session") AND session_set(' . $_nom . ',' . $_val . '))'; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#EVAL` qui évalue un code PHP * * À utiliser avec précautions ! * * @balise * @link http://www.spip.net/4587 * @example * ``` * #EVAL{6+9} * #EVAL{'date("Y-m-d")'} * #EVAL{$_SERVER['REQUEST_URI']} * #EVAL{'str_replace("r","z", "roger")'} (attention les "'" sont interdits) * ``` * * @note * `#EVAL{code}` produit `eval('return code;')` * mais si le code est une expression sans balise, on se dispense * de passer par une construction si compliquée, et le code est * passé tel quel (entre parenthèses, et protégé par interdire_scripts) * * @param Champ $p * Pile au niveau de la balise. * @return Champ * Pile completée du code PHP d'exécution de la balise **/ function balise_EVAL_dist($p) { $php = interprete_argument_balise(1, $p); if ($php) { # optimisation sur les #EVAL{une expression sans #BALISE} # attention au commentaire "// x signes" qui precede if (preg_match(",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms", $php, $r)) { $p->code = /* $r[1]. */ '(' . $r[2] . ')'; } else { $p->code = "eval('return '.$php.';')"; } } else { $msg = array('zbug_balise_sans_argument', array('balise' => ' EVAL')); erreur_squelette($msg, $p); } #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#CHAMP_SQL` qui renvoie la valeur d'un champ SQL * * Signature : `#CHAMP_SQL{champ}` * * Cette balise permet de récupérer par exemple un champ `notes` dans une table * SQL externe (impossible avec la balise `#NOTES` qui est une balise calculée). * * Ne permet pas de passer une expression comme argument, qui ne peut * être qu'un texte statique ! * * @balise * @link http://www.spip.net/4041 * @see champ_sql() * @example * ``` * #CHAMP_SQL{notes} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CHAMP_SQL_dist($p) { if ($p->param and isset($p->param[0][1][0]) and $champ = ($p->param[0][1][0]->texte) ) { $p->code = champ_sql($champ, $p); } else { $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => ' CHAMP_SQL')); erreur_squelette($err_b_s_a, $p); } #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#VAL` qui retourne simplement le premier argument * qui lui est transmis * * Cela permet d'appliquer un filtre à une chaîne de caractère * * @balise * @link http://www.spip.net/4026 * @example * ``` * #VAL retourne '' * #VAL{x} retourne 'x' * #VAL{1,2} renvoie '1' (2 est considéré comme un autre paramètre) * #VAL{'1,2'} renvoie '1,2' * [(#VAL{a_suivre}|bouton_spip_rss)] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_VAL_dist($p) { $p->code = interprete_argument_balise(1, $p); if (!strlen($p->code)) { $p->code = "''"; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#NOOP`, alias (déprécié) de `#VAL` * * Alias pour regler #948. Ne plus utiliser. * * @balise * @see balise_VAL_dist() * @deprecated Utiliser #VAL * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_NOOP_dist($p) { return balise_VAL_dist($p); } /** * Compile la balise `#REM` servant à commenter du texte * * Retourne toujours une chaîne vide. * * @balise * @link http://www.spip.net/4578 * @example * ``` * [(#REM) * Ceci est une remarque ou un commentaire, * non affiché dans le code généré * ] * ``` * * @note * La balise `#REM` n'empêche pas l'exécution des balises SPIP contenues * dedans (elle ne sert pas à commenter du code pour empêcher son * exécution). * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_REM_dist($p) { $p->code = "''"; $p->interdire_scripts = false; return $p; } /** * Une balise #NULL quand on a besoin de passer un argument null sur l'appel d'un filtre ou formulaire * (evite un #EVAL{null}) * @param $p * @return mixed */ function balise_NULL_dist($p) { $p->code = "null"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#HTTP_HEADER` envoyant des entêtes de retour HTTP * * Doit être placée en tête de fichier et ne fonctionne pas dans une * inclusion. * * @balise * @link http://www.spip.net/4631 * @example * ``` * #HTTP_HEADER{Content-Type: text/csv; charset=#CHARSET} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_HTTP_HEADER_dist($p) { $header = interprete_argument_balise(1, $p); if (!$header) { $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'HTTP_HEADER')); erreur_squelette($err_b_s_a, $p); } else { $p->code = "'<'.'?php header(' . _q(" . $header . ") . '); ?'.'>'"; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#FILTRE` qui exécute un filtre à l'ensemble du squelette * une fois calculé. * * Le filtrage se fait au niveau du squelette, sans s'appliquer aux ``. * Plusieurs filtres peuvent être indiqués, séparés par des barres verticales `|` * * @balise * @link http://www.spip.net/4894 * @example * ``` * #FILTRE{compacte_head} * #FILTRE{supprimer_tags|filtrer_entites|trim} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_FILTRE_dist($p) { if ($p->param) { $args = array(); foreach ($p->param as $i => $ignore) { $args[] = interprete_argument_balise($i + 1, $p); } $p->code = "'<' . '" . '?php header("X-Spip-Filtre: \'.' . join('.\'|\'.', $args) . " . '\"); ?'.'>'"; $p->interdire_scripts = false; return $p; } } /** * Compile la balise `#CACHE` definissant la durée de validité du cache du squelette * * Signature : `#CACHE{duree[,type]}` * * Le premier argument est la durée en seconde du cache. Le second * (par défaut `statique`) indique le type de cache : * * - `cache-client` autorise gestion du IF_MODIFIED_SINCE * - `statique` ne respecte pas l'invalidation par modif de la base * (mais s'invalide tout de même à l'expiration du delai) * * @balise * @see ecrire/public/cacher.php * @link http://www.spip.net/4330 * @example * ``` * #CACHE{24*3600} * #CACHE{24*3600, cache-client} * #CACHE{0} pas de cache * ``` * @note * En absence de cette balise la durée est du cache est donné * par la constante `_DUREE_CACHE_DEFAUT` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CACHE_dist($p) { if ($p->param) { $duree = valeur_numerique($p->param[0][1][0]->texte); // noter la duree du cache dans un entete proprietaire $code = "'<'.'" . '?php header("X-Spip-Cache: ' . $duree . '"); ?' . "'.'>'"; // Remplir le header Cache-Control // cas #CACHE{0} if ($duree == 0) { $code .= ".'<'.'" . '?php header("Cache-Control: no-cache, must-revalidate"); ?' . "'.'><'.'" . '?php header("Pragma: no-cache"); ?' . "'.'>'"; } // recuperer les parametres suivants $i = 1; while (isset($p->param[0][++$i])) { $pa = ($p->param[0][$i][0]->texte); if ($pa == 'cache-client' and $duree > 0 ) { $code .= ".'<'.'" . '?php header("Cache-Control: max-age=' . $duree . '"); ?' . "'.'>'"; // il semble logique, si on cache-client, de ne pas invalider $pa = 'statique'; } if ($pa == 'statique' and $duree > 0 ) { $code .= ".'<'.'" . '?php header("X-Spip-Statique: oui"); ?' . "'.'>'"; } } } else { $code = "''"; } $p->code = $code; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#INSERT_HEAD` permettant d'insérer du contenu dans * le `` d'une page HTML * * La balise permet aux plugins d'insérer des styles, js ou autre * dans l'entête sans modification du squelette. * Les css doivent être inserées de préférence par `#INSERT_HEAD_CSS` * pour en faciliter la surcharge. * * On insère ici aussi un morceau de PHP qui verifiera à l'exécution * que le pipeline `insert_head_css` a bien été vu * et dans le cas contraire l'appelera. Ceal permet de ne pas oublier * les css de `#INSERT_HEAD_CSS` même si cette balise n'est pas presente. * * Il faut mettre ce php avant le `insert_head` car le compresseur y mets * ensuite un php du meme type pour collecter * CSS et JS, et on ne veut pas qu'il rate les css insérées en fallback * par `insert_head_css_conditionnel`. * * @link http://www.spip.net/4629 * @see balise_INSERT_HEAD_CSS_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_INSERT_HEAD_dist($p) { $p->code = "'<'.'" . '?php header("X-Spip-Filtre: insert_head_css_conditionnel"); ?' . "'.'>'"; $p->code .= ". pipeline('insert_head','')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#INSERT_HEAD_CSS` homologue de `#INSERT_HEAD` pour les CSS * * Et par extension pour le JS inline qui doit préférentiellement * être inséré avant les CSS car bloquant sinon. * * @link http://www.spip.net/4605 * @see balise_INSERT_HEAD_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_INSERT_HEAD_CSS_dist($p) { $p->code = "pipeline('insert_head_css','')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#INCLUDE` alias de `#INCLURE` * * @balise * @see balise_INCLURE_dist() * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_INCLUDE_dist($p) { if (function_exists('balise_INCLURE')) { return balise_INCLURE($p); } else { return balise_INCLURE_dist($p); } } /** * Compile la balise `#INCLURE` qui inclut un résultat de squelette * * Signature : `[(#INCLURE{fond=nom_du_squelette, argument, argument=xx})]` * * L'argument `env` permet de transmettre tout l'environnement du squelette * en cours au squelette inclus. * * On parle d’inclusion « statique » car le résultat de compilation est * ajouté au squelette en cours, dans le même fichier de cache. * Cette balise est donc différente d’une inclusion « dynamique » avec * `` qui, elle, crée un fichier de cache séparé * (avec une durée de cache qui lui est propre). * * L'inclusion est realisée au calcul du squelette, pas au service * ainsi le produit du squelette peut être utilisé en entrée de filtres * à suivre. On peut faire un `#INCLURE{fichier}` sans squelette * (Incompatible avec les balises dynamiques). * * @balise * @example * ``` * [(#INCLURE{fond=inclure/documents,id_article, env})] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_INCLURE_dist($p) { $id_boucle = $p->id_boucle; // la lang n'est pas passe de facon automatique par argumenter // mais le sera pas recuperer_fond, sauf si etoile=>true est passe // en option $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false); // erreur de syntaxe = fond absent // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP if (!$_contexte) { $contexte = array(); } if (isset($_contexte['fond'])) { $f = $_contexte['fond']; // toujours vrai : if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) { $f = $r[1]; unset($_contexte['fond']); } else { spip_log("compilation de #INCLURE a revoir"); } // #INCLURE{doublons} if (isset($_contexte['doublons'])) { $_contexte['doublons'] = "'doublons' => \$doublons"; } // Critere d'inclusion {env} (et {self} pour compatibilite ascendante) $flag_env = false; if (isset($_contexte['env']) or isset($_contexte['self'])) { $flag_env = true; unset($_contexte['env']); } $_options = array(); if (isset($_contexte['ajax'])) { $_options[] = preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']); unset($_contexte['ajax']); } if ($p->etoile) { $_options[] = "'etoile'=>true"; } $_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) . ")"; $_l = 'array(' . join(",\n\t", $_contexte) . ')'; if ($flag_env) { $_l = "array_merge(\$Pile[0],$_l)"; } $p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',', $_options), "_request('connect')"); } elseif (!isset($_contexte[1])) { $msg = array('zbug_balise_sans_argument', array('balise' => ' INCLURE')); erreur_squelette($msg, $p); } else { $p->code = 'charge_scripts(' . $_contexte[1] . ',false)'; } $p->interdire_scripts = false; // la securite est assuree par recuperer_fond return $p; } /** * Compile la balise `#MODELE` qui inclut un résultat de squelette de modèle * * `#MODELE{nom}` insère le résultat d’un squelette contenu dans le * répertoire `modeles/`. L’identifiant de la boucle parente est transmis * par défaut avec le paramètre `id` à cette inclusion. * * Des arguments supplémentaires peuvent être transmis : * `[(#MODELE{nom, argument=xx, argument})]` * * @balise * @see balise_INCLURE_dist() * @example * ``` * #MODELE{article_traductions} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_MODELE_dist($p) { $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false); // erreur de syntaxe = fond absent // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP if (!$_contexte) { $contexte = array(); } if (!isset($_contexte[1])) { $msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE')); erreur_squelette($msg, $p); } else { $nom = $_contexte[1]; unset($_contexte[1]); if (preg_match("/^\s*'[^']*'/s", $nom)) { $nom = "'modeles/" . substr($nom, 1); } else { $nom = "'modeles/' . $nom"; } $flag_env = false; if (isset($_contexte['env'])) { $flag_env = true; unset($_contexte['env']); } // Incoherence dans la syntaxe du contexte. A revoir. // Reserver la cle primaire de la boucle courante si elle existe if (isset($p->boucles[$p->id_boucle]->primary)) { $primary = $p->boucles[$p->id_boucle]->primary; if (!strpos($primary, ',')) { $id = champ_sql($primary, $p); $_contexte[] = "'$primary'=>" . $id; $_contexte[] = "'id'=>" . $id; } } $_contexte[] = "'recurs'=>(++\$recurs)"; $connect = ''; if (isset($p->boucles[$p->id_boucle])) { $connect = $p->boucles[$p->id_boucle]->sql_serveur; } $_options = memoriser_contexte_compil($p); $_options = "'compil'=>array($_options), 'trim'=>true"; if (isset($_contexte['ajax'])) { $_options .= ", " . preg_replace(",=>(.*)$,ims", '=> ($v=(\\1))?$v:true', $_contexte['ajax']); unset($_contexte['ajax']); } $_l = 'array(' . join(",\n\t", $_contexte) . ')'; if ($flag_env) { $_l = "array_merge(\$Pile[0],$_l)"; } $page = sprintf(CODE_RECUPERER_FOND, $nom, $_l, $_options, _q($connect)); $p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n"; $p->interdire_scripts = false; // securite assuree par le squelette } return $p; } /** * Compile la balise `#SET` qui affecte une variable locale au squelette * * Signature : `#SET{cle,valeur}` * * @balise * @link http://www.spip.net/3990 Balises #SET et #GET * @see balise_GET_dist() * @example * ``` * #SET{nb,5} * #GET{nb} // affiche 5 * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_SET_dist($p) { $_nom = interprete_argument_balise(1, $p); $_val = interprete_argument_balise(2, $p); if (!$_nom or !$_val) { $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SET')); erreur_squelette($err_b_s_a, $p); } // affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4 // cf https://bugs.php.net/bug.php?id=65845 else { $p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)"; } $p->interdire_scripts = false; // la balise ne renvoie rien return $p; } /** * Compile la balise `#GET` qui récupère une variable locale au squelette * * Signature : `#GET{cle[,defaut]}` * * La clé peut obtenir des sous clés séparés par des `/` * * @balise * @link http://www.spip.net/3990 Balises #SET et #GET * @see balise_SET_dist() * @example * ``` * #SET{nb,5} * #GET{nb} affiche 5 * #GET{nb,3} affiche la valeur de nb, sinon 3 * * #SET{nb,#ARRAY{boucles,3}} * #GET{nb/boucles} affiche 3, équivalent à #GET{nb}|table_valeur{boucles} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_GET_dist($p) { $p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance if (function_exists('balise_ENV')) { return balise_ENV($p, '$Pile["vars"]'); } else { return balise_ENV_dist($p, '$Pile["vars"]'); } } /** * Compile la balise `#DOUBLONS` qui redonne les doublons enregistrés * * - `#DOUBLONS{mots}` ou `#DOUBLONS{mots,famille}` * donne l'état des doublons `(MOTS)` à cet endroit * sous forme de tableau d'id_mot comme `array(1,2,3,...)` * - `#DOUBLONS` tout seul donne la liste brute de tous les doublons * - `#DOUBLONS*{mots}` donne la chaine brute `,1,2,3,...` * (changera si la gestion des doublons evolue) * * @balise * @link http://www.spip.net/4123 * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_DOUBLONS_dist($p) { if ($type = interprete_argument_balise(1, $p)) { if ($famille = interprete_argument_balise(2, $p)) { $type .= '.' . $famille; } $p->code = '(isset($doublons[' . $type . ']) ? $doublons[' . $type . '] : "")'; if (!$p->etoile) { $p->code = 'array_filter(array_map("intval",explode(",",' . $p->code . ')))'; } } else { $p->code = '$doublons'; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#PIPELINE` pour permettre d'insérer des sorties de * pipeline dans un squelette * * @balise * @see pipeline() * @example * ``` * #PIPELINE{nom} * #PIPELINE{nom,données} * #PIPELINE{boite_infos,#ARRAY{data,'',args,#ARRAY{type,rubrique,id,#ENV{id_rubrique}}}} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_PIPELINE_dist($p) { $_pipe = interprete_argument_balise(1, $p); if (!$_pipe) { $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'PIPELINE')); erreur_squelette($err_b_s_a, $p); } else { $_flux = interprete_argument_balise(2, $p); $_flux = $_flux ? $_flux : "''"; $p->code = "pipeline( $_pipe , $_flux )"; $p->interdire_scripts = false; } return $p; } /** * Compile la balise `#EDIT` qui ne fait rien dans SPIP * * Cette balise ne retourne rien mais permet d'indiquer, pour certains plugins * qui redéfinissent cette balise, le nom du champ SQL (ou le nom d'un contrôleur) * correspondant à ce qui est édité. Cela sert particulièrement au plugin Crayons. * Ainsi en absence du plugin, la balise est toujours reconnue (mais n'a aucune action). * * @balise * @link http://www.spip.net/4584 * @example * ``` * [
(#TEXTE)
] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_EDIT_dist($p) { $p->code = "''"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#TOTAL_UNIQUE` qui récupère le nombre d'éléments * différents affichés par le filtre `unique` * * @balise * @link http://www.spip.net/4374 * @see unique() * @example * ``` * #TOTAL_UNIQUE affiche le nombre de #BALISE|unique * #TOTAL_UNIQUE{famille} afiche le nombre de #BALISE|unique{famille} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_TOTAL_UNIQUE_dist($p) { $_famille = interprete_argument_balise(1, $p); $_famille = $_famille ? $_famille : "''"; $p->code = "unique('', $_famille, true)"; return $p; } /** * Compile la balise `#ARRAY` créant un tableau PHP associatif * * Crée un `array` PHP à partir d'arguments calculés. * Chaque paire d'arguments représente la clé et la valeur du tableau. * * @balise * @link http://www.spip.net/4009 * @example * ``` * #ARRAY{key1,val1,key2,val2 ...} retourne * array( key1 => val1, key2 => val2, ...) * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_ARRAY_dist($p) { $_code = array(); $n = 1; do { $_key = interprete_argument_balise($n++, $p); $_val = interprete_argument_balise($n++, $p); if ($_key and $_val) { $_code[] = "$_key => $_val"; } } while ($_key && $_val); $p->code = 'array(' . join(', ', $_code) . ')'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#LISTE` qui crée un tableau PHP avec les valeurs, sans préciser les clés * * @balise * @link http://www.spip.net/5547 * @example * ``` * #LISTE{a,b,c,d,e} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_LISTE_dist($p) { $_code = array(); $n = 1; while ($_val = interprete_argument_balise($n++, $p)) { $_code[] = $_val; } $p->code = 'array(' . join(', ', $_code) . ')'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#AUTORISER` qui teste une autorisation * * Appelle la fonction `autoriser()` avec les mêmes arguments, * et renvoie un espace ' ' si OK (l'action est autorisée), * sinon une chaine vide '' (l'action n'est pas autorisée). * * Cette balise créée un cache par session. * * Signature : `#AUTORISER{faire[,type[,id[,auteur[,options]]]}` * * @note * La priorité des opérateurs exige && plutot que AND * * @balise * @link http://www.spip.net/3896 * @see autoriser() * @see sinon_interdire_acces() * @example * ``` * [(#AUTORISER{modifier,rubrique,#ID_RUBRIQUE}) ... ] * [(#AUTORISER{voir,rubrique,#ID_RUBRIQUE}|sinon_interdire_acces)] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_AUTORISER_dist($p) { $_code = array(); $p->descr['session'] = true; // faire un cache par session $n = 1; while ($_v = interprete_argument_balise($n++, $p)) { $_code[] = $_v; } $p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(', ', $_code) . ')?" ":"")'; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#PLUGIN` qui permet d’afficher les informations d'un plugin actif * * @balise * @see filtre_info_plugin_dist() * @link http://www.spip.net/4591 * @example * ``` * #PLUGIN Retourne la liste sérialisée des préfixes de plugins actifs * #PLUGIN{prefixe} Renvoie true si le plugin avec ce préfixe est actif * #PLUGIN{prefixe, x} Renvoie l'information x du plugin (s'il est actif) * #PLUGIN{prefixe, tout} Renvoie toutes les informations du plugin (s'il est actif) * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_PLUGIN_dist($p) { $plugin = interprete_argument_balise(1, $p); $plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""'; $type_info = interprete_argument_balise(2, $p); $type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"'; $f = chercher_filtre('info_plugin'); $p->code = $f . '(' . $plugin . ', ' . $type_info . ')'; return $p; } /** * Compile la balise `#AIDER` qui permet d’afficher l’icone de l’aide * au sein des squelettes. * * @balise * @see inc_aide_dist() * @link http://www.spip.net/4733 * @example * ``` * #AIDER{titre} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_AIDER_dist($p) { $_motif = interprete_argument_balise(1, $p); $s = "'" . addslashes($p->descr['sourcefile']) . "'"; $p->code = "((\$aider=charger_fonction('aide','inc',true))?\$aider($_motif,$s, \$Pile[0]):'')"; return $p; } /** * Compile la balise `#ACTION_FORMULAIRE` qui insère le contexte * des formulaires charger / vérifier / traiter avec les hidden de * l'URL d'action * * Accèpte 2 arguments optionnels : * - L'url de l'action (par défaut `#ENV{action}` * - Le nom du formulaire (par défaut `#ENV{form}` * * @balise * @see form_hidden() * @example * ``` *
* #ACTION_FORMULAIRE * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_ACTION_FORMULAIRE($p) { if (!$_url = interprete_argument_balise(1, $p)) { $_url = "@\$Pile[0]['action']"; } if (!$_form = interprete_argument_balise(2, $p)) { $_form = "@\$Pile[0]['form']"; } // envoyer le nom du formulaire que l'on traite // transmettre les eventuels args de la balise formulaire $p->code = " '
' . form_hidden($_url) . '' . '' . '' . (!empty(\$Pile[0]['_hidden']) ? @\$Pile[0]['_hidden'] : '') . '
'"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#BOUTON_ACTION` qui génère un bouton d'action en post, ajaxable * * Cette balise s'utilise à la place des liens `action_auteur`, sous la forme * * - `#BOUTON_ACTION{libelle,url}` * - ou `#BOUTON_ACTION{libelle,url,ajax}` pour que l'action soit ajax comme un lien `class='ajax'` * - ou `#BOUTON_ACTION{libelle,url,ajax,message_confirmation}` pour utiliser un message de confirmation * - ou encore `#BOUTON_ACTION{libelle[,url[,ajax[,message_confirmation[,title[,callback]]]]]}` * * @balise * @link http://www.spip.net/4583 * @example * ``` * [(#AUTORISER{reparer,base}) * [(#BOUTON_ACTION{<:bouton_tenter_recuperation:>,#URL_ECRIRE{base_repair}})] * ] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_BOUTON_ACTION_dist($p) { $args = array(); for ($k = 1; $k <= 6; $k++) { $_a = interprete_argument_balise($k, $p); if (!$_a) { $_a = "''"; } $args[] = $_a; } // supprimer les args vides while (end($args) == "''" and count($args) > 2) { array_pop($args); } $args = implode(",", $args); $bouton_action = chercher_filtre("bouton_action"); $p->code = "$bouton_action($args)"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#SLOGAN_SITE_SPIP` qui retourne le slogan du site * * @balise * @example * ``` * [

(#SLOGAN_SITE_SPIP)

] * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_SLOGAN_SITE_SPIP_dist($p) { $p->code = "\$GLOBALS['meta']['slogan_site']"; #$p->interdire_scripts = true; return $p; } /** * Compile la balise `#HTML5` indiquant si l'espace public peut utiliser du HTML5 * * Renvoie `' '` si le webmestre souhaite que SPIP génère du code (X)HTML5 sur * le site public, et `''` si le code doit être strictement compatible HTML4 * * @balise * @uses html5_permis() * @example * ``` * [(#HTML5) required="required"] * * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_HTML5_dist($p) { $p->code = html5_permis() ? "' '" : "''"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#TRI` permettant d'afficher un lien de changement d'ordre de tri * d'une colonne de la boucle * * La balise `#TRI{champ[,libelle]}` champ prend `>` ou `<` pour afficher * le lien de changement de sens croissant ou decroissant (`>` `<` indiquent * un sens par une flèche) * * @balise * @example * ``` * [(#TRI{titre,<:info_titre:>,ajax})] * ``` * * @param Champ $p * Pile au niveau de la balise * @param string $liste * Inutilisé * @return Champ * Pile complétée par le code à générer */ function balise_TRI_dist($p, $liste = 'true') { $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere']; // s'il n'y a pas de nom de boucle, on ne peut pas trier if ($b === '') { erreur_squelette( _T('zbug_champ_hors_boucle', array('champ' => '#TRI') ), $p->id_boucle); $p->code = "''"; return $p; } $boucle = $p->boucles[$b]; // s'il n'y a pas de tri_champ, c'est qu'on se trouve // dans un boucle recursive ou qu'on a oublie le critere {tri} if (!isset($boucle->modificateur['tri_champ'])) { erreur_squelette( _T('zbug_tri_sans_critere', array('champ' => '#TRI') ), $p->id_boucle); $p->code = "''"; return $p; } $_champ = interprete_argument_balise(1, $p); // si pas de champ, renvoyer le critere de tri utilise if (!$_champ) { $p->code = $boucle->modificateur['tri_champ']; return $p; } // forcer la jointure si besoin, et si le champ est statique if (preg_match(",^'([\w.]+)'$,i", $_champ, $m)) { index_pile($b, $m[1], $p->boucles, '', null, true, false); } $_libelle = interprete_argument_balise(2, $p); $_libelle = $_libelle ? $_libelle : $_champ; $_class = interprete_argument_balise(3, $p); // si champ = ">" c'est un lien vers le tri croissant : de gauche a droite ==> 1 // si champ = "<" c'est un lien vers le tri decroissant : (sens inverse) == -1 $_issens = "in_array($_champ,array('>','<'))"; $_sens = "(strpos('< >',$_champ)-1)"; $_variable = "((\$s=$_issens)?'sens':'tri')." . $boucle->modificateur['tri_nom']; $_url = "parametre_url(self(),$_variable,\$s?$_sens:$_champ)"; $_url = "parametre_url($_url,'var_memotri',strncmp(" . $boucle->modificateur['tri_nom'] . ",'session',7)==0?$_variable:'')"; $_on = "\$s?(" . $boucle->modificateur['tri_sens'] . "==$_sens" . '):(' . $boucle->modificateur['tri_champ'] . "==$_champ)"; $p->code = "lien_ou_expose($_url,$_libelle,$_on" . ($_class ? ",$_class" : "") . ")"; //$p->code = "''"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#SAUTER{n}` qui permet de sauter en avant n resultats dans une boucle * * La balise modifie le compteur courant de la boucle, mais pas les autres * champs qui restent les valeurs de la boucle avant le saut. Il est donc * preferable d'utiliser la balise juste avant la fermeture `` * * L'argument `n` doit être supérieur à zéro sinon la balise ne fait rien * * @balise * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_SAUTER_dist($p) { $id_boucle = $p->id_boucle; if (empty($p->boucles[$id_boucle])) { $msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER')); erreur_squelette($msg, $p); } else { $boucle = $p->boucles[$id_boucle]; $_saut = interprete_argument_balise(1, $p); $_compteur = "\$Numrows['$id_boucle']['compteur_boucle']"; $_total = "\$Numrows['$id_boucle']['total']"; $p->code = "vide($_compteur=\$iter->skip($_saut,$_total))"; } $p->interdire_scripts = false; return $p; } /** * Compile la balise `#PUBLIE` qui indique si un objet est publié ou non * * @balise * @link http://www.spip.net/5545 * @see objet_test_si_publie() * @example * ``` * #PUBLIE : porte sur la boucle en cours * [(#PUBLIE{article, 3}|oui) ... ] : pour l'objet indiqué * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_PUBLIE_dist($p) { if (!$_type = interprete_argument_balise(1, $p)) { $_type = _q($p->type_requete); $_id = champ_sql($p->boucles[$p->id_boucle]->primary, $p); } else { $_id = interprete_argument_balise(2, $p); } $connect = ''; if (isset($p->boucles[$p->id_boucle])) { $connect = $p->boucles[$p->id_boucle]->sql_serveur; } $p->code = "(objet_test_si_publie(" . $_type . ",intval(" . $_id . ")," . _q($connect) . ")?' ':'')"; $p->interdire_scripts = false; return $p; } /** * Compile la balise `#PRODUIRE` qui génère un fichier statique à partir * d'un squelette SPIP * * Le format du fichier sera extrait de la pre-extension du squelette * (typo.css.html, messcripts.js.html) * ou par l'argument `format=css` ou `format=js` passé en argument. * * S'il n'y a pas de format détectable, on utilise `.html`, comme pour les squelettes. * * La syntaxe de la balise est la même que celle de `#INCLURE`. * * @balise * @see balise_INCLURE_dist() * @link http://www.spip.net/5505 * @example * ``` * * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_PRODUIRE_dist($p) { $balise_inclure = charger_fonction('INCLURE', 'balise'); $p = $balise_inclure($p); $p->code = str_replace('recuperer_fond(', 'produire_fond_statique(', $p->code); return $p; } /** * Compile la balise `#LARGEUR_ECRAN` qui définit la largeur d'écran * dans l'espace privé * * @balise * @example * ``` * #LARGEUR_ECRAN{pleine_largeur} * ``` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer */ function balise_LARGEUR_ECRAN_dist($p) { $_class = interprete_argument_balise(1, $p); if (!$_class) { $_class = 'null'; } $p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))"; return $p; } /** * Compile la balise `#CONST` qui retourne la valeur de la constante passée en argument * * @balise * @example `#CONST{_DIR_IMG}` * * @param Champ $p * Pile au niveau de la balise * @return Champ * Pile complétée par le code à générer **/ function balise_CONST_dist($p) { $_const = interprete_argument_balise(1, $p); if (!strlen($_const)) { $p->code = "''"; } else { $p->code = "(defined($_const)?constant($_const):'')"; } $p->interdire_scripts = false; return $p; }