1<?php 2/** 3 * Rule comparing the value of the field with some other value 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: Compare.php 299480 2010-05-19 06:55:03Z avb $ 43 * @link http://pear.php.net/package/HTML_QuickForm2 44 */ 45 46/** 47 * Base class for HTML_QuickForm2 rules 48 */ 49// require_once 'HTML/QuickForm2/Rule.php'; 50 51/** 52 * Rule comparing the value of the field with some other value 53 * 54 * The Rule needs two configuration parameters for its work 55 * - comparison operator (defaults to equality) 56 * - operand to compare with; this can be either a constant or another form 57 * element (its value will be used) 58 * See {@link mergeConfig()} for description of possible ways to pass 59 * configuration parameters. 60 * 61 * Note that 'less than [or equal]' and 'greater than [or equal]' operators 62 * compare the operands numerically, since this is considered as more useful 63 * approach by the authors. 64 * 65 * For convenience, this Rule is already registered in the Factory with the 66 * names 'eq', 'neq', 'lt', 'gt', 'lte', 'gte' corresponding to the relevant 67 * operators: 68 * <code> 69 * $password->addRule('eq', 'Passwords do not match', $passwordRepeat); 70 * $orderQty->addRule('lte', 'Should not order more than 10 of these', 10); 71 * </code> 72 * 73 * @category HTML 74 * @package HTML_QuickForm2 75 * @author Alexey Borzov <avb@php.net> 76 * @author Bertrand Mansion <golgote@mamasam.com> 77 * @version Release: @package_version@ 78 */ 79class HTML_QuickForm2_Rule_Compare extends HTML_QuickForm2_Rule 80{ 81 /** 82 * Possible comparison operators 83 * @var array 84 */ 85 protected $operators = array('==', '!=', '===', '!==', '<', '<=', '>', '>='); 86 87 protected function doOperation($a, $b, $operator) 88 { 89 switch ($operator) { 90 case "==": return $a == $b; 91 case "!=": return $a != $b; 92 case "===": return $a === $b; 93 case "!==": return $a !== $b; 94 case ">": return $a > $b; 95 case "<=": return $a <= $b; 96 case "<": return $a < $b; 97 case ">=": return $a >= $b; 98 default: return true; 99 } 100 } 101 102 /** 103 * Validates the owner element 104 * 105 * @return bool whether (element_value operator operand) expression is true 106 */ 107 protected function validateOwner() 108 { 109 $value = $this->owner->getValue(); 110 $config = $this->getConfig(); 111 112 if ($config['operand'] instanceof HTML_QuickForm2_Node) { 113 $b = $config['operand']->getValue(); 114 } else { 115 $b = $config['operand']; 116 } 117 118 if (!in_array($config['operator'], array('===', '!=='))) { 119 $a = floatval($value); 120 $b = floatval($b); 121 } else { 122 $a = strval($value); 123 $b = strval($b); 124 } 125 126 return $this->doOperation($a, $b, $config['operator']); 127 } 128 129 protected function getJavascriptCallback() 130 { 131 $config = $this->getConfig(); 132 $operand1 = $this->owner->getJavascriptValue(); 133 $operand2 = $config['operand'] instanceof HTML_QuickForm2_Node 134 ? $config['operand']->getJavascriptValue() 135 : "'" . strtr($config['operand'], array( 136 "\r" => '\r', 137 "\n" => '\n', 138 "\t" => '\t', 139 "'" => "\\'", 140 '"' => '\"', 141 '\\' => '\\\\' 142 )) . "'"; 143 144 if (!in_array($config['operator'], array('===', '!=='))) { 145 $check = "Number({$operand1}) {$config['operator']} Number({$operand2})"; 146 } else { 147 $check = "String({$operand1}) {$config['operator']} String({$operand2})"; 148 } 149 150 return "function () { return {$check}; }"; 151 } 152 153 /** 154 * Merges local configuration with that provided for registerRule() 155 * 156 * "Global" configuration may be passed to 157 * {@link HTML_QuickForm2_Factory::registerRule()} in 158 * either of the following formats 159 * - operator 160 * - array(operator[, operand]) 161 * - array(['operator' => operator, ]['operand' => operand]) 162 163 * "Local" configuration may be passed to the constructor in either of 164 * the following formats 165 * - operand 166 * - array([operator, ]operand) 167 * - array(['operator' => operator, ]['operand' => operand]) 168 * 169 * As usual, global configuration overrides local one. 170 * 171 * @param mixed Local configuration 172 * @param mixed Global configuration 173 * @return mixed Merged configuration 174 */ 175 public static function mergeConfig($localConfig, $globalConfig) 176 { 177 $config = null; 178 if (is_array($globalConfig) && 0 < count($globalConfig)) { 179 $config = self::toCanonicalForm($globalConfig, 'operator'); 180 } 181 if (is_array($localConfig) && 0 < count($localConfig)) { 182 $config = (isset($config)? $config: array()) 183 + self::toCanonicalForm($localConfig); 184 } 185 return $config; 186 } 187 188 /** 189 * Converts configuration data to a canonical associative array form 190 * 191 * @param mixed Configuration data 192 * @param string Array key to assign $config to if it is scalar 193 * @return array Associative array that may contain 'operand' and 'operator' keys 194 */ 195 protected static function toCanonicalForm($config, $key = 'operand') 196 { 197 if (!is_array($config)) { 198 return array($key => $config); 199 200 } elseif (array_key_exists('operator', $config) 201 || array_key_exists('operand', $config) 202 ) { 203 return $config; 204 205 } elseif (1 == count($config)) { 206 return array($key => end($config)); 207 208 } else { 209 return array('operator' => reset($config), 'operand' => end($config)); 210 } 211 } 212 213 /** 214 * Sets the comparison operator and operand to compare to 215 * 216 * $config can be either of the following 217 * - operand 218 * - array([operator, ]operand) 219 * - array(['operator' => operator, ]['operand' => operand]) 220 * If operator is missing it will default to '===' 221 * 222 * @param mixed Configuration data 223 * @return HTML_QuickForm2_Rule 224 * @throws HTML_QuickForm2_InvalidArgumentException if a bogus comparison 225 * operator is used for configuration, if an operand is missing 226 */ 227 public function setConfig($config) 228 { 229 if (0 == count($config)) { 230 throw new HTML_QuickForm2_InvalidArgumentException( 231 'Compare Rule requires an argument to compare with' 232 ); 233 } 234 $config = self::toCanonicalForm($config); 235 236 $config += array('operator' => '==='); 237 if (!in_array($config['operator'], $this->operators)) { 238 throw new HTML_QuickForm2_InvalidArgumentException( 239 'Compare Rule requires a valid comparison operator, ' . 240 preg_replace('/\s+/', ' ', var_export($config['operator'], true)) . ' given' 241 ); 242 } 243 if (in_array($config['operator'], array('==', '!='))) { 244 $config['operator'] .= '='; 245 } 246 247 return parent::setConfig($config); 248 } 249} 250?> 251