From c81d961b972089fecdd667ac359182ef0ab22101 Mon Sep 17 00:00:00 2001 From: Fil <fil@rezo.net> Date: Sun, 6 Apr 2008 01:43:26 +0000 Subject: [PATCH] Possibilite de passer des {doublons} dans les inclusions et dans le contexte general ; application : passer la gestion des documents du squelette article.html vers un inclure(inc-documents) --- dist/article.html | 61 ++++++++++----------------- dist/inc-documents.html | 77 ++++++++++++++++++++++++++++++++-- ecrire/public/balises.php | 10 +++++ ecrire/public/compiler.php | 44 ++++++++++++------- ecrire/public/composer.php | 21 ++++++++++ ecrire/public/phraser_html.php | 38 ++++++++--------- ecrire/public/references.php | 21 ++++++++-- 7 files changed, 190 insertions(+), 82 deletions(-) diff --git a/dist/article.html b/dist/article.html index ebc417cc88..3af2c4f2ec 100644 --- a/dist/article.html +++ b/dist/article.html @@ -42,50 +42,31 @@ [<div class="#EDIT{chapo} chapo">(#CHAPO|image_reduire{500,0})</div>] [<div class="#EDIT{texte} texte entry-content">(#TEXTE|image_reduire{500,0})</div>] </div> - - [(#REM) Portfolio : album d'images ] - <B_documents_portfolio> - <div id="documents_portfolio"> - <h2><:info_portfolio:></h2> - <BOUCLE_documents_portfolio(DOCUMENTS) {id_article} {mode=document} {extension IN png,jpg,gif} {par num titre, date} {doublons}>[ - <a href="(#URL_DOCUMENT)" type="#MIME_TYPE" onClick="location.href='[(#URL_ARTICLE|parametre_url{id_document,#ID_DOCUMENT})]#documents_portfolio';return false;"[ title="(#TITRE|couper{80}|texte_backend)"][ class="(#_article_principal:EXPOSE)"]>[(#FICHIER|copie_locale|image_reduire{0,60}|inserer_attribut{class,spip_logos}|inserer_attribut{alt,[(#TITRE|couper{80}|texte_backend)]})]</a> - ]</BOUCLE_documents_portfolio> - </div> - </B_documents_portfolio> - <BOUCLE_afficher_document(DOCUMENTS) {id_article}{id_document} {mode=document}{extension IN png,jpg,gif}> - <div class="spip_documents spip_documents_center" id="document_actif"> - [(#EMBED_DOCUMENT|image_reduire{500,0})] - [<div class="#EDIT{titre} spip_doc_titre">(#TITRE)</div>] - [<div class="#EDIT{descriptif} spip_doc_descriptif">(#DESCRIPTIF)</div>] - </div> - </BOUCLE_afficher_document> - + + [<p class="#EDIT{hyperlien} hyperlien"><:voir_en_ligne:> : <a href="(#URL_SITE)" class="spip_out">[(#NOM_SITE|sinon{[(#URL_SITE|couper{80})]})]</a></p>] [<div class="ps surlignable"><h2 class="pas_surlignable"><:info_ps:></h2><div class="#EDIT{ps}">(#PS|image_reduire{500,0})</div></div>] - [(#REM) Autres documents joints a l'article. Si un seul et texte vide, incrustation automatique ; a noter : le {!doublons A} permet de retrouver les documents dans la boucle suivante ] - <BOUCLE_documents_decompte(DOCUMENTS) {id_article} {mode=document}{doublons}{doublons A} - />[(#TOTAL_BOUCLE|<>{1}|?{' ',#TEXTE**}|?{'',' '}) - <INCLURE{fond=inc-documents}{id_article}>] - <//B_documents_decompte> - - <B_documents_joints> - <div class="menu" id="documents_joints"> - <h2><:titre_documents_joints:></h2> - <ul> - <BOUCLE_documents_joints(DOCUMENTS){!doublons A} {par num titre, date}>[ - <li> - <strong><a href="(#URL_DOCUMENT)" title="<:bouton_telecharger:>" type="#MIME_TYPE">[(#TITRE|sinon{<:info_document:>})]</a></strong> - <small>(<span>#TYPE_DOCUMENT[ – (#TAILLE|taille_en_octets)]</span>)</small> - #DESCRIPTIF - ]</li> - </BOUCLE_documents_joints> - </ul> - </div> - </B_documents_joints>[ - - (#REM) Petition : + + + [(#REM) Gestion du portfolio et des documents + Le critere d'inclusion {doublons} permet d'eviter de lister + les documents deja integres dans la balise # TEXTE + Le critere d'incrustation permet d'incruster un document + qui serait unique : on le fait si # TEXTE est vide + Le critere {env} permet de passer d'autres arguments de la page + par exemple l'id_document choisi pour un affichage complet + ] + [(#INCLURE{fond=inc-documents} + {id_article} + {doublons} + {incruster=[(#TEXTE**|=={''})]} + {env} + )] + + + [(#REM) Petition : La petition ayant une PAGINATION il faut absolument {env}][ (#PETITION|?{' '})<INCLURE{fond=inc-petition}{id_article}{env}>] diff --git a/dist/inc-documents.html b/dist/inc-documents.html index 21fa7d4dcc..1854493a9c 100644 --- a/dist/inc-documents.html +++ b/dist/inc-documents.html @@ -1,3 +1,74 @@ -<BOUCLE1 (DOCUMENTS){id_article}{extension !IN png,jpg,gif}> -<INCLURE{fond=modeles/emb}{id_document}> -</BOUCLE1> + + [(#REM) Portfolio : album d'images ] + <B_documents_portfolio> + <div id="documents_portfolio"> + <h2><:info_portfolio:></h2> + <BOUCLE_documents_portfolio(DOCUMENTS) {id_article ?} + {mode=document} + {extension IN png,jpg,gif} + {par num titre, date} + {doublons}>[ + <a href="(#URL_DOCUMENT)" type="#MIME_TYPE" + onClick="location.href='[(#URL_ARTICLE + |parametre_url{id_document,#ID_DOCUMENT} + )]#documents_portfolio';return false;"[ + class="(#EXPOSER)"][ + title="(#TITRE|couper{80}|texte_backend)"]>[(#FICHIER + |image_reduire{0,60} + |inserer_attribut{class,spip_logos} + |inserer_attribut{alt,[(#TITRE|couper{80}|texte_backend)]})]</a> + ]</BOUCLE_documents_portfolio> + </div> + </B_documents_portfolio> + + [(#REM) + Afficher en grand le document demande dans l'URL + ] + <BOUCLE_afficher_document(DOCUMENTS) + {id_document} + {id_article ?} + {mode=document} + {extension IN png,jpg,gif}> + <div class="spip_documents spip_documents_center" id="document_actif"> + [(#EMBED_DOCUMENT|image_reduire{500,0})] + [<div class="#EDIT{titre} spip_doc_titre">(#TITRE)</div>] + [<div class="#EDIT{descriptif} spip_doc_descriptif">(#DESCRIPTIF)</div>] + </div> + </BOUCLE_afficher_document> + + + [(#REM) + Si un seul document est joint a l'article, et si le texte est vide, + on incruste automatiquement ce document + ] + <BOUCLE_documents_decompte(DOCUMENTS) {id_article ?} + {mode=document} + {doublons} + {doublons A} + >[(#TOTAL_BOUCLE|=={1} + |?{#ENV{incruster}} + |?{[(#INCLURE{fond=modeles/emb}{id_document}|trim)]})]</BOUCLE_documents_decompte> + + [(#REM) + Liste des autres documents joints + ] + <B_documents_joints> + <div class="menu" id="documents_joints"> + <h2><:titre_documents_joints:></h2> + <ul> + <BOUCLE_documents_joints(DOCUMENTS) + {id_article ?} + {!doublons A} {par num titre, date}>[ + <li> + <strong><a href="(#URL_DOCUMENT)" title="<:bouton_telecharger:>" + type="#MIME_TYPE">[(#TITRE|sinon{<:info_document:>})]</a></strong> + <small>(<span>#TYPE_DOCUMENT[ – + (#TAILLE|taille_en_octets)]</span>)</small> + #DESCRIPTIF + ]</li> + </BOUCLE_documents_joints> + </ul> + </div> + </B_documents_joints> + + <//B_documents_decompte> diff --git a/ecrire/public/balises.php b/ecrire/public/balises.php index 6d5c8a1d75..8ec251c9b1 100644 --- a/ecrire/public/balises.php +++ b/ecrire/public/balises.php @@ -1059,11 +1059,19 @@ function balise_INCLURE_dist($p) { $_contexte = argumenter_inclure($champ, $p->descr, $p->boucles, $id_boucle, false); if (isset($_contexte['fond'])) { + + // Gerer ajax if (isset($_contexte['ajax'])){ $_contexte['fond_ajax'] = preg_replace(",fond,","fond_ajax",$_contexte['fond'],1); $_contexte['fond'] = "'fond' => 'fond/ajax_stat'"; unset($_contexte['ajax']); } + + // #INCLURE{doublons} + if (isset($_contexte['doublons'])) { + $_contexte['doublons'] = "'doublons' => \$doublons"; + } + // Critere d'inclusion {env} (et {self} pour compatibilite ascendante) if (isset($_contexte['env']) || isset($_contexte['self']) @@ -1071,10 +1079,12 @@ function balise_INCLURE_dist($p) { $flag_env = true; unset($_contexte['env']); } else $flag_env = false; + $l = 'array(' . join(",\n\t", $_contexte) .')'; if ($flag_env) { $l = "array_merge(\$Pile[0],$l)"; } + $connect = !$id_boucle ? '' : $p->boucles[$id_boucle]->sql_serveur; diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php index 717d374924..80026a3478 100644 --- a/ecrire/public/compiler.php +++ b/ecrire/public/compiler.php @@ -68,12 +68,12 @@ function argumenter_inclure($struct, $descr, &$boucles, $id_boucle, $echap=true) // Calculer un <INCLURE()> // // http://doc.spip.org/@calculer_inclure -function calculer_inclure($struct, $descr, &$boucles, $id_boucle) { +function calculer_inclure($p, $descr, &$boucles, $id_boucle) { # Si pas raccourci <INCLURE{fond=xxx}> # chercher le fichier, eventuellement en changeant.php3 => .php # et en gardant la compatibilite <INCLURE(page.php3)> - if ($fichier = $struct->texte) { + if ($fichier = $p->texte) { if (preg_match(',^(.*[.]php)3$,', $fichier, $r)) { $fichier = $r[1]; } @@ -91,7 +91,7 @@ function calculer_inclure($struct, $descr, &$boucles, $id_boucle) { } } - $_contexte = argumenter_inclure($struct, $descr, $boucles, $id_boucle); + $_contexte = argumenter_inclure($p, $descr, $boucles, $id_boucle); if (isset($_contexte['fond']) && isset($_contexte['ajax'])){ $_contexte['fond_ajax'] = preg_replace(",fond,","fond_ajax",$_contexte['fond'],1); $_contexte['fond'] = "\'fond\' => ' . argumenter_squelette('fond/ajax') . '"; @@ -100,6 +100,13 @@ function calculer_inclure($struct, $descr, &$boucles, $id_boucle) { if ($env = (isset($_contexte['env'])|| isset($_contexte['self']))) { unset($_contexte['env']); } + + // <INCLURE{doublons}> + if (isset($_contexte['doublons'])) { + // noter les doublons dans l'appel a public.php + $_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'"; + } + $contexte = 'array(' . join(",\n\t", $_contexte) .')'; if ($env) { $contexte = "array_merge('.var_export(\$Pile[0],1).',$contexte)"; @@ -107,9 +114,9 @@ function calculer_inclure($struct, $descr, &$boucles, $id_boucle) { return "\n'<". "?php\n\t\$contexte_inclus = $contexte;" - . "\n\tinclude(" . + . "\n\tinclude " . ($fichier ? "\\'$path\\'" : ('_DIR_RESTREINT . "public.php"')). - ");" . + ";" . "\n?'." . "'>'"; } @@ -721,21 +728,22 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') include_spip('inc/charsets'); $squelette = transcoder_page($squelette); + // Informations sur le squelette + $descr = array('nom' => $nom, 'sourcefile' => $sourcefile, + 'squelette' => $squelette); + unset($squelette); + // Phraser le squelette, selon sa grammaire // pour le moment: "html" seul connu (HTML+balises BOUCLE) $boucles = array(); spip_timer('calcul_skel'); - $f = charger_fonction('phraser_'.$gram, 'public'); - - $racine = $f($squelette, '',$boucles, $nom); - // tableau des informations sur le squelette - $descr = array('nom' => $nom, 'sourcefile' => $sourcefile); + $f = charger_fonction('phraser_'.$gram, 'public'); - // Signaler une boucle documents (les autres influent dessus) - // Et demander la description des tables une fois pour toutes + $racine = $f($descr['squelette'], '', $boucles, $nom); + // Demander la description des tables une fois pour toutes foreach($boucles as $id => $boucle) { $type = $boucle->type_requete; if ($type != 'boucle') { @@ -753,8 +761,6 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') if ((!$boucles[$id]->jointures) AND (is_array($x = $tables_jointures[$nom_table]))) $boucles[$id]->jointures = $x; - if (($type == 'documents') && $boucle->doublons) - { $descr['documents'] = true; } } else { $boucles[$id]->type_requete = ''; $x = $boucles[$id]->sql_serveur; @@ -769,6 +775,7 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') } } } + // Commencer par reperer les boucles appelees explicitement // car elles indexent les arguments de maniere derogatoire foreach($boucles as $id => $boucle) { @@ -870,6 +877,13 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect='') ($connect ? " pour $connect" : '') . ". // function " . $nom . '($Cache, $Pile, $doublons=array(), $Numrows=array(), $SP=0) { + +' + // reporter de maniere securisee les doublons inclus +.' + if (is_array($Pile[0]["doublons"])) + $doublons = nettoyer_env_doublons($Pile[0]["doublons"]); + $connect = ' . _q($connect) . '; $page = ' . @@ -884,7 +898,7 @@ function " . $nom . '($Cache, $Pile, $doublons=array(), $Numrows=array(), $SP=0) ?".">"; if (isset($GLOBALS['var_mode']) AND $GLOBALS['var_mode'] == 'debug') - squelette_debug_compile($nom, $sourcefile, $code, $squelette); + squelette_debug_compile($nom, $sourcefile, $code, $descr['squelette']); return $code; } diff --git a/ecrire/public/composer.php b/ecrire/public/composer.php index fcdeb7a763..a9599c3665 100644 --- a/ecrire/public/composer.php +++ b/ecrire/public/composer.php @@ -482,6 +482,27 @@ function calculer_notes() { return $r; } + +// Si un tableau &doublons[articles] est passe en parametre, +// il faut le nettoyer car il pourrait etre injecte en SQL +// http://doc.spip.org/@nettoyer_env_doublons +function nettoyer_env_doublons($envd) { + foreach ($envd as $table => $liste) { + $n = ''; + foreach(explode(',',$liste) as $val) { + if ($a = intval($val) AND $val === strval($a)) + $n.= ','.$val; + } + if (strlen($n)) + $envd[$table] = $n; + else + unset($envd[$table]); + } + return $envd; +} + + + // Ajouter "&lang=..." si la langue de base n'est pas celle du site. // Si le 2e parametre n'est pas une chaine, c'est qu'on n'a pas pu // determiner la table a la compil, on le fait maintenant. diff --git a/ecrire/public/phraser_html.php b/ecrire/public/phraser_html.php index 2459764111..93d104131a 100644 --- a/ecrire/public/phraser_html.php +++ b/ecrire/public/phraser_html.php @@ -48,24 +48,24 @@ function phraser_arguments_inclure($p,$rejet_filtres = false){ else $champ->param[$k] = $v; } - else { - if ($var->type != 'texte') - if ($rejet_filtres) - break; // on est arrive sur un filtre sans argument qui suit la balise - else - erreur_squelette(_T('zbug_parametres_inclus_incorrects'),$var); - else { - $champ->param[$k] = $v; - preg_match(",^([^=]*)(=)?(.*)$,", $var->texte,$m); - if ($m[2]) { - $champ->param[$k][0] = $m[1]; - $val = $m[3]; - if (preg_match(',^[\'"](.*)[\'"]$,', $val, $m)) $val = $m[1]; - $champ->param[$k][1][0]->texte = $val; - } - else - $champ->param[$k] = array($m[1]); + else + if ($var->type != 'texte') { + if ($rejet_filtres) + break; // on est arrive sur un filtre sans argument qui suit la balise + else + erreur_squelette(_T('zbug_parametres_inclus_incorrects'),$var); + } else { + $champ->param[$k] = $v; + preg_match(",^([^=]*)(=)?(.*)$,", $var->texte,$m); + if ($m[2]) { + $champ->param[$k][0] = $m[1]; + $val = $m[3]; + if (preg_match(',^[\'"](.*)[\'"]$,', $val, $m)) $val = $m[1]; + $champ->param[$k][1][0]->texte = $val; } + else + $champ->param[$k] = array($m[1]); + } } return $champ; @@ -90,9 +90,7 @@ function phraser_inclure($texte, $ligne, $result) { $champ->param = $champ_->param; $texte = substr($champ->apres, strpos($champ->apres, '>')+1); $champ->apres = ""; - if (preg_match(',^</INCLU[DR]E>,', $texte)) { - $texte = substr($texte,10); - } + $texte = preg_replace(',^</INCLU[DR]E>,', '', $texte); $result[] = $champ; } return (($texte==="") ? $result : phraser_idiomes($texte, $ligne, $result)); diff --git a/ecrire/public/references.php b/ecrire/public/references.php index b5a5cff660..59f092fab0 100644 --- a/ecrire/public/references.php +++ b/ecrire/public/references.php @@ -296,6 +296,7 @@ function balise_distante_interdite($p) { // http://doc.spip.org/@champs_traitements function champs_traitements ($p) { global $table_des_traitements; + static $test_doublons = array(); if (!isset($table_des_traitements[$p->nom_champ])) return $p->code; @@ -312,15 +313,27 @@ function champs_traitements ($p) { if (!$ps) return $p->code; - // Si une boucle documents est presente dans le squelette, + + // Si une boucle DOCUMENTS{doublons} est presente dans le squelette, + // ou si in INCLURE contient {doublons} // on insere une fonction de remplissage du tableau des doublons // dans les filtres propre() ou typo() // (qui traitent les raccourcis <docXX> referencant les docs) - if (isset($p->descr['documents']) - AND ((strpos($ps,'propre') !== false) - OR (strpos($ps,'typo') !== false))) + // NB: le test permet d'eviter ce calcul quand on sait qu'il ne servira pas + if (!isset($test_doublons[$p->descr['sourcefile']])) + $test_doublons[$p->descr['sourcefile']] + = preg_match(',([<#]INCLU[RD]E|DOCUMENTS)[^<>]*{doublons,', + $p->descr['squelette']); + + if ($test_doublons[$p->descr['sourcefile']] + AND ( + (strpos($ps,'propre') !== false) + OR + (strpos($ps,'typo') !== false) + )) $ps = 'traiter_doublons_documents($doublons, '.$ps.')'; + // Passer |safehtml sur les boucles "sensibles" // sauf sur les champs dont on est surs switch ($p->type_requete) { -- GitLab