--- /dev/null
+<?php\r
+/**\r
+ * Fonctions utiles pour le Porte Plume\r
+ * \r
+ * @plugin Porte Plume pour SPIP\r
+ * @license GPL\r
+ * @package SPIP\PortePlume\BarreOutils\r
+ */\r
+\r
+if (!defined("_ECRIRE_INC_VERSION")) return;\r
+\r
+/**\r
+ * Objet contenant les différents paramètres definissant une barre d'outils\r
+ * Markitup et permettant d'agir dessus\r
+ *\r
+ * @example\r
+ * $barre = new Barre_Outil($description);\r
+ * \r
+ * @package SPIP\PortePlume\BarreOutils\r
+ */\r
+class Barre_outils{\r
+ /**\r
+ * Identifiant HTML de la barre\r
+ * @todo À supprimer car non utilisé !\r
+ * @var string */\r
+ public $id = "";\r
+\r
+ /**\r
+ * Nom de la barre d'outil\r
+ * @var string */\r
+ public $nameSpace = "";\r
+\r
+ /**\r
+ * Langue\r
+ * @todo À supprimer car non utilisé !\r
+ * @var string */\r
+ public $lang = "";\r
+\r
+ /**\r
+ * Option de markitup : rafraîchir la prévisu ?\r
+ * @todo À supprimer car non utilisé !\r
+ * @var bool */\r
+ public $previewAutoRefresh = false;\r
+\r
+ /**\r
+ * Option de markitup : nom de la fonction de prévisu\r
+ * @todo À supprimer car on le redéfini dans l'appel javascript !\r
+ * @var bool */\r
+ public $previewParserPath = "";\r
+\r
+ /**\r
+ * Option de markitup : que faire sur l'appuie de Entrée ?\r
+ * @var array */\r
+ public $onEnter = array();\r
+ \r
+\r
+ /**\r
+ * Option de markitup : que faire sur l'appuie de Shift+Entrée ?\r
+ * @example array('keepDefault'=>false, 'replaceWith'=>"\n_ ")\r
+ * @var array */\r
+ public $onShiftEnter = array();\r
+\r
+ /**\r
+ * Option de markitup : que faire sur l'appuie de Control+Entrée ?\r
+ * @var array */\r
+ public $onCtrlEnter = array();\r
+\r
+ /**\r
+ * Option de markitup : que faire sur l'appuie d'une tabulation ?\r
+ * @var array */\r
+ public $onTab = array();\r
+\r
+ /**\r
+ * Option de markitup : Code JS à exécuter avant une insertion\r
+ * @var string */\r
+ public $beforeInsert = "";\r
+\r
+ /**\r
+ * Option de markitup : Code JS à exécuter après une insertion\r
+ * @var string */\r
+ public $afterInsert = "";\r
+\r
+ /**\r
+ * Description des outils/boutons et leurs sous boutons éventuels\r
+ * @var array */\r
+ public $markupSet = array();\r
+\r
+ /**\r
+ * Fonctions JS supplémentaires à écrire après la déclaration JSON\r
+ * des outils. Ces fonctions peuvent servir aux boutons.\r
+ * @var string */\r
+ public $functions = "";\r
+\r
+ /**\r
+ * Liste des paramètres valides pour une description d'outils (markupSet)\r
+ * @var array */\r
+ private $_liste_params_autorises = array(\r
+ \r
+ 'replaceWith',\r
+ 'openWith',\r
+ 'closeWith',\r
+ 'openBlockWith', // sur multiline, avant les lignes selectionnees\r
+ 'closeBlockWith', // sur multiline, apres les lignes selectionnees\r
+ 'placeHolder', // remplace par ce texte lorsqu'il n'y a pas de selection\r
+ \r
+ 'beforeInsert', // avant l'insertion\r
+ 'afterInsert', // apres l'insertion\r
+ 'beforeMultiInsert',\r
+ 'afterMultiInsert',\r
+\r
+ 'dropMenu', // appelle un sous menu\r
+ \r
+ 'name', // nom affiche au survol\r
+ 'key', // raccourcis clavier\r
+ 'className', // classe css utilisee\r
+ 'lang', // langues dont le bouton doit apparaitre - array\r
+ 'lang_not', // langues dont le bouton ne doit pas apparaitre - array\r
+ 'selectionType', // '','word','line' : type de selection (normale, aux mots les plus proches, a la ligne la plus proche) \r
+ 'multiline', // open/close sur chaque ligne (mais replace est applique sur l'ensemble de la selection)\r
+ 'forceMultiline', // pour faire comme si on faisait systematiquement un control+shift (et replace est applique sur chaque ligne de la selection)\r
+ \r
+ 'separator',\r
+ \r
+ 'call',\r
+ 'keepDefault',\r
+ \r
+ // cacher ou afficher facilement des boutons\r
+ 'display',\r
+ // donner un identifiant unique au bouton (pour le php)\r
+ 'id',\r
+ );\r
+\r
+ /**\r
+ * Constructeur\r
+ * \r
+ * Initialise la barre avec les paramètres transmis\r
+ * en n'adressant que les paramètres effectivement valides\r
+ *\r
+ * @api\r
+ * @param array $params Paramètres de la barre d'outil\r
+ * @return void\r
+ */\r
+ function Barre_outils($params=array()){\r
+ foreach ($params as $p=>$v) {\r
+ if (isset($this->$p)) {\r
+ // si tableau, on verifie les entrees\r
+ if (is_array($v)) {\r
+ $v = $this->verif_params($p,$v);\r
+ }\r
+ $this->$p = $v;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Vérifie que les paramètres d'une clé existent\r
+ * et retourne un tableau des paramètres valides\r
+ * \r
+ * @param string $nom\r
+ * Clé à vérifier (ex: 'markupSet')\r
+ * @param array $params\r
+ * Paramètres de cette clé (description des boutons ou sous boutons)\r
+ * @return array\r
+ * Paramètres, soustrait de ceux qui ne sont pas valides\r
+ */\r
+ function verif_params($nom, $params=array()) {\r
+ // si markupset, on boucle sur les items\r
+ if (stripos($nom, 'markupSet')!==false) {\r
+ foreach ($params as $i=>$v) {\r
+ $params[$i] = $this->verif_params($i, $v);\r
+ }\r
+ } \r
+ // sinon on teste la validite\r
+ else {\r
+ foreach ($params as $p=>$v) {\r
+ if (!in_array($p, $this->_liste_params_autorises)) {\r
+ unset($params[$p]);\r
+ }\r
+ }\r
+ }\r
+ return $params;\r
+ }\r
+\r
+ /**\r
+ * Permet d'affecter des paramètres à un élément de la barre\r
+ * \r
+ * La fonction retourne les paramètres, de sorte qu'on peut s'en servir\r
+ * pour simplement récupérer ceux-ci.\r
+ * \r
+ * Il est possible d'affecter des paramètres avant/après l'élément trouvé\r
+ * en definisant une valeur différente pour le $lieu : 'dedans','avant','apres'\r
+ * par defaut 'dedans' (modifie l'élément trouvé).\r
+ * \r
+ * Lorsqu'on demande d'insérer avant ou après, la fonction retourne\r
+ * les paramètres inserés\r
+ * \r
+ * @param array $tableau\r
+ * Tableau ou chercher les elements (sert pour la recursion)\r
+ * @param string $identifiant\r
+ * Identifiant du bouton a afficher\r
+ * @param array $params\r
+ * Paramètres à affecter à la trouvaille (ou avant ou après).\r
+ * Peut être un tableau clé/valeur ou un tableau de tableaux\r
+ * clé/valeur (sauf pour $lieu = dedans)\r
+ * @param string $lieu\r
+ * Lieu d'affectation des paramètres (dedans, avant, apres)\r
+ * @param bool $plusieurs\r
+ * Définit si $params est une forme simple (tableau cle/valeur)\r
+ * ou comporte plusieurs boutons (tableau de tableaux cle/valeur).\r
+ * @return array|bool\r
+ * Paramètres de l'élément modifié ou paramètres ajoutés\r
+ * False si l'identifiant cherché n'est pas trouvé\r
+ */\r
+ function affecter(&$tableau, $identifiant, $params=array(), $lieu='dedans', $plusieurs=false){\r
+ static $cle_de_recherche = 'id'; // ou className ?\r
+ \r
+ if ($tableau === null) // utile ?\r
+ $tableau = &$this->markupSet;\r
+\r
+ if (!in_array($lieu, array('dedans','avant','apres'))) \r
+ $lieu = 'dedans';\r
+\r
+ // present en premiere ligne ?\r
+ $trouve = false;\r
+ foreach ($tableau as $i=>$v){\r
+ if (isset($v[$cle_de_recherche]) and ($v[$cle_de_recherche] == $identifiant)) {\r
+ $trouve = $i;\r
+ break;\r
+ }\r
+ }\r
+ // si trouve, affectations\r
+ if (($trouve !== false)) {\r
+ if ($params) {\r
+ // verifier que les insertions sont correctes\r
+ $les_params = ($plusieurs ? $params : array($params));\r
+ foreach ($les_params as $i=>$un_params) {\r
+ $les_params[$i] = $this->verif_params($identifiant, $un_params);\r
+ }\r
+ \r
+ // dedans on merge ($params uniquement tableau cle/valeur)\r
+ if ($lieu == 'dedans' && !$plusieurs) {\r
+ return $tableau[$trouve] = array_merge($tableau[$trouve], $les_params[0]);\r
+ }\r
+ // avant ou apres, on insere ($params peut etre tableau cle/valeur ou tableau de tableaux cle/valeur)\r
+ elseif ($lieu == 'avant') {\r
+ array_splice($tableau, $trouve, 0, $les_params);\r
+ return $params;\r
+ }\r
+ elseif ($lieu == 'apres') {\r
+ array_splice($tableau, $trouve+1, 0, $les_params);\r
+ return $params;\r
+ }\r
+ }\r
+ return $tableau[$trouve];\r
+ }\r
+\r
+ // recursivons sinon !\r
+ foreach ($tableau as $i=>$v){\r
+ if (is_array($v)) {\r
+ foreach ($v as $m=>$n) {\r
+ if (is_array($n) AND ($r = $this->affecter($tableau[$i][$m], $identifiant, $params, $lieu, $plusieurs))) \r
+ return $r;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ \r
+ /**\r
+ * Permet d'affecter des paramètres à tous les éléments de la barre\r
+ * ou à une liste d'identifiants d'éléments indiqués.\r
+ * \r
+ * @param array $tableau\r
+ * Tableau où chercher les éléments\r
+ * @param array $params\r
+ * Paramètres à affecter aux éléments\r
+ * @param array $ids\r
+ * Tableau d'identifiants particuliers à qui on affecte les paramètres.\r
+ * Si vide, tous les identifiants seront modifiés\r
+ * @return bool\r
+ * false si aucun paramètre à affecter, true sinon.\r
+ */\r
+ function affecter_a_tous(&$tableau, $params=array(), $ids=array()){\r
+ if (!$params)\r
+ return false;\r
+ \r
+ if ($tableau === null)\r
+ $tableau = &$this->markupSet;\r
+\r
+ $params = $this->verif_params('divers', $params);\r
+\r
+ // merge de premiere ligne\r
+ foreach ($tableau as $i=>$v){\r
+ if (!$ids OR in_array($v['id'], $ids)) {\r
+ $tableau[$i] = array_merge($tableau[$i], $params);\r
+ }\r
+ // recursion si sous-menu\r
+ if (isset($tableau[$i]['dropMenu'])) {\r
+ $this->affecter_a_tous($tableau[$i]['dropMenu'], $params, $ids);\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Affecte les valeurs des paramètres indiqués au bouton demandé\r
+ * et retourne l'ensemble des paramètres du bouton (sinon false)\r
+ *\r
+ * @api\r
+ * @param string|array $identifiant\r
+ * Identifiant du ou des boutons.\r
+ * @param array $params\r
+ * Paramètres de l'ajout (tableau paramètre=>valeur)\r
+ * @return bool|array\r
+ * false si l'identifiant n'a pas été trouvé\r
+ * true si plusieurs identifiants,\r
+ * array sinon : description de l'identifiant cherché.\r
+ */\r
+ function set($identifiant, $params=array()) {\r
+ // prudence tout de meme a pas tout modifier involontairement (si array)\r
+ if (!$identifiant) return false;\r
+ \r
+ if (is_string($identifiant)) {\r
+ return $this->affecter($this->markupSet, $identifiant, $params);\r
+ }\r
+ elseif (is_array($identifiant)) {\r
+ return $this->affecter_a_tous($this->markupSet, $params, $identifiant);\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ /**\r
+ * Retourne les parametres du bouton demande\r
+ *\r
+ * @api\r
+ * @param string|array $identifiant\r
+ * Identifiant du ou des boutons.\r
+ * @return bool|array\r
+ * false si l'identifiant n'est pas trouvé\r
+ * array sinon : Description de l'identifiant cherché.\r
+ */\r
+ function get($identifiant) {\r
+ if ($a = $this->affecter($this->markupSet, $identifiant)) {\r
+ return $a;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Affiche le ou les boutons demandés\r
+ *\r
+ * @api\r
+ * @param string|array $identifiant\r
+ * Identifiant du ou des boutons\r
+ * @return bool|array\r
+ * false si l'identifiant n'a pas été trouvé\r
+ * true si plusieurs identifiants,\r
+ * array sinon : description de l'identifiant cherché.\r
+ */\r
+ function afficher($identifiant){\r
+ return $this->set($identifiant,array('display'=>true));\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Cache le ou les boutons demandés\r
+ *\r
+ * @api\r
+ * @param string|array $identifiant\r
+ * Identifiant du ou des boutons\r
+ * @return bool|array\r
+ * false si l'identifiant n'a pas été trouvé\r
+ * true si plusieurs identifiants,\r
+ * array sinon : description de l'identifiant cherché.\r
+ */\r
+ function cacher($identifiant){\r
+ return $this->set($identifiant, array('display'=>false));\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Affiche tous les boutons\r
+ *\r
+ * @api\r
+ * @return bool\r
+ * false si aucun paramètre à affecter, true sinon.\r
+ */\r
+ function afficherTout(){\r
+ return $this->affecter_a_tous($this->markupSet, array('display'=>true));\r
+ }\r
+ \r
+ /**\r
+ * Cache tous les boutons\r
+ *\r
+ * @api\r
+ * @return bool\r
+ * false si aucun paramètre à affecter, true sinon.\r
+ */\r
+ function cacherTout(){\r
+ return $this->affecter_a_tous($this->markupSet, array('display'=>false));\r
+ }\r
+ \r
+\r
+ /**\r
+ * Ajoute un bouton ou quelque chose, avant un autre déjà présent\r
+ *\r
+ * @api\r
+ * @param string $identifiant\r
+ * Identifiant du bouton où l'on doit se situer\r
+ * @param array $params\r
+ * Paramètres de l'ajout.\r
+ * Description d'un bouton (tableau clé/valeurs).\r
+ * @return array|bool\r
+ * Paramètres ajoutés avant\r
+ * False si l'identifiant cherché n'est pas trouvé\r
+ */\r
+ function ajouterAvant($identifiant, $params){\r
+ return $this->affecter($this->markupSet, $identifiant, $params, 'avant');\r
+ }\r
+\r
+ /**\r
+ * Ajoute plusieurs boutons, avant un autre déjà présent\r
+ *\r
+ * @api\r
+ * @param string $identifiant\r
+ * Identifiant du bouton où l'on doit se situer\r
+ * @param array $tableau_params\r
+ * Paramètres de l'ajout.\r
+ * Description de plusieurs boutons (tableau de tableaux clé/valeurs).\r
+ * @return array|bool\r
+ * Paramètres ajoutés avant\r
+ * False si l'identifiant cherché n'est pas trouvé\r
+ */\r
+ function ajouterPlusieursAvant($identifiant, $tableau_params){\r
+ return $this->affecter($this->markupSet, $identifiant, $tableau_params, 'avant', true);\r
+ }\r
+\r
+ /**\r
+ * Ajoute un bouton ou quelque chose, après un autre déjà présent\r
+ *\r
+ * @api\r
+ * @param string $identifiant\r
+ * Identifiant du bouton où l'on doit se situer\r
+ * @param array $params\r
+ * Paramètres de l'ajout.\r
+ * Description d'un bouton (tableau clé/valeurs).\r
+ * @return array|bool\r
+ * Paramètres ajoutés après\r
+ * False si l'identifiant cherché n'est pas trouvé\r
+ */\r
+ function ajouterApres($identifiant, $params){\r
+ return $this->affecter($this->markupSet, $identifiant, $params, 'apres');\r
+ }\r
+\r
+ /**\r
+ * Ajoute plusieurs boutons, après un autre déjà présent\r
+ *\r
+ * @api\r
+ * @param string $identifiant\r
+ * Identifiant du bouton où l'on doit se situer\r
+ * @param array $tableau_params\r
+ * Paramètres de l'ajout.\r
+ * Description de plusieurs boutons (tableau de tableaux clé/valeurs).\r
+ * @return array|bool\r
+ * Paramètres ajoutés après\r
+ * False si l'identifiant cherché n'est pas trouvé\r
+ */\r
+ function ajouterPlusieursApres($identifiant, $tableau_params){\r
+ return $this->affecter($this->markupSet, $identifiant, $tableau_params, 'apres', true);\r
+ }\r
+ \r
+ /**\r
+ * Ajoute une fonction JS qui pourra être utilisée par les boutons\r
+ *\r
+ * @api\r
+ * @param string $fonction Code de la fonction JS\r
+ * @return void\r
+ */\r
+ function ajouterFonction($fonction){\r
+ if (false === strpos($this->functions, $fonction)){\r
+ $this->functions .= "\n" . $fonction . "\n";\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Supprimer les éléments non affichés (display:false)\r
+ * Et les séparateurs (li vides) selon la configuration\r
+ * \r
+ * @param array $tableau Tableau de description des outils\r
+ * @return void\r
+ */\r
+ function enlever_elements_non_affiches(&$tableau){\r
+ if ($tableau === null) // utile ?\r
+ $tableau = &$this->markupSet;\r
+ \r
+ foreach ($tableau as $p=>$v) {\r
+\r
+ if (isset($v['display']) AND !$v['display']) {\r
+ unset($tableau[$p]);\r
+ $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante.\r
+ }\r
+ // sinon, on lance une recursion sur les sous-menus\r
+ else {\r
+ if (isset($v['dropMenu']) and is_array($v['dropMenu'])) {\r
+ $this->enlever_elements_non_affiches($tableau[$p]['dropMenu']);\r
+ // si le sous-menu est vide\r
+ // on enleve le sous menu.\r
+ // mais pas le parent ($tableau[$p]), qui peut effectuer une action.\r
+ if (!$tableau[$p]['dropMenu']) {\r
+ unset($tableau[$p]['dropMenu']);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Enlève les séparateurs pour améliorer l'accessibilité\r
+ * au détriment du stylage possible de ces séparateurs.\r
+ *\r
+ * Le bouton précédent le séparateur reçoit une classe CSS 'separateur_avant'\r
+ * Celui apres 'separateur_apres'\r
+ * \r
+ * @param array Tableau de description des outils \r
+ * @return void\r
+ **/\r
+ function enlever_separateurs(&$tableau) {\r
+ if ($tableau === null) // utile ?\r
+ $tableau = &$this->markupSet;\r
+\r
+ foreach ($tableau as $p=>$v) {\r
+ if (isset($v['separator']) and $v['separator']) {\r
+ if (isset($tableau[$p-1])) {\r
+ $tableau[$p-1]['className'] .= " separateur_avant";\r
+ }\r
+ if (isset($tableau[$p+1])) {\r
+ $tableau[$p+1]['className'] .= " separateur separateur_apres $v[id]";\r
+ }\r
+ unset($tableau[$p]);\r
+ $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante.\r
+ }\r
+ // sinon, on lance une recursion sur les sous-menus\r
+ else {\r
+ if (isset($v['dropMenu']) and is_array($v['dropMenu'])) {\r
+ #$this->enlever_separateurs($tableau[$p]['dropMenu']);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Supprime les éléments vides (uniquement à la racine de l'objet)\r
+ * et uniquement si chaîne ou tableau.\r
+ * \r
+ * Supprime les paramètres privés\r
+ * Supprime les paramètres inutiles a markitup/json dans les paramètres markupSet\r
+ * (id, display, icone)\r
+ */\r
+ function enlever_parametres_inutiles() {\r
+ foreach($this as $p=>$v){\r
+ if (!$v) {\r
+ if (is_array($v) or is_string($v)) {\r
+ unset($this->$p);\r
+ }\r
+ } elseif ($p == 'functions') {\r
+ unset($this->$p);\r
+ }\r
+ }\r
+ foreach($this->markupSet as $p=>$v) {\r
+ foreach ($v as $n=>$m) {\r
+ if (in_array($n, array('id', 'display'))) {\r
+ unset($this->markupSet[$p][$n]);\r
+ }\r
+ }\r
+ }\r
+ unset ($this->_liste_params_autorises);\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Crée la sortie json pour le javascript des paramètres de la barre\r
+ * \r
+ * @return string Déclaration json de la barre\r
+ */\r
+ function creer_json(){\r
+ $barre = $this;\r
+ $type = $barre->nameSpace;\r
+ $fonctions = $barre->functions;\r
+\r
+ $barre->enlever_elements_non_affiches($this->markupSet);\r
+ $barre->enlever_separateurs($this->markupSet);\r
+ $barre->enlever_parametres_inutiles();\r
+ \r
+ $json = Barre_outils::json_export($barre);\r
+\r
+ // on lance la transformation des &chose; en veritables caracteres\r
+ // sinon markitup restitue « au lieu de « directement\r
+ // lorsqu'on clique sur l'icone\r
+ include_spip('inc/charsets');\r
+ $json = unicode2charset(html2unicode($json));\r
+ return "\n\nbarre_outils_$type = ".$json . "\n\n $fonctions";\r
+ }\r
+\r
+ /**\r
+ * Transforme une variable PHP dans un équivalent javascript (json)\r
+ * \r
+ * Copié depuis ecrire/inc/json, mais modifié pour que les fonctions\r
+ * JavaScript ne soient pas encapsulées dans une chaîne (string)\r
+ * \r
+ * @access private\r
+ * @param mixed the variable\r
+ * @return string js script | boolean false if error\r
+ */\r
+ function json_export($var) {\r
+ $asso = false;\r
+ switch (true) {\r
+ case is_null($var) :\r
+ return 'null';\r
+ case is_string($var) :\r
+ if (strtolower(substr(ltrim($var),0,8))=='function')\r
+ return $var;\r
+ return '"' . addcslashes($var, "\"\\\n\r") . '"';\r
+ case is_bool($var) :\r
+ return $var ? 'true' : 'false';\r
+ case is_scalar($var) :\r
+ return $var;\r
+ case is_object( $var) :\r
+ $var = get_object_vars($var);\r
+ $asso = true;\r
+ case is_array($var) :\r
+ $keys = array_keys($var);\r
+ $ikey = count($keys);\r
+ while (!$asso && $ikey--) {\r
+ $asso = $ikey !== $keys[$ikey];\r
+ }\r
+ $sep = '';\r
+ if ($asso) {\r
+ $ret = '{';\r
+ foreach ($var as $key => $elt) {\r
+ $ret .= $sep . '"' . $key . '":' . Barre_outils::json_export($elt);\r
+ $sep = ',';\r
+ }\r
+ return $ret ."}\n";\r
+ } else {\r
+ $ret = '[';\r
+ foreach ($var as $elt) {\r
+ $ret .= $sep . Barre_outils::json_export($elt);\r
+ $sep = ',';\r
+ }\r
+ return $ret ."]\n";\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+}\r
+\r
+\r
+/**\r
+ * Crée le code CSS pour les images des icones des barres d'outils\r
+ * \r
+ * S'appuie sur la description des jeux de barres disponibles et cherche\r
+ * une fonction barre_outils_($barre)_icones pour chaque barre et\r
+ * l'exécute si existe, attendant alors en retour un tableau de couples :\r
+ * nom de l'outil => nom de l'image\r
+ *\r
+ * @pipeline_appel porte_plume_lien_classe_vers_icone\r
+ * \r
+ * @return string Déclaration CSS des icones\r
+ */\r
+function barre_outils_css_icones(){\r
+ // recuperer la liste, extraire les icones\r
+ $css = "";\r
+ \r
+ // liste des barres\r
+ if (!$barres = barre_outils_liste()) \r
+ return null;\r
+ \r
+ // liste des classes css et leur correspondance avec une icone\r
+ $classe2icone = array();\r
+ foreach ($barres as $barre) {\r
+ include_spip('barre_outils/' . $barre);\r
+ if ($f = charger_fonction($barre . '_icones', 'barre_outils', true)) {\r
+ if (is_array($icones = $f())) {\r
+ $classe2icone = array_merge($classe2icone, $icones);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Permettre aux plugins d'étendre les icones connues du porte plume\r
+ *\r
+ * On passe la liste des icones connues au pipeline pour ceux qui\r
+ * ajoutent de simples icones à des barres existantes\r
+ *\r
+ * @pipeline_appel porte_plume_lien_classe_vers_icone\r
+ * @var array $classe2icone\r
+ * Couples identifiant de bouton => nom de l'image (ou tableau)\r
+ * Dans le cas d'un tableau, cela indique une sprite : (nom de l'image , position haut, position bas)\r
+ * Exemple : 'outil_header1' => array('spt-v1.png','-10px -226px')\r
+ */\r
+ $classe2icone = pipeline('porte_plume_lien_classe_vers_icone', $classe2icone);\r
+ \r
+ // passage en css\r
+ foreach ($classe2icone as $n=>$i) {\r
+ $pos="";\r
+ if (is_array($i)){\r
+ $pos = "background-position:".end($i);\r
+ $i = reset($i);\r
+ }\r
+ if (file_exists($i))\r
+ $file = $i;\r
+ else\r
+ $file = find_in_path("icones_barre/$i");\r
+ if ($file)\r
+ $css .= "\n.markItUp .$n>a>em {background-image:url(".protocole_implicite(url_absolue($file)).");$pos}";\r
+ }\r
+\r
+ return $css;\r
+}\r
+\r
+\r
+/**\r
+ * Retourne une instance de Barre_outils\r
+ * crée à partir du type de barre demandé\r
+ *\r
+ * Une fonction barre_outils_{type}_dist() retournant la barre doit\r
+ * donc exister.\r
+ * \r
+ * @param string $set\r
+ * Type de barre (ex: 'edition')\r
+ * @return Barre_Outils|bool\r
+ * La barre d'outil si la fonction a été trouvée, false sinon\r
+ */\r
+function barre_outils_initialiser($set){\r
+ if ($f = charger_fonction($set, 'barre_outils')) {\r
+ // retourne une instance de l'objet Barre_outils\r
+ return $f();\r
+ }\r
+ return false;\r
+}\r
+\r
+/**\r
+ * Retourne la liste des barres d'outils connues\r
+ *\r
+ * @return array|bool\r
+ * Tableau des noms de barres d'outils trouvées\r
+ * False si on ne trouve aucune barre.\r
+ */\r
+function barre_outils_liste(){\r
+ static $sets = -1;\r
+ if ($sets !== -1) \r
+ return $sets;\r
+\r
+ // on recupere l'ensemble des barres d'outils connues\r
+ if (!$sets = find_all_in_path('barre_outils/','.*[.]php')\r
+ or !is_array($sets)) {\r
+ spip_log("[Scandale] Porte Plume ne trouve pas de barre d'outils !");\r
+ $sets = false;\r
+ return $sets;\r
+ }\r
+\r
+ foreach($sets as $fichier=>$adresse) {\r
+ $sets[$fichier] = substr($fichier,0,-4); // juste le nom\r
+ }\r
+ return $sets;\r
+}\r
+\r
+/**\r
+ * Filtre appliquant les traitements SPIP d'un champ\r
+ *\r
+ * Applique les filtres prévus sur un champ (et eventuellement un type d'objet)\r
+ * sur un texte donné. Sécurise aussi le texte en appliquant safehtml().\r
+ *\r
+ * Ce mécanisme est à préférer au traditionnel #TEXTE*|propre\r
+ * \r
+ * traitements_previsu() consulte la globale $table_des_traitements et\r
+ * applique le traitement adequat. Si aucun traitement n'est trouvé,\r
+ * alors propre() est appliqué.\r
+ *\r
+ * @package SPIP\PortePlume\Fonctions\r
+ * @see champs_traitements() dans public/references.php\r
+ * @global table_des_traitements\r
+ * \r
+ * @param string $texte\r
+ * Texte source\r
+ * @param string $nom_champ\r
+ * Nom du champ (nom de la balise, en majuscules)\r
+ * @param string $type_objet\r
+ * L'objet a qui appartient le champ (en minuscules)\r
+ * @param string $connect\r
+ * Nom du connecteur de base de données\r
+ * @return string\r
+ * Texte traité avec les filtres déclarés pour le champ.\r
+ */\r
+function traitements_previsu($texte, $nom_champ='', $type_objet='', $connect=null) {\r
+ include_spip('public/interfaces'); // charger les traitements\r
+\r
+ global $table_des_traitements;\r
+ if (!strlen($nom_champ) || !isset($table_des_traitements[$nom_champ])) {\r
+ $texte = propre($texte, $connect);\r
+ }\r
+ else {\r
+ include_spip('base/abstract_sql');\r
+ $table = table_objet($type_objet);\r
+ $ps = $table_des_traitements[$nom_champ];\r
+ if (is_array($ps)) {\r
+ $ps = $ps[(strlen($table) && isset($ps[$table])) ? $table : 0];\r
+ }\r
+ if (!$ps) {\r
+ $texte = propre($texte, $connect);\r
+ } else {\r
+ // [FIXME] Éviter une notice sur le eval suivant qui ne connait\r
+ // pas la Pile ici. C'est pas tres joli...\r
+ $Pile = array( 0 => array() );\r
+ // remplacer le placeholder %s par le texte fourni\r
+ eval('$texte=' . str_replace('%s', '$texte', $ps) . ';');\r
+ }\r
+ }\r
+ // il faut toujours securiser le texte prévisualisé car il peut contenir n'importe quoi\r
+ // et servir de support a une attaque xss ou vol de cookie admin\r
+ // on ne peut donc se fier au statut de l'auteur connecté car le contenu ne vient pas\r
+ // forcément de lui\r
+ return safehtml($texte);\r
+}\r
+?>\r