diff options
author | vipsoft <vipsoft@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2010-07-06 21:28:27 +0400 |
---|---|---|
committer | vipsoft <vipsoft@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2010-07-06 21:28:27 +0400 |
commit | adb9a40abd2c4049c5fc7bcd15692f8d3957774c (patch) | |
tree | 46629aa66fb5f130b5eed07902f3930d8404d25c /libs/HTML/QuickForm2/Rule.php | |
parent | 27961c62ce494b0e2e5a3b022202fd820425a4e4 (diff) |
refs #1442 - add HTML_Common2 and HTML_QuickForm2 - New BSD licensed
Diffstat (limited to 'libs/HTML/QuickForm2/Rule.php')
-rw-r--r-- | libs/HTML/QuickForm2/Rule.php | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/libs/HTML/QuickForm2/Rule.php b/libs/HTML/QuickForm2/Rule.php new file mode 100644 index 0000000000..dfb11868b0 --- /dev/null +++ b/libs/HTML/QuickForm2/Rule.php @@ -0,0 +1,333 @@ +<?php +/** + * Base class for HTML_QuickForm2 rules + * + * PHP version 5 + * + * LICENSE: + * + * Copyright (c) 2006-2010, Alexey Borzov <avb@php.net>, + * Bertrand Mansion <golgote@mamasam.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTML + * @package HTML_QuickForm2 + * @author Alexey Borzov <avb@php.net> + * @author Bertrand Mansion <golgote@mamasam.com> + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id: Rule.php 299706 2010-05-24 18:32:37Z avb $ + * @link http://pear.php.net/package/HTML_QuickForm2 + */ + +/** + * Abstract base class for HTML_QuickForm2 rules + * + * This class provides methods that allow chaining several rules together. + * Its validate() method executes the whole rule chain starting from this rule. + * + * @category HTML + * @package HTML_QuickForm2 + * @author Alexey Borzov <avb@php.net> + * @author Bertrand Mansion <golgote@mamasam.com> + * @version Release: @package_version@ + */ +abstract class HTML_QuickForm2_Rule +{ + /** + * Constant showing that validation should be run server-side + * @see HTML_QuickForm2_Node::addRule() + */ + const RUNAT_SERVER = 1; + + /** + * Constant showing that validation should be run client-side + * @see HTML_QuickForm2_Node::addRule() + */ + const RUNAT_CLIENT = 2; + + /** + * An element whose value will be validated by this rule + * @var HTML_QuickForm2_Node + */ + protected $owner; + + /** + * An error message to display if validation fails + * @var string + */ + protected $message; + + /** + * Configuration data for the rule + * @var mixed + */ + protected $config; + + /** + * Rules chained to this via "and" and "or" operators + * + * The contents can be described as "disjunctive normal form", where an outer + * array represents a disjunction of conjunctive clauses represented by inner + * arrays. + * + * @var array + */ + protected $chainedRules = array(array()); + + + /** + * Class constructor + * + * @param HTML_QuickForm2_Node Element to validate + * @param string Error message to display if validation fails + * @param mixed Configuration data for the rule + */ + public function __construct(HTML_QuickForm2_Node $owner, $message = '', $config = null) + { + $this->setOwner($owner); + $this->setMessage($message); + $this->setConfig($config); + } + + /** + * Merges local configuration with that provided for registerRule() + * + * Default behaviour is for global config to override local one, different + * Rules may implement more complex merging behaviours. + * + * @param mixed Local configuration + * @param mixed Global configuration, usually provided to {@link HTML_QuickForm2_Factory::registerRule()} + * @return mixed Merged configuration + */ + public static function mergeConfig($localConfig, $globalConfig) + { + return is_null($globalConfig)? $localConfig: $globalConfig; + } + + /** + * Sets configuration data for the rule + * + * @param mixed Rule configuration data (specific for a Rule) + * @return HTML_QuickForm2_Rule + * @throws HTML_QuickForm2_InvalidArgumentException in case of invalid + * configuration data + */ + public function setConfig($config) + { + $this->config = $config; + return $this; + } + + /** + * Returns the rule's configuration data + * + * @return mixed Configuration data (specific for a Rule) + */ + public function getConfig() + { + return $this->config; + } + + /** + * Sets the error message output by the rule + * + * @param string Error message to display if validation fails + * @return HTML_QuickForm2_Rule + */ + public function setMessage($message) + { + $this->message = (string)$message; + return $this; + } + + /** + * Returns the error message output by the rule + * + * @return string Error message + */ + public function getMessage() + { + return $this->message; + } + + /** + * Sets the element that will be validated by this rule + * + * @param HTML_QuickForm2_Node Element to validate + */ + public function setOwner(HTML_QuickForm2_Node $owner) + { + if (null !== $this->owner) { + $this->owner->removeRule($this); + } + $this->owner = $owner; + } + + /** + * Adds a rule to the chain with an "and" operator + * + * Evaluation is short-circuited, next rule will not be evaluated if the + * previous one returns false. The method is named this way because "and" is + * a reserved word in PHP. + * + * @param HTML_QuickForm2_Rule + * @return HTML_QuickForm2_Rule first rule in the chain (i.e. $this) + * @throws HTML_QuickForm2_InvalidArgumentException when trying to add + * a "required" rule to the chain + */ + public function and_(HTML_QuickForm2_Rule $next) + { + if ($next instanceof HTML_QuickForm2_Rule_Required) { + throw new HTML_QuickForm2_InvalidArgumentException( + 'and_(): Cannot add a "required" rule' + ); + } + $this->chainedRules[count($this->chainedRules) - 1][] = $next; + return $this; + } + + /** + * Adds a rule to the chain with an "or" operator + * + * Evaluation is short-circuited, next rule will not be evaluated if the + * previous one returns true. The method is named this way because "or" is + * a reserved word in PHP. + * + * @param HTML_QuickForm2_Rule + * @return HTML_QuickForm2_Rule first rule in the chain (i.e. $this) + * @throws HTML_QuickForm2_InvalidArgumentException when trying to add + * a "required" rule to the chain + */ + public function or_(HTML_QuickForm2_Rule $next) + { + if ($next instanceof HTML_QuickForm2_Rule_Required) { + throw new HTML_QuickForm2_InvalidArgumentException( + 'or_(): Cannot add a "required" rule' + ); + } + $this->chainedRules[] = array($next); + return $this; + } + + /** + * Performs validation + * + * The whole rule chain is executed. Note that the side effect of this + * method is setting the error message on element if validation fails + * + * @return boolean Whether the element is valid + */ + public function validate() + { + $globalValid = false; + $localValid = $this->validateOwner(); + foreach ($this->chainedRules as $item) { + foreach ($item as $multiplier) { + if (!($localValid = $localValid && $multiplier->validate())) { + break; + } + } + if ($globalValid = $globalValid || $localValid) { + break; + } + $localValid = true; + } + $globalValid or $this->setOwnerError(); + return $globalValid; + } + + /** + * Validates the owner element + * + * @return bool Whether owner element is valid according to the rule + */ + abstract protected function validateOwner(); + + /** + * Sets the error message on the owner element + */ + protected function setOwnerError() + { + if (strlen($this->getMessage()) && !$this->owner->getError()) { + $this->owner->setError($this->getMessage()); + } + } + + /** + * Returns the client-side validation callback + * + * This essentially builds a Javascript version of validateOwner() method, + * with element ID and Rule configuration hardcoded. + * + * @return string Javascript function to validate the element's value + * @throws HTML_QuickForm2_Exception if Rule can only be run server-side + */ + protected function getJavascriptCallback() + { + throw new HTML_QuickForm2_Exception( + get_class($this) . ' does not implement javascript validation' + ); + } + + /** + * Returns the client-side representation of the Rule + * + * The Javascript object returned contains the following fields: + * - callback: {@see getJavascriptCallback()} + * - elementId: element ID to set error for if validation fails + * - errorMessage: error message to set if validation fails + * - chained: chained rules, array of arrays like in $chainedRules property + * + * @return string + * @throws HTML_QuickForm2_Exception if Rule or its chained Rules can only + * be run server-side + */ + public function getJavascript() + { + $js = "{\n\tcallback: " . $this->getJavascriptCallback() . ",\n" . + "\telementId: '" . $this->owner->getId() . "',\n" . + "\terrorMessage: '" . strtr($this->getMessage(), array( + "\r" => '\r', + "\n" => '\n', + "\t" => '\t', + "'" => "\\'", + '"' => '\"', + '\\' => '\\\\' + )) . "',\n\tchained: ["; + $chained = array(); + foreach ($this->chainedRules as $item) { + $multipliers = array(); + foreach ($item as $multiplier) { + $multipliers[] = $multiplier->getJavascript(); + } + $chained[] = '[' . implode(",\n", $multipliers) . ']'; + } + $js .= implode(",\n", $chained) . "]\n}"; + return $js; + } +} +?> |