[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/ -> FormOptions.php (source)

   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  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1