[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Helper class to keep track of options when mixing links and form elements. 4 * 5 * Copyright © 2008, Niklas Laxström 6 * Copyright © 2011, Antoine Musso 7 * Copyright © 2013, Bartosz Dziewoński 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 * http://www.gnu.org/copyleft/gpl.html 23 * 24 * @file 25 * @author Niklas Laxström 26 * @author Antoine Musso 27 */ 28 29 /** 30 * Helper class to keep track of options when mixing links and form elements. 31 * 32 * @todo This badly needs some examples and tests :) The usage in SpecialRecentchanges class is a 33 * good ersatz in the meantime. 34 */ 35 class FormOptions implements ArrayAccess { 36 /** @name Type constants 37 * Used internally to map an option value to a WebRequest accessor 38 */ 39 /* @{ */ 40 /** Mark value for automatic detection (for simple data types only) */ 41 const AUTO = -1; 42 /** String type, maps guessType() to WebRequest::getText() */ 43 const STRING = 0; 44 /** Integer type, maps guessType() to WebRequest::getInt() */ 45 const INT = 1; 46 /** Float type, maps guessType() to WebRequest::getFloat() 47 * @since 1.23 */ 48 const FLOAT = 4; 49 /** Boolean type, maps guessType() to WebRequest::getBool() */ 50 const BOOL = 2; 51 /** Integer type or null, maps to WebRequest::getIntOrNull() 52 * This is useful for the namespace selector. 53 */ 54 const INTNULL = 3; 55 /* @} */ 56 57 /** 58 * Map of known option names to information about them. 59 * 60 * Each value is an array with the following keys: 61 * - 'default' - the default value as passed to add() 62 * - 'value' - current value, start with null, can be set by various functions 63 * - 'consumed' - true/false, whether the option was consumed using 64 * consumeValue() or consumeValues() 65 * - 'type' - one of the type constants (but never AUTO) 66 */ 67 protected $options = array(); 68 69 # Setting up 70 71 /** 72 * Add an option to be handled by this FormOptions instance. 73 * 74 * @param string $name Request parameter name 75 * @param mixed $default Default value when the request parameter is not present 76 * @param int $type One of the type constants (optional, defaults to AUTO) 77 */ 78 public function add( $name, $default, $type = self::AUTO ) { 79 $option = array(); 80 $option['default'] = $default; 81 $option['value'] = null; 82 $option['consumed'] = false; 83 84 if ( $type !== self::AUTO ) { 85 $option['type'] = $type; 86 } else { 87 $option['type'] = self::guessType( $default ); 88 } 89 90 $this->options[$name] = $option; 91 } 92 93 /** 94 * Remove an option being handled by this FormOptions instance. This is the inverse of add(). 95 * 96 * @param string $name Request parameter name 97 */ 98 public function delete( $name ) { 99 $this->validateName( $name, true ); 100 unset( $this->options[$name] ); 101 } 102 103 /** 104 * Used to find out which type the data is. All types are defined in the 'Type constants' section 105 * of this class. 106 * 107 * Detection of the INTNULL type is not supported; INT will be assumed if the data is an integer, 108 * MWException will be thrown if it's null. 109 * 110 * @param mixed $data Value to guess the type for 111 * @throws MWException If unable to guess the type 112 * @return int Type constant 113 */ 114 public static function guessType( $data ) { 115 if ( is_bool( $data ) ) { 116 return self::BOOL; 117 } elseif ( is_int( $data ) ) { 118 return self::INT; 119 } elseif ( is_float( $data ) ) { 120 return self::FLOAT; 121 } elseif ( is_string( $data ) ) { 122 return self::STRING; 123 } else { 124 throw new MWException( 'Unsupported datatype' ); 125 } 126 } 127 128 # Handling values 129 130 /** 131 * Verify that the given option name exists. 132 * 133 * @param string $name Option name 134 * @param bool $strict Throw an exception when the option doesn't exist instead of returning false 135 * @throws MWException 136 * @return bool True if the option exists, false otherwise 137 */ 138 public function validateName( $name, $strict = false ) { 139 if ( !isset( $this->options[$name] ) ) { 140 if ( $strict ) { 141 throw new MWException( "Invalid option $name" ); 142 } else { 143 return false; 144 } 145 } 146 147 return true; 148 } 149 150 /** 151 * Use to set the value of an option. 152 * 153 * @param string $name Option name 154 * @param mixed $value Value for the option 155 * @param bool $force Whether to set the value when it is equivalent to the default value for this 156 * option (default false). 157 */ 158 public function setValue( $name, $value, $force = false ) { 159 $this->validateName( $name, true ); 160 161 if ( !$force && $value === $this->options[$name]['default'] ) { 162 // null default values as unchanged 163 $this->options[$name]['value'] = null; 164 } else { 165 $this->options[$name]['value'] = $value; 166 } 167 } 168 169 /** 170 * Get the value for the given option name. Uses getValueReal() internally. 171 * 172 * @param string $name Option name 173 * @return mixed 174 */ 175 public function getValue( $name ) { 176 $this->validateName( $name, true ); 177 178 return $this->getValueReal( $this->options[$name] ); 179 } 180 181 /** 182 * Return current option value, based on a structure taken from $options. 183 * 184 * @param array $option Array structure describing the option 185 * @return mixed Value, or the default value if it is null 186 */ 187 protected function getValueReal( $option ) { 188 if ( $option['value'] !== null ) { 189 return $option['value']; 190 } else { 191 return $option['default']; 192 } 193 } 194 195 /** 196 * Delete the option value. 197 * This will make future calls to getValue() return the default value. 198 * @param string $name Option name 199 */ 200 public function reset( $name ) { 201 $this->validateName( $name, true ); 202 $this->options[$name]['value'] = null; 203 } 204 205 /** 206 * Get the value of given option and mark it as 'consumed'. Consumed options are not returned 207 * by getUnconsumedValues(). 208 * 209 * @see consumeValues() 210 * @throws MWException If the option does not exist 211 * @param string $name Option name 212 * @return mixed Value, or the default value if it is null 213 */ 214 public function consumeValue( $name ) { 215 $this->validateName( $name, true ); 216 $this->options[$name]['consumed'] = true; 217 218 return $this->getValueReal( $this->options[$name] ); 219 } 220 221 /** 222 * Get the values of given options and mark them as 'consumed'. Consumed options are not returned 223 * by getUnconsumedValues(). 224 * 225 * @see consumeValue() 226 * @throws MWException If any option does not exist 227 * @param array $names Array of option names as strings 228 * @return array Array of option values, or the default values if they are null 229 */ 230 public function consumeValues( $names ) { 231 $out = array(); 232 233 foreach ( $names as $name ) { 234 $this->validateName( $name, true ); 235 $this->options[$name]['consumed'] = true; 236 $out[] = $this->getValueReal( $this->options[$name] ); 237 } 238 239 return $out; 240 } 241 242 /** 243 * @see validateBounds() 244 */ 245 public function validateIntBounds( $name, $min, $max ) { 246 $this->validateBounds( $name, $min, $max ); 247 } 248 249 /** 250 * Constrain a numeric value for a given option to a given range. The value will be altered to fit 251 * in the range. 252 * 253 * @since 1.23 254 * 255 * @param string $name Option name 256 * @param int|float $min Minimum value 257 * @param int|float $max Maximum value 258 * @throws MWException If option is not of type INT 259 */ 260 public function validateBounds( $name, $min, $max ) { 261 $this->validateName( $name, true ); 262 $type = $this->options[$name]['type']; 263 264 if ( $type !== self::INT && $type !== self::FLOAT ) { 265 throw new MWException( "Option $name is not of type INT or FLOAT" ); 266 } 267 268 $value = $this->getValueReal( $this->options[$name] ); 269 $value = max( $min, min( $max, $value ) ); 270 271 $this->setValue( $name, $value ); 272 } 273 274 /** 275 * Get all remaining values which have not been consumed by consumeValue() or consumeValues(). 276 * 277 * @param bool $all Whether to include unchanged options (default: false) 278 * @return array 279 */ 280 public function getUnconsumedValues( $all = false ) { 281 $values = array(); 282 283 foreach ( $this->options as $name => $data ) { 284 if ( !$data['consumed'] ) { 285 if ( $all || $data['value'] !== null ) { 286 $values[$name] = $this->getValueReal( $data ); 287 } 288 } 289 } 290 291 return $values; 292 } 293 294 /** 295 * Return options modified as an array ( name => value ) 296 * @return array 297 */ 298 public function getChangedValues() { 299 $values = array(); 300 301 foreach ( $this->options as $name => $data ) { 302 if ( $data['value'] !== null ) { 303 $values[$name] = $data['value']; 304 } 305 } 306 307 return $values; 308 } 309 310 /** 311 * Format options to an array ( name => value ) 312 * @return array 313 */ 314 public function getAllValues() { 315 $values = array(); 316 317 foreach ( $this->options as $name => $data ) { 318 $values[$name] = $this->getValueReal( $data ); 319 } 320 321 return $values; 322 } 323 324 # Reading values 325 326 /** 327 * Fetch values for all options (or selected options) from the given WebRequest, making them 328 * available for accessing with getValue() or consumeValue() etc. 329 * 330 * @param WebRequest $r The request to fetch values from 331 * @param array $optionKeys Which options to fetch the values for (default: 332 * all of them). Note that passing an empty array will also result in 333 * values for all keys being fetched. 334 * @throws MWException If the type of any option is invalid 335 */ 336 public function fetchValuesFromRequest( WebRequest $r, $optionKeys = null ) { 337 if ( !$optionKeys ) { 338 $optionKeys = array_keys( $this->options ); 339 } 340 341 foreach ( $optionKeys as $name ) { 342 $default = $this->options[$name]['default']; 343 $type = $this->options[$name]['type']; 344 345 switch ( $type ) { 346 case self::BOOL: 347 $value = $r->getBool( $name, $default ); 348 break; 349 case self::INT: 350 $value = $r->getInt( $name, $default ); 351 break; 352 case self::FLOAT: 353 $value = $r->getFloat( $name, $default ); 354 break; 355 case self::STRING: 356 $value = $r->getText( $name, $default ); 357 break; 358 case self::INTNULL: 359 $value = $r->getIntOrNull( $name ); 360 break; 361 default: 362 throw new MWException( 'Unsupported datatype' ); 363 } 364 365 if ( $value !== null ) { 366 $this->options[$name]['value'] = $value === $default ? null : $value; 367 } 368 } 369 } 370 371 /** @name ArrayAccess functions 372 * These functions implement the ArrayAccess PHP interface. 373 * @see http://php.net/manual/en/class.arrayaccess.php 374 */ 375 /* @{ */ 376 /** 377 * Whether the option exists. 378 * @param string $name 379 * @return bool 380 */ 381 public function offsetExists( $name ) { 382 return isset( $this->options[$name] ); 383 } 384 385 /** 386 * Retrieve an option value. 387 * @param string $name 388 * @return mixed 389 */ 390 public function offsetGet( $name ) { 391 return $this->getValue( $name ); 392 } 393 394 /** 395 * Set an option to given value. 396 * @param string $name 397 * @param mixed $value 398 */ 399 public function offsetSet( $name, $value ) { 400 $this->setValue( $name, $value ); 401 } 402 403 /** 404 * Delete the option. 405 * @param string $name 406 */ 407 public function offsetUnset( $name ) { 408 $this->delete( $name ); 409 } 410 /* @} */ 411 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |