1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------+
4// | PHP version 4.0                                                      |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1997-2003 The PHP Group                                |
7// +----------------------------------------------------------------------+
8// | This source file is subject to version 2.0 of the PHP license,       |
9// | that is bundled with this package in the file LICENSE, and is        |
10// | available at through the world-wide-web at                           |
11// | http://www.php.net/license/2_02.txt.                                 |
12// | If you did not receive a copy of the PHP license and are unable to   |
13// | obtain it through the world-wide-web, please send a note to          |
14// | license@php.net so we can mail you a copy immediately.               |
15// +----------------------------------------------------------------------+
16// | Author: Ron McClain <ron@humaniq.com>                                |
17// +----------------------------------------------------------------------+
18//
19// $Id$
20
21require_once('HTML/QuickForm/Renderer.php');
22
23/**
24 * A concrete renderer for HTML_QuickForm, makes an object from form contents
25 *
26 * Based on HTML_Quickform_Renderer_Array code
27 *
28 * @access public
29 */
30class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
31{
32    /**
33     * The object being generated
34     * @var object $_obj
35     */
36    var $_obj= null;
37
38    /**
39     * Number of sections in the form (i.e. number of headers in it)
40     * @var integer $_sectionCount
41     */
42    var $_sectionCount;
43
44    /**
45    * Current section number
46    * @var integer $_currentSection
47    */
48    var $_currentSection;
49
50    /**
51    * Object representing current group
52    * @var object $_currentGroup
53    */
54    var $_currentGroup = null;
55
56    /**
57     * Class of Element Objects
58     * @var object $_elementType
59     */
60    var $_elementType = 'QuickFormElement';
61
62    /**
63    * Additional style information for different elements
64    * @var array $_elementStyles
65    */
66    var $_elementStyles = array();
67
68    /**
69    * true: collect all hidden elements into string; false: process them as usual form elements
70    * @var bool $_collectHidden
71    */
72    var $_collectHidden = false;
73
74
75    /**
76     * Constructor
77     *
78     * @param collecthidden bool    true: collect all hidden elements
79     * @access public
80     */
81    public function __construct($collecthidden = false) {
82        parent::__construct();
83        $this->_collectHidden = $collecthidden;
84        $this->_obj = new QuickformForm;
85    }
86
87    /**
88     * Old syntax of class constructor. Deprecated in PHP7.
89     *
90     * @deprecated since Moodle 3.1
91     */
92    public function HTML_QuickForm_Renderer_Object($collecthidden = false) {
93        debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
94        self::__construct($collecthidden);
95    }
96
97    /**
98     * Return the rendered Object
99     * @access public
100     */
101    function toObject()
102    {
103        return $this->_obj;
104    }
105
106    /**
107     * Set the class of the form elements.  Defaults to QuickformElement.
108     * @param type string   Name of element class
109     * @access public
110     */
111    function setElementType($type)
112    {
113        $this->_elementType = $type;
114    }
115
116    function startForm(&$form)
117    {
118        $this->_obj->frozen = $form->isFrozen();
119        $this->_obj->javascript = $form->getValidationScript();
120        $this->_obj->attributes = $form->getAttributes(true);
121        $this->_obj->requirednote = $form->getRequiredNote();
122        $this->_obj->errors = new StdClass;
123
124        if($this->_collectHidden) {
125            $this->_obj->hidden = '';
126        }
127        $this->_elementIdx = 1;
128        $this->_currentSection = null;
129        $this->_sectionCount = 0;
130    } // end func startForm
131
132    function renderHeader(&$header)
133    {
134        $hobj = new StdClass;
135        $hobj->header = $header->toHtml();
136        $this->_obj->sections[$this->_sectionCount] = $hobj;
137        $this->_currentSection = $this->_sectionCount++;
138    }
139
140    function renderElement(&$element, $required, $error)
141    {
142        $elObj = $this->_elementToObject($element, $required, $error);
143        if(!empty($error)) {
144            $name = $elObj->name;
145            $this->_obj->errors->$name = $error;
146        }
147        $this->_storeObject($elObj);
148    } // end func renderElement
149
150    function renderHidden(&$element)
151    {
152        if($this->_collectHidden) {
153            $this->_obj->hidden .= $element->toHtml() . "\n";
154        } else {
155            $this->renderElement($element, false, null);
156        }
157    } //end func renderHidden
158
159    function startGroup(&$group, $required, $error)
160    {
161        $this->_currentGroup = $this->_elementToObject($group, $required, $error);
162        if(!empty($error)) {
163            $name = $this->_currentGroup->name;
164            $this->_obj->errors->$name = $error;
165        }
166    } // end func startGroup
167
168    function finishGroup(&$group)
169    {
170        $this->_storeObject($this->_currentGroup);
171        $this->_currentGroup = null;
172    } // end func finishGroup
173
174    /**
175     * Creates an object representing an element
176     *
177     * @access private
178     * @param element object    An HTML_QuickForm_element object
179     * @param required bool         Whether an element is required
180     * @param error string    Error associated with the element
181     * @return object
182     */
183    function _elementToObject(&$element, $required, $error)
184    {
185        if($this->_elementType) {
186            $ret = new $this->_elementType;
187        }
188        $ret->name = $element->getName();
189        $ret->value = $element->getValue();
190        $ret->type = $element->getType();
191        $ret->frozen = $element->isFrozen();
192        $labels = $element->getLabel();
193        if (is_array($labels)) {
194            $ret->label = array_shift($labels);
195            foreach ($labels as $key => $label) {
196                $key = is_int($key)? $key + 2: $key;
197                $ret->{'label_' . $key} = $label;
198            }
199        } else {
200            $ret->label = $labels;
201        }
202        $ret->required = $required;
203        $ret->error = $error;
204
205        if(isset($this->_elementStyles[$ret->name])) {
206            $ret->style = $this->_elementStyles[$ret->name];
207            $ret->styleTemplate = "styles/". $ret->style .".html";
208        }
209        if($ret->type == 'group') {
210            $ret->separator = $element->_separator;
211            $ret->elements = array();
212        } else {
213            $ret->html = $element->toHtml();
214        }
215        return $ret;
216    }
217
218    /**
219     * Stores an object representation of an element in the form array
220     *
221     * @access private
222     * @param elObj object     Object representation of an element
223     * @return void
224     */
225    function _storeObject($elObj)
226    {
227        $name = $elObj->name;
228        if(is_object($this->_currentGroup) && $elObj->type != 'group') {
229            $this->_currentGroup->elements[] = $elObj;
230        } elseif (isset($this->_currentSection)) {
231            $this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
232        } else {
233            $this->_obj->elements[] = $elObj;
234        }
235    }
236
237    function setElementStyle($elementName, $styleName = null)
238    {
239        if(is_array($elementName)) {
240            $this->_elementStyles = array_merge($this->_elementStyles, $elementName);
241        } else {
242            $this->_elementStyles[$elementName] = $styleName;
243        }
244    }
245
246} // end class HTML_QuickForm_Renderer_Object
247
248
249
250/**
251 * Convenience class for the form object passed to outputObject()
252 *
253 * Eg.
254 * {form.outputJavaScript():h}
255 * {form.outputHeader():h}
256 *   <table>
257 *     <tr>
258 *       <td>{form.name.label:h}</td><td>{form.name.html:h}</td>
259 *     </tr>
260 *   </table>
261 * </form>
262 */
263class QuickformForm
264{
265   /**
266    * Whether the form has been frozen
267    * @var boolean $frozen
268    */
269    var $frozen;
270
271   /**
272    * Javascript for client-side validation
273    * @var string $javascript
274    */
275    var $javascript;
276
277   /**
278    * Attributes for form tag
279    * @var string $attributes
280    */
281    var $attributes;
282
283   /**
284    * Note about required elements
285    * @var string $requirednote
286    */
287    var $requirednote;
288
289   /**
290    * Collected html of all hidden variables
291    * @var string $hidden
292    */
293    var $hidden;
294
295   /**
296    * Set if there were validation errors.
297    * StdClass object with element names for keys and their
298    * error messages as values
299    * @var object $errors
300    */
301    var $errors;
302
303   /**
304    * Array of QuickformElementObject elements.  If there are headers in the form
305    * this will be empty and the elements will be in the
306    * separate sections
307    * @var array $elements
308    */
309    var $elements;
310
311   /**
312    * Array of sections contained in the document
313    * @var array $sections
314    */
315    var $sections;
316
317   /**
318    * Output &lt;form&gt; header
319    * {form.outputHeader():h}
320    * @return string    &lt;form attributes&gt;
321    */
322    function outputHeader()
323    {
324        return "<form " . $this->attributes . ">\n";
325    }
326
327   /**
328    * Output form javascript
329    * {form.outputJavaScript():h}
330    * @return string    Javascript
331    */
332    function outputJavaScript()
333    {
334        return $this->javascript;
335    }
336} // end class QuickformForm
337
338
339/**
340 * Convenience class describing a form element.
341 * The properties defined here will be available from
342 * your flexy templates by referencing
343 * {form.zip.label:h}, {form.zip.html:h}, etc.
344 */
345class QuickformElement
346{
347    /**
348     * Element name
349     * @var string $name
350     */
351    var $name;
352
353    /**
354     * Element value
355     * @var mixed $value
356     */
357    var $value;
358
359    /**
360     * Type of element
361     * @var string $type
362     */
363    var $type;
364
365    /**
366     * Whether the element is frozen
367     * @var boolean $frozen
368     */
369    var $frozen;
370
371    /**
372     * Label for the element
373     * @var string $label
374     */
375    var $label;
376
377    /**
378     * Whether element is required
379     * @var boolean $required
380     */
381    var $required;
382
383    /**
384     * Error associated with the element
385     * @var string $error
386     */
387    var $error;
388
389    /**
390     * Some information about element style
391     * @var string $style
392     */
393    var $style;
394
395    /**
396     * HTML for the element
397     * @var string $html
398     */
399    var $html;
400
401    /**
402     * If element is a group, the group separator
403     * @var mixed $separator
404     */
405    var $separator;
406
407    /**
408     * If element is a group, an array of subelements
409     * @var array $elements
410     */
411    var $elements;
412
413    function isType($type)
414    {
415        return ($this->type == $type);
416    }
417
418    function notFrozen()
419    {
420        return !$this->frozen;
421    }
422
423    function isButton()
424    {
425        return ($this->type == "submit" || $this->type == "reset");
426    }
427
428
429   /**
430    * XXX: why does it use Flexy when all other stuff here does not depend on it?
431    */
432    function outputStyle()
433    {
434        ob_start();
435        HTML_Template_Flexy::staticQuickTemplate('styles/' . $this->style . '.html', $this);
436        $ret = ob_get_contents();
437        ob_end_clean();
438        return $ret;
439    }
440} // end class QuickformElement
441?>
442