porte_plume_fonctions.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. <?php
  2. /**
  3. * Fonctions utiles pour le Porte Plume
  4. *
  5. * @plugin Porte Plume pour SPIP
  6. * @license GPL
  7. * @package SPIP\PortePlume\BarreOutils
  8. */
  9. if (!defined("_ECRIRE_INC_VERSION")) return;
  10. /**
  11. * Objet contenant les différents paramètres definissant une barre d'outils
  12. * Markitup et permettant d'agir dessus
  13. *
  14. * @example
  15. * $barre = new Barre_Outil($description);
  16. *
  17. * @package SPIP\PortePlume\BarreOutils
  18. */
  19. class Barre_outils{
  20. /**
  21. * Identifiant HTML de la barre
  22. * @todo À supprimer car non utilisé !
  23. * @var string */
  24. public $id = "";
  25. /**
  26. * Nom de la barre d'outil
  27. * @var string */
  28. public $nameSpace = "";
  29. /**
  30. * Langue
  31. * @todo À supprimer car non utilisé !
  32. * @var string */
  33. public $lang = "";
  34. /**
  35. * Option de markitup : rafraîchir la prévisu ?
  36. * @todo À supprimer car non utilisé !
  37. * @var bool */
  38. public $previewAutoRefresh = false;
  39. /**
  40. * Option de markitup : nom de la fonction de prévisu
  41. * @todo À supprimer car on le redéfini dans l'appel javascript !
  42. * @var bool */
  43. public $previewParserPath = "";
  44. /**
  45. * Option de markitup : que faire sur l'appuie de Entrée ?
  46. * @var array */
  47. public $onEnter = array();
  48. /**
  49. * Option de markitup : que faire sur l'appuie de Shift+Entrée ?
  50. * @example array('keepDefault'=>false, 'replaceWith'=>"\n_ ")
  51. * @var array */
  52. public $onShiftEnter = array();
  53. /**
  54. * Option de markitup : que faire sur l'appuie de Control+Entrée ?
  55. * @var array */
  56. public $onCtrlEnter = array();
  57. /**
  58. * Option de markitup : que faire sur l'appuie d'une tabulation ?
  59. * @var array */
  60. public $onTab = array();
  61. /**
  62. * Option de markitup : Code JS à exécuter avant une insertion
  63. * @var string */
  64. public $beforeInsert = "";
  65. /**
  66. * Option de markitup : Code JS à exécuter après une insertion
  67. * @var string */
  68. public $afterInsert = "";
  69. /**
  70. * Description des outils/boutons et leurs sous boutons éventuels
  71. * @var array */
  72. public $markupSet = array();
  73. /**
  74. * Fonctions JS supplémentaires à écrire après la déclaration JSON
  75. * des outils. Ces fonctions peuvent servir aux boutons.
  76. * @var string */
  77. public $functions = "";
  78. /**
  79. * Liste des paramètres valides pour une description d'outils (markupSet)
  80. * @var array */
  81. private $_liste_params_autorises = array(
  82. 'replaceWith',
  83. 'openWith',
  84. 'closeWith',
  85. 'openBlockWith', // sur multiline, avant les lignes selectionnees
  86. 'closeBlockWith', // sur multiline, apres les lignes selectionnees
  87. 'placeHolder', // remplace par ce texte lorsqu'il n'y a pas de selection
  88. 'beforeInsert', // avant l'insertion
  89. 'afterInsert', // apres l'insertion
  90. 'beforeMultiInsert',
  91. 'afterMultiInsert',
  92. 'dropMenu', // appelle un sous menu
  93. 'name', // nom affiche au survol
  94. 'key', // raccourcis clavier
  95. 'className', // classe css utilisee
  96. 'lang', // langues dont le bouton doit apparaitre - array
  97. 'lang_not', // langues dont le bouton ne doit pas apparaitre - array
  98. 'selectionType', // '','word','line' : type de selection (normale, aux mots les plus proches, a la ligne la plus proche)
  99. 'multiline', // open/close sur chaque ligne (mais replace est applique sur l'ensemble de la selection)
  100. 'forceMultiline', // pour faire comme si on faisait systematiquement un control+shift (et replace est applique sur chaque ligne de la selection)
  101. 'separator',
  102. 'call',
  103. 'keepDefault',
  104. // cacher ou afficher facilement des boutons
  105. 'display',
  106. // donner un identifiant unique au bouton (pour le php)
  107. 'id',
  108. );
  109. /**
  110. * Constructeur
  111. *
  112. * Initialise la barre avec les paramètres transmis
  113. * en n'adressant que les paramètres effectivement valides
  114. *
  115. * @api
  116. * @param array $params Paramètres de la barre d'outil
  117. * @return void
  118. */
  119. function Barre_outils($params=array()){
  120. foreach ($params as $p=>$v) {
  121. if (isset($this->$p)) {
  122. // si tableau, on verifie les entrees
  123. if (is_array($v)) {
  124. $v = $this->verif_params($p,$v);
  125. }
  126. $this->$p = $v;
  127. }
  128. }
  129. }
  130. /**
  131. * Vérifie que les paramètres d'une clé existent
  132. * et retourne un tableau des paramètres valides
  133. *
  134. * @param string $nom
  135. * Clé à vérifier (ex: 'markupSet')
  136. * @param array $params
  137. * Paramètres de cette clé (description des boutons ou sous boutons)
  138. * @return array
  139. * Paramètres, soustrait de ceux qui ne sont pas valides
  140. */
  141. function verif_params($nom, $params=array()) {
  142. // si markupset, on boucle sur les items
  143. if (stripos($nom, 'markupSet')!==false) {
  144. foreach ($params as $i=>$v) {
  145. $params[$i] = $this->verif_params($i, $v);
  146. }
  147. }
  148. // sinon on teste la validite
  149. else {
  150. foreach ($params as $p=>$v) {
  151. if (!in_array($p, $this->_liste_params_autorises)) {
  152. unset($params[$p]);
  153. }
  154. }
  155. }
  156. return $params;
  157. }
  158. /**
  159. * Permet d'affecter des paramètres à un élément de la barre
  160. *
  161. * La fonction retourne les paramètres, de sorte qu'on peut s'en servir
  162. * pour simplement récupérer ceux-ci.
  163. *
  164. * Il est possible d'affecter des paramètres avant/après l'élément trouvé
  165. * en definisant une valeur différente pour le $lieu : 'dedans','avant','apres'
  166. * par defaut 'dedans' (modifie l'élément trouvé).
  167. *
  168. * Lorsqu'on demande d'insérer avant ou après, la fonction retourne
  169. * les paramètres inserés
  170. *
  171. * @param array $tableau
  172. * Tableau ou chercher les elements (sert pour la recursion)
  173. * @param string $identifiant
  174. * Identifiant du bouton a afficher
  175. * @param array $params
  176. * Paramètres à affecter à la trouvaille (ou avant ou après).
  177. * Peut être un tableau clé/valeur ou un tableau de tableaux
  178. * clé/valeur (sauf pour $lieu = dedans)
  179. * @param string $lieu
  180. * Lieu d'affectation des paramètres (dedans, avant, apres)
  181. * @param bool $plusieurs
  182. * Définit si $params est une forme simple (tableau cle/valeur)
  183. * ou comporte plusieurs boutons (tableau de tableaux cle/valeur).
  184. * @return array|bool
  185. * Paramètres de l'élément modifié ou paramètres ajoutés
  186. * False si l'identifiant cherché n'est pas trouvé
  187. */
  188. function affecter(&$tableau, $identifiant, $params=array(), $lieu='dedans', $plusieurs=false){
  189. static $cle_de_recherche = 'id'; // ou className ?
  190. if ($tableau === null) // utile ?
  191. $tableau = &$this->markupSet;
  192. if (!in_array($lieu, array('dedans','avant','apres')))
  193. $lieu = 'dedans';
  194. // present en premiere ligne ?
  195. $trouve = false;
  196. foreach ($tableau as $i=>$v){
  197. if (isset($v[$cle_de_recherche]) and ($v[$cle_de_recherche] == $identifiant)) {
  198. $trouve = $i;
  199. break;
  200. }
  201. }
  202. // si trouve, affectations
  203. if (($trouve !== false)) {
  204. if ($params) {
  205. // verifier que les insertions sont correctes
  206. $les_params = ($plusieurs ? $params : array($params));
  207. foreach ($les_params as $i=>$un_params) {
  208. $les_params[$i] = $this->verif_params($identifiant, $un_params);
  209. }
  210. // dedans on merge ($params uniquement tableau cle/valeur)
  211. if ($lieu == 'dedans' && !$plusieurs) {
  212. return $tableau[$trouve] = array_merge($tableau[$trouve], $les_params[0]);
  213. }
  214. // avant ou apres, on insere ($params peut etre tableau cle/valeur ou tableau de tableaux cle/valeur)
  215. elseif ($lieu == 'avant') {
  216. array_splice($tableau, $trouve, 0, $les_params);
  217. return $params;
  218. }
  219. elseif ($lieu == 'apres') {
  220. array_splice($tableau, $trouve+1, 0, $les_params);
  221. return $params;
  222. }
  223. }
  224. return $tableau[$trouve];
  225. }
  226. // recursivons sinon !
  227. foreach ($tableau as $i=>$v){
  228. if (is_array($v)) {
  229. foreach ($v as $m=>$n) {
  230. if (is_array($n) AND ($r = $this->affecter($tableau[$i][$m], $identifiant, $params, $lieu, $plusieurs)))
  231. return $r;
  232. }
  233. }
  234. }
  235. return false;
  236. }
  237. /**
  238. * Permet d'affecter des paramètres à tous les éléments de la barre
  239. * ou à une liste d'identifiants d'éléments indiqués.
  240. *
  241. * @param array $tableau
  242. * Tableau où chercher les éléments
  243. * @param array $params
  244. * Paramètres à affecter aux éléments
  245. * @param array $ids
  246. * Tableau d'identifiants particuliers à qui on affecte les paramètres.
  247. * Si vide, tous les identifiants seront modifiés
  248. * @return bool
  249. * false si aucun paramètre à affecter, true sinon.
  250. */
  251. function affecter_a_tous(&$tableau, $params=array(), $ids=array()){
  252. if (!$params)
  253. return false;
  254. if ($tableau === null)
  255. $tableau = &$this->markupSet;
  256. $params = $this->verif_params('divers', $params);
  257. // merge de premiere ligne
  258. foreach ($tableau as $i=>$v){
  259. if (!$ids OR in_array($v['id'], $ids)) {
  260. $tableau[$i] = array_merge($tableau[$i], $params);
  261. }
  262. // recursion si sous-menu
  263. if (isset($tableau[$i]['dropMenu'])) {
  264. $this->affecter_a_tous($tableau[$i]['dropMenu'], $params, $ids);
  265. }
  266. }
  267. return true;
  268. }
  269. /**
  270. * Affecte les valeurs des paramètres indiqués au bouton demandé
  271. * et retourne l'ensemble des paramètres du bouton (sinon false)
  272. *
  273. * @api
  274. * @param string|array $identifiant
  275. * Identifiant du ou des boutons.
  276. * @param array $params
  277. * Paramètres de l'ajout (tableau paramètre=>valeur)
  278. * @return bool|array
  279. * false si l'identifiant n'a pas été trouvé
  280. * true si plusieurs identifiants,
  281. * array sinon : description de l'identifiant cherché.
  282. */
  283. function set($identifiant, $params=array()) {
  284. // prudence tout de meme a pas tout modifier involontairement (si array)
  285. if (!$identifiant) return false;
  286. if (is_string($identifiant)) {
  287. return $this->affecter($this->markupSet, $identifiant, $params);
  288. }
  289. elseif (is_array($identifiant)) {
  290. return $this->affecter_a_tous($this->markupSet, $params, $identifiant);
  291. }
  292. return false;
  293. }
  294. /**
  295. * Retourne les parametres du bouton demande
  296. *
  297. * @api
  298. * @param string|array $identifiant
  299. * Identifiant du ou des boutons.
  300. * @return bool|array
  301. * false si l'identifiant n'est pas trouvé
  302. * array sinon : Description de l'identifiant cherché.
  303. */
  304. function get($identifiant) {
  305. if ($a = $this->affecter($this->markupSet, $identifiant)) {
  306. return $a;
  307. }
  308. return false;
  309. }
  310. /**
  311. * Affiche le ou les boutons demandés
  312. *
  313. * @api
  314. * @param string|array $identifiant
  315. * Identifiant du ou des boutons
  316. * @return bool|array
  317. * false si l'identifiant n'a pas été trouvé
  318. * true si plusieurs identifiants,
  319. * array sinon : description de l'identifiant cherché.
  320. */
  321. function afficher($identifiant){
  322. return $this->set($identifiant,array('display'=>true));
  323. }
  324. /**
  325. * Cache le ou les boutons demandés
  326. *
  327. * @api
  328. * @param string|array $identifiant
  329. * Identifiant du ou des boutons
  330. * @return bool|array
  331. * false si l'identifiant n'a pas été trouvé
  332. * true si plusieurs identifiants,
  333. * array sinon : description de l'identifiant cherché.
  334. */
  335. function cacher($identifiant){
  336. return $this->set($identifiant, array('display'=>false));
  337. }
  338. /**
  339. * Affiche tous les boutons
  340. *
  341. * @api
  342. * @return bool
  343. * false si aucun paramètre à affecter, true sinon.
  344. */
  345. function afficherTout(){
  346. return $this->affecter_a_tous($this->markupSet, array('display'=>true));
  347. }
  348. /**
  349. * Cache tous les boutons
  350. *
  351. * @api
  352. * @return bool
  353. * false si aucun paramètre à affecter, true sinon.
  354. */
  355. function cacherTout(){
  356. return $this->affecter_a_tous($this->markupSet, array('display'=>false));
  357. }
  358. /**
  359. * Ajoute un bouton ou quelque chose, avant un autre déjà présent
  360. *
  361. * @api
  362. * @param string $identifiant
  363. * Identifiant du bouton où l'on doit se situer
  364. * @param array $params
  365. * Paramètres de l'ajout.
  366. * Description d'un bouton (tableau clé/valeurs).
  367. * @return array|bool
  368. * Paramètres ajoutés avant
  369. * False si l'identifiant cherché n'est pas trouvé
  370. */
  371. function ajouterAvant($identifiant, $params){
  372. return $this->affecter($this->markupSet, $identifiant, $params, 'avant');
  373. }
  374. /**
  375. * Ajoute plusieurs boutons, avant un autre déjà présent
  376. *
  377. * @api
  378. * @param string $identifiant
  379. * Identifiant du bouton où l'on doit se situer
  380. * @param array $tableau_params
  381. * Paramètres de l'ajout.
  382. * Description de plusieurs boutons (tableau de tableaux clé/valeurs).
  383. * @return array|bool
  384. * Paramètres ajoutés avant
  385. * False si l'identifiant cherché n'est pas trouvé
  386. */
  387. function ajouterPlusieursAvant($identifiant, $tableau_params){
  388. return $this->affecter($this->markupSet, $identifiant, $tableau_params, 'avant', true);
  389. }
  390. /**
  391. * Ajoute un bouton ou quelque chose, après un autre déjà présent
  392. *
  393. * @api
  394. * @param string $identifiant
  395. * Identifiant du bouton où l'on doit se situer
  396. * @param array $params
  397. * Paramètres de l'ajout.
  398. * Description d'un bouton (tableau clé/valeurs).
  399. * @return array|bool
  400. * Paramètres ajoutés après
  401. * False si l'identifiant cherché n'est pas trouvé
  402. */
  403. function ajouterApres($identifiant, $params){
  404. return $this->affecter($this->markupSet, $identifiant, $params, 'apres');
  405. }
  406. /**
  407. * Ajoute plusieurs boutons, après un autre déjà présent
  408. *
  409. * @api
  410. * @param string $identifiant
  411. * Identifiant du bouton où l'on doit se situer
  412. * @param array $tableau_params
  413. * Paramètres de l'ajout.
  414. * Description de plusieurs boutons (tableau de tableaux clé/valeurs).
  415. * @return array|bool
  416. * Paramètres ajoutés après
  417. * False si l'identifiant cherché n'est pas trouvé
  418. */
  419. function ajouterPlusieursApres($identifiant, $tableau_params){
  420. return $this->affecter($this->markupSet, $identifiant, $tableau_params, 'apres', true);
  421. }
  422. /**
  423. * Ajoute une fonction JS qui pourra être utilisée par les boutons
  424. *
  425. * @api
  426. * @param string $fonction Code de la fonction JS
  427. * @return void
  428. */
  429. function ajouterFonction($fonction){
  430. if (false === strpos($this->functions, $fonction)){
  431. $this->functions .= "\n" . $fonction . "\n";
  432. }
  433. }
  434. /**
  435. * Supprimer les éléments non affichés (display:false)
  436. * Et les séparateurs (li vides) selon la configuration
  437. *
  438. * @param array $tableau Tableau de description des outils
  439. * @return void
  440. */
  441. function enlever_elements_non_affiches(&$tableau){
  442. if ($tableau === null) // utile ?
  443. $tableau = &$this->markupSet;
  444. foreach ($tableau as $p=>$v) {
  445. if (isset($v['display']) AND !$v['display']) {
  446. unset($tableau[$p]);
  447. $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante.
  448. }
  449. // sinon, on lance une recursion sur les sous-menus
  450. else {
  451. if (isset($v['dropMenu']) and is_array($v['dropMenu'])) {
  452. $this->enlever_elements_non_affiches($tableau[$p]['dropMenu']);
  453. // si le sous-menu est vide
  454. // on enleve le sous menu.
  455. // mais pas le parent ($tableau[$p]), qui peut effectuer une action.
  456. if (!$tableau[$p]['dropMenu']) {
  457. unset($tableau[$p]['dropMenu']);
  458. }
  459. }
  460. }
  461. }
  462. }
  463. /**
  464. * Enlève les séparateurs pour améliorer l'accessibilité
  465. * au détriment du stylage possible de ces séparateurs.
  466. *
  467. * Le bouton précédent le séparateur reçoit une classe CSS 'separateur_avant'
  468. * Celui apres 'separateur_apres'
  469. *
  470. * @param array Tableau de description des outils
  471. * @return void
  472. **/
  473. function enlever_separateurs(&$tableau) {
  474. if ($tableau === null) // utile ?
  475. $tableau = &$this->markupSet;
  476. foreach ($tableau as $p=>$v) {
  477. if (isset($v['separator']) and $v['separator']) {
  478. if (isset($tableau[$p-1])) {
  479. $tableau[$p-1]['className'] .= " separateur_avant";
  480. }
  481. if (isset($tableau[$p+1])) {
  482. $tableau[$p+1]['className'] .= " separateur separateur_apres $v[id]";
  483. }
  484. unset($tableau[$p]);
  485. $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante.
  486. }
  487. // sinon, on lance une recursion sur les sous-menus
  488. else {
  489. if (isset($v['dropMenu']) and is_array($v['dropMenu'])) {
  490. #$this->enlever_separateurs($tableau[$p]['dropMenu']);
  491. }
  492. }
  493. }
  494. }
  495. /**
  496. * Supprime les éléments vides (uniquement à la racine de l'objet)
  497. * et uniquement si chaîne ou tableau.
  498. *
  499. * Supprime les paramètres privés
  500. * Supprime les paramètres inutiles a markitup/json dans les paramètres markupSet
  501. * (id, display, icone)
  502. */
  503. function enlever_parametres_inutiles() {
  504. foreach($this as $p=>$v){
  505. if (!$v) {
  506. if (is_array($v) or is_string($v)) {
  507. unset($this->$p);
  508. }
  509. } elseif ($p == 'functions') {
  510. unset($this->$p);
  511. }
  512. }
  513. foreach($this->markupSet as $p=>$v) {
  514. foreach ($v as $n=>$m) {
  515. if (in_array($n, array('id', 'display'))) {
  516. unset($this->markupSet[$p][$n]);
  517. }
  518. }
  519. }
  520. unset ($this->_liste_params_autorises);
  521. }
  522. /**
  523. * Crée la sortie json pour le javascript des paramètres de la barre
  524. *
  525. * @return string Déclaration json de la barre
  526. */
  527. function creer_json(){
  528. $barre = $this;
  529. $type = $barre->nameSpace;
  530. $fonctions = $barre->functions;
  531. $barre->enlever_elements_non_affiches($this->markupSet);
  532. $barre->enlever_separateurs($this->markupSet);
  533. $barre->enlever_parametres_inutiles();
  534. $json = Barre_outils::json_export($barre);
  535. // on lance la transformation des &chose; en veritables caracteres
  536. // sinon markitup restitue &laquo; au lieu de « directement
  537. // lorsqu'on clique sur l'icone
  538. include_spip('inc/charsets');
  539. $json = unicode2charset(html2unicode($json));
  540. return "\n\nbarre_outils_$type = ".$json . "\n\n $fonctions";
  541. }
  542. /**
  543. * Transforme une variable PHP dans un équivalent javascript (json)
  544. *
  545. * Copié depuis ecrire/inc/json, mais modifié pour que les fonctions
  546. * JavaScript ne soient pas encapsulées dans une chaîne (string)
  547. *
  548. * @access private
  549. * @param mixed the variable
  550. * @return string js script | boolean false if error
  551. */
  552. function json_export($var) {
  553. $asso = false;
  554. switch (true) {
  555. case is_null($var) :
  556. return 'null';
  557. case is_string($var) :
  558. if (strtolower(substr(ltrim($var),0,8))=='function')
  559. return $var;
  560. return '"' . addcslashes($var, "\"\\\n\r") . '"';
  561. case is_bool($var) :
  562. return $var ? 'true' : 'false';
  563. case is_scalar($var) :
  564. return $var;
  565. case is_object( $var) :
  566. $var = get_object_vars($var);
  567. $asso = true;
  568. case is_array($var) :
  569. $keys = array_keys($var);
  570. $ikey = count($keys);
  571. while (!$asso && $ikey--) {
  572. $asso = $ikey !== $keys[$ikey];
  573. }
  574. $sep = '';
  575. if ($asso) {
  576. $ret = '{';
  577. foreach ($var as $key => $elt) {
  578. $ret .= $sep . '"' . $key . '":' . Barre_outils::json_export($elt);
  579. $sep = ',';
  580. }
  581. return $ret ."}\n";
  582. } else {
  583. $ret = '[';
  584. foreach ($var as $elt) {
  585. $ret .= $sep . Barre_outils::json_export($elt);
  586. $sep = ',';
  587. }
  588. return $ret ."]\n";
  589. }
  590. }
  591. return false;
  592. }
  593. }
  594. /**
  595. * Crée le code CSS pour les images des icones des barres d'outils
  596. *
  597. * S'appuie sur la description des jeux de barres disponibles et cherche
  598. * une fonction barre_outils_($barre)_icones pour chaque barre et
  599. * l'exécute si existe, attendant alors en retour un tableau de couples :
  600. * nom de l'outil => nom de l'image
  601. *
  602. * @pipeline_appel porte_plume_lien_classe_vers_icone
  603. *
  604. * @return string Déclaration CSS des icones
  605. */
  606. function barre_outils_css_icones(){
  607. // recuperer la liste, extraire les icones
  608. $css = "";
  609. // liste des barres
  610. if (!$barres = barre_outils_liste())
  611. return null;
  612. // liste des classes css et leur correspondance avec une icone
  613. $classe2icone = array();
  614. foreach ($barres as $barre) {
  615. include_spip('barre_outils/' . $barre);
  616. if ($f = charger_fonction($barre . '_icones', 'barre_outils', true)) {
  617. if (is_array($icones = $f())) {
  618. $classe2icone = array_merge($classe2icone, $icones);
  619. }
  620. }
  621. }
  622. /**
  623. * Permettre aux plugins d'étendre les icones connues du porte plume
  624. *
  625. * On passe la liste des icones connues au pipeline pour ceux qui
  626. * ajoutent de simples icones à des barres existantes
  627. *
  628. * @pipeline_appel porte_plume_lien_classe_vers_icone
  629. * @var array $classe2icone
  630. * Couples identifiant de bouton => nom de l'image (ou tableau)
  631. * Dans le cas d'un tableau, cela indique une sprite : (nom de l'image , position haut, position bas)
  632. * Exemple : 'outil_header1' => array('spt-v1.png','-10px -226px')
  633. */
  634. $classe2icone = pipeline('porte_plume_lien_classe_vers_icone', $classe2icone);
  635. // passage en css
  636. foreach ($classe2icone as $n=>$i) {
  637. $pos="";
  638. if (is_array($i)){
  639. $pos = "background-position:".end($i);
  640. $i = reset($i);
  641. }
  642. if (file_exists($i))
  643. $file = $i;
  644. else
  645. $file = find_in_path("icones_barre/$i");
  646. if ($file)
  647. $css .= "\n.markItUp .$n>a>em {background-image:url(".protocole_implicite(url_absolue($file)).");$pos}";
  648. }
  649. return $css;
  650. }
  651. /**
  652. * Retourne une instance de Barre_outils
  653. * crée à partir du type de barre demandé
  654. *
  655. * Une fonction barre_outils_{type}_dist() retournant la barre doit
  656. * donc exister.
  657. *
  658. * @param string $set
  659. * Type de barre (ex: 'edition')
  660. * @return Barre_Outils|bool
  661. * La barre d'outil si la fonction a été trouvée, false sinon
  662. */
  663. function barre_outils_initialiser($set){
  664. if ($f = charger_fonction($set, 'barre_outils')) {
  665. // retourne une instance de l'objet Barre_outils
  666. return $f();
  667. }
  668. return false;
  669. }
  670. /**
  671. * Retourne la liste des barres d'outils connues
  672. *
  673. * @return array|bool
  674. * Tableau des noms de barres d'outils trouvées
  675. * False si on ne trouve aucune barre.
  676. */
  677. function barre_outils_liste(){
  678. static $sets = -1;
  679. if ($sets !== -1)
  680. return $sets;
  681. // on recupere l'ensemble des barres d'outils connues
  682. if (!$sets = find_all_in_path('barre_outils/','.*[.]php')
  683. or !is_array($sets)) {
  684. spip_log("[Scandale] Porte Plume ne trouve pas de barre d'outils !");
  685. $sets = false;
  686. return $sets;
  687. }
  688. foreach($sets as $fichier=>$adresse) {
  689. $sets[$fichier] = substr($fichier,0,-4); // juste le nom
  690. }
  691. return $sets;
  692. }
  693. /**
  694. * Filtre appliquant les traitements SPIP d'un champ
  695. *
  696. * Applique les filtres prévus sur un champ (et eventuellement un type d'objet)
  697. * sur un texte donné. Sécurise aussi le texte en appliquant safehtml().
  698. *
  699. * Ce mécanisme est à préférer au traditionnel #TEXTE*|propre
  700. *
  701. * traitements_previsu() consulte la globale $table_des_traitements et
  702. * applique le traitement adequat. Si aucun traitement n'est trouvé,
  703. * alors propre() est appliqué.
  704. *
  705. * @package SPIP\PortePlume\Fonctions
  706. * @see champs_traitements() dans public/references.php
  707. * @global table_des_traitements
  708. *
  709. * @param string $texte
  710. * Texte source
  711. * @param string $nom_champ
  712. * Nom du champ (nom de la balise, en majuscules)
  713. * @param string $type_objet
  714. * L'objet a qui appartient le champ (en minuscules)
  715. * @param string $connect
  716. * Nom du connecteur de base de données
  717. * @return string
  718. * Texte traité avec les filtres déclarés pour le champ.
  719. */
  720. function traitements_previsu($texte, $nom_champ='', $type_objet='', $connect=null) {
  721. include_spip('public/interfaces'); // charger les traitements
  722. global $table_des_traitements;
  723. if (!strlen($nom_champ) || !isset($table_des_traitements[$nom_champ])) {
  724. $texte = propre($texte, $connect);
  725. }
  726. else {
  727. include_spip('base/abstract_sql');
  728. $table = table_objet($type_objet);
  729. $ps = $table_des_traitements[$nom_champ];
  730. if (is_array($ps)) {
  731. $ps = $ps[(strlen($table) && isset($ps[$table])) ? $table : 0];
  732. }
  733. if (!$ps) {
  734. $texte = propre($texte, $connect);
  735. } else {
  736. // [FIXME] Éviter une notice sur le eval suivant qui ne connait
  737. // pas la Pile ici. C'est pas tres joli...
  738. $Pile = array( 0 => array() );
  739. // remplacer le placeholder %s par le texte fourni
  740. eval('$texte=' . str_replace('%s', '$texte', $ps) . ';');
  741. }
  742. }
  743. // il faut toujours securiser le texte prévisualisé car il peut contenir n'importe quoi
  744. // et servir de support a une attaque xss ou vol de cookie admin
  745. // on ne peut donc se fier au statut de l'auteur connecté car le contenu ne vient pas
  746. // forcément de lui
  747. return safehtml($texte);
  748. }
  749. ?>