source: spip-zone/_plugins_/crayons/action/crayons_html.php @ 69369

Last change on this file since 69369 was 69369, checked in by marcimat@…, 7 years ago

Gérer les crayons sur des parties de configuration, avec #EDIT{meta-demo/truc} ou #EDIT_CONFIG{demo/truc}.

Attention, cette nouvelle balise (#EDIT_CONFIG) n'étant pas présente dans SPIP, si le plugin crayon est désactivé, le contenu de la balise s'affiche dans les squelettes ({demo/truc}).

Par ailleurs, enregistrer des sous configurations nécessite soit SPIP 3, soit SPIP 2.x + Bonux 2 ou CFG

On change de stratégie pour l'autorisation de lire ou d'écrire des metas : on dit que celles de SPIP qu'on pouvait éditer ne changent pas (pouvoir configurer le site), mais les autres, plutôt que de les interdire nécessitent d'être webmestre pour être modifiées.

Ces 2 écritures sont donc valables :

<div class="#EDIT_CONFIG{demo/truc}">#CONFIG{demo/truc,---}</div>
<div class="#EDIT{meta-demo/truc}">#CONFIG{demo/truc,---}</div>

On ajoute quelques PHPDocs au passage.

File size: 12.7 KB
Line 
1<?php
2
3if (!defined("_ECRIRE_INC_VERSION")) return;
4
5/**
6 * Affiche le controleur (formulaire) d'un crayon
7 * suivant la classe CSS décrivant le champ à éditer (produit par #EDIT)
8 *
9 * @param string $class
10 *   Class CSS décrivant le champ
11 * @param null $c
12 *
13 * @return array
14 *   Tableau avec 2 entrées possibles :
15 *   - '$erreur' : texte d'erreur éventuel
16 *   - '$html' : code HTML du controleur
17**/
18function affiche_controleur($class, $c=null) {
19        $return = array('$erreur'=>'');
20
21        if (preg_match(_PREG_CRAYON, $class, $regs)) {
22                list(,$nomcrayon,$type,$champ,$id) = $regs;
23                $regs[] = $class;
24
25                // A-t-on le droit de crayonner ?
26                spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$champ)","crayons_distant");
27                if (!autoriser('crayonner',$type, $id, NULL, array('modele'=>$champ))) {
28                        $return['$erreur'] = "$type $id: " . _U('crayons:non_autorise');
29                } else {
30                        $f = charger_fonction($type.'_'.$champ, 'controleurs', true)
31                        OR $f = charger_fonction($champ, 'controleurs', true)
32                        OR $f = charger_fonction($type, 'controleurs', true)
33                        OR $f = 'controleur_dist';
34                        list($html,$status) = $f($regs, $c);
35                        if ($status) {
36                                $return['$erreur'] = $html;
37                        } else {
38                                $return['$html'] = $html;
39                        }
40                }
41        } else {
42                $return['$erreur'] = _U('crayons:donnees_mal_formatees');
43        }
44
45        return $return;
46}
47
48function controleur_dist($regs, $c=null) {
49        list( , $nomcrayon, $type, $champ, $id, $class) = $regs;
50        $options = array(
51                'class' => $class
52        );
53        list($distant,$table) = distant_table($type);
54
55        // Si le controleur est un squelette html, on va chercher
56        // les champs qu'il lui faut dans la table demandee
57        // Attention, un controleur multi-tables ne fonctionnera
58        // que si les champs ont le meme nom dans toutes les tables
59        // (par exemple: hyperlien est ok, mais pas nom)
60        if (($fichier = find_in_path(
61        ($controleur = 'controleurs/' . $type . '_' . $champ) . '.html'))
62        || ($fichier = find_in_path(
63        ($controleur = 'controleurs/' . $champ) .'.html'))) {
64                if (!lire_fichier($fichier, $controldata))
65                        die('erreur lecture controleur');
66                if (preg_match_all('/\bname=(["\'])#ENV\{name_(\w+)\}\1/',
67                $controldata, $matches, PREG_PATTERN_ORDER)) {
68                        $champ = $matches[2];
69                }
70        } else {
71                $controleur = '';
72        }
73
74        $valeur = valeur_colonne_table($type, $champ, $id);
75
76        #spip_log("$valeur = valeur_colonne_table($type, $champ, $id);");
77        #spip_log($champ);
78
79        if ($valeur === false) {
80                return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6);
81        }
82/*      if (is_scalar($valeur)) {
83                $valeur = array($champ => $valeur);
84        }*/
85
86        // type du crayon (a revoir quand le core aura type ses donnees)
87        $inputAttrs = array();
88        if ($controleur) {
89                $options['hauteurMini'] = 80; // base de hauteur mini
90                $option['inmode'] = 'controleur';
91                $options['controleur'] = $controleur;
92        } else
93        // si la valeur fait plusieurs lignes on doit mettre un textarea
94        // derogation specifique pour descriptif_site de spip_metas
95        if (
96        preg_match(",[\n\r],", $valeur[$champ])
97                OR (($champ == 'valeur') && ($id == 'descriptif_site'))
98                OR
99        // on regarde le type tel que defini dans serial
100        // (attention il y avait des blob dans les vieux spip)
101        ($sqltype = colonne_table($type, $champ)) &&
102           ( in_array($sqltype['type'] , array('mediumtext', 'longblob', 'longtext')) ||
103           (($sqltype['type'] == 'text' || $sqltype['type'] == 'blob') && in_array($champ, array('descriptif', 'bio'))))) {
104                $options['hauteurMini'] = 80; // hauteur mini d'un textarea
105                $option['inmode'] = 'texte';
106        } else { // ligne, hauteur naturelle
107                $options['hauteurMaxi'] = 0;
108                $option['inmode'] = 'ligne';
109                if ($sqltype['long']) {
110                        $inputAttrs['maxlength'] = is_array($sqltype['long']) ?
111                                        $sqltype['long'][0] : $sqltype['long'];
112                }
113        }
114
115        $crayon = new Crayon($nomcrayon, $valeur, $options, $c);
116        $inputAttrs['style'] = join($crayon->styles);
117
118        if (!$controleur) {
119                $inputAttrs['style'] .= 'width:' . $crayon->largeur . 'px;' .
120                 ($crayon->hauteur ? ' height:' . $crayon->hauteur . 'px;' : '');
121        }
122
123        $html = $controleur ? $crayon->formulaire(null, $inputAttrs) :
124                                        $crayon->formulaire($option['inmode'], $inputAttrs);
125        $status = NULL;
126
127        return array($html,$status);
128}
129
130// Definition des crayons
131class Crayon {
132        // le nom du crayon "type-modele-id" comme "article-introduction-237"
133        var $name;
134        // type, a priori une table, extrait du nom plus eventuellement base distante
135        var $type;
136        // table la table a crayonner
137        var $table;
138        // distant base distante
139        var $distant;
140        // modele, un champ comme "texte" ou un modele, extrait du nom
141        var $modele;
142        // l'identificateur dans le type, comme un numero d'article
143        var $id;
144        // la ou les valeurs des champs du crayon, tableau associatif champ => valeur
145        var $texts = array();
146        // une cle unique pour chaque crayon demande
147        var $key;
148        // un md5 associe aux valeurs pour verifier et detecter si elles changent
149        var $md5;
150        // dimensions indicatives
151        var $largeurMini = 170;
152        var $largeurMaxi = 700;
153        var $hauteurMini = 80;
154        var $hauteurMaxi = 700;
155        var $largeur;
156        // le mode d'entree: texte, ligne ou controleur
157        var $inmode = '';
158        // eventuellement le fond modele pour le controleur
159        var $controleur = '';
160        var $styles = array();
161
162        // le constructeur du crayon
163        // $name : son nom
164        // $texts : tableau associatif des valeurs ou valeur unique si crayon monochamp
165        // $options : options directes du crayon (developpement)
166        function Crayon($name, $texts = array(), $options = array(), $c=null) {
167                $this->name = $name;
168                list($this->type, $this->modele, $this->id) = explode('-', $this->name, 3);
169                list($this->distant,$this->table) = distant_table($this->type);
170                if (is_scalar($texts) || is_null($texts)) {
171                        $texts = array($this->modele => $texts);
172                }
173                $this->texts = $texts;
174                $this->key = strtr(uniqid('wid', true), '.', '_');
175                $this->md5 = $this->md5();
176                foreach ($options as $opt=>$val) {
177                        $this->$opt = $val;
178                }
179                $this->dimension($c);
180                $this->css();
181        }
182
183        // calcul du md5 associe aux valeurs
184        function md5() {
185                #spip_log($this->texts, 'crayons');
186                return md5(serialize($this->texts));
187        }
188
189        // dimensions indicatives
190        function dimension($c) {
191                // largeur du crayon
192                $this->largeur = min(max(intval(_request('w', $c)),
193                                        $this->largeurMini), $this->largeurMaxi);
194                // hauteur maxi d'un textarea selon wh: window height
195                $maxheight = min(max(intval(_request('wh', $c)) - 50, 400), $this->hauteurMaxi);
196                $this->hauteur = min(max(intval(_request('h', $c)), $this->hauteurMini), $maxheight);
197                $this->left = _request('left');
198                $this->top = _request('top');
199                $this->w = _request('w');
200                $this->h = _request('h');
201                $this->ww = _request('ww');
202                $this->wh = _request('wh');
203        }
204
205        // recuperer les elements de style
206        function css() {
207                foreach(array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) {
208                        if (null !== ($p = _request($property)))
209                                $this->styles[] = "$property:$p;";
210                }
211
212                $property = 'background-color';
213                if (!$p = _request($property)
214                OR $p == 'transparent') {
215                        $p = 'white';
216                }
217                $this->styles[] = "$property:$p;";
218        }
219
220        // formulaire standard
221        function formulaire($contexte = array(), $inputAttrs = array()) {
222                return
223                        $this->code() .
224                        $this->input($contexte, $inputAttrs);
225        }
226
227        // balises input type hidden d'identification du crayon
228        function code() {
229                return
230                 '<input type="hidden" class="crayon-id" name="crayons[]"'
231                .' value="'.$this->key.'" />'."\n"
232                . '<input type="hidden" name="name_'.$this->key
233                .'" value="'.$this->name.'" />'."\n"
234                . '<input type="hidden" name="class_' . $this->key
235                . '" value="' . $this->class . '" />' . "\n"
236                . '<input type="hidden" name="md5_'.$this->key
237                .'" value="'.$this->md5.'" />'."\n"
238                . '<input type="hidden" name="fields_'.$this->key
239                .'" value="'.join(',',array_keys($this->texts)).'" />'
240                ."\n"
241                ;
242        }
243
244/*
245 Fabriquer les balises des champs d'apres un modele controleurs/(type_)modele.html
246        $contexte est un tableau (nom=>valeur) qui sera enrichi puis passe à recuperer_fond
247*/
248        function fond($contexte = array()) {
249                include_spip('inc/filtres');
250                $contexte['id_' . $this->type] = $this->id;
251                $contexte['id_' . $this->table] = $this->id;
252                $contexte['crayon_type'] = $this->type;
253                $contexte['crayon_modele'] = $this->modele;
254                $contexte['lang'] = $GLOBALS['spip_lang'];
255                $contexte['key'] = $this->key;
256                $contexte['largeur'] = $this->largeur;
257                $contexte['hauteur'] = $this->hauteur;
258                $contexte['self'] = _request('self');
259                foreach ($this->texts as $champ => $val) {
260                        $contexte['name_' . $champ] = 'content_' . $this->key . '_' . $champ;
261                }
262                $contexte['style'] = join(' ',$this->styles);
263                include_spip('public/assembler');
264                return recuperer_fond($this->controleur, $contexte);
265        }
266
267/*
268 Fabriquer les balises du ou des champs
269        $spec est soit un scalaire 'ligne' ou 'texte' précisant le type de balise
270        soit un array($champ=>array('type'=>'...', 'attrs'=>array(attributs specifique du champs)))
271        $attrs est un tableau (attr=>val) d'attributs communs ou pour le champs unique
272*/
273        function input($spec = 'ligne', $attrs = array()) {
274                if ($this->controleur) {
275                        return $this->fond($spec);
276                }
277                include_spip('inc/filtres');
278                $return = '';
279                foreach ($this->texts as $champ => $val) {
280                        $type = is_array($spec) ? $spec[$champ]['type'] : $spec;
281                        switch ($type) {
282                                case 'texte':
283                                        $id = uniqid('wid');
284                                        $input = '<textarea style="width:100%;" class="crayon-active"'
285                                        . ' name="content_'.$this->key.'_'.$champ.'" id="'.$id.'">'
286                                        . "\n"
287                                        . entites_html($val)
288                                        . "</textarea>\n";
289                                        break;
290                                case 'ligne':
291                                default:
292                                        $input = '<input class="crayon-active text" type="text"'
293                                        . ' name="content_'.$this->key.'_'.$champ.'"'
294                                        . ' value="'
295                                        . entites_html($val)
296                                        . '" />'."\n";
297                        }
298                        if (is_array($spec) && isset($spec[$champ]['attrs'])) {
299                                foreach ($spec[$champ]['attrs'] as $attr=>$val) {
300                                        $input = inserer_attribut($input, $attr, $val);
301                                }
302                        }
303
304                        foreach ($attrs as $attr=>$val) {
305                                $input = inserer_attribut($input, $attr, $val);
306                        }
307
308                        // petit truc crado pour mettre la barre typo si demandee
309                        // pour faire propre il faudra reprogrammer la bt en jquery
310                        $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']) : array();
311                        if (isset($meta_crayon['barretypo'])
312                        AND $meta_crayon['barretypo']
313                        AND $type == 'texte') {
314                                // Pas la peine de mettre cette barre si PortePlume est la
315                                if (
316                                        !(
317                                                function_exists('chercher_filtre')
318                                                AND $f = chercher_filtre('info_plugin')
319                                                AND $f('PORTE_PLUME','est_actif')
320                                        )
321                                ) {
322                                        include_spip('inc/barre');
323                                        $input = "<div style='width:".$this->largeur."px;height:23px;'>"
324                                                . (function_exists('afficher_barre')
325                                                        ? afficher_barre("document.getElementById('$id')")
326                                                        : '')
327                                                . '</div>'
328                                                . $input;
329                                }
330                        }
331
332                        $return .= $input;
333                }
334                return $return;
335        }
336
337}
338
339
340/*
341        Fabriquer les boutons du formulaire
342*/
343function crayons_boutons($boutons = array()) {
344        $crayonsImgPath = dirname(url_absolue(find_in_path('images/cancel.png')));
345        $boutons['submit'] = array('ok', texte_backend(_T('bouton_enregistrer')));
346        $boutons['cancel'] = array('cancel', texte_backend(_T('crayons:annuler')));
347
348        $html = '';
349        foreach ($boutons as $bnam => $bdef) if ($bdef) {
350                $html .= '<button type="button" class="crayon-' . $bnam .
351                        '" title="' . $bdef[1] . '">' . $bdef[1] . '</button>';
352        }
353
354        if ($html)
355                return '<div class="crayon-boutons"><div>'.$html.'</div></div>';
356}
357
358function crayons_formulaire($html, $action='crayons_store') {
359        if (!$html)
360                return '';
361
362        include_spip('inc/filtres');
363        return liens_absolus(
364                '<div class="formulaire_spip">'
365                . '<form class="formulaire_crayon" method="post" action="'
366                . url_absolue(parametre_url(self(),'action', $action))
367                . '" enctype="multipart/form-data">'
368                . $html
369                . crayons_boutons()
370                . '</form>'
371                .'</div>'
372        );
373}
374
375//
376// Un Crayon avec une verification de code de securite
377//
378class SecureCrayon extends Crayon {
379
380        function SecureCrayon($name, $text='') {
381                parent::Crayon($name, $text);
382        }
383
384        function code() {
385                $code = parent::code();
386                $secu = md5($GLOBALS['meta']['alea_ephemere']. '=' . $this->name);
387
388                return
389                        $code
390                        .'<input type="hidden" name="secu_'.$this->key.'" value="'.$secu.'" />'."\n";
391        }
392}
393
394function action_crayons_html_dist() {
395        // CONTROLEUR
396        // on affiche le formulaire demande (controleur associe au crayon)
397        // Si le crayon n'est pas de type "crayon", c'est un crayon etendu, qui
398        // integre le formulaire requis à son controleur (pour avoir les boutons
399        // du formulaire dans un controleur Draggable, par exemple, mais il y a
400        // d'autres usages possibles)
401        include_spip('inc/crayons');
402        lang_select($GLOBALS['auteur_session']['lang']);
403        $return = affiche_controleur(_request('class'));
404        if (!_request('type') OR _request('type') == 'crayon')
405          $return['$html'] = crayons_formulaire($return['$html']);
406
407        $json = trim(crayons_json_encode($return));
408
409        header("Content-Type: text/plain; charset=utf-8");
410        die($json);
411}
412
413?>
Note: See TracBrowser for help on using the repository browser.