Newer
Older
<?php
/***************************************************************************\
* SPIP, Système de publication pour l'internet *
* Copyright © avec tendresse depuis 2001 *
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James *
* Ce programme est un logiciel libre distribué sous licence GNU/GPL. *
\***************************************************************************/
/**
* Utilitaires indispensables autour du serveur Http.
*
* @package SPIP\Core\Utilitaires
cerdic
a validé
**/
cerdic
a validé
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
* Cherche une fonction surchargeable et en retourne le nom exact,
* après avoir chargé le fichier la contenant si nécessaire.
* Charge un fichier (suivant les chemins connus) et retourne si elle existe
* le nom de la fonction homonyme `$dir_$nom`, ou suffixé `$dir_$nom_dist`
* Peut être appelé plusieurs fois, donc optimisé.
* @api
* @uses include_spip() Pour charger le fichier
* @example
* ```
* $envoyer_mail = charger_fonction('envoyer_mail', 'inc');
* $envoyer_mail($email, $sujet, $texte);
* ```
* Nom de la fonction (et du fichier)
* Nom du dossier conteneur
* true pour ne pas râler si la fonction n'est pas trouvée
* Nom de la fonction, ou false.
gilles.vincent
a validé
function charger_fonction($nom, $dossier = 'exec', $continue = false) {
if (strlen($dossier) && !str_ends_with($dossier, '/')) {
cerdic
a validé
$dossier .= '/';
}
$f = str_replace('/', '_', $dossier) . $nom;
cerdic
a validé
if (function_exists($f)) {
return $f;
cerdic
a validé
}
if (function_exists($g = $f . '_dist')) {
return $g;
cerdic
a validé
}
cerdic
a validé
if (isset($echecs[$f])) {
return $echecs[$f];
}
// Sinon charger le fichier de declaration si plausible
cerdic
a validé
if (!preg_match(',^\w+$,', $f)) {
if ($continue) {
return false;
} //appel interne, on passe
include_spip('inc/minipres');
echo minipres();
exit;
}
// passer en minuscules (cf les balises de formulaires)
// et inclure le fichier
!($inc = include_spip($dossier . ($d = strtolower($nom))))
&& strlen(dirname($dossier))
&& dirname($dossier) != '.'
cerdic
a validé
) {
include_spip(substr($dossier, 0, -1));
}
if (function_exists($f)) {
return $f;
}
if (function_exists($g)) {
return $g;
}
cerdic
a validé
if ($continue) {
return $echecs[$f] = false;
}
spip_log("fonction $nom ($f ou $g) indisponible" .
include_spip('inc/filtres_mini');
_T('fonction_introuvable', ['fonction' => '<code>' . spip_htmlentities($f) . '</code>'])
. '<br />'
. _T('fonction_introuvable', ['fonction' => '<code>' . spip_htmlentities($g) . '</code>'])
_T('fichier_introuvable', ['fichier' => '<code>' . spip_htmlentities($d) . '</code>']),
['all_inline' => true,'status' => 404]
/**
* Inclusion unique avec verification d'existence du fichier + log en crash sinon
cerdic
a validé
*
* @param string $file
* @return bool
*/
cerdic
a validé
function include_once_check($file) {
if (file_exists($file)) {
include_once $file;
return true;
}
$crash = (isset($GLOBALS['meta']['message_crash_plugins']) ? unserialize($GLOBALS['meta']['message_crash_plugins']) : '');
$crash[$file] = true;
cerdic
a validé
ecrire_meta('message_crash_plugins', serialize($crash));
return false;
}
cerdic
a validé
/**
* Inclut un fichier PHP (en le cherchant dans les chemins)
* @api
* @uses find_in_path()
* @example
* ```
* include_spip('inc/texte');
* ```
* @param string $f
* Nom du fichier (sans l'extension)
* @param bool $include
* - true pour inclure le fichier,
* - false ne fait que le chercher
* @return string|bool
* - false : fichier introuvable
* - string : chemin du fichier trouvé
cerdic
a validé
**/
function include_spip($f, $include = true) {
return find_in_path($f . '.php', '', $include);
}
/**
* Requiert un fichier PHP (en le cherchant dans les chemins)
* @uses find_in_path()
cerdic
a validé
* @see include_spip()
* @example
* ```
* require_spip('inc/texte');
* ```
* @param string $f
* Nom du fichier (sans l'extension)
* @return string|bool
* - false : fichier introuvable
* - string : chemin du fichier trouvé
cerdic
a validé
**/
function require_spip($f) {
return find_in_path($f . '.php', '', 'required');
}
/**
* Raccourci pour inclure mes_fonctions.php et tous les fichiers _fonctions.php des plugin
* quand on a besoin dans le PHP de filtres/fonctions qui y sont definis
*/
function include_fichiers_fonctions() {
static $done = false;
if (!$done) {
include_spip('inc/lang');
// NB: mes_fonctions peut initialiser $dossier_squelettes (old-style)
// donc il faut l'inclure "en globals"
if ($f = find_in_path('mes_fonctions.php')) {
global $dossier_squelettes;
include_once(_ROOT_CWD . $f);
}
if (@is_readable(_CACHE_PLUGINS_FCT)) {
// chargement optimise precompile
include_once(_CACHE_PLUGINS_FCT);
}
if (test_espace_prive()) {
include_spip('inc/filtres_ecrire');
}
include_spip('public/fonctions'); // charger les fichiers fonctions associes aux criteres, balises..
$done = true;
}
}
kent1
a validé
/**
* Exécute une fonction (appellée par un pipeline) avec la donnée transmise.
kent1
a validé
* Un pipeline est lie a une action et une valeur
* chaque element du pipeline est autorise a modifier la valeur
* le pipeline execute les elements disponibles pour cette action,
* les uns apres les autres, et retourne la valeur finale
kent1
a validé
* Cf. compose_filtres dans references.php, qui est la
* version compilee de cette fonctionnalite
* appel unitaire d'une fonction du pipeline
* utilisee dans le script pipeline precompile
kent1
a validé
* on passe $val par reference pour limiter les allocations memoire
* @param string $fonc
* Nom de la fonction appelée par le pipeline
kent1
a validé
* @param string|array $val
kent1
a validé
* @return string|array $val
cerdic
a validé
**/
function minipipe($fonc, &$val) {
Fil
a validé
// fonction
cerdic
a validé
if (function_exists($fonc)) {
cerdic
a validé
} // Class::Methode
else {
&& ($methode = [$regs[1], $regs[2]])
&& is_callable($methode)
cerdic
a validé
) {
$val = $methode($val);
cerdic
a validé
} else {
spip_log("Erreur - '$fonc' non definie !");
}
}
/**
* Appel d’un pipeline
*
* Exécute le pipeline souhaité, éventuellement avec des données initiales.
* Chaque plugin qui a demandé à voir ce pipeline vera sa fonction spécifique appelée.
* Les fonctions (des plugins) appelées peuvent modifier à leur guise le contenu.
*
* Deux types de retours. Si `$val` est un tableau de 2 éléments, avec une clé `data`
* on retourne uniquement ce contenu (`$val['data']`) sinon on retourne tout `$val`.
*
*
* @example
* Appel du pipeline `pre_insertion`
* ```
* $champs = pipeline('pre_insertion', array(
* 'args' => array('table' => 'spip_articles'),
* 'data' => $champs
* ));
* ```
*
* @param string $action
* Nom du pipeline
* Données à l’entrée du pipeline
* @return mixed|null
* Résultat
*/
gilles.vincent
a validé
function pipeline($action, $val = null) {
static $charger;
// chargement initial des fonctions mises en cache, ou generation du cache
if (!$charger) {
if (!($ok = @is_readable($charger = _CACHE_PIPELINES))) {
include_spip('inc/plugin');
// generer les fichiers php precompiles
// de chargement des plugins et des pipelines
cerdic
a validé
if (!($ok = @is_readable($charger))) {
cerdic
a validé
}
}
// appliquer notre fonction si elle existe
cerdic
a validé
$fonc = 'execute_pipeline_' . strtolower($action);
if (function_exists($fonc)) {
$val = $fonc($val);
cerdic
a validé
} // plantage ?
else {
cerdic
a validé
spip_log("fonction $fonc absente : pipeline desactive", _LOG_ERREUR);
Fil
a validé
}
// si le flux est une table avec 2 cle args&data
// on ne ressort du pipe que les donnees dans 'data'
// array_key_exists pour php 4.1.0
&& count($val) == 2
&& array_key_exists('data', $val)
cerdic
a validé
) {
cerdic
a validé
}
Fil
a validé
return $val;
}
* Enregistrement des événements
*
* Signature : `spip_log(message[,niveau|type|type.niveau])`
*
* Le niveau de log par défaut est la valeur de la constante `_LOG_INFO`
* Les différents niveaux possibles sont :
*
* - `_LOG_HS` : écrira 'HS' au début de la ligne logguée
* - `_LOG_ALERTE_ROUGE` : 'ALERTE'
* - `_LOG_CRITIQUE` : 'CRITIQUE'
* - `_LOG_ERREUR` : 'ERREUR'
* - `_LOG_AVERTISSEMENT` : 'WARNING'
* - `_LOG_INFO_IMPORTANTE` : '!INFO'
* - `_LOG_INFO` : 'info'
* - `_LOG_DEBUG` : 'debug'
*
* spip_log($message, 'recherche')
* spip_log($message, _LOG_DEBUG)
* spip_log($message, 'recherche.'._LOG_DEBUG)
*
* @api
* @link https://programmer.spip.net/spip_log
* @uses inc_log_dist()
*
* @param string $message
* @param string|int $name
* - int indique le niveau de log, tel que `_LOG_DEBUG`
* - string indique le type de log
* - `string.int` indique les 2 éléments.
* Cette dernière notation est controversée mais le 3ème
* paramètre est planté pour cause de compatibilité ascendante.
cerdic
a validé
function spip_log($message = null, $name = null) {
cerdic
a validé
preg_match('/^([a-z_]*)\.?(\d)?$/iS', (string)$name, $regs);
if (!isset($regs[1]) || !$logname = $regs[1]) {
$logname = null;
cerdic
a validé
}
cerdic
a validé
if (!isset($regs[2])) {
$niveau = _LOG_INFO;
cerdic
a validé
}
cerdic
a validé
else {
$niveau = intval($regs[2]);
}
if ($niveau <= (defined('_LOG_FILTRE_GRAVITE') ? _LOG_FILTRE_GRAVITE : _LOG_INFO_IMPORTANTE)) {
cerdic
a validé
if (!$pre) {
cerdic
a validé
_LOG_HS => 'HS:',
_LOG_ALERTE_ROUGE => 'ALERTE:',
_LOG_CRITIQUE => 'CRITIQUE:',
_LOG_ERREUR => 'ERREUR:',
_LOG_AVERTISSEMENT => 'WARNING:',
_LOG_INFO_IMPORTANTE => '!INFO:',
_LOG_INFO => 'info:',
_LOG_DEBUG => 'debug:'
$log = charger_fonction('log', 'inc');
}
cerdic
a validé
if (!is_string($message)) {
$message = print_r($message, true);
}
$log($pre[$niveau] . ' ' . $message, $logname);
/**
* Enregistrement des journaux
*
* @uses inc_journal_dist()
* @param string $phrase texte du journal
* @param array $opt Tableau d'options
cerdic
a validé
**/
marcimat
a validé
$journal = charger_fonction('journal', 'inc');
$journal($phrase, $opt);
}
/**
* Renvoie le `$_GET` ou le `$_POST` émis par l'utilisateur
* ou pioché dans un tableau transmis
*
* @api
* @param string $var
* Clé souhaitée
* @param bool|array $c
* Tableau transmis (sinon cherche dans GET ou POST)
* @return mixed|null
* - null si la clé n'a pas été trouvée
* - la valeur de la clé sinon.
cerdic
a validé
**/
gilles.vincent
a validé
function _request($var, $c = false) {
cerdic
a validé
if (is_array($c)) {
cerdic
a validé
}
cerdic
a validé
if (isset($_GET[$var])) {
$a = $_GET[$var];
} elseif (isset($_POST[$var])) {
$a = $_POST[$var];
} else {
return null;
}
// Si on est en ajax et en POST tout a ete encode
// via encodeURIComponent, il faut donc repasser
&& _AJAX
&& isset($GLOBALS['meta']['charset'])
&& $GLOBALS['meta']['charset'] != 'utf-8'
cerdic
a validé
// check rapide mais pas fiable
&& is_string($a)
&& preg_match(',[\x80-\xFF],', $a)
cerdic
a validé
// check fiable
&& include_spip('inc/charsets')
&& is_utf8($a)
return importer_charset($a, 'utf-8');
}
return $a;
}
/**
* Affecte une valeur à une clé (pour usage avec `_request()`)
*
* @see _request() Pour obtenir la valeur
* @note Attention au cas ou l'on fait `set_request('truc', NULL);`
* @param string $var Nom de la clé
* @param string $val Valeur à affecter
* @param bool|array $c Tableau de données (sinon utilise `$_GET` et `$_POST`)
* @return array|bool
* - array $c complété si un $c est transmis,
* - false sinon
cerdic
a validé
**/
function set_request($var, $val = null, $c = false) {
if (is_array($c)) {
unset($c[$var]);
cerdic
a validé
if ($val !== null) {
$c[$var] = $val;
cerdic
a validé
}
return $c;
}
unset($_GET[$var]);
cerdic
a validé
if ($val !== null) {
cerdic
a validé
}
return false; # n'affecte pas $c
/**
* Sanitizer une valeur *SI* elle provient du GET ou POST
* Utile dans les squelettes pour les valeurs qu'on attrape dans le env,
* dont on veut permettre à un squelette de confiance appelant de fournir une valeur complexe
* mais qui doit etre nettoyee si elle provient de l'URL
*
* On peut sanitizer
* - une valeur simple : `$where = spip_sanitize_from_request($value, 'where')`
* - un tableau en partie : `$env = spip_sanitize_from_request($env, ['key1','key2'])`
* - un tableau complet : `$env = spip_sanitize_from_request($env, '*')`
*
* @param string|array $value
* @param string|array $key
* @param string $sanitize_function
* @return array|mixed|string
*/
function spip_sanitize_from_request($value, $key, $sanitize_function = 'entites_html') {
if (is_array($value)) {
$key = array_keys($value);
}
if (!is_array($key)) {
$key = [$key];
}
foreach ($key as $k) {
if (!empty($value[$k])) {
$value[$k] = spip_sanitize_from_request($value[$k], $k, $sanitize_function);
}
}
return $value;
}
// si la valeur vient des GET ou POST on la sanitize
if (!empty($value) && $value == _request($key)) {
$value = $sanitize_function($value);
}
return $value;
}
* Tester si une URL est absolue
*
* On est sur le web, on exclut certains protocoles,
* notamment 'file://', 'php://' et d'autres…
* @param string $url
cerdic
a validé
function tester_url_absolue($url) {
$url = trim($url ?? '');
if ($url && preg_match(';^([a-z]{3,7}:)?//;Uims', $url, $m)) {
if (
isset($m[1])
&& ($p = strtolower(rtrim($m[1], ':')))
&& in_array($p, ['file', 'php', 'zlib', 'glob', 'phar', 'ssh2', 'rar', 'ogg', 'expect', 'zip'])
return false;
}
return true;
}
return false;
* Prend une URL et lui ajoute/retire un paramètre
* @filtre
* @link https://www.spip.net/4255
* @example
* ```
* [(#SELF|parametre_url{suite,18})] (ajout)
* [(#SELF|parametre_url{suite,''})] (supprime)
* [(#SELF|parametre_url{suite[],1})] (tableaux valeurs multiples)
* ```
* @param string $url URL
* @param string $c Nom du paramètre
* @param string|array|null $v Valeur du paramètre
* @param string $sep Séparateur entre les paramètres
* @return string URL
cerdic
a validé
function parametre_url($url, $c, $v = null, $sep = '&') {
// requete erronnee : plusieurs variable dans $c et aucun $v
if (str_contains($c, '|') && is_null($v)) {
return null;
cerdic
a validé
}
// lever l'#ancre
if (preg_match(',^([^#]*)(#.*)$,', $url, $r)) {
$url = $r[1];
$ancre = $r[2];
cerdic
a validé
} else {
$ancre = '';
cerdic
a validé
}
// eclater
$url = preg_split(',[?]|&|&,', $url);
// recuperer la base
$a = array_shift($url);
cerdic
a validé
if (!$a) {
$a = './';
}
// preparer la regexp de maniere securisee
$regexp = explode('|', $c);
foreach ($regexp as $r => $e) {
$regexp[$r] = str_replace('[]', '\[\]', preg_replace(',[^\w\d\[\]-],', '', $e));
}
$regexp = ',^(' . implode('|', $regexp) . '[[]?[]]?)(=.*)?$,';
cerdic
a validé
$ajouts = array_flip(explode('|', $c));
$u = is_array($v) ? $v : rawurlencode((string) $v);
$testv = (is_array($v) ? count($v) : strlen((string) $v));
$v_read = null;
// lire les variables et agir
foreach ($url as $n => $val) {
if (preg_match($regexp, urldecode($val), $r)) {
cerdic
a validé
if ($v === null) {
// c'est un tableau, on memorise les valeurs
if (str_ends_with($r[1], '[]')) {
cerdic
a validé
if (!$v_read) {
cerdic
a validé
}
$v_read[] = $r[2] ? substr($r[2], 1) : '';
} // c'est un scalaire, on retourne direct
else {
cerdic
a validé
return $r[2] ? substr($r[2], 1) : '';
cerdic
a validé
} // suppression
elseif (!$testv) {
unset($url[$n]);
// Ajout. Pour une variable, remplacer au meme endroit,
// pour un tableau ce sera fait dans la prochaine boucle
elseif (!str_ends_with($r[1], '[]')) {
cerdic
a validé
$url[$n] = $r[1] . '=' . $u;
unset($ajouts[$r[1]]);
}
// Pour les tableaux on laisse tomber les valeurs de
// départ, on remplira à l'étape suivante
else {
}
}
// traiter les parametres pas encore trouves
&& ($args = func_get_args())
&& count($args) == 2
cerdic
a validé
) {
return $v_read; // rien trouve ou un tableau
cerdic
a validé
foreach ($ajouts as $k => $n) {
if (!is_array($v)) {
$url[] = $k . '=' . $u;
} else {
$id = (str_ends_with($k, '[]')) ? $k : ($k . '[]');
cerdic
a validé
$url[] = $id . '=' . (is_array($w) ? 'Array' : rawurlencode($w));
// eliminer les vides
$url = array_filter($url);
// recomposer l'adresse
cerdic
a validé
if ($url) {
$a .= '?' . join($sep, $url);
cerdic
a validé
}
return $a . $ancre;
/**
* Ajoute (ou retire) une ancre sur une URL
*
* L’ancre est nettoyée : on translitère, vire les non alphanum du début,
* et on remplace ceux à l'interieur ou au bout par `-`
*
* @example
* - `$url = ancre_url($url, 'navigation'); // => mettra l’ancre #navigation
* - `$url = ancre_url($url, ''); // => enlèvera une éventuelle ancre
* @uses translitteration()
*/
function ancre_url(string $url, ?string $ancre = ''): string {
$ancre ??= '';
// lever l'#ancre
if (preg_match(',^([^#]*)(#.*)$,', $url, $r)) {
$url = $r[1];
}
cerdic
a validé
if (preg_match('/[^-_a-zA-Z0-9]+/S', $ancre)) {
if (!function_exists('translitteration')) {
include_spip('inc/charsets');
cerdic
a validé
}
['/^[^-_a-zA-Z0-9]+/', '/[^-_a-zA-Z0-9]/'],
['', '-'],
}
cerdic
a validé
return $url . (strlen($ancre) ? '#' . $ancre : '');
}
/**
*
* @param string|null $reset
* @return string
*/
cerdic
a validé
function nettoyer_uri($reset = null) {
static $done = false;
static $propre = '';
cerdic
a validé
if (!is_null($reset)) {
return $propre = $reset;
}
if ($done) {
return $propre;
}
return $propre = nettoyer_uri_var($GLOBALS['REQUEST_URI']);
}
marcimat
a validé
* Nettoie une URI de certains paramètres (var_xxx, utm_xxx, etc.)
*
* La regexp des paramètres nettoyés est calculée à partir de la constante `_CONTEXTE_IGNORE_LISTE_VARIABLES`
* (qui peut être redéfinie dans mes_options.php)
* @uses _CONTEXTE_IGNORE_LISTE_VARIABLES
* @return string
*/
function nettoyer_uri_var($request_uri) {
static $preg_nettoyer;
if (!defined('_CONTEXTE_IGNORE_LISTE_VARIABLES')) {
marcimat
a validé
/** @var array<string> Liste (regexp) de noms de variables à ignorer d’une URI */
define('_CONTEXTE_IGNORE_LISTE_VARIABLES', ['^var_', '^PHPSESSID$', '^fbclid$', '^utm_']);
}
if (empty($preg_nettoyer)) {
$preg_nettoyer_vars = _CONTEXTE_IGNORE_LISTE_VARIABLES;
foreach ($preg_nettoyer_vars as &$var) {
if (str_starts_with($var, '^')) {
$var = substr($var, 1);
} else {
$var = '[^=&]*' . $var;
}
if (str_ends_with($var, '$')) {
$var = substr($var, 0, -1);
} else {
$var .= '[^=&]*';
}
}
$preg_nettoyer = ',([?&])(' . implode('|', $preg_nettoyer_vars) . ')=[^&]*(&|$),i';
}
if (empty($request_uri)) {
return $request_uri;
}
$uri1 = $request_uri;
do {
$uri = $uri1;
$uri1 = preg_replace($preg_nettoyer, '\1', $uri);
cerdic
a validé
} while ($uri <> $uri1);
return rtrim($uri1, '?&');
}
/**
* Donner l'URL de base d'un lien vers "soi-meme", modulo les trucs inutiles
*
* @param string $amp
* Style des esperluettes
* @param bool $root
* @return string
* URL vers soi-même
cerdic
a validé
**/
function self($amp = '&', $root = false) {
$url = nettoyer_uri();
// si pas de profondeur on peut tronquer
cerdic
a validé
$GLOBALS['profondeur_url'] < (_DIR_RESTREINT ? 1 : 2)
// sinon c'est OK si _SET_HTML_BASE a ete force a false
|| defined('_SET_HTML_BASE') && !_SET_HTML_BASE
)
cerdic
a validé
) {
$url = preg_replace(',^[^?]*/,', '', $url);
cerdic
a validé
}
// ajouter le cas echeant les variables _POST['id_...']
cerdic
a validé
foreach ($_POST as $v => $c) {
if (str_starts_with($v, 'id_')) {
$url = parametre_url($url, $v, $c, '&');
cerdic
a validé
}
}
// supprimer les variables sans interet
if (test_espace_prive()) {
cerdic
a validé
$url = preg_replace(',([?&])('
. 'lang|show_docs|'
. 'changer_lang|var_lang|action)=[^&]*,i', '\1', $url);
$url = preg_replace(',([?&])[&]+,', '\1', $url);
$url = preg_replace(',[&]$,', '\1', $url);
}
include_spip('inc/filtres_mini');
$url = spip_htmlspecialchars($url);
$url = str_replace(["'", '"', '<', '[', ']', ':'], ['%27', '%22', '%3C', '%5B', '%5D', '%3A'], $url);
// & ?
cerdic
a validé
if ($amp != '&') {
$url = str_replace('&', $amp, $url);
cerdic
a validé
}
// Si ca demarre par ? ou vide, donner './'
$url = preg_replace(',^([?].*)?$,', './\1', $url);
return $url;
}
/**
* Indique si on est dans l'espace prive
*
* @return bool
* true si c'est le cas, false sinon.
*/
function test_espace_prive() {
return defined('_ESPACE_PRIVE') ? _ESPACE_PRIVE : false;
}
cerdic
a validé
/**
* Vérifie la présence d'un plugin actif, identifié par son préfixe
cerdic
a validé
*
* @param string $plugin
* @return bool
*/
cerdic
a validé
function test_plugin_actif($plugin) {
return ($plugin && defined('_DIR_PLUGIN_' . strtoupper($plugin))) ? true : false;
cerdic
a validé
}
cerdic
a validé
/**
* Traduction des textes de SPIP
*
* Traduit une clé de traduction en l'obtenant dans les fichiers de langues.
* @api
* @uses inc_traduire_dist()
* @uses _L()
* @example
* ```
* _T('bouton_enregistrer')
* _T('medias:image_tourner_droite')
* _T('medias:erreurs', array('nb'=>3))
* _T("email_sujet", array('spip_lang'=>$lang_usager))
cerdic
a validé
* @param string $texte
* Clé de traduction
cerdic
a validé
* @param array $args
* Couples (variable => valeur) pour passer des variables à la chaîne traduite. la variable spip_lang permet de forcer la langue
cerdic
a validé
* @param array $options
* - string class : nom d'une classe a ajouter sur un span pour encapsuler la chaine
* - bool force : forcer un retour meme si la chaine n'a pas de traduction
* - bool sanitize : nettoyer le html suspect dans les arguments
* @return string
cerdic
a validé
*/
cerdic
a validé
static $traduire = false;
$o = ['class' => '', 'force' => true, 'sanitize' => true];
cerdic
a validé
if ($options) {
cerdic
a validé
// support de l'ancien argument $class
cerdic
a validé
if (is_string($options)) {
cerdic
a validé
}
$o = array_merge($o, $options);
cerdic
a validé
}
cerdic
a validé
if (!$traduire) {
$traduire = charger_fonction('traduire', 'inc');
include_spip('inc/lang');
}
RastaPopoulos
a validé
// On peut passer explicitement la langue dans le tableau
// On utilise le même nom de variable que la globale
cerdic
a validé
if (isset($args['spip_lang'])) {
RastaPopoulos
a validé
$lang = $args['spip_lang'];
// On l'enleve pour ne pas le passer au remplacement
unset($args['spip_lang']);
cerdic
a validé
} // Sinon on prend la langue du contexte
RastaPopoulos
a validé
$lang = $GLOBALS['spip_lang'];
}
$text = $traduire($texte, $lang);
if ($text === null || !strlen($text)) {
cerdic
a validé
if (!$o['force']) {
cerdic
a validé
return '';
cerdic
a validé
}
cerdic
a validé
$text = $texte;
// pour les chaines non traduites, assurer un service minimum
if (!$GLOBALS['test_i18n'] && _request('var_mode') != 'traduction') {
$n = strpos($text, ':');
if ($n !== false) {
$text = substr($text, $n + 1);
}
$text = str_replace('_', ' ', $text);
cerdic
a validé
}
$o['class'] = null;
}
return _L($text, $args, $o);
/**
* Remplace les variables `@...@` par leur valeur dans une chaîne de langue.
*
* Cette fonction est également appelée dans le code source de SPIP quand une
* chaîne n'est pas encore dans les fichiers de langue.
*
* @see _T()
* @example
* ```
* _L('Texte avec @nb@ ...', array('nb'=>3)
* ```
* @param string $text
* @param array $args
* Couples (variable => valeur) à transformer dans le texte
* @param array $options
* - string class : nom d'une classe a ajouter sur un span pour encapsuler la chaine
* - bool sanitize : nettoyer le html suspect dans les arguments
* @return string
$f = $text;
'class' => null,
'sanitize' => true,
// support de l'ancien argument $class
if ($options && is_string($options)) {
}
if (is_array($options)) {
$options += $defaut_options;
} else {
$options = $defaut_options;
}
if (is_array($args) && count($args)) {
if (!function_exists('interdire_scripts')) {
include_spip('inc/texte');
}
if (!function_exists('echapper_html_suspect')) {
include_spip('inc/texte_mini');
}
foreach ($args as $name => $value) {
if (str_contains($text, (string) "@$name@")) {
cerdic
a validé
if ($options['sanitize']) {
$value = echapper_html_suspect($value);
$value = interdire_scripts($value, -1);
}
if (!empty($options['class'])) {
$value = "<span class='" . $options['class'] . "'>$value</span>";
cerdic
a validé
}
$text = str_replace("@$name@", (string) $value, (string) $text);
cerdic
a validé
unset($args[$name]);
}
// Si des variables n'ont pas ete inserees, le signaler
// (chaines de langues pas a jour)
cerdic
a validé
if ($args) {
spip_log("$f: variables inutilisees " . join(', ', array_keys($args)), _LOG_DEBUG);
}
if (($GLOBALS['test_i18n'] || _request('var_mode') == 'traduction') && is_null($options['class'])) {
return "<span class='debug-traduction-erreur'>$text</span>";
cerdic
a validé
} else {
return $text;
cerdic
a validé
}
/**
* Retourne un joli chemin de répertoire
*
* Pour afficher `ecrire/action/` au lieu de `action/` dans les messages
* ou `tmp/` au lieu de `../tmp/`
*
function joli_repertoire($rep) {
cerdic
a validé
$a = substr($rep, 0, 1);
if ($a <> '.' && $a <> '/') {