PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.3.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.3.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / libs / HTML / QuickForm2 / Renderer / Default.php
matomo / app / libs / HTML / QuickForm2 / Renderer Last commit date
Array.php 6 years ago Default.php 6 years ago Plugin.php 6 years ago Proxy.php 6 years ago Smarty.php 6 years ago
Default.php
599 lines
1 <?php
2 /**
3 * Default renderer for HTML_QuickForm2
4 *
5 * PHP version 5
6 *
7 * LICENSE:
8 *
9 * Copyright (c) 2006-2010, Alexey Borzov <avb@php.net>,
10 * Bertrand Mansion <golgote@mamasam.com>
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * * Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * * The names of the authors may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
26 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
33 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * @category HTML
38 * @package HTML_QuickForm2
39 * @author Alexey Borzov <avb@php.net>
40 * @author Bertrand Mansion <golgote@mamasam.com>
41 * @license http://opensource.org/licenses/bsd-license.php New BSD License
42 * @version SVN: $Id: Default.php 299706 2010-05-24 18:32:37Z avb $
43 * @link http://pear.php.net/package/HTML_QuickForm2
44 */
45
46 /**
47 * Abstract base class for QuickForm2 renderers
48 */
49 // require_once 'HTML/QuickForm2/Renderer.php';
50
51 /**
52 * Default renderer for QuickForm2
53 *
54 * Mostly a direct port of Default renderer from QuickForm 3.x package.
55 *
56 * While almost everything in this class is defined as public, its properties
57 * and those methods that are not published (i.e. not in array returned by
58 * exportMethods()) will be available to renderer plugins only.
59 *
60 * The following methods are published:
61 * - {@link reset()}
62 * - {@link setTemplateForClass()}
63 * - {@link setTemplateForId()}
64 * - {@link setErrorTemplate()}
65 * - {@link setElementTemplateForGroupClass()}
66 * - {@link setElementTemplateForGroupId()}
67 *
68 * @category HTML
69 * @package HTML_QuickForm2
70 * @author Alexey Borzov <avb@php.net>
71 * @author Bertrand Mansion <golgote@mamasam.com>
72 * @version Release: @package_version@
73 */
74 class HTML_QuickForm2_Renderer_Default extends HTML_QuickForm2_Renderer
75 {
76 /**
77 * Whether the form contains required elements
78 * @var bool
79 */
80 public $hasRequired = false;
81
82 /**
83 * HTML generated for the form
84 * @var array
85 */
86 public $html = array(array());
87
88 /**
89 * HTML for hidden elements if 'group_hiddens' option is on
90 * @var string
91 */
92 public $hiddenHtml = '';
93
94 /**
95 * Array of validation errors if 'group_errors' option is on
96 * @var array
97 */
98 public $errors = array();
99
100 /**
101 * Default templates for elements of the given class
102 * @var array
103 */
104 public $templatesForClass = array(
105 'html_quickform2_element_inputhidden' => '<div style="display: none;">{element}</div>',
106 'html_quickform2' => '<div class="quickform">{errors}<form{attributes}>{hidden}{content}</form><qf:reqnote><div class="reqnote">{reqnote}</div></qf:reqnote></div>',
107 'html_quickform2_container_fieldset' => '<fieldset{attributes}><qf:label><legend id="{id}-legend">{label}</legend></qf:label>{content}</fieldset>',
108 'special:error' => array(
109 'prefix' => '<div class="errors"><qf:message><p>{message}</p></qf:message><ul><li>',
110 'separator' => '</li><li>',
111 'suffix' => '</li></ul><qf:message><p>{message}</p></qf:message></div>'
112 ),
113 'html_quickform2_element' => '<div class="row"><label for="{id}" class="element"><qf:required><span class="required">* </span></qf:required>{label}</label><div class="element<qf:error> error</qf:error>"><qf:error><span class="error">{error}</span><br /></qf:error>{element}</div></div>',
114 'html_quickform2_container_group' => '<div class="row"><label class="element"><qf:required><span class="required">* </span></qf:required>{label}</label><div class="element group<qf:error> error</qf:error>"><qf:error><span class="error">{error}</span><br /></qf:error>{content}</div></div>'
115 );
116
117 /**
118 * Custom templates for elements with the given IDs
119 * @var array
120 */
121 public $templatesForId = array();
122
123 /**
124 * Default templates for elements in groups of the given classes
125 *
126 * Array has the form ('group class' => ('element class' => 'template', ...), ...)
127 *
128 * @var array
129 */
130 public $elementTemplatesForGroupClass = array(
131 'html_quickform2_container' => array(
132 'html_quickform2_element' => '{element}',
133 'html_quickform2_container_fieldset' => '<fieldset{attributes}><qf:label><legend id="{id}-legend">{label}</legend></qf:label>{content}</fieldset>'
134 )
135 );
136
137 /**
138 * Custom templates for grouped elements in the given group IDs
139 *
140 * Array has the form ('group id' => ('element class' => 'template', ...), ...)
141 *
142 * @var array
143 */
144 public $elementTemplatesForGroupId = array();
145
146 /**
147 * Array containing IDs of the groups being rendered
148 * @var array
149 */
150 public $groupId = array();
151
152 public function exportMethods()
153 {
154 return array(
155 'reset',
156 'setTemplateForClass',
157 'setTemplateForId',
158 'setErrorTemplate',
159 'setGroupedTemplateForClass',
160 'setElementTemplateForGroupClass',
161 'setElementTemplateForGroupId'
162 );
163 }
164
165 /**
166 * Sets template for form elements that are instances of the given class
167 *
168 * When searching for a template to use, renderer will check for templates
169 * set for element's class and its parent classes, until found. Thus a more
170 * specific template will override a more generic one.
171 *
172 * @param string Class name
173 * @param mixed Template to use for elements of that class
174 * @return HTML_QuickForm2_Renderer_Default
175 */
176 public function setTemplateForClass($className, $template)
177 {
178 $this->templatesForClass[strtolower($className)] = $template;
179 return $this;
180 }
181
182 /**
183 * Sets template for form element with the given id
184 *
185 * If a template is set for an element via this method, it will be used.
186 * In the other case a generic template set by {@link setTemplateForClass()}
187 * or {@link setGroupedTemplateForClass()} will be used.
188 *
189 * @param string Element's id
190 * @param mixed Template to use for rendering of that element
191 * @return HTML_QuickForm2_Renderer_Default
192 */
193 public function setTemplateForId($id, $template)
194 {
195 $this->templatesForId[$id] = $template;
196 return $this;
197 }
198
199 /**
200 * Sets template for rendering validation errors
201 *
202 * This template will be used if 'group_errors' option is set to true.
203 * The template array should contain 'prefix', 'suffix' and 'separator'
204 * keys.
205 *
206 * @param array Template for validation errors
207 * @return HTML_QuickForm2_Renderer_Default
208 */
209 public function setErrorTemplate(array $template)
210 {
211 return $this->setTemplateForClass('special:error', $template);
212 }
213
214 /**
215 * Sets grouped elements templates using group class
216 *
217 * Templates set via {@link setTemplateForClass()} will not be used for
218 * grouped form elements. When searching for a template to use, the renderer
219 * will first consider template set for a specific group id, then the
220 * group templates set by group class.
221 *
222 * @param string Group class name
223 * @param string Element class name
224 * @param mixed Template
225 * @return HTML_QuickForm2_Renderer_Default
226 */
227 public function setElementTemplateForGroupClass($groupClass, $elementClass, $template)
228 {
229 $this->elementTemplatesForGroupClass[strtolower($groupClass)][strtolower($elementClass)] = $template;
230 return $this;
231 }
232
233 /**
234 * Sets grouped elements templates using group id
235 *
236 * Templates set via {@link setTemplateForClass()} will not be used for
237 * grouped form elements. When searching for a template to use, the renderer
238 * will first consider template set for a specific group id, then the
239 * group templates set by group class.
240 *
241 * @param string Group id
242 * @param string Element class name
243 * @param mixed Template
244 * @return HTML_QuickForm2_Renderer_Default
245 */
246 public function setElementTemplateForGroupId($groupId, $elementClass, $template)
247 {
248 $this->elementTemplatesForGroupId[$groupId][strtolower($elementClass)] = $template;
249 return $this;
250 }
251
252 /**
253 * Resets the accumulated data
254 *
255 * This method is called automatically by startForm() method, but should
256 * be called manually before calling other rendering methods separately.
257 *
258 * @return HTML_QuickForm2_Renderer_Default
259 */
260 public function reset()
261 {
262 $this->html = array(array());
263 $this->hiddenHtml = '';
264 $this->errors = array();
265 $this->hasRequired = false;
266 $this->groupId = array();
267
268 return $this;
269 }
270
271 /**
272 * Returns generated HTML
273 *
274 * @return string
275 */
276 public function __toString()
277 {
278 return (isset($this->html[0][0])? $this->html[0][0]: '') .
279 $this->hiddenHtml;
280 }
281
282 /**
283 * Renders a generic element
284 *
285 * @param HTML_QuickForm2_Node Element being rendered
286 */
287 public function renderElement(HTML_QuickForm2_Node $element)
288 {
289 $elTpl = $this->prepareTemplate($this->findTemplate($element), $element);
290 $this->html[count($this->html) - 1][] = str_replace(array('{element}', '{id}'),
291 array($element, $element->getId()), $elTpl);
292 }
293
294 /**
295 * Renders a hidden element
296 *
297 * @param HTML_QuickForm2_Node Hidden element being rendered
298 */
299 public function renderHidden(HTML_QuickForm2_Node $element)
300 {
301 if ($this->options['group_hiddens']) {
302 $this->hiddenHtml .= $element->__toString();
303 } else {
304 $this->html[count($this->html) - 1][] = str_replace('{element}', $element,
305 $this->findTemplate($element));
306 }
307 }
308
309 /**
310 * Starts rendering a generic container, called before processing contained elements
311 *
312 * @param HTML_QuickForm2_Node Container being rendered
313 */
314 public function startContainer(HTML_QuickForm2_Node $container)
315 {
316 $this->html[] = array();
317 $this->groupId[] = false;
318 }
319
320 /**
321 * Finishes rendering a generic container, called after processing contained elements
322 *
323 * @param HTML_QuickForm2_Node Container being rendered
324 */
325 public function finishContainer(HTML_QuickForm2_Node $container)
326 {
327 array_pop($this->groupId);
328
329 $cTpl = str_replace(
330 array('{attributes}', '{id}'),
331 array($container->getAttributes(true), $container->getId()),
332 $this->prepareTemplate($this->findTemplate($container, '{content}'), $container)
333 );
334 $cHtml = array_pop($this->html);
335 $break = HTML_Common2::getOption('linebreak');
336 $indent = str_repeat(HTML_Common2::getOption('indent'), count($this->html));
337 $this->html[count($this->html) - 1][] = str_replace(
338 '{content}', $break . $indent . implode($break . $indent, $cHtml), $cTpl
339 );
340 }
341
342 /**
343 * Starts rendering a group, called before processing grouped elements
344 *
345 * @param HTML_QuickForm2_Node Group being rendered
346 */
347 public function startGroup(HTML_QuickForm2_Node $group)
348 {
349 $this->html[] = array();
350 $this->groupId[] = $group->getId();
351 }
352
353 /**
354 * Finishes rendering a group, called after processing grouped elements
355 *
356 * @param HTML_QuickForm2_Node Group being rendered
357 */
358 public function finishGroup(HTML_QuickForm2_Node $group)
359 {
360 $gTpl = str_replace(
361 array('{attributes}', '{id}'),
362 array($group->getAttributes(true), array_pop($this->groupId)),
363 $this->prepareTemplate($this->findTemplate($group, '{content}'), $group)
364 );
365
366 $separator = $group->getSeparator();
367 $elements = array_pop($this->html);
368 if (!is_array($separator)) {
369 $content = implode((string)$separator, $elements);
370 } else {
371 $content = '';
372 $cSeparator = count($separator);
373 for ($i = 0, $count = count($elements); $i < $count; $i++) {
374 $content .= (0 == $i? '': $separator[($i - 1) % $cSeparator]) .
375 $elements[$i];
376 }
377 }
378
379 $this->html[count($this->html) - 1][] = str_replace('{content}', $content, $gTpl);
380 }
381
382 /**
383 * Starts rendering a form, called before processing contained elements
384 *
385 * @param HTML_QuickForm2_Node Form being rendered
386 */
387 public function startForm(HTML_QuickForm2_Node $form)
388 {
389 $this->reset();
390 }
391
392 /**
393 * Finishes rendering a form, called after processing contained elements
394 *
395 * @param HTML_QuickForm2_Node Form being rendered
396 */
397 public function finishForm(HTML_QuickForm2_Node $form)
398 {
399 $formTpl = str_replace(
400 array('{attributes}', '{hidden}', '{errors}'),
401 array($form->getAttributes(true), $this->hiddenHtml,
402 $this->outputGroupedErrors()),
403 $this->findTemplate($form, '{content}')
404 );
405 $this->hiddenHtml = '';
406
407 // required note
408 if (!$this->hasRequired || $form->toggleFrozen() ||
409 empty($this->options['required_note']))
410 {
411 $formTpl = preg_replace('!<qf:reqnote>.*</qf:reqnote>!isU', '', $formTpl);
412 } else {
413 $formTpl = str_replace(
414 array('<qf:reqnote>', '</qf:reqnote>', '{reqnote}'),
415 array('', '', $this->options['required_note']),
416 $formTpl
417 );
418 }
419
420 $break = HTML_Common2::getOption('linebreak');
421 $script = $this->getJavascriptBuilder()->__toString();
422 $this->html[0] = array((empty($script)? '': $script . $break) . str_replace(
423 '{content}', $break . implode($break, $this->html[0]), $formTpl
424 ));
425 }
426
427 /**
428 * Creates a error list if 'group_errors' option is true
429 *
430 * @return string HTML with a list of all validation errors
431 */
432 public function outputGroupedErrors()
433 {
434 if (empty($this->errors)) {
435 return '';
436 }
437 if (!empty($this->options['errors_prefix'])) {
438 $errorHtml = str_replace(array('<qf:message>', '</qf:message>', '{message}'),
439 array('', '', $this->options['errors_prefix']),
440 $this->templatesForClass['special:error']['prefix']);
441 } else {
442 $errorHtml = preg_replace('!<qf:message>.*</qf:message>!isU', '',
443 $this->templatesForClass['special:error']['prefix']);
444 }
445 $errorHtml .= implode($this->templatesForClass['special:error']['separator'], $this->errors);
446 if (!empty($this->options['errors_suffix'])) {
447 $errorHtml .= str_replace(array('<qf:message>', '</qf:message>', '{message}'),
448 array('', '', $this->options['errors_suffix']),
449 $this->templatesForClass['special:error']['suffix']);
450 } else {
451 $errorHtml .= preg_replace('!<qf:message>.*</qf:message>!isU', '',
452 $this->templatesForClass['special:error']['suffix']);
453 }
454 return $errorHtml;
455 }
456
457 /**
458 * Finds a proper template for the element
459 *
460 * Templates are scanned in a predefined order. First, if a template was
461 * set for a specific element by id, it is returned, no matter if the
462 * element belongs to a group. If the element does not belong to a group,
463 * we try to match a template using the element class.
464 * But, if the element belongs to a group, templates are first looked up
465 * using the containing group id, then using the containing group class.
466 * When no template is found, the provided default template is returned.
467 *
468 * @param HTML_QuickForm2_Node Element being rendered
469 * @param string Default template to use if not found
470 * @return string Template
471 */
472 public function findTemplate(HTML_QuickForm2_Node $element, $default = '{element}')
473 {
474 if (!empty($this->templatesForId[$element->getId()])) {
475 return $this->templatesForId[$element->getId()];
476 }
477 $class = strtolower(get_class($element));
478 $groupId = end($this->groupId);
479 $elementClasses = array();
480 do {
481 if (empty($groupId) && !empty($this->templatesForClass[$class])) {
482 return $this->templatesForClass[$class];
483 }
484 $elementClasses[$class] = true;
485 } while ($class = strtolower(get_parent_class($class)));
486
487 if (!empty($groupId)) {
488 if (!empty($this->elementTemplatesForGroupId[$groupId])) {
489 while (list($elClass) = each($elementClasses)) {
490 if (!empty($this->elementTemplatesForGroupId[$groupId][$elClass])) {
491 return $this->elementTemplatesForGroupId[$groupId][$elClass];
492 }
493 }
494 }
495
496 $group = $element->getContainer();
497 $grClass = strtolower(get_class($group));
498 do {
499 if (!empty($this->elementTemplatesForGroupClass[$grClass])) {
500 reset($elementClasses);
501 while (list($elClass) = each($elementClasses)) {
502 if (!empty($this->elementTemplatesForGroupClass[$grClass][$elClass])) {
503 return $this->elementTemplatesForGroupClass[$grClass][$elClass];
504 }
505 }
506 }
507 } while ($grClass = strtolower(get_parent_class($grClass)));
508 }
509 return $default;
510 }
511
512 /**
513 * Processes the element's template, adding label(s), required note and error message
514 *
515 * @param string Element template
516 * @param HTML_QuickForm2_Node Element being rendered
517 * @return string Template with some substitutions done
518 */
519 public function prepareTemplate($elTpl, HTML_QuickForm2_Node $element)
520 {
521 // if element is required
522 $elTpl = $this->markRequired($elTpl, $element->isRequired());
523 $elTpl = $this->outputError($elTpl, $element->getError());
524 return $this->outputLabel($elTpl, $element->getLabel());
525 }
526
527 /**
528 * Marks element required or removes "required" block
529 *
530 * @param string Element template
531 * @param bool Whether element is required
532 * @return string Template with processed "required" block
533 */
534 public function markRequired($elTpl, $required)
535 {
536 if ($required) {
537 $this->hasRequired = true;
538 $elTpl = str_replace(array('<qf:required>', '</qf:required>'),
539 array('', ''), $elTpl);
540 } else {
541 $elTpl = preg_replace('!<qf:required>.*</qf:required>!isU', '', $elTpl);
542 }
543 return $elTpl;
544 }
545
546 /**
547 * Outputs element error, removes empty error blocks
548 *
549 * @param string Element template
550 * @param string Validation error for the element
551 * @return string Template with error substitutions done
552 */
553 public function outputError($elTpl, $error)
554 {
555 if ($error && !$this->options['group_errors']) {
556 $elTpl = str_replace(array('<qf:error>', '</qf:error>', '{error}'),
557 array('', '', $error), $elTpl);
558 } else {
559 if ($error && $this->options['group_errors']) {
560 $this->errors[] = $error;
561 }
562 $elTpl = preg_replace('!<qf:error>.*</qf:error>!isU', '', $elTpl);
563 }
564 return $elTpl;
565 }
566
567 /**
568 * Outputs element's label(s), removes empty label blocks
569 *
570 * @param string Element template
571 * @param mixed Element label(s)
572 * @return string Template with label substitutions done
573 */
574 public function outputLabel($elTpl, $label)
575 {
576 $mainLabel = is_array($label)? array_shift($label): $label;
577 $elTpl = str_replace('{label}', $mainLabel, $elTpl);
578 if (false !== strpos($elTpl, '<qf:label>')) {
579 if ($mainLabel) {
580 $elTpl = str_replace(array('<qf:label>', '</qf:label>'), array('', ''), $elTpl);
581 } else {
582 $elTpl = preg_replace('!<qf:label>.*</qf:label>!isU', '', $elTpl);
583 }
584 }
585 if (is_array($label)) {
586 foreach($label as $key => $text) {
587 $key = is_int($key)? $key + 2: $key;
588 $elTpl = str_replace(array('<qf:label_' . $key . '>', '</qf:label_' . $key . '>', '{label_' . $key . '}'),
589 array('', '', $text), $elTpl);
590 }
591 }
592 if (strpos($elTpl, '{label_')) {
593 $elTpl = preg_replace('!<qf:label_([^>]+)>.*</qf:label_\1>!isU', '', $elTpl);
594 }
595 return $elTpl;
596 }
597 }
598 ?>
599