Dotclear

source: inc/admin/class.dc.form.php @ 1147:2e5cb79e4782

Revision 1147:2e5cb79e4782, 12.8 KB checked in by Dsls <dsls@…>, 13 years ago (diff)

Oops, I did it again (c).

Fist draft of merge from formfilters to dctwig. lists need to be broken up too.

From now all post lists are broken.

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14/**
15* dcFormNode
16*
17* @uses     Twig_Node
18*
19*/
20class dcFormNode extends Twig_Node
21{
22     public function __construct($name,Twig_NodeInterface $body,$lineno,$tag=null)
23     {
24          parent::__construct(array('body' => $body),array('name' => $name),$lineno,$tag);
25     }
26     
27     /**
28     * Compiles the node to PHP.
29     *
30     * @param Twig_Compiler A Twig_Compiler instance
31     */
32     public function compile(Twig_Compiler $compiler)
33     {
34          $compiler
35               ->addDebugInfo($this);
36          $compiler
37               ->write("\$context['dc_form']->beginForm(")
38               ->subcompile($this->getAttribute('name'))
39               ->write(");\n");
40          $compiler
41               ->subcompile($this->getNode('body'))
42               ->write("\$context['dc_form']->renderHiddenWidgets();\n")
43               ->write("\$context['dc_form']->endForm();\n")
44          ;
45     }
46}
47
48/**
49 * Template form token parser
50 */
51class dcFormTokenParser extends Twig_TokenParser
52{
53     public function parse(Twig_Token $token)
54     {
55          $lineno = $token->getLine();
56          $stream = $this->parser->getStream();
57          $name = $this->parser->getExpressionParser()->parseExpression();
58          $stream->expect(Twig_Token::BLOCK_END_TYPE);
59          $body = $this->parser->subparse(array($this,'decideBlockEnd'),true);
60          $stream->expect(Twig_Token::BLOCK_END_TYPE);
61         
62          return new dcFormNode($name,$body,$token->getLine(),$this->getTag());
63     }
64     
65     public function decideBlockEnd(Twig_Token $token)
66     {
67          return $token->test('endform');
68     }
69     
70     public function getTag()
71     {
72          return 'form';
73     }
74}
75
76/**
77 * Template form extension
78 */
79class dcFormExtension extends Twig_Extension
80{
81     protected $template;
82     protected $tpl;
83     protected $core;
84     protected $twig;
85     protected $forms;
86     protected $currentForm;
87     protected $blocks;
88     
89     public function __construct($core)
90     {
91          $this->core = $core;
92          $this->tpl = 'form_layout.html.twig';
93          $this->forms = array();
94          $this->currentForm = null;
95     }
96     
97     public function initRuntime(Twig_Environment $environment)
98     {
99          $this->twig = $environment;
100          $this->template = $this->twig->loadTemplate($this->tpl);
101          $this->blocks = $this->template->getBlocks();
102     }
103     
104     public function addTemplate($tpl) {
105          $t = $this->twig->loadTemplate($tpl);
106          $this->blocks = array_merge($this->blocks,$t->getBlocks());
107     }
108
109     public function getGlobals()
110     {
111          return array('dc_form' => $this);
112     }
113     
114     public function getFunctions()
115     {
116          return array(
117               'form_field' => new Twig_Function_Method(
118                    $this,
119                    'renderWidget',
120                    array('is_safe' => array('html'))
121               ),
122               '_form_is_choice_group' => new Twig_Function_Method(
123                    $this,
124                    'isChoiceGroup',
125                    array('is_safe' => array('html'))
126               ),
127               '_form_is_choice_selected' => new Twig_Function_Method(
128                    $this,
129                    'isChoiceSelected',
130                    array('is_safe' => array('html'))
131               )
132          );
133     }
134     
135     public function isChoiceGroup($choice)
136     {
137          return is_array($choice);
138     }
139     
140     public function isChoiceSelected($choice,$value)
141     {
142          return $choice == $value;
143     }
144     
145     public function getTokenParsers()
146     {
147          return array(new dcFormTokenParser());
148     }
149     
150     public function renderBlock($name,$attr) {
151          echo $this->template->renderBlock(
152               $name,
153               $attr,
154               $this->blocks
155          );
156     }
157
158     public function getCurrentForm() {
159          return $this->currentForm;
160     }
161
162     public function renderWidget($name,$attributes=array(),$extra=array())
163     {
164          $field = $this->currentForm->$name;
165          if ($field) {
166               $attr = $field->getAttributes();
167               if (isset($attr['attr'])) {
168                    $attr['attr'] = array_merge($attr['attr'],$attributes);
169               } else {
170                    $attr['attr'] = $attributes;
171               }
172               $this->renderBlock(
173                    $field->getWidgetBlock(),
174                    array_merge(
175                         $attr,
176                         $extra
177                    )
178               );
179          }
180     }
181
182     public function renderHiddenWidgets()
183     {
184          foreach ($this->currentForm->getHiddenFields() as $h) {
185               $this->renderWidget($h->getName());
186          }
187     }
188
189     public function getName()
190     {
191          return 'dc_form';
192     }
193
194     public function addForm(dcForm $form)
195     {
196          $this->forms[$form->getName()] = $form;
197     }
198
199     public function beginForm($name)
200     {
201          if (isset($this->forms[$name])) {
202               $this->currentForm = $this->forms[$name];
203               $this->currentForm->begin();
204          }
205          else {
206               throw new Twig_Error_Runtime(sprintf(
207                    'Form "%s" does not exist',
208                    $name
209               ));
210          }
211     }
212     
213     public function endForm()
214     {
215          $this->currentForm->end();
216          $this->currentForm = null;
217     }
218}
219
220/**
221 * Template form exception
222 */
223class InvalidFieldException extends Exception {
224}
225
226/**
227* dcForm - Template form
228*
229*/
230class dcForm
231{
232     protected $id;
233     protected $name;
234     protected $core;
235     protected $action;
236     protected $fields;
237     protected $method;
238     protected $submitfields;
239     protected $hiddenfields;
240     protected $errors;
241     
242
243    /**
244     * addNonce -- adds dc nonce to form fields
245     *
246     * @access protected
247     *
248     * @return nothing
249     */
250     protected function addNonce()
251     {
252          $this->addField(
253               new dcFieldHidden(array('xd_check'),
254               $this->core->getNonce())
255          );
256     }
257     
258
259    /**
260     * Defines Name & ID from field
261     *
262     * @param mixed $nid either an array (name, id) or a string (name only, id will be set to null).
263     *
264     * @access protected
265     *
266     * @return nothing.
267     */
268     protected function setNID($nid)
269     {
270          if (is_array($nid)) {
271               $this->name = $nid[0];
272               $this->id = !empty($nid[1]) ? $nid[1] : null;
273          }
274          else {
275               $this->id = null;
276               $this->name = $nid;
277          }
278     }
279     
280     public function getContext() {
281          return array();
282     }
283
284    /**
285     * Class constructor
286     *
287     * @param mixed  $core   dotclear core
288     * @param mixed  $name   form name
289     * @param mixed  $action form action
290     * @param string $method form method ('GET' or 'POST')
291     *
292     * @access public
293     *
294     * @return mixed Value.
295     */
296     public function __construct($core,$name,$action,$method='POST')
297     {
298          $this->core = $core;
299          $this->setNID($name);
300          $this->method = $method;
301          $this->action = $action;
302          $this->fields = array();
303          $this->core->tpl->getExtension('dc_form')->addForm($this);
304          $this->submitfields = array();
305          $this->hiddenfields = array();
306          $this->errors = array();
307          if ($method == 'POST') {
308               $this->addNonce();
309          }
310     }
311     
312
313    /**
314     * Returns form name
315     *
316     * @access public
317     *
318     * @return mixed Value.
319     */
320     public function getName()
321     {
322          return $this->name;
323     }
324     
325     public function getErrors()
326     {
327          return $this->errors;
328     }
329     
330     public function addField(dcField $f)
331     {
332          if ($f instanceof dcFieldAction) {
333               $this->submitfields[$f->getName()] = $f;
334          }
335          if ($f instanceof dcFieldHidden) {
336               $this->hiddenfields[$f->getName()] = $f;
337          }
338          $this->fields[$f->getName()] = $f;
339         
340          return $this;
341     }
342     
343     public function removeField(dcField $f) {
344          $n = $f->getName();
345          if (isset($this->fields[$n])){
346               unset($this->fields[$n]);
347          }
348
349     }
350     public function renameField($field,$newname) {
351          $oldname = $field->getName();
352          if (isset($this->fields[$oldname])) {
353               unset($this->fields[$oldname]);
354               $field->setName($newname);
355               $this->fields[$newname] = $field;
356          }
357          //print_r($this->fields);
358     }
359     public function begin()
360     {
361          echo sprintf(
362               '<form%s method="%s" action="%s">',
363               empty($this->id) ? '' : ' id="'.$this->id.'"',
364               $this->method,
365               $this->action
366          );
367     }
368     
369     public function end()
370     {
371          echo '</form>';
372     }
373     
374     public function __isset($name)
375     {
376          return isset($this->fields[$name]);
377     }
378     
379     public function __get($name)
380     {
381          return isset($this->fields[$name]) ?
382               $this->fields[$name] : null;
383     }
384
385     public function __set($name,$value)
386     {
387          if (isset($this->fields[$name])) {
388               $this->fields[$name]->setAttribute('value',$value);
389          }
390     }
391
392     public function isSubmitted()
393     {
394          $from = $this->method == 'POST' ? $_POST : $_GET;
395     }
396
397     protected function setupFields() {
398          $from = $this->method == 'POST' ? $_POST : $_GET;
399          foreach ($this->fields as $f) {
400               $f->setup($from);
401          }
402     }
403
404     protected function handleActions($submitted) {
405          foreach ($submitted as $f) {
406               $action = $f->getAction();
407               if ($action != NULL) {
408                    $ret = call_user_func($action,$this);
409               }
410          }
411     }
412
413     protected function getSubmittedFields() {
414          $s = array();
415          foreach ($this->submitfields as $f) {
416               if ($f->isDefined()) {
417                    $s[$f->getName()] = $f;
418               }
419          }
420          return $s;
421     }
422
423     public function setup()
424     {
425          $this->setupFields();
426          $submitted = $this->getSubmittedFields();
427          $this->handleActions($submitted);
428     }
429
430     public function check()
431     {
432          foreach ($this->fields as $f) {
433               try {
434                    $f->check();
435               }
436               catch (InvalidFieldException $e) {
437                    $this->errors[] = $e->getMessage();
438               }
439          }
440     }
441     
442     public function getHiddenFields()
443     {
444          return $this->hiddenfields;
445     }
446}
447
448/**
449 * Template form field
450 */
451abstract class dcField
452{
453     protected $attributes;
454     protected $name;
455     protected $value;
456     protected $id;
457     protected $defined;
458     
459     protected function setNID($nid)
460     {
461          if (is_array($nid)) {
462               $this->name = $nid[0];
463               $this->id = !empty($nid[1]) ? $nid[1] : null;
464          }
465          else {
466               $this->id = $this->name = $nid;
467          }
468     }
469     
470     public function __construct($name,$value,$attributes=array())
471     {
472          $this->setNID($name);
473          $this->attributes = $attributes;
474          $this->setValue($value);
475          $this->attributes['name'] = $this->name;
476          $this->attributes['id'] = $this->id;
477          $this->defined = false;
478     }
479     
480     public function setValue($value) {
481          $this->value = $value;
482          $this->attributes['value'] = $this->value;
483     }
484
485     public function getValue() {
486          return $this->value;
487     }
488
489     public function __toString()
490     {
491          return $this->value;
492     }
493     
494     abstract public function getWidgetBlock();
495     
496     public function setAttribute($name,$value)
497     {
498          $this->attributes[$name] = $value;
499     }
500     
501     public function getAttributes()
502     {
503          return $this->attributes;
504     }
505     
506     public function getName()
507     {
508          return $this->name;
509     }
510     public function setName($name) {
511          $this->setNID($name);
512          $this->attributes['name'] = $this->name;
513          $this->attributes['id'] = $this->id;
514     }
515
516     public function check()
517     {
518          if (!$this->defined && $this->attributes['defined']) {
519               throw new InvalidFieldException(sprintf(
520                    'Field "%s" is mandatory',
521                    $this->attributes['label'])
522               );
523          }
524     }
525     
526     public function parseValue($from) {
527          if (isset($from[$this->id])) {
528               return $from[$this->id];
529          }
530          return null;
531     }
532
533     public function setup($from)
534     {
535          $value = $this->parseValue($from);
536          if ($value !== null) {
537               $this->setValue($value);
538               $this->defined = true;
539          }
540     }
541     
542     public function isDefined()
543     {
544          return $this->defined;
545     }
546}
547
548/**
549 * Template form field of type "password"
550 */
551class dcFieldPassword extends dcField
552{
553     public function getWidgetBlock()
554     {
555          return "field_password";
556     }
557}
558
559/**
560 * Template form field of type "text"
561 */
562class dcFieldText extends dcField
563{
564     public function getWidgetBlock()
565     {
566     return "field_text";
567     }
568}
569
570/**
571 * Template form field of type "textarea"
572 */
573class dcFieldTextArea extends dcField
574{
575     public function getWidgetBlock()
576     {
577          return "field_textarea";
578     }
579}
580
581/**
582 * Template form field of type "hidden"
583 */
584class dcFieldHidden extends dcField
585{
586     public function getWidgetBlock()
587     {
588          return "field_hidden";
589     }
590}
591
592/**
593 * Template form field of type "checkbox"
594 */
595class dcFieldCheckbox extends dcField
596{
597     public function getWidgetBlock()
598     {
599          return "field_checkbox";
600     }
601}
602
603/**
604 * Template form action
605 */
606abstract class dcFieldAction extends dcField
607{
608     protected $action;
609     
610     public function __construct($name,$value,$attributes=array())
611     {
612          parent::__construct($name,$value,$attributes);
613         
614          if (isset($attributes['action'])) {
615               $this->action = $attributes['action'];
616          } else {
617               $this->action = NULL;
618          }
619     }
620     
621     public function getAction()
622     {
623          return $this->action;
624     }
625}
626
627/**
628 * Template form field of type "submit"
629 */
630class dcFieldSubmit extends dcFieldAction
631{
632     public function getWidgetBlock()
633     {
634          return "field_submit";
635     }
636}
637
638/**
639 * Template form field of type "combo"
640 */
641class dcFieldCombo extends dcField
642{
643     protected $options;
644     
645     public function __construct($name,$value,$options,$attributes=array())
646     {
647          $this->options = $options;
648          parent::__construct($name,$value,$attributes);
649          $this->attributes['options']=$options;
650     }
651     
652     public function getWidgetBlock()
653     {
654          return "field_combo";
655     }
656
657     public function parseValue($from) {
658
659          $v = parent::parseValue($from);
660          if (!isset($this->options[$v])) {
661               return $this->value;
662          } else {
663               return $v;
664          }
665     }
666}
667?>
Note: See TracBrowser for help on using the repository browser.

Sites map