source: spip-zone/_core_/plugins/porte_plume/porte_plume_fonctions.php

Last change on this file was 112006, checked in by marcimat@…, 13 months ago

Accélérer un peu le calcul du javascript du porte plume : on utilise json_encode natif de PHP, modulo un échappement pour les appels de fonctions.

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