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

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

Ne pas faire croire que le champ est limité à 4 caractères s'il a comme valeur SQL : decimal(4,3) qui autorise 8 caractères maxi...

File size: 13.0 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                // c'est un nombre entier
110                if ($sqltype['long']) {
111                        // si long est [4,3] sa longueur maxi est 8 (1234,123)
112                        if (is_array($sqltype['long'])) {
113                                if (count($sqltype['long']) == 2) {
114                                        $inputAttrs['maxlength'] = $sqltype['long'][0] + 1 + $sqltype['long'][1];
115                                }
116                                // on ne sait pas ce que c'est !
117                                else {
118                                        $inputAttrs['maxlength'] = $sqltype['long'][0];
119                                }
120                        } else {
121                                $inputAttrs['maxlength'] = $sqltype['long'];
122                        } 
123                }
124        }
125
126        $crayon = new Crayon($nomcrayon, $valeur, $options, $c);
127        $inputAttrs['style'] = join($crayon->styles);
128
129        if (!$controleur) {
130                $inputAttrs['style'] .= 'width:' . $crayon->largeur . 'px;' .
131                 ($crayon->hauteur ? ' height:' . $crayon->hauteur . 'px;' : '');
132        }
133
134        $html = $controleur ? $crayon->formulaire(null, $inputAttrs) :
135                                        $crayon->formulaire($option['inmode'], $inputAttrs);
136        $status = NULL;
137
138        return array($html,$status);
139}
140
141// Definition des crayons
142class Crayon {
143        // le nom du crayon "type-modele-id" comme "article-introduction-237"
144        var $name;
145        // type, a priori une table, extrait du nom plus eventuellement base distante
146        var $type;
147        // table la table a crayonner
148        var $table;
149        // distant base distante
150        var $distant;
151        // modele, un champ comme "texte" ou un modele, extrait du nom
152        var $modele;
153        // l'identificateur dans le type, comme un numero d'article
154        var $id;
155        // la ou les valeurs des champs du crayon, tableau associatif champ => valeur
156        var $texts = array();
157        // une cle unique pour chaque crayon demande
158        var $key;
159        // un md5 associe aux valeurs pour verifier et detecter si elles changent
160        var $md5;
161        // dimensions indicatives
162        var $largeurMini = 170;
163        var $largeurMaxi = 700;
164        var $hauteurMini = 80;
165        var $hauteurMaxi = 700;
166        var $largeur;
167        // le mode d'entree: texte, ligne ou controleur
168        var $inmode = '';
169        // eventuellement le fond modele pour le controleur
170        var $controleur = '';
171        var $styles = array();
172
173        // le constructeur du crayon
174        // $name : son nom
175        // $texts : tableau associatif des valeurs ou valeur unique si crayon monochamp
176        // $options : options directes du crayon (developpement)
177        function Crayon($name, $texts = array(), $options = array(), $c=null) {
178                $this->name = $name;
179                list($this->type, $this->modele, $this->id) = explode('-', $this->name, 3);
180                list($this->distant,$this->table) = distant_table($this->type);
181                if (is_scalar($texts) || is_null($texts)) {
182                        $texts = array($this->modele => $texts);
183                }
184                $this->texts = $texts;
185                $this->key = strtr(uniqid('wid', true), '.', '_');
186                $this->md5 = $this->md5();
187                foreach ($options as $opt=>$val) {
188                        $this->$opt = $val;
189                }
190                $this->dimension($c);
191                $this->css();
192        }
193
194        // calcul du md5 associe aux valeurs
195        function md5() {
196                #spip_log($this->texts, 'crayons');
197                return md5(serialize($this->texts));
198        }
199
200        // dimensions indicatives
201        function dimension($c) {
202                // largeur du crayon
203                $this->largeur = min(max(intval(_request('w', $c)),
204                                        $this->largeurMini), $this->largeurMaxi);
205                // hauteur maxi d'un textarea selon wh: window height
206                $maxheight = min(max(intval(_request('wh', $c)) - 50, 400), $this->hauteurMaxi);
207                $this->hauteur = min(max(intval(_request('h', $c)), $this->hauteurMini), $maxheight);
208                $this->left = _request('left');
209                $this->top = _request('top');
210                $this->w = _request('w');
211                $this->h = _request('h');
212                $this->ww = _request('ww');
213                $this->wh = _request('wh');
214        }
215
216        // recuperer les elements de style
217        function css() {
218                foreach(array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) {
219                        if (null !== ($p = _request($property)))
220                                $this->styles[] = "$property:$p;";
221                }
222
223                $property = 'background-color';
224                if (!$p = _request($property)
225                OR $p == 'transparent') {
226                        $p = 'white';
227                }
228                $this->styles[] = "$property:$p;";
229        }
230
231        // formulaire standard
232        function formulaire($contexte = array(), $inputAttrs = array()) {
233                return
234                        $this->code() .
235                        $this->input($contexte, $inputAttrs);
236        }
237
238        // balises input type hidden d'identification du crayon
239        function code() {
240                return
241                 '<input type="hidden" class="crayon-id" name="crayons[]"'
242                .' value="'.$this->key.'" />'."\n"
243                . '<input type="hidden" name="name_'.$this->key
244                .'" value="'.$this->name.'" />'."\n"
245                . '<input type="hidden" name="class_' . $this->key
246                . '" value="' . $this->class . '" />' . "\n"
247                . '<input type="hidden" name="md5_'.$this->key
248                .'" value="'.$this->md5.'" />'."\n"
249                . '<input type="hidden" name="fields_'.$this->key
250                .'" value="'.join(',',array_keys($this->texts)).'" />'
251                ."\n"
252                ;
253        }
254
255/*
256 Fabriquer les balises des champs d'apres un modele controleurs/(type_)modele.html
257        $contexte est un tableau (nom=>valeur) qui sera enrichi puis passe à recuperer_fond
258*/
259        function fond($contexte = array()) {
260                include_spip('inc/filtres');
261                $contexte['id_' . $this->type] = $this->id;
262                $contexte['id_' . $this->table] = $this->id;
263                $contexte['crayon_type'] = $this->type;
264                $contexte['crayon_modele'] = $this->modele;
265                $contexte['lang'] = $GLOBALS['spip_lang'];
266                $contexte['key'] = $this->key;
267                $contexte['largeur'] = $this->largeur;
268                $contexte['hauteur'] = $this->hauteur;
269                $contexte['self'] = _request('self');
270                foreach ($this->texts as $champ => $val) {
271                        $contexte['name_' . $champ] = 'content_' . $this->key . '_' . $champ;
272                }
273                $contexte['style'] = join(' ',$this->styles);
274                include_spip('public/assembler');
275                return recuperer_fond($this->controleur, $contexte);
276        }
277
278/*
279 Fabriquer les balises du ou des champs
280        $spec est soit un scalaire 'ligne' ou 'texte' précisant le type de balise
281        soit un array($champ=>array('type'=>'...', 'attrs'=>array(attributs specifique du champs)))
282        $attrs est un tableau (attr=>val) d'attributs communs ou pour le champs unique
283*/
284        function input($spec = 'ligne', $attrs = array()) {
285                if ($this->controleur) {
286                        return $this->fond($spec);
287                }
288                include_spip('inc/filtres');
289                $return = '';
290                foreach ($this->texts as $champ => $val) {
291                        $type = is_array($spec) ? $spec[$champ]['type'] : $spec;
292                        switch ($type) {
293                                case 'texte':
294                                        $id = uniqid('wid');
295                                        $input = '<textarea style="width:100%;" class="crayon-active"'
296                                        . ' name="content_'.$this->key.'_'.$champ.'" id="'.$id.'">'
297                                        . "\n"
298                                        . entites_html($val)
299                                        . "</textarea>\n";
300                                        break;
301                                case 'ligne':
302                                default:
303                                        $input = '<input class="crayon-active text" type="text"'
304                                        . ' name="content_'.$this->key.'_'.$champ.'"'
305                                        . ' value="'
306                                        . entites_html($val)
307                                        . '" />'."\n";
308                        }
309                        if (is_array($spec) && isset($spec[$champ]['attrs'])) {
310                                foreach ($spec[$champ]['attrs'] as $attr=>$val) {
311                                        $input = inserer_attribut($input, $attr, $val);
312                                }
313                        }
314
315                        foreach ($attrs as $attr=>$val) {
316                                $input = inserer_attribut($input, $attr, $val);
317                        }
318
319                        // petit truc crado pour mettre la barre typo si demandee
320                        // pour faire propre il faudra reprogrammer la bt en jquery
321                        $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']) : array();
322                        if (isset($meta_crayon['barretypo'])
323                        AND $meta_crayon['barretypo']
324                        AND $type == 'texte') {
325                                // Pas la peine de mettre cette barre si PortePlume est la
326                                if (
327                                        !(
328                                                function_exists('chercher_filtre')
329                                                AND $f = chercher_filtre('info_plugin')
330                                                AND $f('PORTE_PLUME','est_actif')
331                                        )
332                                ) {
333                                        include_spip('inc/barre');
334                                        $input = "<div style='width:".$this->largeur."px;height:23px;'>"
335                                                . (function_exists('afficher_barre')
336                                                        ? afficher_barre("document.getElementById('$id')")
337                                                        : '')
338                                                . '</div>'
339                                                . $input;
340                                }
341                        }
342
343                        $return .= $input;
344                }
345                return $return;
346        }
347
348}
349
350
351/*
352        Fabriquer les boutons du formulaire
353*/
354function crayons_boutons($boutons = array()) {
355        $crayonsImgPath = dirname(url_absolue(find_in_path('images/cancel.png')));
356        $boutons['submit'] = array('ok', texte_backend(_T('bouton_enregistrer')));
357        $boutons['cancel'] = array('cancel', texte_backend(_T('crayons:annuler')));
358
359        $html = '';
360        foreach ($boutons as $bnam => $bdef) if ($bdef) {
361                $html .= '<button type="button" class="crayon-' . $bnam .
362                        '" title="' . $bdef[1] . '">' . $bdef[1] . '</button>';
363        }
364
365        if ($html)
366                return '<div class="crayon-boutons"><div>'.$html.'</div></div>';
367}
368
369function crayons_formulaire($html, $action='crayons_store') {
370        if (!$html)
371                return '';
372
373        include_spip('inc/filtres');
374        return liens_absolus(
375                '<div class="formulaire_spip">'
376                . '<form class="formulaire_crayon" method="post" action="'
377                . url_absolue(parametre_url(self(),'action', $action))
378                . '" enctype="multipart/form-data">'
379                . $html
380                . crayons_boutons()
381                . '</form>'
382                .'</div>'
383        );
384}
385
386//
387// Un Crayon avec une verification de code de securite
388//
389class SecureCrayon extends Crayon {
390
391        function SecureCrayon($name, $text='') {
392                parent::Crayon($name, $text);
393        }
394
395        function code() {
396                $code = parent::code();
397                $secu = md5($GLOBALS['meta']['alea_ephemere']. '=' . $this->name);
398
399                return
400                        $code
401                        .'<input type="hidden" name="secu_'.$this->key.'" value="'.$secu.'" />'."\n";
402        }
403}
404
405function action_crayons_html_dist() {
406        // CONTROLEUR
407        // on affiche le formulaire demande (controleur associe au crayon)
408        // Si le crayon n'est pas de type "crayon", c'est un crayon etendu, qui
409        // integre le formulaire requis à son controleur (pour avoir les boutons
410        // du formulaire dans un controleur Draggable, par exemple, mais il y a
411        // d'autres usages possibles)
412        include_spip('inc/crayons');
413        lang_select($GLOBALS['auteur_session']['lang']);
414        $return = affiche_controleur(_request('class'));
415        if (!_request('type') OR _request('type') == 'crayon')
416          $return['$html'] = crayons_formulaire($return['$html']);
417
418        $json = trim(crayons_json_encode($return));
419
420        header("Content-Type: text/plain; charset=utf-8");
421        die($json);
422}
423
424?>
Note: See TracBrowser for help on using the repository browser.