2008-04-19 17:38:06 +00:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Helper class to keep track of options when mixing links and form elements.
|
|
|
|
|
*
|
|
|
|
|
* @author Niklas Laxström
|
|
|
|
|
* @copyright Copyright © 2008, Niklas Laxström
|
|
|
|
|
*/
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
class FormOptions implements ArrayAccess {
|
2010-05-30 14:28:54 +00:00
|
|
|
const AUTO = -1; // ! Automatically detects simple data types
|
2008-04-19 17:38:06 +00:00
|
|
|
const STRING = 0;
|
|
|
|
|
const INT = 1;
|
|
|
|
|
const BOOL = 2;
|
2010-05-30 14:28:54 +00:00
|
|
|
const INTNULL = 3; // ! Useful for namespace selector
|
2008-04-19 17:38:06 +00:00
|
|
|
|
|
|
|
|
protected $options = array();
|
|
|
|
|
|
|
|
|
|
# Setting up
|
|
|
|
|
|
|
|
|
|
public function add( $name, $default, $type = self::AUTO ) {
|
|
|
|
|
$option = array();
|
|
|
|
|
$option['default'] = $default;
|
|
|
|
|
$option['value'] = null;
|
|
|
|
|
$option['consumed'] = false;
|
|
|
|
|
|
|
|
|
|
if ( $type !== self::AUTO ) {
|
|
|
|
|
$option['type'] = $type;
|
|
|
|
|
} else {
|
|
|
|
|
$option['type'] = self::guessType( $default );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->options[$name] = $option;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
public function delete( $name ) {
|
|
|
|
|
$this->validateName( $name, true );
|
2010-05-30 14:28:54 +00:00
|
|
|
unset( $this->options[$name] );
|
2008-06-08 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
public static function guessType( $data ) {
|
2010-05-30 14:28:54 +00:00
|
|
|
if ( is_bool( $data ) ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
return self::BOOL;
|
2010-05-30 14:28:54 +00:00
|
|
|
} elseif ( is_int( $data ) ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
return self::INT;
|
2010-05-30 14:28:54 +00:00
|
|
|
} elseif ( is_string( $data ) ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
return self::STRING;
|
|
|
|
|
} else {
|
|
|
|
|
throw new MWException( 'Unsupported datatype' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Handling values
|
|
|
|
|
|
|
|
|
|
public function validateName( $name, $strict = false ) {
|
2010-05-30 14:28:54 +00:00
|
|
|
if ( !isset( $this->options[$name] ) ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
if ( $strict ) {
|
|
|
|
|
throw new MWException( "Invalid option $name" );
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function setValue( $name, $value, $force = false ) {
|
|
|
|
|
$this->validateName( $name, true );
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
if ( !$force && $value === $this->options[$name]['default'] ) {
|
|
|
|
|
// null default values as unchanged
|
|
|
|
|
$this->options[$name]['value'] = null;
|
|
|
|
|
} else {
|
|
|
|
|
$this->options[$name]['value'] = $value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getValue( $name ) {
|
|
|
|
|
$this->validateName( $name, true );
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
return $this->getValueReal( $this->options[$name] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getValueReal( $option ) {
|
|
|
|
|
if ( $option['value'] !== null ) {
|
|
|
|
|
return $option['value'];
|
|
|
|
|
} else {
|
|
|
|
|
return $option['default'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
public function reset( $name ) {
|
|
|
|
|
$this->validateName( $name, true );
|
|
|
|
|
$this->options[$name]['value'] = null;
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
public function consumeValue( $name ) {
|
|
|
|
|
$this->validateName( $name, true );
|
|
|
|
|
$this->options[$name]['consumed'] = true;
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
return $this->getValueReal( $this->options[$name] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function consumeValues( /*Array*/ $names ) {
|
|
|
|
|
$out = array();
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
foreach ( $names as $name ) {
|
|
|
|
|
$this->validateName( $name, true );
|
|
|
|
|
$this->options[$name]['consumed'] = true;
|
|
|
|
|
$out[] = $this->getValueReal( $this->options[$name] );
|
|
|
|
|
}
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Validating values
|
|
|
|
|
|
|
|
|
|
public function validateIntBounds( $name, $min, $max ) {
|
|
|
|
|
$this->validateName( $name, true );
|
|
|
|
|
|
2010-05-30 14:28:54 +00:00
|
|
|
if ( $this->options[$name]['type'] !== self::INT ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
throw new MWException( "Option $name is not of type int" );
|
2010-05-30 14:28:54 +00:00
|
|
|
}
|
2008-04-19 17:38:06 +00:00
|
|
|
|
|
|
|
|
$value = $this->getValueReal( $this->options[$name] );
|
|
|
|
|
$value = max( $min, min( $max, $value ) );
|
|
|
|
|
|
|
|
|
|
$this->setValue( $name, $value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Getting the data out for use
|
|
|
|
|
|
|
|
|
|
public function getUnconsumedValues( $all = false ) {
|
|
|
|
|
$values = array();
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
foreach ( $this->options as $name => $data ) {
|
|
|
|
|
if ( !$data['consumed'] ) {
|
|
|
|
|
if ( $all || $data['value'] !== null ) {
|
|
|
|
|
$values[$name] = $this->getValueReal( $data );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
return $values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getChangedValues() {
|
|
|
|
|
$values = array();
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
foreach ( $this->options as $name => $data ) {
|
|
|
|
|
if ( $data['value'] !== null ) {
|
|
|
|
|
$values[$name] = $data['value'];
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
return $values;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
public function getAllValues() {
|
|
|
|
|
$values = array();
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
foreach ( $this->options as $name => $data ) {
|
|
|
|
|
$values[$name] = $this->getValueReal( $data );
|
|
|
|
|
}
|
2010-05-30 14:28:54 +00:00
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
return $values;
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-19 17:38:06 +00:00
|
|
|
# Reading values
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
public function fetchValuesFromRequest( WebRequest $r, $values = false ) {
|
|
|
|
|
if ( !$values ) {
|
2010-05-30 14:28:54 +00:00
|
|
|
$values = array_keys( $this->options );
|
2008-06-08 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ( $values as $name ) {
|
2008-04-19 17:38:06 +00:00
|
|
|
$default = $this->options[$name]['default'];
|
|
|
|
|
$type = $this->options[$name]['type'];
|
|
|
|
|
|
|
|
|
|
switch( $type ) {
|
|
|
|
|
case self::BOOL:
|
|
|
|
|
$value = $r->getBool( $name, $default ); break;
|
|
|
|
|
case self::INT:
|
|
|
|
|
$value = $r->getInt( $name, $default ); break;
|
|
|
|
|
case self::STRING:
|
|
|
|
|
$value = $r->getText( $name, $default ); break;
|
|
|
|
|
case self::INTNULL:
|
|
|
|
|
$value = $r->getIntOrNull( $name ); break;
|
|
|
|
|
default:
|
|
|
|
|
throw new MWException( 'Unsupported datatype' );
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-25 18:06:29 +00:00
|
|
|
if ( $value !== null ) {
|
|
|
|
|
$this->options[$name]['value'] = $value === $default ? null : $value;
|
2008-04-19 17:38:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 19:23:54 +00:00
|
|
|
/* ArrayAccess methods */
|
|
|
|
|
public function offsetExists( $name ) {
|
2010-05-30 14:28:54 +00:00
|
|
|
return isset( $this->options[$name] );
|
2008-06-08 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function offsetGet( $name ) {
|
|
|
|
|
return $this->getValue( $name );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function offsetSet( $name, $value ) {
|
2010-02-28 17:38:26 +00:00
|
|
|
$this->setValue( $name, $value );
|
2008-06-08 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function offsetUnset( $name ) {
|
2010-02-28 17:38:26 +00:00
|
|
|
$this->delete( $name );
|
2008-06-08 19:23:54 +00:00
|
|
|
}
|
2008-04-22 01:05:15 +00:00
|
|
|
}
|