Dotclear

source: inc/admin/class.dc.form.php @ 1090:ed55b73cde39

Revision 1090:ed55b73cde39, 10.0 KB checked in by JcDenis, 13 years ago (diff)

Added support of id on forms

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 * Template form node
16 */
17class dcFormNode extends Twig_Node
18{
19     public function __construct($name,Twig_NodeInterface $body,$lineno,$tag=null)
20     {
21          parent::__construct(array('body' => $body),array('name' => $name),$lineno,$tag);
22     }
23     
24     /**
25     * Compiles the node to PHP.
26     *
27     * @param Twig_Compiler A Twig_Compiler instance
28     */
29     public function compile(Twig_Compiler $compiler)
30     {
31          $compiler
32               ->addDebugInfo($this)
33               ->write("\$context['dc_form']->beginForm('".
34                    $this->getAttribute('name')."');\n")
35               ->subcompile($this->getNode('body'))
36               ->write("\$context['dc_form']->renderHiddenWidgets();\n")
37               ->write("\$context['dc_form']->endForm();\n")
38          ;
39     }
40}
41
42/**
43 * Template form token parser
44 */
45class dcFormTokenParser extends Twig_TokenParser
46{
47     public function parse(Twig_Token $token)
48     {
49          $lineno = $token->getLine();
50          $stream = $this->parser->getStream();
51          $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
52          $stream->expect(Twig_Token::BLOCK_END_TYPE);
53          $body = $this->parser->subparse(array($this,'decideBlockEnd'),true);
54          $stream->expect(Twig_Token::BLOCK_END_TYPE);
55         
56          return new dcFormNode($name,$body,$token->getLine(),$this->getTag());
57     }
58     
59     public function decideBlockEnd(Twig_Token $token)
60     {
61          return $token->test('endform');
62     }
63     
64     public function getTag()
65     {
66          return 'form';
67     }
68}
69
70/**
71 * Template form extension
72 */
73class dcFormExtension extends Twig_Extension
74{
75     protected $template;
76     protected $tpl;
77     protected $core;
78     protected $twig;
79     protected $blocks;
80     protected $forms;
81     protected $currentForm;
82     
83     public function __construct($core)
84     {
85          $this->core = $core;
86          $this->tpl = 'form_layout.html.twig';
87          $this->forms = array();
88          $this->currentForm = null;
89     }
90     
91     public function initRuntime(Twig_Environment $environment)
92     {
93          $this->twig = $environment;
94          $this->template = $this->twig->loadTemplate($this->tpl);
95          $this->blocks = $this->template->getBlocks();
96     }
97     
98     public function getGlobals()
99     {
100          return array('dc_form' => $this);
101     }
102     
103     public function getFunctions()
104     {
105          return array(
106               'form_field' => new Twig_Function_Method(
107                    $this,
108                    'renderWidget',
109                    array('is_safe' => array('html'))
110               ),
111               '_form_is_choice_group' => new Twig_Function_Method(
112                    $this,
113                    'isChoiceGroup',
114                    array('is_safe' => array('html'))
115               ),
116               '_form_is_choice_selected' => new Twig_Function_Method(
117                    $this,
118                    'isChoiceSelected',
119                    array('is_safe' => array('html'))
120               )
121          );
122     }
123     
124     public function isChoiceGroup($choice)
125     {
126          return is_array($choice);
127     }
128     
129     public function isChoiceSelected($choice,$value)
130     {
131          return $choice == $value;
132     }
133     
134     public function getTokenParsers()
135     {
136          return array(new dcFormTokenParser());
137     }
138     
139     public function renderWidget($name,$attributes=array())
140     {
141          $field = $this->currentForm->$name;
142          if ($field) {
143               echo $this->template->renderBlock(
144                    $field->getWidgetBlock(),
145                    array_merge(
146                         $field->getAttributes(),
147                         array('attr' => $attributes)
148                    ),
149                    $this->blocks
150               );
151          }
152     }
153
154     public function renderHiddenWidgets()
155     {
156          foreach ($this->currentForm->getHiddenFields() as $h) {
157               $this->renderWidget($h->getName());
158          }
159     }
160
161     public function getName()
162     {
163          return 'dc_form';
164     }
165
166     public function addForm(dcForm $form)
167     {
168          $this->forms[$form->getName()] = $form;
169     }
170
171     public function beginForm($name)
172     {
173          if (isset($this->forms[$name])) {
174               $this->currentForm = $this->forms[$name];
175               $this->currentForm->begin();
176          }
177          else {
178               throw new Twig_Error_Runtime(sprintf(
179                    'Form "%s" does not exist',
180                    $name
181               ));
182          }
183     }
184     
185     public function endForm()
186     {
187          $this->currentForm->end();
188          $this->currentForm = null;
189     }
190}
191
192/**
193 * Template form exception
194 */
195class InvalidFieldException extends Exception {
196}
197
198/**
199 * Template form
200 */
201class dcForm
202{
203     protected $id;
204     protected $name;
205     protected $core;
206     protected $action;
207     protected $fields;
208     protected $method;
209     protected $submitfields;
210     protected $hiddenfields;
211     protected $errors;
212     
213     private function addNonce()
214     {
215          $this->addField(
216               new dcFieldHidden(array('xd_check'),
217               $this->core->getNonce())
218          );
219     }
220     
221     protected function getNID($nid)
222     {
223          if (is_array($nid)) {
224               $this->name = $nid[0];
225               $this->id = !empty($nid[1]) ? $nid[1] : null;
226          }
227          else {
228               $this->id = null;
229               $this->name = $nid;
230          }
231     }
232     
233     public function __construct($core,$name,$action,$method='POST')
234     {
235          $this->core = $core;
236          $this->getNID($name);
237          $this->method = $method;
238          $this->action = $action;
239          $this->fields = array();
240          $this->core->tpl->getExtension('dc_form')->addForm($this);
241          $this->submitfields = array();
242          $this->hiddenfields = array();
243          $this->errors = array();
244          if ($method == 'POST') {
245               $this->addNonce();
246          }
247     }
248     
249     public function getName()
250     {
251          return $this->name;
252     }
253     
254     public function getErrors()
255     {
256          return $this->errors;
257     }
258     
259     public function addField(dcField $f)
260     {
261          if ($f instanceof dcFieldAction) {
262               $this->submitfields[$f->getName()] = $f;
263          }
264          if ($f instanceof dcFieldHidden) {
265               $this->hiddenfields[$f->getName()] = $f;
266          }
267          $this->fields[$f->getName()] = $f;
268         
269          return $this;
270     }
271     
272     public function begin()
273     {
274          echo sprintf(
275               '<form%s method="%s" action="%s">',
276               empty($this->id) ? '' : ' id="'.$this->id.'"',
277               $this->method,
278               $this->action
279          );
280     }
281     
282     public function end()
283     {
284          echo '</form>';
285     }
286     
287     public function __isset($name)
288     {
289          return isset($this->fields[$name]);
290     }
291     
292     public function __get($name)
293     {
294          return isset($this->fields[$name]) ? 
295               $this->fields[$name] : null;
296     }
297     
298     public function __set($name,$value)
299     {
300          if (isset($this->fields[$name])) {
301               $this->fields[$name]->setAttribute('value',$value);
302          }
303     }
304     
305     public function isSubmitted()
306     {
307          $from = $this->method == 'POST' ? $_POST : $_GET;
308          echo "form fields :\n";
309     }
310     
311     public function setup()
312     {
313          $from = $this->method == 'POST' ? $_POST : $_GET;
314          foreach ($this->fields as $f) {
315               $f->setup($from);
316          }
317          foreach ($this->submitfields as $f) {
318               if ($f->isDefined()) {
319                    $ret = call_user_func($f->getAction(),$this);
320                    return;
321               }
322          }
323     }
324     
325     public function check()
326     {
327          foreach ($this->fields as $f) {
328               try {
329                    $f->check();
330               }
331               catch (InvalidFieldException $e) {
332                    $this->errors[] = $e->getMessage();
333               }
334          }
335     }
336     
337     public function getHiddenFields()
338     {
339          return $this->hiddenfields;
340     }
341}
342
343/**
344 * Template form field
345 */
346abstract class dcField
347{
348     protected $attributes;
349     protected $name;
350     protected $value;
351     protected $id;
352     protected $defined;
353     
354     protected function getNID($nid)
355     {
356          if (is_array($nid)) {
357               $this->name = $nid[0];
358               $this->id = !empty($nid[1]) ? $nid[1] : null;
359          }
360          else {
361               $this->id = $this->name = $nid;
362          }
363     }
364     
365     public function __construct($name,$value,$attributes=array())
366     {
367          $this->getNID($name);
368          $this->attributes = $attributes;
369          $this->value = $value;
370          $this->attributes['name'] = $this->name;
371          $this->attributes['id'] = $this->id;
372          $this->attributes['value'] = $this->value;
373          $this->defined = false;
374     }
375     
376     public function __toString()
377     {
378          return $this->value;
379     }
380     
381     abstract public function getWidgetBlock();
382     
383     public function setAttribute($name,$value)
384     {
385          $this->attributes[$name] = $value;
386     }
387     
388     public function getAttributes()
389     {
390          return $this->attributes;
391     }
392     
393     public function getName()
394     {
395          return $this->name;
396     }
397     
398     public function check()
399     {
400          if (!$this->defined && $this->attributes['defined']) {
401               throw new InvalidFieldException(sprintf(
402                    'Field "%s" is mandatory',
403                    $this->attributes['label'])
404               );
405          }
406     }
407     
408     public function setup($from)
409     {
410          if (isset($from[$this->id])) {
411               $this->value = $from[$this->id];
412               $this->defined = true;
413          }
414     }
415     
416     public function isDefined()
417     {
418          return $this->defined;
419     }
420}
421
422/**
423 * Template form field of type "password"
424 */
425class dcFieldPassword extends dcField
426{
427     public function getWidgetBlock()
428     {
429          return "field_password";
430     }
431}
432
433/**
434 * Template form field of type "text"
435 */
436class dcFieldText extends dcField
437{
438     public function getWidgetBlock()
439     {
440     return "field_text";
441     }
442}
443
444/**
445 * Template form field of type "textarea"
446 */
447class dcFieldTextArea extends dcField
448{
449     public function getWidgetBlock()
450     {
451          return "field_textarea";
452     }
453}
454
455/**
456 * Template form field of type "hidden"
457 */
458class dcFieldHidden extends dcField
459{
460     public function getWidgetBlock()
461     {
462          return "field_hidden";
463     }
464}
465
466/**
467 * Template form field of type "checkbox"
468 */
469class dcFieldCheckbox extends dcField
470{
471     public function getWidgetBlock()
472     {
473          return "field_checkbox";
474     }
475}
476
477/**
478 * Template form action
479 */
480abstract class dcFieldAction extends dcField
481{
482     protected $action;
483     
484     public function __construct($name,$value,$attributes=array())
485     {
486          parent::__construct($name,$value,$attributes);
487         
488          if (isset($attributes['action'])) {
489               $this->action = $attributes['action'];
490          }
491     }
492     
493     public function getAction()
494     {
495          return $this->action;
496     }
497}
498
499/**
500 * Template form field of type "submit"
501 */
502class dcFieldSubmit extends dcFieldAction
503{
504     public function getWidgetBlock()
505     {
506          return "field_submit";
507     }
508}
509
510/**
511 * Template form field of type "combo"
512 */
513class dcFieldCombo extends dcField
514{
515     protected $options;
516     
517     public function __construct($name,$value,$options,$attributes=array())
518     {
519          $this->options = $options;
520          parent::__construct($name,$value,$attributes);
521          $this->attributes['options']=$options;
522     }
523     
524     public function getWidgetBlock()
525     {
526          return "field_combo";
527     }
528
529}
530?>
Note: See TracBrowser for help on using the repository browser.

Sites map