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

Last change on this file since 50583 was 50583, checked in by cedric@…, 8 years ago

ne pas générer d'url absolue mais uniquement des urls relatives au protocole dans la css calculée du porte-plume

File size: 16.8 KB
Line 
1<?php
2/*
3 * Plugin Porte Plume pour SPIP 2
4 * Licence GPL
5 * Auteur Matthieu Marcillaud
6 */
7include_spip('public/admin'); // pour stripos()
8
9/* pour compat 2.0 (inutile a partir de  2.1) */
10if (version_compare($GLOBALS['spip_version_branche'],'2.1.0 dev','<')) {
11        include_spip('inc/layer'); // pour effacer la globale browser_caret
12        $GLOBALS['browser_caret']="";
13}
14
15/**
16 * La class Barre_outils est un objet contenant les differents
17 * parametres definissant une barre markitup
18 *
19 */
20class Barre_outils{
21        var $id = "";
22        var $nameSpace = "";
23        var $lang = "";
24        var $previewAutoRefresh = false;
25        var $previewParserPath = "";
26        var $onEnter = array();
27        var $onShiftEnter = array();
28        var $onCtrlEnter = array();
29        var $onTab = array();
30        var $beforeInsert = "";
31        var $afterInsert = "";
32        var $markupSet = array();
33       
34        // liste de fonctions supplementaires a mettre apres le json
35        var $functions = "";
36       
37        // private
38        var $_liste_params_autorises = array(
39       
40                'replaceWith',
41                'openWith',
42                'closeWith',
43                'placeHolder', // remplace par ce texte lorsqu'il n'y a pas de selection
44               
45                'beforeInsert', // avant l'insertion
46                'afterInsert', // apres l'insertion
47                'beforeMultiInsert',
48                'afterMultiInsert',
49
50                'dropMenu', // appelle un sous menu
51               
52                'name', // nom affiche au survol
53                'key', // raccourcis clavier
54                'className', // classe css utilisee
55                'lang', // langues dont le bouton doit apparaitre - array
56                'lang_not', // langues dont le bouton ne doit pas apparaitre - array
57                'selectionType', // '','word','line' : type de selection (normale, aux mots les plus proches, a la ligne la plus proche)
58                'forceMultiline', // pour faire comme si on faisait systematiquement un control+shift (multi ligne)
59               
60                'separator',
61               
62                'call',
63                'keepDefault',
64               
65               
66                // icon est ajoute pour eventuellement creer un jour
67                // la css automatiquement...
68                // mais ca pose des problemes la tout de suite
69                // car il faudrait generer une css differente des qu'un bouton change
70                // ce qui est assez idiot
71                // ou alors il faudrait que jquery mette l'icone en fond des boutons automatiquement
72                'icon', 
73               
74                // cacher ou afficher facilement des boutons
75                'display',
76                // donner un identifiant unique au bouton (pour le php)
77                'id',
78        );
79       
80        /**
81         * Initialise les parametres
82         * @param array $params :  param->valeur
83         */
84        function Barre_outils($params=array()){
85                foreach ($params as $p=>$v) {
86                        if (isset($this->$p)) {
87                                // si tableau, on verifie les entrees
88                                if (is_array($v)) {
89                                        $v = $this->verif_params($p,$v);
90                                }
91                                $this->$p = $v;
92                        }
93                }
94        }
95       
96        /**
97         * Verifie que les parametres transmis existent
98         * et retourne un tableau des parametres valides
99         *
100         * @param string $nom : cle du parametre (eventuel)
101         * @param array  $params : parametres du parametre (param->valeur)
102         */
103        function verif_params($nom, $params=array()) {
104                // si markupset, on boucle sur les items
105                if (stripos($nom, 'markupSet')!==false) {
106                        foreach ($params as $i=>$v) {
107                                $params[$i] = $this->verif_params($i, $v);
108                        }
109                } 
110                // sinon on teste la validite
111                else {
112                        foreach ($params as $p=>$v) {
113                                if (!in_array($p, $this->_liste_params_autorises)) {
114                                        unset($params[$p]);
115                                }
116                        }
117                }
118                return $params;
119        }
120       
121        /**
122         * Permet d'affecter des parametres a un element de la barre
123         * La fonction retourne les parametres, de sorte qu'on peut s'en servir pour simplement recuperer ceux-ci.
124         *
125         * Il est possible d'affecter des parametres avant/apres l'element trouve
126         * en definisant une valeur differente pour le $lieu : 'dedans','avant','apres'
127         * par defaut 'dedans' (modifie l'element trouve).
128         *
129         * Lorsqu'on demande d'inserer avant ou apres, la fonction retourne les parametres inseres
130         *
131         * @param string $identifiant : identifiant du bouton a afficher
132         * @param array $params : parametres a affecter a la trouvaille
133         * @param string $lieu : lieu d'affectation des parametres (dedans, avant, apres)
134         * @param false/array $tableau : tableau ou chercher les elements (sert pour la recursion)
135         */
136        function affecter(&$tableau, $identifiant, $params=array(), $lieu='dedans'){
137                static $cle_de_recherche = 'id'; // ou className ?
138               
139                if ($tableau === null)
140                        $tableau = &$this->markupSet;
141                       
142                if (!in_array($lieu, array('dedans','avant','apres'))) 
143                        $lieu = 'dedans';
144               
145                // present en premiere ligne ?
146                $trouve = false;
147                foreach ($tableau as $i=>$v){
148                        if (isset($v[$cle_de_recherche]) and ($v[$cle_de_recherche] == $identifiant)) {
149                                $trouve = $i;
150                                break;
151                        }
152                }
153                // si trouve, affectations
154                if (($trouve !== false)) {
155                        if ($params) {
156                                $params = $this->verif_params($identifiant, $params);
157                                // dedans on merge
158                                if ($lieu == 'dedans') {
159                                        return $tableau[$trouve] = array_merge($tableau[$trouve], $params);
160                                }
161                                // avant ou apres, on insere
162                                elseif ($lieu == 'avant') {
163                                        array_splice($tableau, $trouve, 0, array($params));
164                                        return $params;
165                                }
166                                elseif ($lieu == 'apres') {
167                                        array_splice($tableau, $trouve+1, 0, array($params));
168                                        return $params;
169                                }
170                        }
171                        return $tableau[$trouve];
172                }
173                               
174                // recursivons sinon !
175                foreach ($tableau as $i=>$v){
176                        if (is_array($v)) {
177                                foreach ($v as $m=>$n) {
178                                        if (is_array($n) AND ($r = $this->affecter($tableau[$i][$m], $identifiant, $params, $lieu))) 
179                                                return $r;
180                                }
181                        }
182                }
183                return false;
184        }
185
186       
187        /**
188         * Permet d'affecter des parametres toutes les elements de la barre
189         *
190         * @param array $params : parametres a affecter a la trouvaille
191         * @param array $ids : tableau identifiants particuliers a qui on affecte les parametres
192         *                     si vide, tous les identifiants seront modifies
193         * @param false/array $tableau : tableau ou chercher les elements (sert pour la recursion)
194         */
195        function affecter_a_tous(&$tableau, $params=array(), $ids=array()){
196                if (!$params)
197                        return false;
198               
199                if ($tableau === null)
200                        $tableau = &$this->markupSet;
201
202                $params = $this->verif_params('divers', $params);
203
204                // merge de premiere ligne
205                foreach ($tableau as $i=>$v){
206                        if (!$ids OR in_array($v['id'], $ids)) {
207                                $tableau[$i] = array_merge($tableau[$i], $params);
208                        }
209                        // recursion si sous-menu
210                        if (isset($tableau[$i]['dropMenu'])) {
211                                $this->affecter_a_tous($tableau[$i]['dropMenu'], $params, $ids);
212                        }
213                }
214                return true;
215        }
216       
217               
218        /**
219         * Affecte les valeurs des parametres indiques au bouton demande
220         * et retourne l'ensemble des parametres du bouton (sinon false)
221         *
222         * @param string/array $identifiant : id du ou des boutons a afficher
223         * @param array $params : param->valeur
224         * @return mixed
225         */
226        function set($identifiant, $params=array()) {
227                // prudence tout de meme a pas tout modifier involontairement (si array)
228                if (!$identifiant) return false;
229                       
230                if (is_string($identifiant)) {
231                        return $this->affecter($this->markupSet, $identifiant, $params);
232                }
233                elseif (is_array($identifiant)) {
234                        return $this->affecter_a_tous($this->markupSet, $params, $identifiant);
235                }
236                return false;           
237        }
238       
239        /**
240         * Retourne les parametres du bouton demande
241         *
242         * @param string $identifiant : nom (de la classe du) bouton
243         * @return mixed
244         */
245        function get($identifiant) {
246                if ($a = $this->affecter($this->markupSet, $identifiant)) {
247                        return $a;
248                }
249                return false;           
250        }
251       
252                               
253        /**
254         * Affiche le bouton demande
255         *
256         * @param string $identifiant : nom (de la classe du) bouton a afficher
257         * @return true/false
258         */
259        function afficher($identifiant){
260                return $this->set($identifiant,array('display'=>true));
261        }
262       
263               
264        /**
265         * Cache le bouton demande
266         *
267         * @param string $identifiant : nom (de la classe du) bouton a afficher
268         * @return true/false
269         */
270        function cacher($identifiant){
271                return $this->set($identifiant,array('display'=>false));
272        }
273       
274                               
275        /**
276         * Affiche tous les boutons
277         *
278         * @param string $identifiant : nom (de la classe du) bouton a afficher
279         * @return true/false
280         */
281        function afficherTout(){
282                return $this->affecter_a_tous($this->markupSet, array('display'=>true));
283        }
284       
285        /**
286         * Cache tous les boutons
287         *
288         * @param string $identifiant : nom (de la classe du) bouton a afficher
289         * @return true/false
290         */
291        function cacherTout(){
292                return $this->affecter_a_tous($this->markupSet, array('display'=>false));
293        }
294       
295
296        /**
297         * ajouter un bouton ou quelque chose, avant un autre deja present
298         *
299         * @param string $identifiant : identifiant du bouton ou l'on doit se situer
300         * @param array $params : parametres de l'ajout
301         */
302        function ajouterAvant($identifiant, $params){
303                return $this->affecter($this->markupSet, $identifiant, $params, 'avant');
304        }
305       
306        /**
307         * ajouter un bouton ou quelque chose, apres un autre deja present
308         *
309         * @param string $identifiant : identifiant du bouton ou l'on doit se situer
310         * @param array $params : parametres de l'ajout
311         */
312        function ajouterApres($identifiant, $params){
313                return $this->affecter($this->markupSet, $identifiant, $params, 'apres');
314               
315        }
316               
317        /**
318         * ajouter une fonction js pour etre utilises dans les boutons
319         *
320         * @param string $fonction : code de la fonction js
321         * @return null
322         */
323        function ajouterFonction($fonction){
324                if (false === strpos($this->functions, $fonction)){
325                        $this->functions .= "\n" . $fonction . "\n";
326                }
327        }
328               
329        /**
330         * Supprimer les elements non affiches (display:false)
331         *
332         * @param false/array $tableau : tableau a analyser (sert pour la recursion)
333         */
334        function enlever_elements_non_affiches(&$tableau){
335                if ($tableau === null)
336                        $tableau = &$this->markupSet;
337               
338                foreach ($tableau as $p=>$v){
339
340                        if (isset($v['display']) AND !$v['display']) {
341                                unset($tableau[$p]);
342                                $tableau = array_values($tableau); // remettre les cles automatiques sinon json les affiche et ça plante.
343                        }
344                        // sinon, on lance une recursion sur les sous-menus
345                        else {
346                                if (isset($v['dropMenu']) and is_array($v['dropMenu'])) {
347                                        $this->enlever_elements_non_affiches($tableau[$p]['dropMenu']);
348                                        // si le sous-menu est vide, on enleve l'icone
349                                        if (!$tableau[$p]['dropMenu']) {
350                                                unset($tableau[$p]);
351                                                $tableau = array_values($tableau);
352                                        }
353                                }
354                        }
355                }
356        }
357       
358        /**
359         * Supprime les elements vides (uniquement a la racine de l'objet)
360         * et uniquement si chaine ou tableau.
361         *
362         * Supprime les parametres prives
363         * Supprime les parametres inutiles a markitup/json dans les parametres markupSet
364         * (id, display, icone)
365         */
366        function enlever_parametres_inutiles() {
367                foreach($this as $p=>$v){
368                        if (!$v) {
369                                if (is_array($v) or is_string($v)) {
370                                        unset($this->$p);
371                                }
372                        } elseif ($p == 'functions') {
373                                unset($this->$p);
374                        }
375                }
376                foreach($this->markupSet as $p=>$v) {
377                        foreach ($v as $n=>$m) {
378                                if (in_array($n, array('id', 'display', 'icon'))) {
379                                        unset($this->markupSet[$p][$n]);
380                                }
381                        }
382                }
383                unset ($this->_liste_params_autorises);
384        }
385       
386       
387        /**
388         * Cree la sortie json pour le javascript des parametres de la barre
389         * et la retourne
390         *
391         * @return string : declaration json de la barre
392         */
393        function creer_json(){
394                $barre = $this;
395                $type = $barre->nameSpace;
396                $fonctions = $barre->functions;
397               
398                $barre->enlever_elements_non_affiches($this->markupSet);
399                $barre->enlever_parametres_inutiles();
400               
401                $json = Barre_outils::json_export($barre);
402
403                // on lance la transformation des &chose; en veritables caracteres
404                // sinon markitup restitue &laquo; au lieu de « directement
405                // lorsqu'on clique sur l'icone
406                include_spip('inc/charsets');
407                $json = unicode2charset(html2unicode($json));
408                return "\n\nbarre_outils_$type = ".$json . "\n\n $fonctions";           
409        }
410       
411        /**
412         * Transform a variable into its javascript equivalent (recursive)
413         * (depuis ecrire/inc/json, mais modifie pour que les fonctions
414         * js ne soient pas mises dans un string
415         *
416         * @access private
417         * @param mixed the variable
418         * @return string js script | boolean false if error
419         */
420        function json_export($var) {
421                $asso = false;
422                switch (true) {
423                        case is_null($var) :
424                                return 'null';
425                        case is_string($var) :
426                                if (strtolower(substr(ltrim($var),0,8))=='function')
427                                        return $var;
428                                return '"' . addcslashes($var, "\"\\\n\r") . '"';
429                        case is_bool($var) :
430                                return $var ? 'true' : 'false';
431                        case is_scalar($var) :
432                                return $var;
433                        case is_object( $var) :
434                                $var = get_object_vars($var);
435                                $asso = true;
436                        case is_array($var) :
437                                $keys = array_keys($var);
438                                $ikey = count($keys);
439                                while (!$asso && $ikey--) {
440                                        $asso = $ikey !== $keys[$ikey];
441                                }
442                                $sep = '';
443                                if ($asso) {
444                                        $ret = '{';
445                                        foreach ($var as $key => $elt) {
446                                                $ret .= $sep . '"' . $key . '":' . Barre_outils::json_export($elt);
447                                                $sep = ',';
448                                        }
449                                        return $ret ."}\n";
450                                } else {
451                                        $ret = '[';
452                                        foreach ($var as $elt) {
453                                                $ret .= $sep . Barre_outils::json_export($elt);
454                                                $sep = ',';
455                                        }
456                                        return $ret ."]\n";
457                                }
458                }
459                return false;
460        }
461       
462}
463
464
465
466/**
467 * Cette fonction cree la css pour les images
468 * des icones des barres d'outils
469 * en s'appuyant sur la description des jeux de barres disponibles.
470 *
471 * elle cherche une fonction barre_outils_($barre)_icones pour chaque
472 * barre et l'appelle si existe.
473 *
474 * @return string : declaration css des icones
475 */
476function barre_outils_css_icones(){
477        // recuperer la liste, extraire les icones
478        $css = "";
479       
480        // liste des barres
481        if (!$barres = barre_outils_liste()) 
482                return null;
483               
484        // liste des classes css et leur correspondance avec une icone
485        $classe2icone = array();
486        foreach ($barres as $barre) {
487                include_spip('barre_outils/' . $barre);
488                if ($f = charger_fonction($barre . '_icones', 'barre_outils', true)) {
489                        if (is_array($icones = $f())) {
490                                $classe2icone = array_merge($classe2icone, $icones);
491                        }
492                }
493        }
494       
495        // passer le tout dans un pipeline pour ceux qui ajoute de simples icones a des barres existantes
496        $classe2icone = pipeline('porte_plume_lien_classe_vers_icone',$classe2icone);
497       
498        // passage en css
499        foreach ($classe2icone as $n=>$i) {
500                $pos="";
501                if (is_array($i)){
502                        $pos = "background-position:".end($i);
503                  $i = reset($i);
504                }
505                $css .= "\n.markItUp .$n a b {background-image:url(".url_relative_protocole(url_absolue(find_in_path("icones_barre/$i"))).");$pos}";
506        }
507
508        return $css;
509}
510
511
512/**
513 * Retourne une instance de Barre_outils
514 * cree a partir du type de barre demande
515 *
516 * @param string $set : type de barre
517 * @return object/false : objet de type barre_outil
518 */
519function barre_outils_initialiser($set){
520        if ($f = charger_fonction($set, 'barre_outils')) {
521                // retourne une instance de l'objet Barre_outils
522                return $f();
523        }
524        return false;
525}
526
527/**
528 * Retourne la liste des barres d'outils connues
529 *
530 * @return array/false : tableau des noms de barres trouvees
531 */
532function barre_outils_liste(){
533        static $sets = -1;
534        if ($sets !== -1) 
535                return $sets;
536       
537        // on recupere l'ensemble des barres d'outils connues
538        if (!$sets = find_all_in_path('barre_outils/','.*[.]php')
539        or !is_array($sets)) {
540                spip_log("[Scandale] Porte Plume ne trouve pas de barre d'outils !");
541                $sets = false;
542                return $sets;
543        }
544               
545        foreach($sets as $fichier=>$adresse) {
546                $sets[$fichier] = substr($fichier,0,-4); // juste le nom
547        }
548        return $sets;   
549}
550
551/**
552 * filtre appliquant les traitements SPIP d'un champ (et eventuellement d'un type d'objet) sur un texte
553 * (voir la fonction champs_traitements($p) dans : public/references.php)
554 * ce mecanisme est a preferer au traditionnel #TEXTE*|propre
555 * traitements_previsu() consulte la globale $table_des_traitements et applique le traitement adequat
556 * si aucun traitement n'est trouve, alors propre() est applique
557 *
558 * @param string $texte : texte source
559 * @param string $nom_champ : champ (en majuscules)
560 * @param string $type_objet : objet (en minuscules)
561 * @return string : texte traite
562 */
563function traitements_previsu($texte, $nom_champ='', $type_objet='', $connect=null) {
564        include_spip('public/interfaces'); // charger les traitements
565        safehtml($t);
566        global $table_des_traitements;
567        if(!strlen($nom_champ) || !isset($table_des_traitements[$nom_champ])) {
568                $texte = propre($texte, $connect);
569        }
570        else {
571                include_spip('base/abstract_sql');
572                $table = table_objet($type_objet);
573                $ps = $table_des_traitements[$nom_champ];
574                if(is_array($ps))
575                        $ps = $ps[(strlen($table) && isset($ps[$table])) ? $table : 0];
576                if(!$ps)
577                        $texte = propre($texte, $connect);
578                else
579                        // remplacer le placeholder %s par le texte fourni
580                        eval('$texte=' . str_replace('%s', '$texte', $ps) . ';');
581        }
582        // il faut toujours securiser le texte preivusalise car il peut contenir n'importe quoi
583        // et servir de support a une attaque xss ou vol de cookie admin
584        // on ne peut donc se fier au statut de l'auteur connecte car le contenu ne vient pas
585        // forcement de lui
586        return safehtml($texte);
587}
588?>
Note: See TracBrowser for help on using the repository browser.