source: spip-zone/_plugins_/crayons/branches/v3/crayons_fonctions.php @ 108761

Last change on this file since 108761 was 108761, checked in by p@…, 21 months ago

Encore un alias $

File size: 11.7 KB
Line 
1<?php
2/**
3 * Crayons
4 * plugin for spip
5 * (c) Fil, toggg 2006-2014
6 * licence GPL
7 *
8 * @package SPIP\Crayons\Fonctions
9 */
10
11if (!defined('_ECRIRE_INC_VERSION')) {
12        return;
13}
14
15if (!defined('_DEBUG_CRAYONS')) {
16        /**
17         * Débuguer les crayons
18         *
19         * Mettre a true dans mes_options pour avoir les crayons non compresses
20         */
21        define('_DEBUG_CRAYONS', false);
22}
23
24include_spip('inc/config');
25
26/**
27 * Dire rapidement si ca vaut le coup de chercher des droits
28 *
29 * @return bool
30**/
31function analyse_droits_rapide_dist() {
32        return isset($GLOBALS['auteur_session']['statut']);
33}
34
35/**
36 * Vérifier si un exec du privé est crayonnable
37 *
38 * @param string $exec
39 *
40 * @return bool
41 **/
42function test_exec_crayonnable($exec) {
43        if ($exec_autorise = lire_config('crayons/exec_autorise')) {
44                $execs = explode(',', $exec_autorise);
45                foreach ($execs as $key => $value) {
46                        $execs[$key] = trim($value);
47                }
48                if ($exec_autorise == '*' || in_array($exec, $execs)) {
49                        return true;
50                }
51        }
52
53        return false;
54}
55
56function crayons_affichage_final_prive($page) {
57        // verifie la presence d'une meta crayons, si c'est vide
58        // on ne cherche meme pas a traiter l'espace prive
59        $config_espace_prive = lire_config('crayons/espaceprive');
60        if ($config_espace_prive == 'on') {
61                // determine les pages (exec) crayonnables
62                if (test_exec_crayonnable(_request('exec'))) {
63                        // Calcul des droits
64                        include_spip('inc/crayons');
65                        $page = Crayons_preparer_page($page, '*', wdgcfg());
66                }
67        }
68
69        return $page;
70}
71
72/**
73 * Ajouter la gestion des crayons dans l'espace public
74 *
75 * @pipeline affichage_final
76 * @uses analyse_droits_rapide_dist()
77 * @uses Crayons_preparer_page()
78 * @note
79 *     Le pipeline affichage_final est executé à chaque hit sur toute la page
80 *
81 * @param string $page
82 *     Contenu de la page à envoyer au navigateur
83 * @return string
84 *     Contenu de la page à envoyer au navigateur
85**/
86function crayons_affichage_final($page) {
87        // ne pas se fatiguer si le visiteur n'a aucun droit
88        if (!(function_exists('analyse_droits_rapide')?analyse_droits_rapide():analyse_droits_rapide_dist())) {
89                return $page;
90        }
91
92        // sinon regarder rapidement si la page a des classes crayon
93        if (strpos($page, 'crayon')===false) {
94                return $page;
95        }
96
97        // voir un peu plus precisement lesquelles
98        include_spip('inc/crayons');
99        if (!preg_match_all(_PREG_CRAYON, $page, $regs, PREG_SET_ORDER)) {
100                return $page;
101        }
102
103        $wdgcfg = wdgcfg();
104
105        // calculer les droits sur ces crayons
106        include_spip('inc/autoriser');
107        $droits = array();
108        $droits_accordes = 0;
109        foreach ($regs as $reg) {
110                list(,$crayon,$type,$champ,$id) = $reg;
111                if (_DEBUG_CRAYONS) {
112                        spip_log("autoriser('modifier', $type, $id, NULL, array('champ'=>$champ))", 'crayons_distant');
113                }
114                if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) {
115                        if (!isset($droits['.' . $crayon])) {
116                                $droits['.' . $crayon] = 0;
117                        }
118                        $droits['.' . $crayon]++;
119                        $droits_accordes ++;
120                }
121        }
122
123
124        // et les signaler dans la page
125        if ($droits_accordes == count($regs)) { // tous les droits
126                $page = Crayons_preparer_page($page, '*', $wdgcfg);
127        } elseif ($droits) { // seulement certains droits, preciser lesquels
128                $page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg);
129        }
130
131        return $page;
132}
133
134/**
135 * Ajoute les scripts css et js nécessaires aux crayons dans le code HTML
136 *
137 * @uses crayons_var2js()
138 *
139 * @param string $page
140 *     Code HTML de la page complète ou du header seulement
141 * @param string $droits
142 *     - Liste de css définissant les champs crayonnables
143 *       (séparés par virgule) dont l'édition est autorisée
144 *     - "*" si tous sont autorisés
145 * @param array $wdgcfg
146 *     Description de la configuration des crayons (attribut => valeur)
147 * @param string $mode
148 *     - page : toute la page est présente dans `$page`
149 *     - head : seul le header est présent dans `$page`
150 * @return
151**/
152function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') {
153        /**
154         * Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé
155         */
156        if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) {
157                lang_select($GLOBALS['auteur_session']['lang']);
158        }
159
160        $jsFile = generer_url_public('crayons.js');
161        if (_DEBUG_CRAYONS) {
162                $jsFile = parametre_url($jsFile, 'debug_crayons', 1, '&');
163        }
164        include_spip('inc/filtres'); // rien que pour direction_css() :(
165        $cssFile = direction_css(find_in_path('crayons.css'));
166
167        $config = crayons_var2js(array(
168                'imgPath' => dirname(find_in_path('images/crayon.png')),
169                'droits' => $droits,
170                'dir_racine' => _DIR_RACINE,
171                'self' => self('&'),
172                'txt' => array(
173                        'error' => _U('crayons:svp_copier_coller'),
174                        'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : ''
175                ),
176                'img' => array(
177                        'searching' => array(
178                                'txt' => _U('crayons:veuillez_patienter')
179                        ),
180                        'crayon' => array(
181                                'txt' => _U('crayons:editer')
182                        ),
183                        'edit' => array(
184                                'txt' => _U('crayons:editer_tout')
185                        ),
186                        'img-changed' => array(
187                                'txt' => _U('crayons:deja_modifie')
188                        )
189                ),
190                'cfg' => $wdgcfg
191        ));
192
193        // Est-ce que PortePlume est la ?
194        $pp = '';
195        include_spip('inc/utils');
196        if (lire_config('crayons/barretypo') == 'on' and test_plugin_actif('porte_plume')) {
197                $pp = <<<EOF
198$(function() {
199        if (typeof onAjaxLoad == 'function') {
200                function barrebouilles_crayons() {
201                        $('.formulaire_crayon textarea.crayon-active')
202                        .barre_outils('edition');
203                }
204                onAjaxLoad(barrebouilles_crayons);
205        }
206});
207EOF;
208        }
209
210        $jquery_path = find_in_path('javascript/jquery.js');
211        $incCSS = "<link rel=\"stylesheet\" href=\"{$cssFile}\" type=\"text/css\" media=\"all\" />";
212        $incJS = <<<EOH
213<script type="text/javascript">/* <![CDATA[ */
214var configCrayons;
215function startCrayons() {
216        configCrayons = new $.prototype.cfgCrayons({$config});
217        $.fn.crayonsstart();
218{$pp}
219}
220
221function chargerCrayons() {
222        var cr = document.createElement('script');
223        cr.type = 'text/javascript';
224        cr.async = true;
225        cr.src = '{$jsFile}\x26callback=startCrayons';
226        var s = document.getElementsByTagName('script')[0];
227        s.parentNode.insertBefore(cr, s);
228}
229
230if (typeof window.jQuery == "undefined") {
231        var crj = document.createElement('script');
232        crj.type = 'text/javascript';
233        crj.src = '{$jquery_path}';
234        var sj = document.getElementsByTagName('script')[0];
235        crj.onload = chargerCrayons;
236        sj.parentNode.insertBefore(crj, sj);
237} else {
238        chargerCrayons();
239}
240/* ]]> */</script>
241
242EOH;
243
244        if ($mode == 'head') {
245                //js inline avant les css, sinon ca bloque le chargement
246                $page = $page . $incJS . $incCSS;
247                return $page;
248        }
249
250        $pos_head = strpos($page, '</head>');
251        if ($pos_head === false) {
252                return $page;
253        }
254
255        $page = substr_replace($page, $incJS, $pos_head, 0);
256
257        // css avant la fin du head
258        $pos_head = strpos($page, '</head>');
259        $page = substr_replace($page, $incCSS, $pos_head, 0);
260
261        return $page;
262}
263
264/**
265 * Balise indiquant un champ SQL crayonnable
266 *
267 * @note
268 *   Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP
269 *   ne retourne rien
270 *
271 * @example
272 *     ```
273 *     <div class="#EDIT{texte}">#TEXTE</div>
274 *     <div class="#EDIT{ps}">#PS</div>
275 *     ```
276 *
277 * @param Champ $p
278 *   Pile au niveau de la balise
279 * @return Champ
280 *   Pile complétée par le code à générer
281**/
282function balise_EDIT($p) {
283
284        // le code compile de ce qui se trouve entre les {} de la balise
285        $label = interprete_argument_balise(1, $p);
286
287        // Verification si l'on est dans le cas d'une meta
288        // #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc}
289        if (preg_match('/meta-(.*)\'/', $label, $meta)) {
290                $type = 'meta';
291                $label= 'valeur';
292                $primary = $meta[1];
293                $p->code = "classe_boucle_crayon('"
294                        . $type
295                        ."','"
296                        .$label
297                        ."',"
298                        . "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS.
299                        .").' '";
300                $p->interdire_scripts = false;
301                return $p;
302        }
303
304        $i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
305        // #EDIT hors boucle? ne rien faire
306        if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) {
307                $p->code = "''";
308                $p->interdire_scripts = false;
309                return $p;
310        }
311
312        // crayon sur une base distante 'nua__article-intro-5'
313        if ($distant = $p->boucles[$i_boucle]->sql_serveur) {
314                $type = $distant.'__'.$type;
315        }
316
317        $primary = $p->boucles[$i_boucle]->primary;
318
319        // On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée.
320        // Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement
321        // dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus.
322        if (!$primary) {
323                erreur_squelette(_T('crayons:absence_cle_primaire'), $p);
324        }
325
326        $primary = explode(',', $primary);
327        $id = array();
328        foreach ($primary as $key) {
329                $id[] = champ_sql(trim($key), $p);
330        }
331        $primary = implode(".'-'.", $id);
332
333        $p->code = "classe_boucle_crayon('"
334                . $type
335                ."',"
336                .sinon($label, "''")
337                .','
338                . $primary
339                .").' '";
340        $p->interdire_scripts = false;
341        return $p;
342}
343
344/**
345 * Balise indiquant une configuration crayonnable
346 *
347 * @example
348 *     ```
349 *     <div class="#EDIT_CONFIG{descriptif_site}">#DESCRIPTIF_SITE_SPIP</div>
350 *     <div class="#EDIT_CONFIG{demo/truc}">#CONFIG{demo/truc}</div>
351 *     ```
352 *
353 * @param Champ $p
354 *   Pile au niveau de la balise
355 * @return Champ
356 *   Pile complétée par le code à générer
357**/
358if (!function_exists('balise_EDIT_CONFIG_dist')) {
359        function balise_EDIT_CONFIG_dist($p) {
360
361                // le code compile de ce qui se trouve entre les {} de la balise
362                $config = interprete_argument_balise(1, $p);
363                if (!$config) {
364                        return $p;
365                }
366
367                // chaque / du nom de config doit être transformé pour css.
368                // nous utiliserons '__' à la place.
369
370                $type = 'meta';
371                $label= 'valeur';
372
373                $p->code = "classe_boucle_crayon('"
374                        . $type
375                        . "','"
376                        . $label
377                        . "',"
378                        . "str_replace('/', '__', $config)"
379                        . ").' '";
380                $p->interdire_scripts = false;
381                return $p;
382        }
383}
384
385/**
386 * Crée le controleur du crayon indiqué par la classe CSS
387 *
388 * @param string $class
389 *   Class CSS de crayon tel que créé par #EDIT
390 * @return string
391 *   HTML du crayon, sinon texte d'erreur
392**/
393function creer_le_crayon($class) {
394        include_spip('inc/crayons');
395        include_spip('action/crayons_html');
396        $a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500));
397        return $a['$erreur'] ? $a['$erreur'] : $a['$html'];
398}
399
400/**
401 * Balise `#CRAYON` affichant un formulaire de crayon
402 *
403 * SI `?edit=1;`
404 *
405 * @example
406 *    ```
407 *    #CRAYON{ps}
408 *    ```
409 *
410 * @param Champ $p
411 *   Pile au niveau de la balise
412 * @return Champ
413 *   Pile complétée par le code à générer
414**/
415function balise_CRAYON($p) {
416        $p = balise_EDIT($p);
417        $p->code = 'creer_le_crayon('.$p->code.')';
418        return $p;
419}
420
421
422/**
423 * Donne la classe CSS crayon
424 *
425 * En fonction :
426 * - du type de la boucle
427 *   (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES)
428 * - du champ demande (vide, + ou se terminant par + : (+)classe type--id)
429 * - de l'id courant
430 *
431 * @param string $type
432 *   Type d'objet, ou "meta" pour un champ de configuration
433 * @param string $champ
434 *   Champ SQL concerné
435 * @param int|string $id
436 *   Identifiant de la ligne sql
437 * @return string
438 *   Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons)
439**/
440function classe_boucle_crayon($type, $champ, $id) {
441
442        // Certain objets SPIP porte mal leur nom
443        if ($type == 'hierarchie') {
444                $type = 'rubrique';
445        } elseif ($type == 'syndication') {
446                $type = 'site';
447        }
448        // On récupère objet_type
449        $type = objet_type($type);
450
451        // ??
452        $plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1))
453                ? " $type--$id"
454                : '';
455
456        // test rapide pour verifier que l'id est valide (a-zA-Z0-9)
457        if (false !== strpos($id, ' ')) {
458                spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons');
459                return 'crayon_id_ingerable';
460        }
461
462        return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus;
463}
Note: See TracBrowser for help on using the repository browser.