PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/system/library/PEAR/HTML/QuickForm2/Node.php

https://bitbucket.org/spekkionu/passworddb
PHP | 804 lines | 312 code | 73 blank | 419 comment | 50 complexity | c1dab36f6f69003bb355b9e29f4042b3 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. <?php
  2. /**
  3. * Base class for all HTML_QuickForm2 elements
  4. *
  5. * PHP version 5
  6. *
  7. * LICENSE:
  8. *
  9. * Copyright (c) 2006-2012, 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: Node.php 324926 2012-04-06 17:08:12Z avb $
  43. * @link http://pear.php.net/package/HTML_QuickForm2
  44. */
  45. /**
  46. * HTML_Common2 - base class for HTML elements
  47. */
  48. require_once 'HTML/Common2.php';
  49. // By default, we generate element IDs with numeric indexes appended even for
  50. // elements with unique names. If you want IDs to be equal to the element
  51. // names by default, set this configuration option to false.
  52. if (null === HTML_Common2::getOption('id_force_append_index')) {
  53. HTML_Common2::setOption('id_force_append_index', true);
  54. }
  55. // set the default language for various elements' messages
  56. if (null === HTML_Common2::getOption('language')) {
  57. HTML_Common2::setOption('language', 'en');
  58. }
  59. /**
  60. * Exception classes for HTML_QuickForm2
  61. */
  62. require_once 'HTML/QuickForm2/Exception.php';
  63. /**
  64. * Static factory class for QuickForm2 elements
  65. */
  66. require_once 'HTML/QuickForm2/Factory.php';
  67. /**
  68. * Base class for HTML_QuickForm2 rules
  69. */
  70. require_once 'HTML/QuickForm2/Rule.php';
  71. /**
  72. * Abstract base class for all QuickForm2 Elements and Containers
  73. *
  74. * This class is mostly here to define the interface that should be implemented
  75. * by the subclasses. It also contains static methods handling generation
  76. * of unique ids for elements which do not have ids explicitly set.
  77. *
  78. * @category HTML
  79. * @package HTML_QuickForm2
  80. * @author Alexey Borzov <avb@php.net>
  81. * @author Bertrand Mansion <golgote@mamasam.com>
  82. * @license http://opensource.org/licenses/bsd-license.php New BSD License
  83. * @version Release: 2.0.0
  84. * @link http://pear.php.net/package/HTML_QuickForm2
  85. */
  86. abstract class HTML_QuickForm2_Node extends HTML_Common2
  87. {
  88. /**
  89. * Array containing the parts of element ids
  90. * @var array
  91. */
  92. protected static $ids = array();
  93. /**
  94. * Element's "frozen" status
  95. * @var boolean
  96. */
  97. protected $frozen = false;
  98. /**
  99. * Whether element's value should persist when element is frozen
  100. * @var boolean
  101. */
  102. protected $persistent = false;
  103. /**
  104. * Element containing current
  105. * @var HTML_QuickForm2_Container
  106. */
  107. protected $container = null;
  108. /**
  109. * Contains options and data used for the element creation
  110. * @var array
  111. */
  112. protected $data = array();
  113. /**
  114. * Validation rules for element
  115. * @var array
  116. */
  117. protected $rules = array();
  118. /**
  119. * An array of callback filters for element
  120. * @var array
  121. */
  122. protected $filters = array();
  123. /**
  124. * Recursive filter callbacks for element
  125. *
  126. * These are recursively applied for array values of element or propagated
  127. * to contained elements if the element is a Container
  128. *
  129. * @var array
  130. */
  131. protected $recursiveFilters = array();
  132. /**
  133. * Error message (usually set via Rule if validation fails)
  134. * @var string
  135. */
  136. protected $error = null;
  137. /**
  138. * Changing 'name' and 'id' attributes requires some special handling
  139. * @var array
  140. */
  141. protected $watchedAttributes = array('id', 'name');
  142. /**
  143. * Intercepts setting 'name' and 'id' attributes
  144. *
  145. * These attributes should always be present and thus trying to remove them
  146. * will result in an exception. Changing their values is delegated to
  147. * setName() and setId() methods, respectively
  148. *
  149. * @param string $name Attribute name
  150. * @param string $value Attribute value, null if attribute is being removed
  151. *
  152. * @throws HTML_QuickForm2_InvalidArgumentException if trying to
  153. * remove a required attribute
  154. */
  155. protected function onAttributeChange($name, $value = null)
  156. {
  157. if ('name' == $name) {
  158. if (null === $value) {
  159. throw new HTML_QuickForm2_InvalidArgumentException(
  160. "Required attribute 'name' can not be removed"
  161. );
  162. } else {
  163. $this->setName($value);
  164. }
  165. } elseif ('id' == $name) {
  166. if (null === $value) {
  167. throw new HTML_QuickForm2_InvalidArgumentException(
  168. "Required attribute 'id' can not be removed"
  169. );
  170. } else {
  171. $this->setId($value);
  172. }
  173. }
  174. }
  175. /**
  176. * Class constructor
  177. *
  178. * @param string $name Element name
  179. * @param string|array $attributes HTML attributes (either a string or an array)
  180. * @param array $data Element data (label, options used for element setup)
  181. */
  182. public function __construct($name = null, $attributes = null, array $data = array())
  183. {
  184. parent::__construct($attributes);
  185. $this->setName($name);
  186. // Autogenerating the id if not set on previous steps
  187. if ('' == $this->getId()) {
  188. $this->setId();
  189. }
  190. if (!empty($data)) {
  191. $this->data = array_merge($this->data, $data);
  192. }
  193. }
  194. /**
  195. * Generates an id for the element
  196. *
  197. * Called when an element is created without explicitly given id
  198. *
  199. * @param string $elementName Element name
  200. *
  201. * @return string The generated element id
  202. */
  203. protected static function generateId($elementName)
  204. {
  205. $stop = !self::getOption('id_force_append_index');
  206. $tokens = strlen($elementName)
  207. ? explode('[', str_replace(']', '', $elementName))
  208. : ($stop? array('qfauto', ''): array('qfauto'));
  209. $container =& self::$ids;
  210. $id = '';
  211. do {
  212. $token = array_shift($tokens);
  213. // prevent generated ids starting with numbers
  214. if ('' == $id && is_numeric($token)) {
  215. $token = 'qf' . $token;
  216. }
  217. // Handle the 'array[]' names
  218. if ('' === $token) {
  219. if (empty($container)) {
  220. $token = 0;
  221. } else {
  222. $keys = array_filter(array_keys($container), 'is_numeric');
  223. $token = empty($keys) ? 0 : end($keys);
  224. while (isset($container[$token])) {
  225. $token++;
  226. }
  227. }
  228. }
  229. $id .= '-' . $token;
  230. if (!isset($container[$token])) {
  231. $container[$token] = array();
  232. // Handle duplicate names when not having mandatory indexes
  233. } elseif (empty($tokens) && $stop) {
  234. $tokens[] = '';
  235. }
  236. // Handle mandatory indexes
  237. if (empty($tokens) && !$stop) {
  238. $tokens[] = '';
  239. $stop = true;
  240. }
  241. $container =& $container[$token];
  242. } while (!empty($tokens));
  243. return substr($id, 1);
  244. }
  245. /**
  246. * Stores the explicitly given id to prevent duplicate id generation
  247. *
  248. * @param string $id Element id
  249. */
  250. protected static function storeId($id)
  251. {
  252. $tokens = explode('-', $id);
  253. $container =& self::$ids;
  254. do {
  255. $token = array_shift($tokens);
  256. if (!isset($container[$token])) {
  257. $container[$token] = array();
  258. }
  259. $container =& $container[$token];
  260. } while (!empty($tokens));
  261. }
  262. /**
  263. * Returns the element options
  264. *
  265. * @return array
  266. */
  267. public function getData()
  268. {
  269. return $this->data;
  270. }
  271. /**
  272. * Returns the element's type
  273. *
  274. * @return string
  275. */
  276. abstract public function getType();
  277. /**
  278. * Returns the element's name
  279. *
  280. * @return string
  281. */
  282. public function getName()
  283. {
  284. return isset($this->attributes['name'])? $this->attributes['name']: null;
  285. }
  286. /**
  287. * Sets the element's name
  288. *
  289. * @param string $name
  290. *
  291. * @return HTML_QuickForm2_Node
  292. */
  293. abstract public function setName($name);
  294. /**
  295. * Returns the element's id
  296. *
  297. * @return string
  298. */
  299. public function getId()
  300. {
  301. return isset($this->attributes['id'])? $this->attributes['id']: null;
  302. }
  303. /**
  304. * Sets the element's id
  305. *
  306. * Please note that elements should always have an id in QuickForm2 and
  307. * therefore it will not be possible to remove the element's id or set it to
  308. * an empty value. If id is not explicitly given, it will be autogenerated.
  309. *
  310. * @param string $id Element's id, will be autogenerated if not given
  311. *
  312. * @return HTML_QuickForm2_Node
  313. * @throws HTML_QuickForm2_InvalidArgumentException if id contains invalid
  314. * characters (i.e. spaces)
  315. */
  316. public function setId($id = null)
  317. {
  318. if (is_null($id)) {
  319. $id = self::generateId($this->getName());
  320. // HTML5 specification only disallows having space characters in id,
  321. // so we don't do stricter checks here
  322. } elseif (strpbrk($id, " \r\n\t\x0C")) {
  323. throw new HTML_QuickForm2_InvalidArgumentException(
  324. "The value of 'id' attribute should not contain space characters"
  325. );
  326. } else {
  327. self::storeId($id);
  328. }
  329. $this->attributes['id'] = (string)$id;
  330. return $this;
  331. }
  332. /**
  333. * Returns the element's value without filters applied
  334. *
  335. * @return mixed
  336. */
  337. abstract public function getRawValue();
  338. /**
  339. * Returns the element's value, possibly with filters applied
  340. *
  341. * @return mixed
  342. */
  343. public function getValue()
  344. {
  345. $value = $this->getRawValue();
  346. return is_null($value)? null: $this->applyFilters($value);
  347. }
  348. /**
  349. * Sets the element's value
  350. *
  351. * @param mixed $value
  352. *
  353. * @return HTML_QuickForm2_Node
  354. */
  355. abstract public function setValue($value);
  356. /**
  357. * Returns the element's label(s)
  358. *
  359. * @return string|array
  360. */
  361. public function getLabel()
  362. {
  363. if (isset($this->data['label'])) {
  364. return $this->data['label'];
  365. }
  366. return null;
  367. }
  368. /**
  369. * Sets the element's label(s)
  370. *
  371. * @param string|array $label Label for the element (may be an array of labels)
  372. *
  373. * @return HTML_QuickForm2_Node
  374. */
  375. public function setLabel($label)
  376. {
  377. $this->data['label'] = $label;
  378. return $this;
  379. }
  380. /**
  381. * Changes the element's frozen status
  382. *
  383. * @param bool $freeze Whether the element should be frozen or editable. If
  384. * omitted, the method will not change the frozen status,
  385. * just return its current value
  386. *
  387. * @return bool Old value of element's frozen status
  388. */
  389. public function toggleFrozen($freeze = null)
  390. {
  391. $old = $this->frozen;
  392. if (null !== $freeze) {
  393. $this->frozen = (bool)$freeze;
  394. }
  395. return $old;
  396. }
  397. /**
  398. * Changes the element's persistent freeze behaviour
  399. *
  400. * If persistent freeze is on, the element's value will be kept (and
  401. * submitted) in a hidden field when the element is frozen.
  402. *
  403. * @param bool $persistent New value for "persistent freeze". If omitted, the
  404. * method will not set anything, just return the current
  405. * value of the flag.
  406. *
  407. * @return bool Old value of "persistent freeze" flag
  408. */
  409. public function persistentFreeze($persistent = null)
  410. {
  411. $old = $this->persistent;
  412. if (null !== $persistent) {
  413. $this->persistent = (bool)$persistent;
  414. }
  415. return $old;
  416. }
  417. /**
  418. * Adds the link to the element containing current
  419. *
  420. * @param HTML_QuickForm2_Container $container Element containing
  421. * the current one, null if the link should
  422. * really be removed (if removing from container)
  423. *
  424. * @throws HTML_QuickForm2_InvalidArgumentException If trying to set a
  425. * child of an element as its container
  426. */
  427. protected function setContainer(HTML_QuickForm2_Container $container = null)
  428. {
  429. if (null !== $container) {
  430. $check = $container;
  431. do {
  432. if ($this === $check) {
  433. throw new HTML_QuickForm2_InvalidArgumentException(
  434. 'Cannot set an element or its child as its own container'
  435. );
  436. }
  437. } while ($check = $check->getContainer());
  438. if (null !== $this->container && $container !== $this->container) {
  439. $this->container->removeChild($this);
  440. }
  441. }
  442. $this->container = $container;
  443. if (null !== $container) {
  444. $this->updateValue();
  445. }
  446. }
  447. /**
  448. * Returns the element containing current
  449. *
  450. * @return HTML_QuickForm2_Container|null
  451. */
  452. public function getContainer()
  453. {
  454. return $this->container;
  455. }
  456. /**
  457. * Returns the data sources for this element
  458. *
  459. * @return array
  460. */
  461. protected function getDataSources()
  462. {
  463. if (empty($this->container)) {
  464. return array();
  465. } else {
  466. return $this->container->getDataSources();
  467. }
  468. }
  469. /**
  470. * Called when the element needs to update its value from form's data sources
  471. */
  472. abstract protected function updateValue();
  473. /**
  474. * Adds a validation rule
  475. *
  476. * @param HTML_QuickForm2_Rule|string $rule Validation rule or rule type
  477. * @param string|int $messageOrRunAt If first parameter is rule type,
  478. * then message to display if validation fails, otherwise constant showing
  479. * whether to perfom validation client-side and/or server-side
  480. * @param mixed $options Configuration data for the rule
  481. * @param int $runAt Whether to perfom validation
  482. * server-side and/or client side. Combination of
  483. * HTML_QuickForm2_Rule::SERVER and HTML_QuickForm2_Rule::CLIENT constants
  484. *
  485. * @return HTML_QuickForm2_Rule The added rule
  486. * @throws HTML_QuickForm2_InvalidArgumentException if $rule is of a
  487. * wrong type or rule name isn't registered with Factory
  488. * @throws HTML_QuickForm2_NotFoundException if class for a given rule
  489. * name cannot be found
  490. */
  491. public function addRule(
  492. $rule, $messageOrRunAt = '', $options = null,
  493. $runAt = HTML_QuickForm2_Rule::SERVER
  494. ) {
  495. if ($rule instanceof HTML_QuickForm2_Rule) {
  496. $rule->setOwner($this);
  497. $runAt = '' == $messageOrRunAt? HTML_QuickForm2_Rule::SERVER: $messageOrRunAt;
  498. } elseif (is_string($rule)) {
  499. $rule = HTML_QuickForm2_Factory::createRule($rule, $this, $messageOrRunAt, $options);
  500. } else {
  501. throw new HTML_QuickForm2_InvalidArgumentException(
  502. 'addRule() expects either a rule type or ' .
  503. 'a HTML_QuickForm2_Rule instance'
  504. );
  505. }
  506. $this->rules[] = array($rule, $runAt);
  507. return $rule;
  508. }
  509. /**
  510. * Removes a validation rule
  511. *
  512. * The method will *not* throw an Exception if the rule wasn't added to the
  513. * element.
  514. *
  515. * @param HTML_QuickForm2_Rule $rule Validation rule to remove
  516. *
  517. * @return HTML_QuickForm2_Rule Removed rule
  518. */
  519. public function removeRule(HTML_QuickForm2_Rule $rule)
  520. {
  521. foreach ($this->rules as $i => $r) {
  522. if ($r[0] === $rule) {
  523. unset($this->rules[$i]);
  524. break;
  525. }
  526. }
  527. return $rule;
  528. }
  529. /**
  530. * Creates a validation rule
  531. *
  532. * This method is mostly useful when when chaining several rules together
  533. * via {@link HTML_QuickForm2_Rule::and_()} and {@link HTML_QuickForm2_Rule::or_()}
  534. * methods:
  535. * <code>
  536. * $first->addRule('nonempty', 'Fill in either first or second field')
  537. * ->or_($second->createRule('nonempty'));
  538. * </code>
  539. *
  540. * @param string $type Rule type
  541. * @param string $message Message to display if validation fails
  542. * @param mixed $options Configuration data for the rule
  543. *
  544. * @return HTML_QuickForm2_Rule The created rule
  545. * @throws HTML_QuickForm2_InvalidArgumentException If rule type is unknown
  546. * @throws HTML_QuickForm2_NotFoundException If class for the rule
  547. * can't be found and/or loaded from file
  548. */
  549. public function createRule($type, $message = '', $options = null)
  550. {
  551. return HTML_QuickForm2_Factory::createRule($type, $this, $message, $options);
  552. }
  553. /**
  554. * Checks whether an element is required
  555. *
  556. * @return boolean
  557. */
  558. public function isRequired()
  559. {
  560. foreach ($this->rules as $rule) {
  561. if ($rule[0] instanceof HTML_QuickForm2_Rule_Required) {
  562. return true;
  563. }
  564. }
  565. return false;
  566. }
  567. /**
  568. * Adds element's client-side validation rules to a builder object
  569. *
  570. * @param HTML_QuickForm2_JavascriptBuilder $builder
  571. */
  572. protected function renderClientRules(HTML_QuickForm2_JavascriptBuilder $builder)
  573. {
  574. if ($this->toggleFrozen()) {
  575. return;
  576. }
  577. $onblur = HTML_QuickForm2_Rule::ONBLUR_CLIENT ^ HTML_QuickForm2_Rule::CLIENT;
  578. foreach ($this->rules as $rule) {
  579. if ($rule[1] & HTML_QuickForm2_Rule::CLIENT) {
  580. $builder->addRule($rule[0], $rule[1] & $onblur);
  581. }
  582. }
  583. }
  584. /**
  585. * Performs the server-side validation
  586. *
  587. * @return boolean Whether the element is valid
  588. */
  589. protected function validate()
  590. {
  591. foreach ($this->rules as $rule) {
  592. if (strlen($this->error)) {
  593. break;
  594. }
  595. if ($rule[1] & HTML_QuickForm2_Rule::SERVER) {
  596. $rule[0]->validate();
  597. }
  598. }
  599. return !strlen($this->error);
  600. }
  601. /**
  602. * Sets the error message to the element
  603. *
  604. * @param string $error
  605. *
  606. * @return HTML_QuickForm2_Node
  607. */
  608. public function setError($error = null)
  609. {
  610. $this->error = (string)$error;
  611. return $this;
  612. }
  613. /**
  614. * Returns the error message for the element
  615. *
  616. * @return string
  617. */
  618. public function getError()
  619. {
  620. return $this->error;
  621. }
  622. /**
  623. * Returns Javascript code for getting the element's value
  624. *
  625. * @param bool $inContainer Whether it should return a parameter for
  626. * qf.form.getContainerValue()
  627. *
  628. * @return string
  629. */
  630. abstract public function getJavascriptValue($inContainer = false);
  631. /**
  632. * Returns IDs of form fields that should trigger "live" Javascript validation
  633. *
  634. * Rules added to this element with parameter HTML_QuickForm2_Rule::ONBLUR_CLIENT
  635. * will be run by after these form elements change or lose focus
  636. *
  637. * @return array
  638. */
  639. abstract public function getJavascriptTriggers();
  640. /**
  641. * Adds a filter
  642. *
  643. * A filter is simply a PHP callback which will be applied to the element value
  644. * when getValue() is called.
  645. *
  646. * @param callback $callback The PHP callback used for filter
  647. * @param array $options Optional arguments for the callback. The first parameter
  648. * will always be the element value, then these options will
  649. * be used as parameters for the callback.
  650. *
  651. * @return HTML_QuickForm2_Node The element
  652. * @throws HTML_QuickForm2_InvalidArgumentException If callback is incorrect
  653. */
  654. public function addFilter($callback, array $options = array())
  655. {
  656. if (!is_callable($callback, false, $callbackName)) {
  657. throw new HTML_QuickForm2_InvalidArgumentException(
  658. "Filter should be a valid callback, '{$callbackName}' was given"
  659. );
  660. }
  661. $this->filters[] = array($callback, $options);
  662. return $this;
  663. }
  664. /**
  665. * Adds a recursive filter
  666. *
  667. * A filter is simply a PHP callback which will be applied to the element value
  668. * when getValue() is called. If the element value is an array, for example with
  669. * selects of type 'multiple', the filter is applied to all values recursively.
  670. * A filter on a container will not be applied on a container value but
  671. * propagated to all contained elements instead.
  672. *
  673. * If the element is not a container and its value is not an array the behaviour
  674. * will be identical to filters added via addFilter().
  675. *
  676. * @param callback $callback The PHP callback used for filter
  677. * @param array $options Optional arguments for the callback. The first parameter
  678. * will always be the element value, then these options will
  679. * be used as parameters for the callback.
  680. *
  681. * @return HTML_QuickForm2_Node The element
  682. * @throws HTML_QuickForm2_InvalidArgumentException If callback is incorrect
  683. */
  684. public function addRecursiveFilter($callback, array $options = array())
  685. {
  686. if (!is_callable($callback, false, $callbackName)) {
  687. throw new HTML_QuickForm2_InvalidArgumentException(
  688. "Filter should be a valid callback, '{$callbackName}' was given"
  689. );
  690. }
  691. $this->recursiveFilters[] = array($callback, $options);
  692. return $this;
  693. }
  694. /**
  695. * Helper function for applying filter callback to a value
  696. *
  697. * @param mixed &$value Value being filtered
  698. * @param mixed $key Array key (not used, present to be able to use this
  699. * method as a callback to array_walk_recursive())
  700. * @param array $filter Array containing callback and additional callback
  701. * parameters
  702. */
  703. protected static function applyFilter(&$value, $key, $filter)
  704. {
  705. list($callback, $options) = $filter;
  706. array_unshift($options, $value);
  707. $value = call_user_func_array($callback, $options);
  708. }
  709. /**
  710. * Applies non-recursive filters on element value
  711. *
  712. * @param mixed $value Element value
  713. *
  714. * @return mixed Filtered value
  715. */
  716. protected function applyFilters($value)
  717. {
  718. foreach ($this->filters as $filter) {
  719. self::applyFilter($value, null, $filter);
  720. }
  721. return $value;
  722. }
  723. /**
  724. * Renders the element using the given renderer
  725. *
  726. * @param HTML_QuickForm2_Renderer $renderer
  727. * @return HTML_QuickForm2_Renderer
  728. */
  729. abstract public function render(HTML_QuickForm2_Renderer $renderer);
  730. }
  731. ?>