Elle rajoute le traitements de raccourcis SPIP pour rédiger simplement une FAQ et une configuration pour des fonctionnalités supplémentaires. Par défaut, cette version repoduit le comportement de la branche 2svn/root/tags/v3.1.0

@ -1,13 +1,11 @@
|
||||
* text=auto !eol |
||||
css/faq.css -text |
||||
css/img/bg-dt.png -text |
||||
css/img/faq-close.png -text |
||||
css/img/faq-open.png -text |
||||
css/img/puce-dt.png -text |
||||
/faq_logo-128.png -text |
||||
/faq_pipelines.php -text |
||||
icon/faq-128.png -text |
||||
icon/faq-32.png -text |
||||
/inc-rubrique-faq.html -text |
||||
inclure/rubrique-faq.html -text |
||||
icones_barre/faq-16.png -text |
||||
icones_barre/faq_question-16.png -text |
||||
icones_barre/faq_titre-16.png -text |
||||
js/faq.js -text |
||||
/plugin.xml -text |
||||
prive/themes/spip/images/faq-24.png -text |
||||
|
@ -0,0 +1,12 @@
|
||||
/* -------------------------------------------------------------- |
||||
faq.css |
||||
Style des Questions-Réponse |
||||
inspiré du plugin FAQ et définitions de romy.tetue.net |
||||
-------------------------------------------------------------- */ |
||||
|
||||
dl.faq { border: 0; } |
||||
dl.faq dt, |
||||
dl.faq dd { padding: .4em; background: inherit; border: 0; } |
||||
dl.faq dt { position: relative; padding-right: 3em; background-color: #ddd; margin-bottom: .4em; } |
||||
dl.faq dd { margin-left: 1em; margin-bottom: 2em; padding-right: 1em; border-left: 1px solid #ddd; } |
||||
dl.faq.js dt { background-position: 0 0.6em; } |
Before Width: | Height: | Size: 200 B |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,9 @@
|
||||
<?php |
||||
|
||||
// Sécurité |
||||
if (!defined('_ECRIRE_INC_VERSION')) return; |
||||
|
||||
// Ajout des raccourcis dans la liste des wheels |
||||
$GLOBALS['spip_wheels']['raccourcis'][] = 'faq.yaml'; |
||||
|
||||
?> |
@ -1,24 +1,111 @@
|
||||
<?php |
||||
|
||||
function faq_css(){ |
||||
$css =""; |
||||
$css .= '<link rel="stylesheet" href="'.find_in_path('css/faq.css').'" type="text/css" media="all" />'; |
||||
return $css; |
||||
// Sécurité |
||||
if (!defined('_ECRIRE_INC_VERSION')) return; |
||||
|
||||
function faq_insert_head_css($flux){ |
||||
// On inclut systématiquement les CSS de base |
||||
$flux .= '<link rel="stylesheet" href="'.find_in_path('css/faq.css').'" type="text/css" media="all" />'; |
||||
|
||||
// On ajoute si la config le demande les CSS propres aux dl |
||||
include_spip('inc/config'); |
||||
$charger_css = lire_config('faq/charger_css') ? true : false; |
||||
if ($charger_css) |
||||
$flux .= '<link rel="stylesheet" href="'.find_in_path('css/faq_dl.css').'" type="text/css" media="all" />'; |
||||
return $flux; |
||||
} |
||||
|
||||
function faq_insert_head($flux) { |
||||
if (intval($GLOBALS['spip_version_branche'])<3){ |
||||
$flux .= faq_css(); |
||||
} |
||||
$flux .= '<script src="'.find_in_path('js/faq.js').'" type="text/javascript"></script>'; |
||||
function faq_insert_head($flux){ |
||||
include_spip('inc/config'); |
||||
$charger_js = lire_config('faq/charger_js') ? true : false; |
||||
if ($charger_js) |
||||
$flux .= '<script src="'.find_in_path('js/faq.js').'" type="text/javascript"></script>'; |
||||
return $flux; |
||||
} |
||||
|
||||
function faq_insert_head_css($flux) { |
||||
if (intval($GLOBALS['spip_version_branche'])>=3){ |
||||
$flux .= faq_css(); |
||||
function faq_porte_plume_barre_pre_charger($barres){ |
||||
// on ajoute les boutons dans la barre d'édition seulement |
||||
foreach (array('edition') as $nom) { |
||||
$barre = &$barres[$nom]; |
||||
$barre->ajouterPlusieursApres('grpCaracteres', array( |
||||
array( |
||||
"id" => "faq_sep", |
||||
"separator" => "---------------", |
||||
"display" => true, |
||||
), |
||||
array( |
||||
"id" => 'faq', |
||||
"name" => _T('faq:outil_inserer_faq'), |
||||
"className" => 'outil_faq', |
||||
"openBlockWith" => "<faq>\n", |
||||
"closeBlockWith" => "\n</faq>", |
||||
"replaceWith" => "function(h){ return outil_faq(h, '?', true);}", |
||||
"selectionType" => "line", |
||||
"display" => true, |
||||
"dropMenu" => array( |
||||
// bouton ? |
||||
array( |
||||
"id" => 'faq_question', |
||||
"name" => _T('faq:outil_inserer_question'), |
||||
"replaceWith" => "function(h){ return outil_faq(h, '?');}", |
||||
"className" => 'outil_faq_question', |
||||
"selectionType" => "line", |
||||
"forceMultiline" => true, |
||||
"display" => true, |
||||
), |
||||
array( |
||||
"id" => 'faq_titre', |
||||
"name" => _T('faq:outil_inserer_titre'), |
||||
"replaceWith" => "function(h){ return outil_faq(h, ':Nouveau titre');}", |
||||
"className" => 'outil_faq_titre', |
||||
"selectionType" => "line", |
||||
"forceMultiline" => true, |
||||
"display" => true, |
||||
), |
||||
) |
||||
) |
||||
)); |
||||
$barre->ajouterFonction("function outil_faq(h, c,recursif) { |
||||
if(recursif){ |
||||
// Cas de la sélection de click sur le bouton de création de faq complète |
||||
s = h.selection; |
||||
lines = h.selection.split(/\\r?\\n/); |
||||
var lines_final = []; |
||||
for (j = 0, n = lines.length, i = 0; i < n; i++) { |
||||
// si une seule ligne, on se fiche de savoir qu'elle est vide, |
||||
// c'est volontaire si on clique le bouton |
||||
if (n == 1 || $.trim(lines[i]) !== '') { |
||||
if(r = lines[i].match(/^([+-o]) (.*)$/)){ |
||||
r[1] = r[1].replace(/[+-o]/g, c); |
||||
lines_final[j] = r[1]+' '+r[2]; |
||||
j++; |
||||
} else { |
||||
lines_final[j] = c + ' '+lines[i]; |
||||
j++; |
||||
} |
||||
} |
||||
} |
||||
return lines_final.join('\\n'); |
||||
} |
||||
// Click sur les autres boutons |
||||
if ((s = h.selection) && (r = s.match(/^([+-o]) (.*)$/))){ |
||||
r[1] = r[1].replace(/[+-o]/g, c); |
||||
s = r[1]+' '+r[2]; |
||||
} else { |
||||
s = c + ' '+s; |
||||
} |
||||
return s; |
||||
}"); |
||||
} |
||||
return $flux; |
||||
return $barres; |
||||
} |
||||
|
||||
function faq_porte_plume_lien_classe_vers_icone($flux){ |
||||
return array_merge($flux, array( |
||||
'outil_faq'=>'faq-16.png', |
||||
'outil_faq_question'=>'faq_question-16.png', |
||||
'outil_faq_titre'=>'faq_titre-16.png' |
||||
)); |
||||
} |
||||
|
||||
?> |
@ -0,0 +1,103 @@
|
||||
<div class="formulaire_spip formulaire_configurer formulaire_#FORM"> |
||||
<img src="#CHEMIN_IMAGE{faq-24.png}" class="cadre-icone" /> |
||||
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV**{message_ok})</p>] |
||||
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>] |
||||
|
||||
<BOUCLE_editable(CONDITION) {si #ENV{editable}}> |
||||
<form method="post" action="#ENV{action}" enctype="multipart/form-data"><div> |
||||
[(#REM) <!--declarer les hidden qui declencheront le service du formulaire parametre : url d'action -->] |
||||
#ACTION_FORMULAIRE{#ENV{action}} |
||||
|
||||
<h2 class="titrem"><:faq:titre_form_configurer:></h2> |
||||
<p><:faq:info_config_faq:></p> |
||||
|
||||
<ul> |
||||
<li class="fieldset"> |
||||
<fieldset> |
||||
<h3 class="legend"><:faq:legende_ancre_lien:></h3> |
||||
<ul> |
||||
#SET{name,ancrer_question}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} |
||||
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]"> |
||||
[<span class='erreur_message'>(#GET{erreurs})</span>] |
||||
#SET{val,1} |
||||
<div class="choix"> |
||||
<input type="checkbox" class="checkbox" name="#GET{name}" id="#GET{name}_#GET{val}" value="#GET{val}"[ (#GET{val}|=={#ENV{#GET{name}}}|oui)checked="checked"] /> |
||||
<label for="#GET{name}_#GET{val}"><:faq:label_ancrer_question:></label> |
||||
</div> |
||||
</li> |
||||
#SET{name,lier_faq}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} |
||||
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]"> |
||||
[<span class='erreur_message'>(#GET{erreurs})</span>] |
||||
#SET{val,1} |
||||
<div class="choix"> |
||||
<input type="checkbox" class="checkbox" name="#GET{name}" id="#GET{name}_#GET{val}" value="#GET{val}"[ (#GET{val}|=={#ENV{#GET{name}}}|oui)checked="checked"] /> |
||||
<label for="#GET{name}_#GET{val}"><:faq:label_lier_faq:></label> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</fieldset> |
||||
</li> |
||||
|
||||
<li class="fieldset"> |
||||
<fieldset> |
||||
<h3 class="legend"><:faq:legende_css:></h3> |
||||
<ul> |
||||
#SET{name,charger_css}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} |
||||
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]"> |
||||
[<span class='erreur_message'>(#GET{erreurs})</span>] |
||||
#SET{val,1} |
||||
<div class="choix"> |
||||
<input type="checkbox" class="checkbox" name="#GET{name}" id="#GET{name}_#GET{val}" value="#GET{val}"[ (#GET{val}|=={#ENV{#GET{name}}}|oui)checked="checked"] /> |
||||
<label for="#GET{name}_#GET{val}"><:faq:label_charger_css:></label> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</fieldset> |
||||
</li> |
||||
|
||||
<li class="fieldset"> |
||||
<fieldset> |
||||
<h3 class="legend"><:faq:legende_comportement:></h3> |
||||
<ul> |
||||
#SET{name,charger_js}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} |
||||
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]"> |
||||
[<span class='erreur_message'>(#GET{erreurs})</span>] |
||||
#SET{val,1} |
||||
<div class="choix"> |
||||
<input type="checkbox" class="checkbox" name="#GET{name}" id="#GET{name}_#GET{val}" value="#GET{val}"[ (#GET{val}|=={#ENV{#GET{name}}}|oui)checked="checked"] /> |
||||
<label for="#GET{name}_#GET{val}"><:faq:label_charger_js:></label> |
||||
</div> |
||||
</li> |
||||
#SET{name,iconifier_js}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} |
||||
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]" id="iconifier_js"> |
||||
[<span class='erreur_message'>(#GET{erreurs})</span>] |
||||
#SET{val,1} |
||||
<div class="choix"> |
||||
<input type="checkbox" class="checkbox" name="#GET{name}" id="#GET{name}_#GET{val}" value="#GET{val}"[ (#GET{val}|=={#ENV{#GET{name}}}|oui)checked="checked"] /> |
||||
<label for="#GET{name}_#GET{val}"><:faq:label_iconifier_js:></label> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</fieldset> |
||||
</li> |
||||
</ul> |
||||
|
||||
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ] |
||||
<!--extra--> |
||||
<p class="boutons"><input type='submit' class='submit' value='<:bouton_enregistrer:>' /></p> |
||||
</div></form> |
||||
</BOUCLE_editable> |
||||
</div> |
||||
|
||||
<script type="text/javascript"> |
||||
function toggle_charger_js(){ |
||||
if (jQuery('#charger_js_1').prop('checked')) |
||||
jQuery('li.editer_iconifier_js').show(); |
||||
else |
||||
jQuery('li.editer_iconifier_js').hide(); |
||||
} |
||||
jQuery(document).ready(function(){ |
||||
jQuery('#charger_js_1').bind('change',toggle_charger_js); |
||||
toggle_charger_js(); |
||||
}); |
||||
</script> |
Before Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.0 KiB |
@ -1,6 +0,0 @@
|
||||
[(#REM) |
||||
|
||||
RUSTINE DE COMPATIBILITE |
||||
Ne plus utiliser ce fichier ! |
||||
|
||||
]<INCLURE{fond=inclure/rubrique-faq,id_rubrique,env}> |
@ -0,0 +1,28 @@
|
||||
<?php |
||||
|
||||
if (!defined("_ECRIRE_INC_VERSION")) return; |
||||
|
||||
|
||||
/** |
||||
* Transforme la chaine représentant le nom du tag en un lien vers la page du mot-clé |
||||
* le cas échéans ou renvoie la chaine fournie en entrée. |
||||
* |
||||
* @param string $valeur |
||||
* Le nom du tag qui peut coincinder avec le titre d'un mot-clé |
||||
* |
||||
* @return string |
||||
* La valeur formatée en lien vers le mot-clé ou la valeur d'entrée sinon. |
||||
*/ |
||||
function inc_faq_formater_tag_dist($valeur) { |
||||
$tag = $valeur; |
||||
|
||||
if ($id = sql_getfetsel('id_mot', 'spip_mots', 'titre='. sql_quote($tag))) { |
||||
include_spip('inc/utils'); |
||||
$url = generer_url_entite($id, 'mots'); |
||||
$tag = '<a href="' . $url . '" class="spip_in">' . $valeur . '</a>'; |
||||
} |
||||
|
||||
return $tag; |
||||
} |
||||
|
||||
?> |
@ -0,0 +1,25 @@
|
||||
<B_faq> |
||||
[<h3 class="spip"> |
||||
[<a class="ancre" href="##ENV{ancre}" name="(#ENV{ancre})" id="#ENV{ancre}"></a>] |
||||
(#ENV{titre}) |
||||
</h3>] |
||||
<dl class="faq[ (#CONFIG{faq/charger_js}|et{#CONFIG{faq/iconifier_js}}|oui)js]"> |
||||
<BOUCLE_faq(DATA){source table, #ENV{faq}}{par cle}> |
||||
[(#CONFIG{faq/ancrer_question}|oui) |
||||
[<a class="ancre" href="##ENV{ancre}_#CLE" name="(#ENV{ancre})_#CLE" id="#ENV{ancre}_#CLE"></a>]] |
||||
<dt> |
||||
[(#VALEUR|table_valeur{question})] |
||||
</dt> |
||||
<dd> |
||||
<BOUCLE_tags(DATA){source table, #VALEUR|table_valeur{tags}}{par valeur}> |
||||
[(#COMPTEUR_BOUCLE|=={1}|oui)<ul class="liste-tags">] |
||||
<li class="tag">#VALEUR</li> |
||||
[(#COMPTEUR_BOUCLE|=={#TOTAL_BOUCLE}|oui)</ul>] |
||||
</BOUCLE_tags> |
||||
[(#VALEUR|table_valeur{reponse})] |
||||
[(#CONFIG{faq/lier_faq}|oui) |
||||
[<a class="retour" rel="nofollow" href="#(#ENV{ancre})"><:faq:lien_debut_faq:></a>]] |
||||
</dd> |
||||
</BOUCLE_faq> |
||||
</dl> |
||||
</B_faq> |
@ -1,8 +0,0 @@
|
||||
<B_faq> |
||||
<dl class="faq"> |
||||
<BOUCLE_faq(ARTICLES){id_rubrique}{par num titre}{par date}> |
||||
<dt id="dt#COMPTEUR_BOUCLE">#TITRE</dt> |
||||
<dd>#TEXTE</dd> |
||||
</BOUCLE_faq> |
||||
</dl> |
||||
</B_faq> |
@ -0,0 +1,30 @@
|
||||
<?php |
||||
// This is a SPIP language file -- Ceci est un fichier langue de SPIP |
||||
if (!defined('_ECRIRE_INC_VERSION')) return; |
||||
|
||||
$GLOBALS[$GLOBALS['idx_lang']] = array( |
||||
// I |
||||
'info_config_faq' => 'Cette configuration s\'applique aux squelettes d\'affichage des FAQ proposés par le plugin, et plus particulièrement aux listes de définitions. Si vous souhaitez définir vos propres affichages pensez à tenir compte de ces paramètres.' , |
||||
|
||||
// L |
||||
'label_charger_css' => 'Utiliser les styles proposés par défaut par le plugin pour les listes de définitions', |
||||
'label_charger_js' => 'Utiliser la fonction permettant de plier et déplier les listes de définitions', |
||||
'label_iconifier_js' => 'Ajouter des puces en début de chaque question pour matérialiser la fonction de pliage/dépliage', |
||||
'label_ancrer_question' => 'Attacher une ancre à chaque question', |
||||
'label_lier_faq' => 'Insérer un lien vers le début de la FAQ en fin de chaque réponse', |
||||
'legende_ancre_lien' => 'Ancres, liens et tables des matières', |
||||
'legende_comportement' => 'Comportement dynamique', |
||||
'legende_css' => 'Styles', |
||||
'lien_debut_faq' => 'Retour au début de la FAQ', |
||||
|
||||
// O |
||||
'outil_inserer_faq' => 'Insérer une nouvelle FAQ', |
||||
'outil_inserer_question' => 'Insérer une nouvelle question', |
||||
'outil_inserer_titre' => 'Insérer un titre pour la FAQ', |
||||
|
||||
// T |
||||
'titre_page_configurer' => 'Configurer le plugin Questions-Réponses', |
||||
'titre_form_configurer' => 'Affichages des FAQ', |
||||
); |
||||
|
||||
?> |
@ -0,0 +1,16 @@
|
||||
<?php |
||||
// This is a SPIP language file -- Ceci est un fichier langue de SPIP |
||||
if (!defined('_ECRIRE_INC_VERSION')) return; |
||||
|
||||
$GLOBALS[$GLOBALS['idx_lang']] = array( |
||||
|
||||
// T |
||||
'faq_description' => 'Ajoute de nouveaux raccourcis typographiques permettant de décrire de manière simple des <abbr title="Foire Aux Questions">FAQ</abbr> dans un contenu SPIP. |
||||
|
||||
Les raccourcis doivent être utilisés à l\'intérieur du sélecteur «<code>faq</code>». Une configuration permet d\'ajouter des ancres, de rendre la FAQ dépliable, de charger des styles par défaut... |
||||
La structure HTML produite est, par défaut, basée sur une liste de définitions.', |
||||
'faq_nom' => 'FAQ', |
||||
'faq_slogan' => 'Créer simplement une FAQ' |
||||
); |
||||
|
||||
?> |
@ -0,0 +1,26 @@
|
||||
<paquet |
||||
prefix="faq" |
||||
categorie="edition" |
||||
version="3.0.0" |
||||
etat="test" |
||||
compatibilite="[3.0.0;3.0.*]" |
||||
logo="faq_logo-128.png" |
||||
documentation="http://www.spip-contrib.net/?rubrique891" |
||||
> |
||||
|
||||
<nom>Définitions et FAQ</nom> |
||||
<!-- Créer simplement une FAQ --> |
||||
|
||||
<auteur lien="http://romy.tetue.net">romy.tetue.net</auteur> |
||||
<auteur lien="http://blog.smellup.net">Eric Lupinacci</auteur> |
||||
|
||||
<licence lien="http://www.gnu.org/licenses/gpl-3.0.html">GPL 3</licence> |
||||
<copyright>2009-2013</copyright> |
||||
|
||||
<necessite nom="tw" compatibilite="[0.3.1;[" /> |
||||
|
||||
<pipeline nom="insert_head_css" inclure="faq_pipelines.php" /> |
||||
<pipeline nom="insert_head" inclure="faq_pipelines.php" /> |
||||
<pipeline nom="porte_plume_lien_classe_vers_icone" inclure="faq_pipelines.php" /> |
||||
<pipeline nom="porte_plume_barre_pre_charger" inclure="faq_pipelines.php" /> |
||||
</paquet> |
@ -1,21 +0,0 @@
|
||||
<plugin> |
||||
<nom>Définitions et FAQ</nom> |
||||
<icon>icon/faq-32.png</icon> |
||||
<prefix>faq</prefix> |
||||
|
||||
<version>2.1.21</version> |
||||
<etat>dev</etat> |
||||
<categorie>navigation</categorie> |
||||
|
||||
<slogan>FAQ dépliable</slogan> |
||||
<description>Transformez les listes de définitions marquées du sélecteur «<code>faq</code>» en <abbr title="Foire Aux Questions">FAQ</abbr> dépliable.</description> |
||||
<lien>http://www.spip-contrib.net/?rubrique891</lien> |
||||
<auteur>[romy.tetue.net->http://romy.tetue.net]</auteur> |
||||
<licence>GPL 2009</licence> |
||||
|
||||
<pipeline> |
||||
<nom>insert_head</nom> |
||||
<inclure>faq_pipelines.php</inclure> |
||||
</pipeline> |
||||
<necessite id="SPIP" version="[2.0.0;3.0.99]" /> |
||||
</plugin> |
@ -0,0 +1,6 @@
|
||||
[(#AUTORISER{configurer}|sinon_interdire_acces)] |
||||
<h1 class='grostitre'><:faq:titre_page_configurer:></h1> |
||||
|
||||
<div class="ajax"> |
||||
#FORMULAIRE_CONFIGURER_FAQ |
||||
</div> |
After Width: | Height: | Size: 4.5 KiB |
@ -0,0 +1,189 @@
|
||||
<?php |
||||
|
||||
// Regexp permettant de récupérer chacune des informations additionnelles qui peuvent compléter le titre de la tâche : |
||||
// - #tag, tag étant un mot. Exemple : #courses ou #перевод-шаблон |
||||
// - type:valeur ou type et valeur sont des mots. Pas utilisé pour l'instant |
||||
if (!defined('_FAQ_REGEXP_INFOS_COMPLEMENTAIRES')) |
||||
define('_FAQ_REGEXP_INFOS_COMPLEMENTAIRES', '%([\w-]+:|#)([\w.-]+)(?:\s|$)%Uu'); |
||||
|
||||
|
||||
/** |
||||
* Analyse du contenu d'un bloc FAQ inclu entre les marqueurs de début (<faq>) et de fin (</faq>) |
||||
* puis appelle du squelette avec les paramètres calculés. |
||||
* |
||||
* Un bloc de FAQ peut contenir plusieurs sous-FAQ qui sont séparées par un titre. Un titre commence sur |
||||
* une nouvelle ligne avec comme premier caractère ':'. |
||||
* Une question commence sur une nouvelle ligne avec comme premier caractère '?'. La réponse est constituée des lignes |
||||
* qui suivent la question jusqu'à la prochaine question, le prochain titre ou la fin du bloc. |
||||
* Il est possible de choisir le squelette de sortie en utilisant l'attribut format dans la balise <code><faq></code>. |
||||
* |
||||
* @param array $t l'index 4 représente le contenu du bloc, l'index 3 la valeur du format si il existe. |
||||
* @return string le html généré à partir d'un squelette |
||||
*/ |
||||
function tw_faq($t) { |
||||
// Numéro d'appel de la fonction tw_faq dans le hit. |
||||
// -- sert à calculer une ancre unique pour la faq ou sous-faq sans nécessiter d'id ou de titre. |
||||
static $no_bloc = 0; |
||||
|
||||
// Initialisation du html calculé |
||||
$html = $t; |
||||
|
||||
// Extraction de lignes du texte |
||||
// La wheel renvoie un tableau à cette callback qui est le résultat d'un preg_match_all. |
||||
// Le contenu du tableau est le suivant : |
||||
// - index 0 : la capture du pattern complet |
||||
// - index 1 : la capture de l'attribut format si il existe |
||||
// - index 2 : la capture des quotes entourant la valeur de l'attribut format |
||||
// - index 3 : la capture de la valeur de l'attribution format |
||||
// - index 4 : la capture du texte compris entre les balises <faq> et </faq> |
||||
// --> Seuls les index 3 et 4 sont utilisés. |
||||
$lignes = explode("\n", trim($t[4])); |
||||
|
||||
// Initialisation des variables propres à l'ensemble des faqs du bloc |
||||
$faqs = array(); |
||||
$index_faq = 0; |
||||
$index_qr = 0; |
||||
$index_ligne = 0; |
||||
$question_en_cours = false; |
||||
|
||||
// Analyse de chaque ligne du bloc |
||||
while ($index_ligne <= count($lignes)){ |
||||
// Initialisation des variables de la faq en cours |
||||
// (pour un bloc faq contenant plusieurs faq séparées par des titres) |
||||
if (($index_qr == 0) AND !$question_en_cours) { |
||||
$types_info[$index_faq] = array(); |
||||
} |
||||
|
||||
// On vérifie qu'on a atteint la fin du bloc de texte compris entre <faq> et </faq>. |
||||
// -- si c'est le cas, on ajoute la question-reponse en cours si elle existe |
||||
// -- sinon, on traite la nouvelle ligne |
||||
if ($index_ligne == count($lignes)) { |
||||
if ($question_en_cours) { |
||||
$faqs[$index_faq][$index_qr] = array( |
||||
'question' => $question, |
||||
'reponse' => trim($reponse), |
||||
'tags' => $tags, |
||||
'infos' => $infos, |
||||
); |
||||
$question_en_cours = false; |
||||
} |
||||
} |
||||
else { |
||||
// Extraction de la nouvelle ligne à traiter |
||||
$texte = trim($lignes[$index_ligne]); |
||||
|
||||
if ($texte) { |
||||
// Extraction du premier caractère de la ligne qui détermine soit : |
||||
// - l'indicateur du titre de la question, |
||||
// - l'indicateur d'un titre pour la faq, |
||||
// - et sinon la réponse comme un descriptif libre de la question précédente. |
||||
// Le caractère de question '?' est traité par SPIP et précédés |
||||
// d'un ' ' parfois à cause de la typographie et il faut donc au préalable le supprimer. |
||||
if (strpos($texte, ' ') === 0) { |
||||
$texte = substr($texte, 6, strlen($texte)-6); |
||||
} |
||||
$premier = substr($texte, 0, 1); |
||||
|
||||
if (($premier != '?') |
||||
AND ($premier != ':')) { |
||||
// La ligne correspond à un texte de réponse non vide si une question est en cours |
||||
if ($question_en_cours) |
||||
$reponse .= $reponse ? "\n" . $texte : $texte; |
||||
} |
||||
else { |
||||
// Il faut tester si une question est en cours. Si c'est le cas il faut clore la question en cours |
||||
// avant de commencer la nouvelle question ('?') ou la nouvelle faq par son titre (':'). |
||||
if ($question_en_cours) { |
||||
$faqs[$index_faq][$index_qr] = array( |
||||
'question' => $question, |
||||
'reponse' => trim($reponse), |
||||
'tags' => $tags, |
||||
'infos' => $infos, |
||||
); |
||||
$question_en_cours = false; |
||||
$index_qr += 1; |
||||
} |
||||
|
||||
if ($premier == '?') { |
||||
// On démarre une nouvelle question |
||||
// -- initialisation des variables de la question en cours |
||||
$tags = $infos = array(); |
||||
$question_en_cours = true; |
||||
$reponse = ''; |
||||
$texte = trim(substr($texte, 1, strlen($texte)-1)); |
||||
|
||||
// -- le texte de la question, que l'on sépare du reste des informations complémentaires éventuelles |
||||
if (preg_match_all(_FAQ_REGEXP_INFOS_COMPLEMENTAIRES, $texte, $infos_complementaires)) { |
||||
// Extraction du titre |
||||
$question = trim(str_replace($infos_complementaires[0], '', $texte)); |
||||
|
||||
// Extraction des informations complémentaires |
||||
foreach($infos_complementaires[1] as $_cle => $_prefixe) { |
||||
$type = rtrim($_prefixe, ':'); |
||||
$valeur = $infos_complementaires[2][$_cle]; |
||||
if ($type == '#') { |
||||
// -- les étiquettes |
||||
if ($formater = charger_fonction("faq_formater_tag", 'inc', true)) |
||||
$tags[] = $formater($valeur); |
||||
else |
||||
$tags[] = $valeur; |
||||
} |
||||
else { |
||||
// -- les informations typées |
||||
if ($formater = charger_fonction("faq_formater_${type}", 'inc', true)) { |
||||
$infos[$type] = $formater($valeur); |
||||
} |
||||
else |
||||
$infos[$type] = $valeur; |
||||
if (!in_array($type, $types_info[$index_faq])) |
||||
$types_info[$index_faq][] = $type; |
||||
} |
||||
} |
||||
} |
||||
else |
||||
$question = $texte; |
||||
} |
||||
elseif ($premier == ':') { |
||||
// Titre d'une nouvelle faq incluse dans le bloc faq en cours de traitement |
||||
$index_faq += 1; |
||||
$titres[$index_faq] = trim(substr($texte, 1, strlen($texte)-1)); |
||||
$index_qr = 0; |
||||
} |
||||
} |
||||
} |
||||
elseif ($question_en_cours) { |
||||
// Ligne vide. Comme elle est incluse dans le texte de la réponse on la conserve |
||||
$reponse .= $reponse ? "\n" . $texte : $texte; |
||||
} |
||||
} |
||||
|
||||
$index_ligne++; |
||||
} |
||||
|
||||
// Appel pour chaque FAQ du modèle demandé ou par défaut |
||||
if ($faqs) { |
||||
$html = ''; |
||||
$format = $t[3] ? $t[3] : 'dl'; |
||||
foreach($faqs as $_cle => $_faq) { |
||||
if ($_faq) { |
||||
$html .= recuperer_fond( |
||||
"inclure/faq_${format}", |
||||
array( |
||||
'titre' => (isset($titres[$_cle]) ? $titres[$_cle] : ''), |
||||
'ancre' => "faq_${no_bloc}_${_cle}", |
||||
'faq' => $_faq, |
||||
'types_info' => $types_info[$_cle] |
||||
), |
||||
array( |
||||
'ajax' => true |
||||
) |
||||
); |
||||
} |
||||
} |
||||
$no_bloc++; |
||||
} |
||||
|
||||
return $html; |
||||
} |
||||
|
||||
?> |