You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
8.8 KiB
320 lines
8.8 KiB
<?php |
|
|
|
/** |
|
* Déclaration de fonctions pour les squelettes |
|
* |
|
* @package SPIP\Saisies\Fonctions |
|
**/ |
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
return; |
|
} |
|
|
|
include_spip('inc/saisies'); |
|
include_spip('balise/saisie'); |
|
include_spip('inc/saisies_afficher_si_js'); |
|
// picker_selected (spip 3) |
|
include_spip('formulaires/selecteur/generique_fonctions'); |
|
|
|
/** |
|
* Retourne une balise dev. Maintenu pour compatibilité historique, ne plus utiliser. |
|
* @deprecated |
|
* Comportement antérieure : |
|
* Retournait une balise `div` si on est en SPIP >= 3.1, sinon le texte en parametre. |
|
* @example `[(#VAL{ul}|saisie_balise_structure_formulaire)]` |
|
* @see balise_DIV_dist() pour une écriture plus courte. |
|
* @note Préférer `[(#DIV|sinon{ul})]` dans les squelettes, plus lisible. |
|
* |
|
* @param $tag |
|
* ul ou li |
|
* @return string |
|
* $tag initial ou div |
|
*/ |
|
function saisie_balise_structure_formulaire($tag) { |
|
return 'div'; |
|
} |
|
|
|
if ( |
|
!function_exists('balise_DIV_dist') |
|
) { |
|
|
|
/** |
|
* Compile la balise `DIV` qui retourne simplement le texte `div` |
|
* |
|
* Maintenu pour ne pas casser les squelettes qui s'appuient dessus, mais à ne plus utiliser. |
|
* Servait à la compatibilité entre SPIP 3.0 et SPIP 3.1+ |
|
* |
|
* Variante d'écriture, plus courte, que le filtre `saisie_balise_structure_formulaire` |
|
* |
|
* À partir de SPIP 3.1 |
|
* - ul.editer-groupe deviennent des div.editer-groupe |
|
* - li.editer devient div.editer |
|
* @deprecated |
|
* @see saisie_balise_structure_formulaire() |
|
* @example |
|
* `[(#DIV|sinon{ul})]` |
|
* |
|
* @param Pile $p |
|
* @return Pile |
|
*/ |
|
function balise_DIV_dist($p) { |
|
$p->code = "'div'"; |
|
$p->interdire_scripts = false; |
|
return $p; |
|
} |
|
} |
|
|
|
/** |
|
* Traiter la valeur de la vue en fonction du env |
|
* si un traitement a ete fait en amont (champs extra) ne rien faire |
|
* si pas de traitement defini (formidable) passer typo ou propre selon le type du champ |
|
* |
|
* @param string $valeur |
|
* @param string|array $env |
|
* @return string |
|
*/ |
|
function saisie_traitement_vue($valeur, $env) { |
|
if (is_string($env)) { |
|
$env = unserialize($env); |
|
} |
|
if (!function_exists('propre')) { |
|
include_spip('inc/texte'); |
|
} |
|
if (!is_array($valeur)) { |
|
$valeur = trim($valeur); |
|
} |
|
// si traitement est renseigne, alors le champ est deja mis en forme |
|
// (saisies) |
|
// sinon on fait une mise en forme smart |
|
if ($valeur and !is_array($valeur) and !isset($env['traitements'])) { |
|
if (in_array($env['type_saisie'], array('textarea'))) { |
|
$valeur = propre($valeur); |
|
} else { |
|
$valeur = '<p>' . typo($valeur) . '</p>'; |
|
} |
|
} |
|
|
|
return $valeur; |
|
} |
|
|
|
/** |
|
* Compile la balise `#GLOBALS{xxx}` qui retourne la valeur d'une vilaine variable globale de même nom si elle existe |
|
* |
|
* @example |
|
* ``` |
|
* #GLOBALS{debut_intertitre} |
|
* ``` |
|
* |
|
* @param Champ $p |
|
* Pile au niveau de la balise |
|
* @return Champ |
|
* Pile complétée du code php de la balise. |
|
**/ |
|
function balise_GLOBALS_dist($p) { |
|
if (function_exists('balise_ENV')) { |
|
return balise_ENV($p, '$GLOBALS'); |
|
} else { |
|
return balise_ENV_dist($p, '$GLOBALS'); |
|
} |
|
} |
|
|
|
/** |
|
* Liste les éléments du sélecteur générique triés |
|
* |
|
* Les éléments sont triés par objets puis par identifiants |
|
* |
|
* @example |
|
* L'entrée : |
|
* 'rubrique|3,rubrique|5,article|2' |
|
* Retourne : |
|
* array( |
|
* 0 => array('objet'=>'article', 'id_objet' => 2), |
|
* 1 => array('objet'=>'rubrique', 'id_objet' => 3), |
|
* 2 => array('objet'=>'rubrique', 'id_objet' => 5), |
|
* ) |
|
* |
|
* @param string $selected |
|
* Liste des objets sélectionnés |
|
* @return array |
|
* Liste des objets triés |
|
**/ |
|
function picker_selected_par_objet($selected) { |
|
$res = array(); |
|
$liste = picker_selected($selected); |
|
// $liste : la sortie dans le désordre |
|
if (!$liste) { |
|
return $res; |
|
} |
|
|
|
foreach ($liste as $l) { |
|
if (!isset($res[ $l['objet'] ])) { |
|
$res[ $l['objet'] ] = array(); |
|
} |
|
$res[$l['objet']][] = $l['id_objet']; |
|
} |
|
// $res est trié par objet, puis par identifiant |
|
ksort($res); |
|
foreach ($res as $objet => $ids) { |
|
sort($res[$objet]); |
|
} |
|
|
|
// on remet tout en file |
|
$liste = array(); |
|
foreach ($res as $objet => $ids) { |
|
foreach ($ids as $id) { |
|
$liste[] = array('objet' => $objet, 'id_objet' => $id); |
|
} |
|
} |
|
|
|
return $liste; |
|
} |
|
|
|
|
|
/** |
|
* Lister les objets qui ont une url_edit renseignée et qui sont éditables. |
|
* |
|
* @return array Liste des objets : |
|
* index : nom de la table (spip_articles, spip_breves, etc.) |
|
* 'type' : le type de l'objet ; |
|
* 'url_edit' : l'url d'édition de l'objet ; |
|
* 'texte_objets' : le nom humain de l'objet éditorial. |
|
*/ |
|
function lister_tables_objets_edit() { |
|
include_spip('base/abstract_sql'); |
|
|
|
$objets = lister_tables_objets_sql(); |
|
$objets_edit = array(); |
|
|
|
foreach ($objets as $objet => $definition) { |
|
if (isset($definition['editable']) and isset($definition['url_edit']) and $definition['url_edit'] != '') { |
|
$objets_edit[$objet] = array('type' => $definition['type'], 'url_edit' => $definition['url_edit'], 'texte_objets' => $definition['texte_objets']); |
|
} |
|
} |
|
$objets_edit = array_filter($objets_edit); |
|
|
|
return $objets_edit; |
|
} |
|
|
|
/** |
|
* Afficher la chaine de langue traduite. |
|
* |
|
* @param string $chaine |
|
* @return string |
|
*/ |
|
function saisies_label($chaine) { |
|
$chaine = trim($chaine); |
|
if (preg_match("/^(<:|<:)/", $chaine)) { |
|
$chaine = preg_replace("/^(<:|<:)/", "", $chaine); |
|
$chaine = preg_replace("/(:>|:>)$/", "", $chaine); |
|
return _T($chaine); |
|
} |
|
|
|
return $chaine; |
|
} |
|
|
|
|
|
/** |
|
* Les liens ouvrants, c'est mal en général. |
|
* Sauf dans un cas particulier : dans les explications dans un formulaire. |
|
* En effet, si le lien n'est pas ouvrant, la personne en train de remplir un formulaire |
|
* a) lis une explication |
|
* b) clique sur le lien pour savoir comment remplir son formulaire |
|
* c) est redirigée directement vers une page |
|
* d) perd du coup ce qu'elle avait commencé remplir. |
|
* Par conséquent, en terme d'accessibilité, il vaut mieux POUR LES EXPLICATIONS DE FORMULAIRE |
|
* avoir des liens systématiquement ouvrant, |
|
* et ce que le lien pointe en interne ou en externe (ce qui distingue du filtre |liens_ouvrants). |
|
* D'où un filtre saisies_liens_ouvrants |
|
* @param string $texte |
|
* @return string $texte |
|
**/ |
|
function saisies_liens_ouvrants($texte) { |
|
$texte = liens_absolus($texte); |
|
if (preg_match_all(",(<a\s+[^>]*https?://[^>]*\b[^>]+>),imsS", |
|
$texte, $liens, PREG_PATTERN_ORDER)) { |
|
foreach ($liens[0] as $a) { |
|
$rel = 'noopener noreferrer ' . extraire_attribut($a, 'rel'); |
|
$ablank = inserer_attribut($a, 'rel', $rel); |
|
$ablank = inserer_attribut($ablank, 'target', '_blank'); |
|
$texte = str_replace($a, $ablank, $texte); |
|
} |
|
} |
|
return $texte; |
|
} |
|
|
|
/** |
|
* Afficher un statut traduit |
|
* |
|
* @param string $statut Le statut (publie, refuse, ...) |
|
* @param string $objet Le type d’objet (article, rubrique, ...) |
|
* @return string La traduction du statut, si on la trouve, sinon simplement la clé... |
|
*/ |
|
function saisies_statut_titre($statut, $objet = '') { |
|
include_spip('inc/puce_statut'); |
|
$titre = statut_titre($objet, $statut); |
|
return $titre ? $titre : $statut; |
|
} |
|
|
|
/** |
|
* Convertit si nécessaire une valeur au format du picker ajax du sélecteur générique |
|
* quand on sait que la valeur ne concerne qu'un seul type d'objet. |
|
* |
|
* Fait en quelque sorte l'inverse de picker_selected(). |
|
* Cela évite d'avoir à modifier le charger des formulaires quand on traite des cas simples : |
|
* juste un plusieurs ids d'un seul type d'objet. |
|
* |
|
* @example |
|
* - Entrée : 10, sortie : array('article|10') |
|
* - Entrée : array(10,20), sortie : array('article|10', 'article|20') |
|
* |
|
* @see picker_selected() |
|
* |
|
* @param array|string|int $valeur |
|
* - Soit un tableau issu du sélecteur (dans ce cas on ne fait rien) : `array('article|1', 'article|2')` |
|
* - Soit l'id d'un objet : 1 |
|
* - Soit un tableau d'ids : array(1,2) |
|
* @param string $objet |
|
* @return array |
|
* Tableau au format du sélecteur générique |
|
*/ |
|
function saisies_picker_preselect_objet($valeur, $objet) { |
|
|
|
// Nb : évitons des preg_match si possible |
|
$is_objet_unique = is_numeric($valeur); // ex. : 10 |
|
$is_objet_multiple = (is_array($valeur) and is_numeric($valeur[0])); // ex. : array(10,20) |
|
|
|
if ( |
|
$is_objet_unique |
|
or $is_objet_multiple |
|
) { |
|
if ($is_objet_unique) { |
|
$valeur = array($valeur); |
|
} |
|
foreach ($valeur as $k => $id_objet) { |
|
$valeur[$k] = "$objet|$id_objet"; |
|
} |
|
} |
|
|
|
return $valeur; |
|
} |
|
|
|
/** |
|
* Function inverse de la fonction du core `utf8_noplanes()` |
|
* Trouve les entités HTML numérique des hautes "planes" |
|
* et les remets en Unicode |
|
* @param string|null le texte |
|
* @return string |
|
**/ |
|
function saisies_utf8_restaurer_planes(?string $x): string { |
|
if (!$x) { |
|
return (string)$x; |
|
} |
|
preg_match_all('/&(amp;)?#(\d+);/U', $x, $matches, PREG_SET_ORDER); |
|
foreach ($matches as $m) { |
|
if ($m[2] > 65535) {//Uniquement les planes 1-16, pas le plane 0 |
|
$decode = html_entity_decode($m[0]); |
|
$x = str_replace($m[0], $decode, $x); |
|
} |
|
} |
|
return $x; |
|
}
|
|
|