Subversion Repositories Applications.papyrus

Rev

Rev 320 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
320 jpm 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
// | Authors: Alexey Borzov <borz_off@cs.msu.su>                          |
17
// |          Bertrand Mansion <bmansion@mamasam.com>                     |
18
// |          Thomas Schulz <ths@4bconsult.de>                            |
19
// +----------------------------------------------------------------------+
20
//
443 ddelon 21
// $Id: ArraySmarty.php,v 1.2 2005-09-20 17:01:22 ddelon Exp $
320 jpm 22
 
23
require_once 'HTML/QuickForm/Renderer/Array.php';
24
 
25
/**
26
 * A static renderer for HTML_QuickForm, makes an array of form content
27
 * useful for an Smarty template
28
 *
29
 * Based on old toArray() code and ITStatic renderer.
30
 *
31
 * The form array structure is the following:
32
 * Array (
33
 *  [frozen]       => whether the complete form is frozen'
34
 *  [javascript]   => javascript for client-side validation
35
 *  [attributes]   => attributes for <form> tag
36
 *  [hidden]       => html of all hidden elements
37
 *  [requirednote] => note about the required elements
38
 *  [errors] => Array
39
 *      (
40
 *          [1st_element_name] => Error for the 1st element
41
 *          ...
42
 *          [nth_element_name] => Error for the nth element
43
 *      )
44
 *
45
 *  [header] => Array
46
 *      (
47
 *          [1st_header_name] => Header text for the 1st header
48
 *          ...
49
 *          [nth_header_name] => Header text for the nth header
50
 *      )
51
 *
52
 *  [1st_element_name] => Array for the 1st element
53
 *  ...
54
 *  [nth_element_name] => Array for the nth element
55
 *
56
 * // where an element array has the form:
57
 *      (
58
 *          [name]      => element name
59
 *          [value]     => element value,
60
 *          [type]      => type of the element
61
 *          [frozen]    => whether element is frozen
62
 *          [label]     => label for the element
63
 *          [required]  => whether element is required
64
 * // if element is not a group:
65
 *          [html]      => HTML for the element
66
 * // if element is a group:
67
 *          [separator] => separator for group elements
68
 *          [1st_gitem_name] => Array for the 1st element in group
69
 *          ...
70
 *          [nth_gitem_name] => Array for the nth element in group
71
 *      )
72
 * )
73
 *
74
 * @access public
75
 */
76
class HTML_QuickForm_Renderer_ArraySmarty extends HTML_QuickForm_Renderer_Array
77
{
78
   /**
79
    * The Smarty template engine instance
80
    * @var object
81
    */
82
    var $_tpl = null;
83
 
84
   /**
85
    * Current element index
86
    * @var integer
87
    */
88
    var $_elementIdx = 0;
89
 
90
    /**
91
    * The current element index inside a group
92
    * @var integer
93
    */
94
    var $_groupElementIdx = 0;
95
 
96
   /**
97
    * How to handle the required tag for required fields
98
    * @var string
99
    * @see      setRequiredTemplate()
100
    */
101
    var $_required = '';
102
 
103
   /**
104
    * How to handle error messages in form validation
105
    * @var string
106
    * @see      setErrorTemplate()
107
    */
108
    var $_error = '';
109
 
110
   /**
111
    * Constructor
112
    *
113
    * @param  object  reference to the Smarty template engine instance
114
    * @param  bool    true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key"
115
    * @access public
116
    */
117
    function HTML_QuickForm_Renderer_ArraySmarty(&$tpl, $staticLabels = false)
118
    {
119
        $this->HTML_QuickForm_Renderer_Array(true, $staticLabels);
120
        $this->_tpl =& $tpl;
121
    } // end constructor
122
 
123
   /**
124
    * Called when visiting a header element
125
    *
126
    * @param    object     An HTML_QuickForm_header element being visited
127
    * @access   public
128
    * @return   void
129
    */
130
    function renderHeader(&$header)
131
    {
132
        if ($name = $header->getName()) {
133
            $this->_ary['header'][$name] = $header->toHtml();
134
        } else {
135
            $this->_ary['header'][$this->_sectionCount] = $header->toHtml();
136
        }
137
        $this->_currentSection = $this->_sectionCount++;
138
    } // end func renderHeader
139
 
140
   /**
141
    * Called when visiting a group, before processing any group elements
142
    *
143
    * @param    object     An HTML_QuickForm_group object being visited
144
    * @param    bool       Whether a group is required
145
    * @param    string     An error message associated with a group
146
    * @access   public
147
    * @return   void
148
    */
149
    function startGroup(&$group, $required, $error)
150
    {
151
        parent::startGroup($group, $required, $error);
152
        $this->_groupElementIdx = 1;
153
    } // end func startGroup
154
 
155
   /**
156
    * Creates an array representing an element containing
157
    * the key for storing this
158
    *
159
    * @access private
160
    * @param  object    An HTML_QuickForm_element object
161
    * @param  bool      Whether an element is required
162
    * @param  string    Error associated with the element
163
    * @return array
164
    */
165
    function _elementToArray(&$element, $required, $error)
166
    {
167
        $ret = parent::_elementToArray($element, $required, $error);
168
 
169
        if ('group' == $ret['type']) {
170
            $ret['html'] = $element->toHtml();
171
            // we don't need the elements, see the array structure
172
            unset($ret['elements']);
173
        }
443 ddelon 174
        if (($required || $error) && !empty($this->_required)){
320 jpm 175
            $this->_renderRequired($ret['label'], $ret['html'], $required, $error);
176
        }
443 ddelon 177
        if ($error && !empty($this->_error)) {
320 jpm 178
            $this->_renderError($ret['label'], $ret['html'], $error);
179
            $ret['error'] = $error;
180
        }
181
        // create keys for elements grouped by native group or name
182
        if (strstr($ret['name'], '[') or $this->_currentGroup) {
183
            preg_match('/([^]]*)\\[([^]]*)\\]/', $ret['name'], $matches);
184
            if (isset($matches[1])) {
185
                $sKeysSub = substr_replace($ret['name'], '', 0, strlen($matches[1]));
186
                $sKeysSub = str_replace(
187
                    array('['  ,   ']', '[\'\']'),
188
                    array('[\'', '\']', '[]'    ),
189
                    $sKeysSub
190
                );
191
                $sKeys = '[\'' . $matches[1]  . '\']' . $sKeysSub;
192
            } else {
193
                $sKeys = '[\'' . $ret['name'] . '\']';
194
            }
195
            // special handling for elements in native groups
196
            if ($this->_currentGroup) {
197
                // skip unnamed group items unless radios: no name -> no static access
198
                // identification: have the same key string as the parent group
199
                if ($this->_currentGroup['keys'] == $sKeys and 'radio' != $ret['type']) {
200
                    return false;
201
                }
202
                // reduce string of keys by remove leading group keys
203
                if (0 === strpos($sKeys, $this->_currentGroup['keys'])) {
204
                    $sKeys = substr_replace($sKeys, '', 0, strlen($this->_currentGroup['keys']));
205
                }
206
            }
207
        // element without a name
208
        } elseif ($ret['name'] == '') {
209
            $sKeys = '[\'element_' . $this->_elementIdx . '\']';
210
        // other elements
211
        } else {
212
            $sKeys = '[\'' . $ret['name'] . '\']';
213
        }
214
        // for radios: add extra key from value
215
        if ('radio' == $ret['type'] and substr($sKeys, -2) != '[]') {
216
            $sKeys .= '[\'' . $ret['value'] . '\']';
217
        }
218
        $this->_elementIdx++;
219
        $ret['keys'] = $sKeys;
220
        return $ret;
221
    } // end func _elementToArray
222
 
223
   /**
224
    * Stores an array representation of an element in the form array
225
    *
226
    * @access private
227
    * @param array  Array representation of an element
228
    * @return void
229
    */
230
    function _storeArray($elAry)
231
    {
232
        if ($elAry) {
233
            $sKeys = $elAry['keys'];
234
            unset($elAry['keys']);
235
            // where should we put this element...
236
            if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) {
237
                $toEval = '$this->_currentGroup' . $sKeys . ' = $elAry;';
238
            } else {
239
                $toEval = '$this->_ary' . $sKeys . ' = $elAry;';
240
            }
241
            eval($toEval);
242
        }
243
        return;
244
    }
245
 
246
   /**
247
    * Called when an element is required
248
    *
249
    * This method will add the required tag to the element label and/or the element html
250
    * such as defined with the method setRequiredTemplate.
251
    *
252
    * @param    string      The element label
253
    * @param    string      The element html rendering
254
    * @param    boolean     The element required
255
    * @param    string      The element error
256
    * @see      setRequiredTemplate()
257
    * @access   private
258
    * @return   void
259
    */
260
    function _renderRequired(&$label, &$html, &$required, &$error)
261
    {
262
        $this->_tpl->assign(array(
263
            'label'    => $label,
264
            'html'     => $html,
265
            'required' => $required,
266
            'error'    => $error
267
        ));
268
        if (!empty($label) && strpos($this->_required, $this->_tpl->left_delimiter . '$label') !== false) {
269
            $label = $this->_tplFetch($this->_required);
270
        }
271
        if (!empty($html) && strpos($this->_required, $this->_tpl->left_delimiter . '$html') !== false) {
272
            $html = $this->_tplFetch($this->_required);
273
        }
274
        $this->_tpl->clear_assign(array('label', 'html', 'required'));
275
    } // end func _renderRequired
276
 
277
   /**
278
    * Called when an element has a validation error
279
    *
280
    * This method will add the error message to the element label or the element html
281
    * such as defined with the method setErrorTemplate. If the error placeholder is not found
282
    * in the template, the error will be displayed in the form error block.
283
    *
284
    * @param    string      The element label
285
    * @param    string      The element html rendering
286
    * @param    string      The element error
287
    * @see      setErrorTemplate()
288
    * @access   private
289
    * @return   void
290
    */
291
    function _renderError(&$label, &$html, &$error)
292
    {
293
        $this->_tpl->assign(array('label' => '', 'html' => '', 'error' => $error));
294
        $error = $this->_tplFetch($this->_error);
295
        $this->_tpl->assign(array('label' => $label, 'html'  => $html));
296
 
297
        if (!empty($label) && strpos($this->_error, $this->_tpl->left_delimiter . '$label') !== false) {
298
            $label = $this->_tplFetch($this->_error);
299
        } elseif (!empty($html) && strpos($this->_error, $this->_tpl->left_delimiter . '$html') !== false) {
300
            $html = $this->_tplFetch($this->_error);
301
        }
302
        $this->_tpl->clear_assign(array('label', 'html', 'error'));
303
    } // end func _renderError
304
 
305
   /**
306
    * Process an template sourced in a string with Smarty
307
    *
308
    * Smarty has no core function to render	a template given as a string.
309
    * So we use the smarty eval plugin function	to do this.
310
    *
311
    * @param    string      The template source
312
    * @access   private
313
    * @return   void
314
    */
315
    function _tplFetch($tplSource)
316
    {
317
        if (!function_exists('smarty_function_eval')) {
318
            require SMARTY_DIR . '/plugins/function.eval.php';
319
        }
320
        return smarty_function_eval(array('var' => $tplSource), $this->_tpl);
321
    }// end func _tplFetch
322
 
323
   /**
324
    * Sets the way required elements are rendered
325
    *
326
    * You can use {$label} or {$html} placeholders to let the renderer know where
327
    * where the element label or the element html are positionned according to the
328
    * required tag. They will be replaced accordingly with the right value.	You
329
    * can use the full smarty syntax here, especially a custom modifier for I18N.
330
    * For example:
331
    * {if $required}<span style="color: red;">*</span>{/if}{$label|translate}
332
    * will put a red star in front of the label if the element is required and
333
    * translate the label.
334
    *
335
    *
336
    * @param    string      The required element template
337
    * @access   public
338
    * @return   void
339
    */
340
    function setRequiredTemplate($template)
341
    {
342
        $this->_required = $template;
343
    } // end func setRequiredTemplate
344
 
345
   /**
346
    * Sets the way elements with validation errors are rendered
347
    *
348
    * You can use {$label} or {$html} placeholders to let the renderer know where
349
    * where the element label or the element html are positionned according to the
350
    * error message. They will be replaced accordingly with the right value.
351
    * The error message will replace the {$error} placeholder.
352
    * For example:
353
    * {if $error}<span style="color: red;">{$error}</span>{/if}<br />{$html}
354
    * will put the error message in red on top of the element html.
355
    *
356
    * If you want all error messages to be output in the main error block, use
357
    * the {$form.errors} part of the rendered array that collects all raw error
358
    * messages.
359
    *
360
    * If you want to place all error messages manually, do not specify {$html}
361
    * nor {$label}.
362
    *
363
    * Groups can have special layouts. With this kind of groups, you have to
364
    * place the formated error message manually. In this case, use {$form.group.error}
365
    * where you want the formated error message to appear in the form.
366
    *
367
    * @param    string      The element error template
368
    * @access   public
369
    * @return   void
370
    */
371
    function setErrorTemplate($template)
372
    {
373
        $this->_error = $template;
374
    } // end func setErrorTemplate
375
}
376
?>