Skip to content
Extraits de code Groupes Projets
texte.php 44,6 ko
Newer Older
// traite les modeles (dans la fonction typo), en remplacant
// le raccourci <modeleN|parametres> par la page calculee a
// partir du squelette modeles/modele.html
// Le nom du modele doit faire au moins trois caracteres (evite <h2>)
// Si $doublons==true, on repere les documents sans calculer les modeles
Fil's avatar
Fil a validé
// mais on renvoie les params (pour l'indexation par le moteur de recherche)
// http://doc.spip.org/@traiter_modeles

define('_RACCOURCI_MODELE', 
	 '(<([a-z_-]{3,})' # <modele
	.'\s*([0-9]*)\s*' # id
	.'([|](?:<[^<>]*>|[^>])*?)?' # |arguments (y compris des tags <...>)
	.'\s*/?'.'>)' # fin du modele >
define('_RACCOURCI_MODELE_DEBUT', '@^' . _RACCOURCI_MODELE .'@is');
Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_modeles
function traiter_modeles($texte, $doublons=false, $echap='', $connect='') {
	// detecter les modeles (rapide)
	if (preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS',
	$texte, $matches, PREG_SET_ORDER)) {
		include_spip('public/assembler');
		foreach ($matches as $match) {
			// Recuperer l'appel complet (y compris un eventuel lien)
			// $regs : 1 => modele, 2 => type, 3 => id, 4 => params, 5 => a
			preg_match(_RACCOURCI_MODELE_DEBUT, substr($texte, $a), $regs);
			',<a\s[^<>]*>\s*$,i', substr($texte, 0, $a), $r)) {
				$lien = array(
					extraire_attribut($r[0],'href'),
					extraire_attribut($r[0],'class')
				);
				$a -= strlen($r[0]);
				$cherche = $r[0].$regs[0];
			} else {
				$lien = false;
				$cherche = $regs[1];
			}
Fil's avatar
Fil a validé
			# hack articles_edit, breves_edit, indexation
			if ($doublons)
				$texte .= preg_replace(',[|][^|=]*,s',' ',$regs[4]);
			# version normale
			else {
				$modele = inclure_modele($regs[2], $regs[3], $regs[4], $lien, $connect);
Fil's avatar
Fil a validé

				// le remplacer dans le texte
				if ($modele !== false) {
					$modele = protege_js_modeles($modele);
					$rempl = code_echappement($modele, $echap);
Fil's avatar
Fil a validé
					$texte = substr($texte, 0, $a)
						. $rempl
						. substr($texte, $a+strlen($cherche));
				}
			if (((!_DIR_RESTREINT) OR ($doublons)) AND ($regs[3]) AND (in_array($regs[2],array('doc','emb','img'))))
				$GLOBALS['doublons_documents_inclus'][] = $regs[3];

//
// Une fonction pour fermer les paragraphes ; on essaie de preserver
// des paragraphes indiques a la main dans le texte
// (par ex: on ne modifie pas un <p align='center'>)
//
// deuxieme argument : forcer les <p> meme pour un seul paragraphe
//
// http://doc.spip.org/@paragrapher
function paragrapher($letexte, $forcer=true) {
	global $class_spip;

	$letexte = trim($letexte);
	if (!strlen($letexte))
		return '';
	if ($forcer OR (
	strstr($letexte,'<') AND preg_match(',<p\b,iS',$letexte)
	)) {

		// Ajouter un espace aux <p> et un "STOP P"
		// transformer aussi les </p> existants en <p>, nettoyes ensuite
		$letexte = preg_replace(',</?p(\s([^>]*))?'.'>,iS', '<STOP P><p \2>',
			'<p>'.$letexte.'<STOP P>');

		// Fermer les paragraphes (y compris sur "STOP P")
		$letexte = preg_replace(
			',(<p\s.*)(</?(STOP P|'._BALISES_BLOCS.')[>[:space:]]),UimsS',
			"\n\\1</p>\n\\2", $letexte);

		// Supprimer les marqueurs "STOP P"
		$letexte = str_replace('<STOP P>', '', $letexte);

		// Reduire les blancs dans les <p>
		// Do not delete multibyte utf character just before </p> having last byte equal to whitespace  
		$u = ($GLOBALS['meta']['charset']=='utf-8' && test_pcre_unicode()) ? 'u':'S';
		$letexte = preg_replace(
		',(<p(>|\s[^>]*)>)\s*|\s*(</p[>[:space:]]),'.$u.'i', '\1\3',
			$letexte);

		// Supprimer les <p xx></p> vides
		$letexte = preg_replace(',<p\s[^>]*></p>\s*,iS', '',
		// Renommer les paragraphes normaux
Fil's avatar
Fil a validé
		$letexte = str_replace('<p >', "<p$class_spip>",
//
// Raccourcis ancre [#ancre<-]
//

define('_RACCOURCI_ANCRE', "|\[#?([^][]*)<-\]|S");

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_raccourci_ancre
function traiter_raccourci_ancre($letexte)
{
	if (preg_match_all(_RACCOURCI_ANCRE, $letexte, $m, PREG_SET_ORDER))
	foreach ($m as $regs)
		$letexte = str_replace($regs[0],
		'<a name="'.entites_html($regs[1]).'"></a>', $letexte);
	return $letexte;
}

//
// Raccourcis automatiques [?SPIP] vers un glossaire
//

define('_RACCOURCI_GLOSSAIRE', "|\[\?+\s*([^][<>]+)\]|S");

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_raccourci_glossaire
function traiter_raccourci_glossaire($letexte)
{
	static $glosateur = NULL, $subst = NULL;
	if ($glosateur === NULL) {
		$glosateur = tester_variable('url_glossaire_externe',
					 "http://@lang@.wikipedia.org/wiki/");
		$subst = strpos($glosateur,"%s") !== false;
	}

	if (empty($glosateur) 
	OR !preg_match_all(_RACCOURCI_GLOSSAIRE, $letexte, $m, PREG_SET_ORDER))
		return $letexte;

	$glosateur = str_replace("@lang@", $GLOBALS['spip_lang'], $glosateur);
	foreach ($m as $regs) {
		list($tout, $terme) = $regs;
		// Eviter les cas particulier genre "[?!?]"
		if (preg_match(',^(.*\w\S*)\s*$,', $terme, $r)) {
			$terme = $r[1];
			$_terme = preg_replace(',\s+,', '_', $terme);
// faire sauter l'eventuelle partie "|bulle d'aide" du lien
// cf. http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Conventions_sur_les_titres
			$_terme = preg_replace(',[|].*,', '', $_terme);
			if ($subst)
				$url = str_replace("%s", rawurlencode($_terme),	$glosateur);
			else $url = $glosateur. $_terme;
			list($terme, $bulle, $hlang) = traiter_raccourci_lien_atts($terme);
			$url = traiter_raccourci_lien_lang($url, 'spip_glossaire', $terme, $hlang, $bulle);
			$letexte = str_replace($tout, $url, $letexte);
		}
	}
	return $letexte;
}

//
// Raccourcis liens [xxx->url]
// Note : complique car c'est ici qu'on applique typo(),
// et en plus on veut pouvoir les passer en pipeline
//

// Regexp des raccouris, aussi utilisee pour la fusion de sauvegarde Spip
define('_RACCOURCI_LIEN', ",\[([^][]*)->(>?)([^]]*)\],msS");

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@expanser_liens
function expanser_liens($letexte, $connect='')
{
	$inserts = array();
	if (preg_match_all(_RACCOURCI_LIEN, $letexte, $matches, PREG_SET_ORDER)) {
		$i = 0;
		foreach ($matches as $regs) {
			$inserts[++$i] = traiter_raccourci_lien($regs, $connect);
			$letexte = str_replace($regs[0], "@@SPIP_ECHAPPE_LIEN_$i@@",
				$letexte);
		}
	}

	$letexte = corriger_typo(traiter_modeles($letexte, false, false, $connect));
	foreach ($inserts as $i => $insert) {
		$letexte = str_replace("@@SPIP_ECHAPPE_LIEN_$i@@", $insert, $letexte);
	}
	return $letexte;
}

//
// Inserer un lien a partir du preg_match du raccourci [xx->url]
// $regs:
// 0=>tout le raccourci
// 1=>texte (ou texte|hreflang ou texte|bulle ou texte|bulle{hreflang})
// 2=>double fleche (historiquement, liens ouvrants)
// 3=>url
// A terme, il faudrait tenir compte de $connect
// http://doc.spip.org/@traiter_raccourci_lien
function traiter_raccourci_lien($regs, $connect='') {
	list($texte, $bulle, $hlang) = traiter_raccourci_lien_atts($texte);
	list ($lien, $class, $texte, $lang) =
	  calculer_url($url, $texte, 'tout');
	return traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $bulle, $connect);
}
Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_raccourci_lien_lang
function traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $bulle, $connect='')
{		
	// Si l'objet n'est pas de la langue courante, on ajoute hreflang
	if (!$hlang AND $lang!=$GLOBALS['spip_lang'])
		$hlang = $lang;
	$lang = ($hlang ? ' hreflang="'.$hlang.'"' : '') . $bulle;

	# Penser au cas [<imgXX|right>->URL]
	# ceci s'execute heureusement avant les tableaux et leur "|".
	# Attention, le texte initial est deja echappe mais pas forcement
	# celui retourne par calculer_url.

	$texte = typo($texte, true, $connect);

	return "<a href=\"$lien\" class=\"$class\"$lang>$texte</a>";
}

// Repere dans la partie texte d'un raccourci [texte->...]
// la langue et la bulle eventuelles

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_raccourci_lien_atts
function traiter_raccourci_lien_atts($texte) {

	$bulle = $hlang = '';
	// title et hreflang donnes par le raccourci ?
	if (preg_match(',^(.*?)([|]([^<>]*?))?([{]([a-z_]+)[}])?$,', $texte, $m)) {
esj's avatar
esj a validé
		$n =count($m);
esj's avatar
esj a validé
		if ($n > 2) {
			$bulle = ' title="'.texte_backend($m[3]).'"';
esj's avatar
esj a validé
			// {hreflang} ?
			if ($n > 4) {
			// si c'est un code de langue connu, on met un hreflang
esj's avatar
esj a validé
				if (traduire_nom_langue($m[5]) <> $m[5]) {
					$hlang = $m[5];
				}
esj's avatar
esj a validé
				else {
					$m[1] .= $m[4];
				}
			
	// S'il n'y a pas de hreflang sous la forme {}, ce qui suit le |
	// est peut-etre une langue
			} else if (preg_match(',^[a-z_]+$,', $m[3])) {
			// si c'est un code de langue connu, on met un hreflang
			// mais on laisse le title (c'est arbitraire tout ca...)
esj's avatar
esj a validé
				if (traduire_nom_langue($m[3]) <> $m[3]) {
				  $hlang = $m[3];
				}
	return array($texte, $bulle, $hlang);
// Fonction pour les champs chapo commencant par =,  redirection qui peut etre:
// 1. un raccourci Spip habituel (premier If) [texte->TYPEnnn]
// 2. un ultra raccourci TYPEnnn voire nnn (article) (deuxieme If)
// 3. une URL std
// renvoie une tableau structure comme ci-dessus mais sans calcul d'URL
// (cf fusion de sauvegardes)

define('_RACCOURCI_CHAPO', ',^(\W*)(\W*)(\w*\d+([?#].*)?)$,');

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@chapo_redirige
function chapo_redirige($chapo, $url=false)
{
	if (!preg_match(_RACCOURCI_LIEN, $chapo, $m))
		if (!preg_match(_RACCOURCI_CHAPO, $chapo, $m))
			return $chapo;
	return !$url ? $m[3] : calculer_url($m[3]);
Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traiter_poesie
function traiter_poesie($letexte)
{
	if (preg_match_all(",<(poesie|poetry)>(.*)<\/(poesie|poetry)>,UimsS",
	$letexte, $regs, PREG_SET_ORDER)) {
		foreach ($regs as $reg) {
			$lecode = preg_replace(",\r\n?,S", "\n", $reg[2]);
			$lecode = preg_replace("/\n[\s]*\n/", "\n&nbsp;\n",$lecode);
			$lecode = "<blockquote class=\"spip_poesie\">\n<div>".preg_replace("/\n+/", "</div>\n<div>", trim($lecode))."</div>\n</blockquote>\n\n";
			$letexte = str_replace($reg[0], $lecode, $letexte);
		}
	}
	return $letexte;
}
// Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
// http://doc.spip.org/@traiter_raccourcis
function traiter_raccourcis($letexte) {
Yannick Patois's avatar
Yannick Patois a validé

Fil's avatar
Fil a validé
	// Appeler les fonctions de pre_traitement
	$letexte = pipeline('pre_propre', $letexte);
	$letexte = traiter_poesie($letexte);
	// Harmoniser les retours chariot
	$letexte = preg_replace(",\r\n?,S", "\n", $letexte);
	// Recuperer les paragraphes HTML
	$letexte = preg_replace(',<p\b,iS', "\n\n\\0", $letexte);
	$letexte = preg_replace(',</p\b,iS', "\\0\n\n", $letexte);
Yannick Patois's avatar
Yannick Patois a validé

	$letexte = traiter_raccourci_glossaire($letexte);
	$letexte = traiter_raccourci_ancre($letexte);

	list($letexte, $mes_notes) = traite_raccourci_notes($letexte);

	// A present on introduit des attributs class_spip*
	// Init de leur valeur et connexes au premier appel
	if (!$remplace) $remplace = traiter_variables_sales();

Yannick Patois's avatar
Yannick Patois a validé
	//
Yannick Patois's avatar
Yannick Patois a validé
	//

	// ne pas oublier les tableaux au debut ou a la fin du texte
	$letexte = preg_replace(",^\n?[|],S", "\n\n|", $letexte);
	$letexte = preg_replace(",\n\n+[|],S", "\n\n\n\n|", $letexte);
	$letexte = preg_replace(",[|](\n\n+|\n?$),S", "|\n\n\n\n", $letexte);

	if (preg_match_all(',[^|](\n[|].*[|]\n)[^|],UmsS', $letexte,
	$regs, PREG_SET_ORDER))
	foreach ($regs as $tab) {
		$letexte = str_replace($tab[1], traiter_tableau($tab[1]), $letexte);
	}

	$letexte = "\n".trim($letexte);

	// les listes
	if (strpos($letexte,"\n-*")!==false OR strpos($letexte,"\n-#")!==false)
		$letexte = traiter_listes($letexte);

	// Proteger les caracteres actifs a l'interieur des tags html
	$protege = "{}_-";
	$illegal = "\x1\x2\x3\x4";
	if (preg_match_all(",</?[a-z!][^<>]*[".preg_quote($protege)."][^<>]*>,imsS",
	$letexte, $regs, PREG_SET_ORDER)) {
		foreach ($regs as $reg) {
			$insert = $reg[0];
			// hack: on transforme les caracteres a proteger en les remplacant
			// par des caracteres "illegaux". (cf corriger_caracteres())
			$insert = strtr($insert, $protege, $illegal);
			$letexte = str_replace($reg[0], $insert, $letexte);
		}
	}

	// autres raccourcis
	$puce = (strpos($letexte, "\n- ") == false) ? '' : definir_puce();
	$puce_rac = array("/\n-- */S", "/\n- */S");
	$puce_long = array("\n<br />&mdash;&nbsp;", "\n<br />$puce&nbsp;");

	$letexte = preg_replace($puce_rac, $puce_long, $letexte);
	$letexte = preg_replace($remplace[0], $remplace[1], $letexte);
	$letexte = preg_replace("@^ <br />@S", "", $letexte);

	// Retablir les caracteres proteges
	$letexte = strtr($letexte, $illegal, $protege);

	// Fermer les paragraphes ; mais ne pas en creer si un seul
	$letexte = paragrapher($letexte, $GLOBALS['toujours_paragrapher']);

	// Appeler les fonctions de post-traitement
	$letexte = pipeline('post_propre', $letexte);

	if ($mes_notes) traiter_les_notes($mes_notes);

	return $letexte;
}

//
// Notes de bas de page
//

Christian Lefebvre's avatar
Christian Lefebvre a validé
// http://doc.spip.org/@traite_raccourci_notes
function traite_raccourci_notes($letexte)
{
	global $compt_note,  $marqueur_notes, $les_notes;
	global $ouvre_ref, $ferme_ref, $ouvre_note, $ferme_note; #static ok
	static $notes_vues = NULL;

	if ($notes_vues === NULL) {
		$ouvre_ref = tester_variable('ouvre_ref', '&nbsp;[');
		$ferme_ref = tester_variable('ferme_ref', ']');
		$ouvre_note = tester_variable('ouvre_note', '[');
		$ferme_note = tester_variable('ferme_note', '] ');
		$les_notes = tester_variable('les_notes', '');
		$compt_note = tester_variable('compt_note', 0);
		$notes_vues === array();
	}

	$regexp = ', *\[\[(.*?)\]\],msS';
	if (preg_match_all($regexp, $letexte, $matches, PREG_SET_ORDER))
	foreach ($matches as $regs) {
		$note_source = $regs[0];
Yannick Patois's avatar
Yannick Patois a validé
		$note_texte = $regs[1];
		$num_note = false;
Fil's avatar
Fil a validé

		// note auto ou pas ?
		if (preg_match(",^<([^>'\"]*)>,", ltrim($note_texte), $r)
		AND strpos($note_texte, '</' . $r[1] .'>') === false) {
			$note_texte = substr_replace(ltrim($note_texte), '', 0, strlen($r[0]));
Fil's avatar
Fil a validé
		} else {
Yannick Patois's avatar
Yannick Patois a validé
			$compt_note++;
			$num_note = $compt_note;
Yannick Patois's avatar
Yannick Patois a validé
		}
Fil's avatar
Fil a validé

		// preparer la note
			if ($marqueur_notes) // quand il y a plusieurs series
								 // de notes sur une meme page
			$ancre = $mn.rawurlencode($num_note);
			// ne mettre qu'une ancre par appel de note (XHTML)
			if (!$notes_vues[$ancre]++)
				$name_id = " name=\"nh$ancre\" id=\"nh$ancre\"";
			else
				$name_id = "";

			$lien = "<a href=\"#nb$ancre\"$name_id class=\"spip_note\" rel=\"footnote\">";
			// creer le popup 'title' sur l'appel de note
			if ($title = supprimer_tags(propre($note_texte))) {
Fil's avatar
 
Fil a validé
				$title = $ouvre_note.$num_note.$ferme_note.$title;
				$title = couper($title,80);
				$lien = inserer_attribut($lien, 'title', $title);
			$insert = "$ouvre_ref$lien$num_note</a>$ferme_ref";

			// on l'echappe
			$insert = code_echappement($insert);
			$appel = "$ouvre_note<a href=\"#nh$ancre\" name=\"nb$ancre\" class=\"spip_note\" title=\"" . _T('info_notes') . " $ancre\" rev=\"footnote\">$num_note</a>$ferme_note";
Yannick Patois's avatar
Yannick Patois a validé
		} else {
			$insert = '';
Fil's avatar
Fil a validé
			$appel = '';
Yannick Patois's avatar
Yannick Patois a validé
		}
		// l'ajouter "tel quel" (echappe) dans les notes
Fil's avatar
Fil a validé
		if ($note_texte) {
			if ($mes_notes)
				$mes_notes .= "\n\n";
			$mes_notes .= code_echappement($appel) . $note_texte;
Fil's avatar
Fil a validé
		}

		// dans le texte, mettre l'appel de note a la place de la note
		$pos = strpos($letexte, $note_source);
		$letexte = substr($letexte, 0, $pos) . $insert
			.  substr($letexte, $pos + strlen($note_source));
	return array($letexte, $mes_notes);
// http://doc.spip.org/@traiter_les_notes
function traiter_les_notes($mes_notes) {
	$mes_notes = propre('<p>'.$mes_notes);

	if ($GLOBALS['class_spip'])
		$mes_notes = str_replace('<p class="spip">', '<p class="spip_note">', $mes_notes);

	$GLOBALS['les_notes'] .= $mes_notes;
Yannick Patois's avatar
Yannick Patois a validé

// Filtre a appliquer aux champs du type #TEXTE*
// http://doc.spip.org/@propre
function propre($t, $connect='') {
	return !$t ? '' :
		echappe_retour_modeles(
			traiter_raccourcis(
				expanser_liens(echappe_html($t),$connect)));
Yannick Patois's avatar
Yannick Patois a validé
}
?>