spip_nursit/plugins-dist/dist/nursit/crayons/crayons_options.php
2023-06-01 17:30:12 +02:00

486 lines
13 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Crayons
* plugin for spip
* (c) Fil, toggg 2006-2019
* licence GPL
*
* @package SPIP\Crayons\Fonctions
*/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
if (!defined('_DEBUG_CRAYONS')) {
/**
* Débuguer les crayons
*
* Mettre a true dans mes_options pour avoir les crayons non compresses
*/
define('_DEBUG_CRAYONS', false);
}
$GLOBALS['marqueur_skel'] = (isset($GLOBALS['marqueur_skel']) ? $GLOBALS['marqueur_skel'] : '') . ':crayons';
/**
* Dire rapidement si ca vaut le coup de chercher des droits
*
* @return bool
**/
function analyse_droits_rapide_dist() {
return isset($GLOBALS['auteur_session']['statut']);
}
/**
* Vérifier si un exec du privé est crayonnable
*
* @param string $exec
*
* @return bool
**/
function test_exec_crayonnable($exec) {
if ($exec_autorise = lire_config('crayons/exec_autorise')) {
$execs = explode(',', $exec_autorise);
foreach ($execs as $key => $value) {
$execs[$key] = trim($value);
}
if ($exec_autorise == '*' || in_array($exec, $execs)) {
return true;
}
}
return false;
}
/**
* Ajouter la gestion des crayons dans l'espace privé
*
* @pipeline header_prive
* @uses Crayons_preparer_page()
*
* @param string $head
* Contenu du header
* @return string
* Contenu du header
**/
function Crayons_insert_head($head) {
// verifie la presence d'une meta crayons, si c'est vide
// on ne cherche meme pas a traiter l'espace prive
if (empty($GLOBALS['meta']['crayons'])) {
return $head;
}
$config_espace_prive = @unserialize($GLOBALS['meta']['crayons']);
if (empty($config_espace_prive)) {
return $head;
}
// verifie que l'edition de l'espace prive est autorisee
if (isset($config_espace_prive['espaceprive']) and $config_espace_prive['espaceprive'] == 'on') {
// determine les pages (exec) crayonnables
if (test_exec_crayonnable(_request('exec'))) {
// Calcul des droits
include_spip('inc/crayons');
$head = Crayons_preparer_page($head, '*', wdgcfg(), 'head');
}
}
// retourne l'entete modifiee
return $head;
}
/**
* Ajouter la gestion des crayons dans l'espace public
*
* @pipeline affichage_final
* @uses analyse_droits_rapide_dist()
* @uses Crayons_preparer_page()
* @note
* Le pipeline affichage_final est executé à chaque hit sur toute la page
*
* @param string $page
* Contenu de la page à envoyer au navigateur
* @return string
* Contenu de la page à envoyer au navigateur
**/
function Crayons_affichage_final($page) {
// ne pas se fatiguer si le visiteur n'a aucun droit
if (!(function_exists('analyse_droits_rapide')?analyse_droits_rapide():analyse_droits_rapide_dist())) {
return $page;
}
// sinon regarder rapidement si la page a des classes crayon
if (strpos($page, 'crayon')===false) {
return $page;
}
// voir un peu plus precisement lesquelles
include_spip('inc/crayons');
if (!preg_match_all(_PREG_CRAYON, $page, $regs, PREG_SET_ORDER)) {
return $page;
}
$wdgcfg = wdgcfg();
// calculer les droits sur ces crayons
include_spip('inc/autoriser');
$droits = array();
$droits_accordes = 0;
foreach ($regs as $reg) {
list(,$crayon,$type,$champ,$id) = $reg;
if (_DEBUG_CRAYONS) {
spip_log("autoriser('modifier', $type, $id, NULL, array('champ'=>$champ))", 'crayons_distant');
}
if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) {
if (!isset($droits['.' . $crayon])) {
$droits['.' . $crayon] = 0;
}
$droits['.' . $crayon]++;
$droits_accordes ++;
}
}
// et les signaler dans la page
if ($droits_accordes == count($regs)) { // tous les droits
$page = Crayons_preparer_page($page, '*', $wdgcfg);
} elseif ($droits) { // seulement certains droits, preciser lesquels
$page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg);
}
return $page;
}
/**
* Ajoute les scripts css et js nécessaires aux crayons dans le code HTML
*
* @uses crayons_var2js()
*
* @param string $page
* Code HTML de la page complète ou du header seulement
* @param string $droits
* - Liste de css définissant les champs crayonnables
* (séparés par virgule) dont l'édition est autorisée
* - "*" si tous sont autorisés
* @param array $wdgcfg
* Description de la configuration des crayons (attribut => valeur)
* @param string $mode
* - page : toute la page est présente dans `$page`
* - head : seul le header est présent dans `$page`
* @return
**/
function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') {
/**
* Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé
*/
if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) {
if (isset($GLOBALS['auteur_session']) and isset($GLOBALS['auteur_session']['lang'])) {
lang_select($GLOBALS['auteur_session']['lang']);
}
}
$jsSkel = find_in_path('crayons.js.html');
$contexte = array('callback' => 'startCrayons');
if (_DEBUG_CRAYONS) {
$contexte['debug_crayons'] = 1;
}
$hash = substr(md5($jsSkel . json_encode($contexte)),0,7);
$jsFile = _DIR_VAR . "crayons-{$hash}.js";
if (!file_exists($jsFile) or _VAR_MODE === 'recalcul') {
include_spip('inc/filtres'); // pour produire_fond_statique()
$jsFondStatique = supprimer_timestamp(produire_fond_statique('crayons.js', $contexte));
@copy($jsFondStatique, $jsFile);
}
$jsFile .= "?" . filemtime($jsFile);
$cssFile = find_in_path('css/crayons.css');
if (lang_dir() === 'rtl') {
include_spip('inc/filtres'); // pour direction_css()
$cssFile = direction_css($cssFile, 'rtl');
}
$cssFile .= "?" . filemtime($cssFile);
$config = crayons_var2js(array(
'imgPath' => dirname(find_in_path('css/images/crayon.svg')), // ne sert visiblement plus ?
'droits' => $droits,
'dir_racine' => _DIR_RACINE,
'self' => self('&'),
'txt' => array(
'error' => _U('crayons:svp_copier_coller'),
'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : ''
),
'img' => array(
'searching' => array(
'txt' => _U('crayons:veuillez_patienter')
),
'crayon' => array(
'txt' => _U('crayons:editer')
),
'edit' => array(
'txt' => _U('crayons:editer_tout')
),
'img-changed' => array(
'txt' => _U('crayons:deja_modifie')
)
),
'cfg' => $wdgcfg
));
// Est-ce que PortePlume est la ?
$meta_crayon = (isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']): array());
$pp = '';
if (isset($meta_crayon['barretypo']) && $meta_crayon['barretypo']) {
if (test_plugin_actif('porte_plume')) {
$pp = <<<EOF
cQuery(function() {
if (typeof onAjaxLoad === 'function' && typeof jQuery.fn.barre_outils === 'function') {
function barrebouilles_crayons() {jQuery('.formulaire_crayon textarea.crayon-active').barre_outils('edition');}
onAjaxLoad(barrebouilles_crayons);
}
});
EOF;
}
}
$incCSS = "<link rel=\"stylesheet\" href=\"{$cssFile}\" type=\"text/css\" media=\"all\" />";
$incJS = <<<EOH
<script type="text/javascript">/* <![CDATA[ */
var configCrayons;
function startCrayons() {
configCrayons = new cQuery.prototype.cfgCrayons({$config});
cQuery.fn.crayonsstart();
{$pp}
}
var cr = document.createElement('script');
cr.type = 'text/javascript'; cr.async = true;
cr.src = '{$jsFile}';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(cr, s);
/* ]]> */</script>
EOH;
if ($mode == 'head') {
//js inline avant les css, sinon ca bloque le chargement
$page = $page . $incJS . $incCSS;
return $page;
}
$pos_head = strpos($page, '</head>');
if ($pos_head === false) {
return $page;
}
// js inline avant la premiere css, ou sinon avant la fin du head
$pos_link = strpos($page, '<link ');
if (!$pos_link) {
$pos_link = $pos_head;
}
$page = substr_replace($page, $incJS, $pos_link, 0);
// css avant la fin du head
$pos_head = strpos($page, '</head>');
$page = substr_replace($page, $incCSS, $pos_head, 0);
return $page;
}
/**
* Balise indiquant un champ SQL crayonnable
*
* @note
* Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP
* ne retourne rien
*
* @example
* ```
* <div class="#EDIT{texte}">#TEXTE</div>
* <div class="#EDIT{ps}">#PS</div>
* ```
*
* @param Champ $p
* Pile au niveau de la balise
* @return Champ
* Pile complétée par le code à générer
**/
function balise_EDIT($p) {
// le code compile de ce qui se trouve entre les {} de la balise
$label = interprete_argument_balise(1, $p);
// Verification si l'on est dans le cas d'une meta
// #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc}
if (preg_match('/meta-(.*)\'/', $label, $meta)) {
$type = 'meta';
$label= 'valeur';
$primary = $meta[1];
$p->code = "classe_boucle_crayon('"
. $type
."','"
.$label
."',"
. "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS.
.").' '";
$p->interdire_scripts = false;
return $p;
}
$i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
// #EDIT hors boucle? ne rien faire
if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) {
$p->code = "''";
$p->interdire_scripts = false;
return $p;
}
// crayon sur une base distante 'nua__article-intro-5'
if ($distant = $p->boucles[$i_boucle]->sql_serveur) {
$type = $distant.'__'.$type;
}
$primary = $p->boucles[$i_boucle]->primary;
// On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée.
// Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement
// dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus.
if (!$primary) {
erreur_squelette(_T('crayons:absence_cle_primaire'), $p);
}
$primary = explode(',', $primary);
$id = array();
foreach ($primary as $key) {
$id[] = champ_sql(trim($key), $p);
}
$primary = implode(".'-'.", $id);
$p->code = "classe_boucle_crayon('"
. $type
."',"
.sinon($label, "''")
.','
. $primary
.").' '";
$p->interdire_scripts = false;
return $p;
}
/**
* Balise indiquant une configuration crayonnable
*
* @example
* ```
* <div class="#EDIT_CONFIG{descriptif_site}">#DESCRIPTIF_SITE_SPIP</div>
* <div class="#EDIT_CONFIG{demo/truc}">#CONFIG{demo/truc}</div>
* ```
*
* @param Champ $p
* Pile au niveau de la balise
* @return Champ
* Pile complétée par le code à générer
**/
if (!function_exists('balise_EDIT_CONFIG_dist')) {
function balise_EDIT_CONFIG_dist($p) {
// le code compile de ce qui se trouve entre les {} de la balise
$config = interprete_argument_balise(1, $p);
if (!$config) {
return $p;
}
// chaque / du nom de config doit être transformé pour css.
// nous utiliserons '__' à la place.
$type = 'meta';
$label= 'valeur';
$p->code = "classe_boucle_crayon('"
. $type
. "','"
. $label
. "',"
. "str_replace('/', '__', $config)"
. ").' '";
$p->interdire_scripts = false;
return $p;
}
}
/**
* Crée le controleur du crayon indiqué par la classe CSS
*
* @param string $class
* Class CSS de crayon tel que créé par #EDIT
* @return string
* HTML du crayon, sinon texte d'erreur
**/
function creer_le_crayon($class) {
include_spip('inc/crayons');
include_spip('action/crayons_html');
$a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500));
return $a['$erreur'] ? $a['$erreur'] : $a['$html'];
}
/**
* Balise `#CRAYON` affichant un formulaire de crayon
*
* SI `?edit=1;`
*
* @example
* ```
* #CRAYON{ps}
* ```
*
* @param Champ $p
* Pile au niveau de la balise
* @return Champ
* Pile complétée par le code à générer
**/
function balise_CRAYON($p) {
$p = balise_EDIT($p);
$p->code = 'creer_le_crayon('.$p->code.')';
return $p;
}
/**
* Donne la classe CSS crayon
*
* En fonction :
* - du type de la boucle
* (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES)
* - du champ demande (vide, + ou se terminant par + : (+)classe type--id)
* - de l'id courant
*
* @param string $type
* Type d'objet, ou "meta" pour un champ de configuration
* @param string $champ
* Champ SQL concerné
* @param int|string $id
* Identifiant de la ligne sql
* @return string
* Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons)
**/
function classe_boucle_crayon($type, $champ, $id) {
// $type = objet_type($type);
$type = $type[strlen($type) - 1] == 's' ?
substr($type, 0, -1) :
str_replace(
array('hierarchie','syndication'),
array('rubrique','site'),
$type
);
$plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1))
? " $type--$id"
: '';
// test rapide pour verifier que l'id est valide (a-zA-Z0-9)
if (false !== strpos($id, ' ')) {
spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons');
return 'crayon_id_ingerable';
}
return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus;
}