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