wiki.techinc.nl/includes/FormOptions.php
Alexandre Emsenhuber 85e0c158ee * Standardised file description headers
* added @file where needed
* added file description headers where needed
2010-10-23 14:16:26 +00:00

214 lines
4.7 KiB
PHP

<?php
/**
* Helper class to keep track of options when mixing links and form elements.
*
* Copyright © 2008, Niklas Laxström
*
* @author Niklas Laxström
*/
class FormOptions implements ArrayAccess {
const AUTO = -1; // ! Automatically detects simple data types
const STRING = 0;
const INT = 1;
const BOOL = 2;
const INTNULL = 3; // ! Useful for namespace selector
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;
}
public function delete( $name ) {
$this->validateName( $name, true );
unset( $this->options[$name] );
}
public static function guessType( $data ) {
if ( is_bool( $data ) ) {
return self::BOOL;
} elseif ( is_int( $data ) ) {
return self::INT;
} elseif ( is_string( $data ) ) {
return self::STRING;
} else {
throw new MWException( 'Unsupported datatype' );
}
}
# Handling values
public function validateName( $name, $strict = false ) {
if ( !isset( $this->options[$name] ) ) {
if ( $strict ) {
throw new MWException( "Invalid option $name" );
} else {
return false;
}
}
return true;
}
public function setValue( $name, $value, $force = false ) {
$this->validateName( $name, true );
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 );
return $this->getValueReal( $this->options[$name] );
}
protected function getValueReal( $option ) {
if ( $option['value'] !== null ) {
return $option['value'];
} else {
return $option['default'];
}
}
public function reset( $name ) {
$this->validateName( $name, true );
$this->options[$name]['value'] = null;
}
public function consumeValue( $name ) {
$this->validateName( $name, true );
$this->options[$name]['consumed'] = true;
return $this->getValueReal( $this->options[$name] );
}
public function consumeValues( /*Array*/ $names ) {
$out = array();
foreach ( $names as $name ) {
$this->validateName( $name, true );
$this->options[$name]['consumed'] = true;
$out[] = $this->getValueReal( $this->options[$name] );
}
return $out;
}
# Validating values
public function validateIntBounds( $name, $min, $max ) {
$this->validateName( $name, true );
if ( $this->options[$name]['type'] !== self::INT ) {
throw new MWException( "Option $name is not of type int" );
}
$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();
foreach ( $this->options as $name => $data ) {
if ( !$data['consumed'] ) {
if ( $all || $data['value'] !== null ) {
$values[$name] = $this->getValueReal( $data );
}
}
}
return $values;
}
public function getChangedValues() {
$values = array();
foreach ( $this->options as $name => $data ) {
if ( $data['value'] !== null ) {
$values[$name] = $data['value'];
}
}
return $values;
}
public function getAllValues() {
$values = array();
foreach ( $this->options as $name => $data ) {
$values[$name] = $this->getValueReal( $data );
}
return $values;
}
# Reading values
public function fetchValuesFromRequest( WebRequest $r, $values = false ) {
if ( !$values ) {
$values = array_keys( $this->options );
}
foreach ( $values as $name ) {
$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' );
}
if ( $value !== null ) {
$this->options[$name]['value'] = $value === $default ? null : $value;
}
}
}
/* ArrayAccess methods */
public function offsetExists( $name ) {
return isset( $this->options[$name] );
}
public function offsetGet( $name ) {
return $this->getValue( $name );
}
public function offsetSet( $name, $value ) {
$this->setValue( $name, $value );
}
public function offsetUnset( $name ) {
$this->delete( $name );
}
}