MediaWiki
REL1_24
|
00001 <?php 00035 class FormOptions implements ArrayAccess { 00039 /* @{ */ 00041 const AUTO = -1; 00043 const STRING = 0; 00045 const INT = 1; 00048 const FLOAT = 4; 00050 const BOOL = 2; 00054 const INTNULL = 3; 00055 /* @} */ 00056 00067 protected $options = array(); 00068 00069 # Setting up 00070 00078 public function add( $name, $default, $type = self::AUTO ) { 00079 $option = array(); 00080 $option['default'] = $default; 00081 $option['value'] = null; 00082 $option['consumed'] = false; 00083 00084 if ( $type !== self::AUTO ) { 00085 $option['type'] = $type; 00086 } else { 00087 $option['type'] = self::guessType( $default ); 00088 } 00089 00090 $this->options[$name] = $option; 00091 } 00092 00098 public function delete( $name ) { 00099 $this->validateName( $name, true ); 00100 unset( $this->options[$name] ); 00101 } 00102 00114 public static function guessType( $data ) { 00115 if ( is_bool( $data ) ) { 00116 return self::BOOL; 00117 } elseif ( is_int( $data ) ) { 00118 return self::INT; 00119 } elseif ( is_float( $data ) ) { 00120 return self::FLOAT; 00121 } elseif ( is_string( $data ) ) { 00122 return self::STRING; 00123 } else { 00124 throw new MWException( 'Unsupported datatype' ); 00125 } 00126 } 00127 00128 # Handling values 00129 00138 public function validateName( $name, $strict = false ) { 00139 if ( !isset( $this->options[$name] ) ) { 00140 if ( $strict ) { 00141 throw new MWException( "Invalid option $name" ); 00142 } else { 00143 return false; 00144 } 00145 } 00146 00147 return true; 00148 } 00149 00158 public function setValue( $name, $value, $force = false ) { 00159 $this->validateName( $name, true ); 00160 00161 if ( !$force && $value === $this->options[$name]['default'] ) { 00162 // null default values as unchanged 00163 $this->options[$name]['value'] = null; 00164 } else { 00165 $this->options[$name]['value'] = $value; 00166 } 00167 } 00168 00175 public function getValue( $name ) { 00176 $this->validateName( $name, true ); 00177 00178 return $this->getValueReal( $this->options[$name] ); 00179 } 00180 00187 protected function getValueReal( $option ) { 00188 if ( $option['value'] !== null ) { 00189 return $option['value']; 00190 } else { 00191 return $option['default']; 00192 } 00193 } 00194 00200 public function reset( $name ) { 00201 $this->validateName( $name, true ); 00202 $this->options[$name]['value'] = null; 00203 } 00204 00214 public function consumeValue( $name ) { 00215 $this->validateName( $name, true ); 00216 $this->options[$name]['consumed'] = true; 00217 00218 return $this->getValueReal( $this->options[$name] ); 00219 } 00220 00230 public function consumeValues( $names ) { 00231 $out = array(); 00232 00233 foreach ( $names as $name ) { 00234 $this->validateName( $name, true ); 00235 $this->options[$name]['consumed'] = true; 00236 $out[] = $this->getValueReal( $this->options[$name] ); 00237 } 00238 00239 return $out; 00240 } 00241 00245 public function validateIntBounds( $name, $min, $max ) { 00246 $this->validateBounds( $name, $min, $max ); 00247 } 00248 00260 public function validateBounds( $name, $min, $max ) { 00261 $this->validateName( $name, true ); 00262 $type = $this->options[$name]['type']; 00263 00264 if ( $type !== self::INT && $type !== self::FLOAT ) { 00265 throw new MWException( "Option $name is not of type INT or FLOAT" ); 00266 } 00267 00268 $value = $this->getValueReal( $this->options[$name] ); 00269 $value = max( $min, min( $max, $value ) ); 00270 00271 $this->setValue( $name, $value ); 00272 } 00273 00280 public function getUnconsumedValues( $all = false ) { 00281 $values = array(); 00282 00283 foreach ( $this->options as $name => $data ) { 00284 if ( !$data['consumed'] ) { 00285 if ( $all || $data['value'] !== null ) { 00286 $values[$name] = $this->getValueReal( $data ); 00287 } 00288 } 00289 } 00290 00291 return $values; 00292 } 00293 00298 public function getChangedValues() { 00299 $values = array(); 00300 00301 foreach ( $this->options as $name => $data ) { 00302 if ( $data['value'] !== null ) { 00303 $values[$name] = $data['value']; 00304 } 00305 } 00306 00307 return $values; 00308 } 00309 00314 public function getAllValues() { 00315 $values = array(); 00316 00317 foreach ( $this->options as $name => $data ) { 00318 $values[$name] = $this->getValueReal( $data ); 00319 } 00320 00321 return $values; 00322 } 00323 00324 # Reading values 00325 00336 public function fetchValuesFromRequest( WebRequest $r, $optionKeys = null ) { 00337 if ( !$optionKeys ) { 00338 $optionKeys = array_keys( $this->options ); 00339 } 00340 00341 foreach ( $optionKeys as $name ) { 00342 $default = $this->options[$name]['default']; 00343 $type = $this->options[$name]['type']; 00344 00345 switch ( $type ) { 00346 case self::BOOL: 00347 $value = $r->getBool( $name, $default ); 00348 break; 00349 case self::INT: 00350 $value = $r->getInt( $name, $default ); 00351 break; 00352 case self::FLOAT: 00353 $value = $r->getFloat( $name, $default ); 00354 break; 00355 case self::STRING: 00356 $value = $r->getText( $name, $default ); 00357 break; 00358 case self::INTNULL: 00359 $value = $r->getIntOrNull( $name ); 00360 break; 00361 default: 00362 throw new MWException( 'Unsupported datatype' ); 00363 } 00364 00365 if ( $value !== null ) { 00366 $this->options[$name]['value'] = $value === $default ? null : $value; 00367 } 00368 } 00369 } 00370 00375 /* @{ */ 00381 public function offsetExists( $name ) { 00382 return isset( $this->options[$name] ); 00383 } 00384 00390 public function offsetGet( $name ) { 00391 return $this->getValue( $name ); 00392 } 00393 00399 public function offsetSet( $name, $value ) { 00400 $this->setValue( $name, $value ); 00401 } 00402 00407 public function offsetUnset( $name ) { 00408 $this->delete( $name ); 00409 } 00410 /* @} */ 00411 }