Dotclear

source: inc/admin/class.dc.form.php @ 1058:d839f35806af

Revision 1058:d839f35806af, 9.8 KB checked in by JcDenis, 13 years ago (diff)
  • Clean up dcForm classes according to Dotclear's coding standards
  • Added magic toString method to dcField
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 $name;
204     protected $core;
205     protected $action;
206     protected $fields;
207     protected $method;
208     protected $submitfields;
209     protected $hiddenfields;
210     protected $errors;
211     
212     private function addNonce()
213     {
214          $this->addField(
215               new dcFieldHidden(array('xd_check'),
216               $this->core->getNonce())
217          );
218     }
219     
220     public function __construct($core,$name,$action,$method='POST')
221     {
222          $this->core = $core;
223          $this->name = $name;
224          $this->method = $method;
225          $this->action = $action;
226          $this->fields = array();
227          $this->core->tpl->getExtension('dc_form')->addForm($this);
228          $this->submitfields = array();
229          $this->hiddenfields = array();
230          $this->errors = array();
231          if ($method == 'POST') {
232               $this->addNonce();
233          }
234     }
235     
236     public function getName()
237     {
238          return $this->name;
239     }
240     
241     public function getErrors()
242     {
243          return $this->errors;
244     }
245     
246     public function addField(dcField $f)
247     {
248          if ($f instanceof dcFieldAction) {
249               $this->submitfields[$f->getName()] = $f;
250          }
251          if ($f instanceof dcFieldHidden) {
252               $this->hiddenfields[$f->getName()] = $f;
253          }
254          $this->fields[$f->getName()] = $f;
255         
256          return $this;
257     }
258     
259     public function begin()
260     {
261          echo sprintf(
262               '<form method="%s" action="%s">',
263               $this->method,
264               $this->action
265          );
266     }
267     
268     public function end()
269     {
270          echo '</form>';
271     }
272     
273     public function __isset($name)
274     {
275          return isset($this->fields[$name]);
276     }
277     
278     public function __get($name)
279     {
280          return isset($this->fields[$name]) ? 
281               $this->fields[$name] : null;
282     }
283     
284     public function __set($name,$value)
285     {
286          if (isset($this->fields[$name])) {
287               $this->fields[$name]->setAttribute('value',$value);
288          }
289     }
290     
291     public function isSubmitted()
292     {
293          $from = $this->method == 'POST' ? $_POST : $_GET;
294          echo "form fields :\n";
295     }
296     
297     public function setup()
298     {
299          $from = $this->method == 'POST' ? $_POST : $_GET;
300          foreach ($this->fields as $f) {
301               $f->setup($from);
302          }
303          foreach ($this->submitfields as $f) {
304               if ($f->isDefined()) {
305                    $ret = call_user_func($f->getAction(),$this);
306                    return;
307               }
308          }
309     }
310     
311     public function check()
312     {
313          foreach ($this->fields as $f) {
314               try {
315                    $f->check();
316               }
317               catch (InvalidFieldException $e) {
318                    $this->errors[] = $e->getMessage();
319               }
320          }
321     }
322     
323     public function getHiddenFields()
324     {
325          return $this->hiddenfields;
326     }
327}
328
329/**
330 * Template form field
331 */
332abstract class dcField
333{
334     protected $attributes;
335     protected $name;
336     protected $value;
337     protected $id;
338     protected $defined;
339     
340     protected function getNID($nid)
341     {
342          if (is_array($nid)) {
343               $this->name = $nid[0];
344               $this->id = !empty($nid[1]) ? $nid[1] : null;
345          }
346          else {
347               $this->id = $this->name = $nid;
348          }
349     }
350     
351     public function __construct($name,$value,$attributes=array())
352     {
353          $this->getNID($name);
354          $this->attributes = $attributes;
355          $this->value = $value;
356          $this->attributes['name'] = $this->name;
357          $this->attributes['id'] = $this->id;
358          $this->attributes['value'] = $this->value;
359          $this->defined = false;
360     }
361     
362     public function __toString()
363     {
364          return $this->value;
365     }
366     
367     abstract public function getWidgetBlock();
368     
369     public function setAttribute($name,$value)
370     {
371          $this->attributes[$name] = $value;
372     }
373     
374     public function getAttributes()
375     {
376          return $this->attributes;
377     }
378     
379     public function getName()
380     {
381          return $this->name;
382     }
383     
384     public function check()
385     {
386          if (!$this->defined && $this->attributes['defined']) {
387               throw new InvalidFieldException(sprintf(
388                    'Field "%s" is mandatory',
389                    $this->attributes['label'])
390               );
391          }
392     }
393     
394     public function setup($from)
395     {
396          if (isset($from[$this->id])) {
397               $this->value = $from[$this->id];
398               $this->defined = true;
399          }
400     }
401     
402     public function isDefined()
403     {
404          return $this->defined;
405     }
406}
407
408/**
409 * Template form field of type "password"
410 */
411class dcFieldPassword extends dcField
412{
413     public function getWidgetBlock()
414     {
415          return "field_password";
416     }
417}
418
419/**
420 * Template form field of type "text"
421 */
422class dcFieldText extends dcField
423{
424     public function getWidgetBlock()
425     {
426     return "field_text";
427     }
428}
429
430/**
431 * Template form field of type "textarea"
432 */
433class dcFieldTextArea extends dcField
434{
435     public function getWidgetBlock()
436     {
437          return "field_textarea";
438     }
439}
440
441/**
442 * Template form field of type "hidden"
443 */
444class dcFieldHidden extends dcField
445{
446     public function getWidgetBlock()
447     {
448          return "field_hidden";
449     }
450}
451
452/**
453 * Template form field of type "checkbox"
454 */
455class dcFieldCheckbox extends dcField
456{
457     public function getWidgetBlock()
458     {
459          return "field_checkbox";
460     }
461}
462
463/**
464 * Template form action
465 */
466abstract class dcFieldAction extends dcField
467{
468     protected $action;
469     
470     public function __construct($name,$value,$attributes=array())
471     {
472          parent::__construct($name,$value,$attributes);
473         
474          if (isset($attributes['action'])) {
475               $this->action = $attributes['action'];
476          }
477     }
478     
479     public function getAction()
480     {
481          return $this->action;
482     }
483}
484
485/**
486 * Template form field of type "submit"
487 */
488class dcFieldSubmit extends dcFieldAction
489{
490     public function getWidgetBlock()
491     {
492          return "field_submit";
493     }
494}
495
496/**
497 * Template form field of type "combo"
498 */
499class dcFieldCombo extends dcField
500{
501     protected $options;
502     
503     public function __construct($name,$value,$options,$attributes=array())
504     {
505          $this->options = $options;
506          parent::__construct($name,$value,$attributes);
507          $this->attributes['options']=$options;
508     }
509     
510     public function getWidgetBlock()
511     {
512          return "field_combo";
513     }
514
515}
516?>
Note: See TracBrowser for help on using the repository browser.

Sites map