MediaWiki
master
|
00001 <?php 00033 class FormOptions implements ArrayAccess { 00037 /* @{ */ 00039 const AUTO = -1; 00041 const STRING = 0; 00043 const INT = 1; 00045 const BOOL = 2; 00049 const INTNULL = 3; 00050 /* @} */ 00051 00055 protected $options = array(); 00056 00057 # Setting up 00058 00059 public function add( $name, $default, $type = self::AUTO ) { 00060 $option = array(); 00061 $option['default'] = $default; 00062 $option['value'] = null; 00063 $option['consumed'] = false; 00064 00065 if ( $type !== self::AUTO ) { 00066 $option['type'] = $type; 00067 } else { 00068 $option['type'] = self::guessType( $default ); 00069 } 00070 00071 $this->options[$name] = $option; 00072 } 00073 00074 public function delete( $name ) { 00075 $this->validateName( $name, true ); 00076 unset( $this->options[$name] ); 00077 } 00078 00090 public static function guessType( $data ) { 00091 if ( is_bool( $data ) ) { 00092 return self::BOOL; 00093 } elseif ( is_int( $data ) ) { 00094 return self::INT; 00095 } elseif ( is_string( $data ) ) { 00096 return self::STRING; 00097 } else { 00098 throw new MWException( 'Unsupported datatype' ); 00099 } 00100 } 00101 00102 # Handling values 00103 00112 public function validateName( $name, $strict = false ) { 00113 if ( !isset( $this->options[$name] ) ) { 00114 if ( $strict ) { 00115 throw new MWException( "Invalid option $name" ); 00116 } else { 00117 return false; 00118 } 00119 } 00120 return true; 00121 } 00122 00131 public function setValue( $name, $value, $force = false ) { 00132 $this->validateName( $name, true ); 00133 00134 if ( !$force && $value === $this->options[$name]['default'] ) { 00135 // null default values as unchanged 00136 $this->options[$name]['value'] = null; 00137 } else { 00138 $this->options[$name]['value'] = $value; 00139 } 00140 } 00141 00149 public function getValue( $name ) { 00150 $this->validateName( $name, true ); 00151 00152 return $this->getValueReal( $this->options[$name] ); 00153 } 00154 00160 protected function getValueReal( $option ) { 00161 if ( $option['value'] !== null ) { 00162 return $option['value']; 00163 } else { 00164 return $option['default']; 00165 } 00166 } 00167 00174 public function reset( $name ) { 00175 $this->validateName( $name, true ); 00176 $this->options[$name]['value'] = null; 00177 } 00178 00184 public function consumeValue( $name ) { 00185 $this->validateName( $name, true ); 00186 $this->options[$name]['consumed'] = true; 00187 00188 return $this->getValueReal( $this->options[$name] ); 00189 } 00190 00196 public function consumeValues( /*Array*/ $names ) { 00197 $out = array(); 00198 00199 foreach ( $names as $name ) { 00200 $this->validateName( $name, true ); 00201 $this->options[$name]['consumed'] = true; 00202 $out[] = $this->getValueReal( $this->options[$name] ); 00203 } 00204 00205 return $out; 00206 } 00207 00219 public function validateIntBounds( $name, $min, $max ) { 00220 $this->validateName( $name, true ); 00221 00222 if ( $this->options[$name]['type'] !== self::INT ) { 00223 throw new MWException( "Option $name is not of type int" ); 00224 } 00225 00226 $value = $this->getValueReal( $this->options[$name] ); 00227 $value = max( $min, min( $max, $value ) ); 00228 00229 $this->setValue( $name, $value ); 00230 } 00231 00237 public function getUnconsumedValues( $all = false ) { 00238 $values = array(); 00239 00240 foreach ( $this->options as $name => $data ) { 00241 if ( !$data['consumed'] ) { 00242 if ( $all || $data['value'] !== null ) { 00243 $values[$name] = $this->getValueReal( $data ); 00244 } 00245 } 00246 } 00247 00248 return $values; 00249 } 00250 00255 public function getChangedValues() { 00256 $values = array(); 00257 00258 foreach ( $this->options as $name => $data ) { 00259 if ( $data['value'] !== null ) { 00260 $values[$name] = $data['value']; 00261 } 00262 } 00263 00264 return $values; 00265 } 00266 00271 public function getAllValues() { 00272 $values = array(); 00273 00274 foreach ( $this->options as $name => $data ) { 00275 $values[$name] = $this->getValueReal( $data ); 00276 } 00277 00278 return $values; 00279 } 00280 00281 # Reading values 00282 00283 public function fetchValuesFromRequest( WebRequest $r, $values = false ) { 00284 if ( !$values ) { 00285 $values = array_keys( $this->options ); 00286 } 00287 00288 foreach ( $values as $name ) { 00289 $default = $this->options[$name]['default']; 00290 $type = $this->options[$name]['type']; 00291 00292 switch( $type ) { 00293 case self::BOOL: 00294 $value = $r->getBool( $name, $default ); break; 00295 case self::INT: 00296 $value = $r->getInt( $name, $default ); break; 00297 case self::STRING: 00298 $value = $r->getText( $name, $default ); break; 00299 case self::INTNULL: 00300 $value = $r->getIntOrNull( $name ); break; 00301 default: 00302 throw new MWException( 'Unsupported datatype' ); 00303 } 00304 00305 if ( $value !== null ) { 00306 $this->options[$name]['value'] = $value === $default ? null : $value; 00307 } 00308 } 00309 } 00310 00315 /* @{ */ 00320 public function offsetExists( $name ) { 00321 return isset( $this->options[$name] ); 00322 } 00327 public function offsetGet( $name ) { 00328 return $this->getValue( $name ); 00329 } 00331 public function offsetSet( $name, $value ) { 00332 $this->setValue( $name, $value ); 00333 } 00335 public function offsetUnset( $name ) { 00336 $this->delete( $name ); 00337 } 00338 /* @} */ 00339 }