MediaWiki  REL1_24
FormOptions.php
Go to the documentation of this file.
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 }