3 * Helper class to keep track of options when mixing links and form elements.
5 * Copyright © 2008, Niklas Laxström
7 * @author Niklas Laxström
10 class FormOptions
implements ArrayAccess
{
11 const AUTO
= -1; // ! Automatically detects simple data types
15 const INTNULL
= 3; // ! Useful for namespace selector
17 protected $options = array();
21 public function add( $name, $default, $type = self
::AUTO
) {
23 $option['default'] = $default;
24 $option['value'] = null;
25 $option['consumed'] = false;
27 if ( $type !== self
::AUTO
) {
28 $option['type'] = $type;
30 $option['type'] = self
::guessType( $default );
33 $this->options
[$name] = $option;
36 public function delete( $name ) {
37 $this->validateName( $name, true );
38 unset( $this->options
[$name] );
41 public static function guessType( $data ) {
42 if ( is_bool( $data ) ) {
44 } elseif ( is_int( $data ) ) {
46 } elseif ( is_string( $data ) ) {
49 throw new MWException( 'Unsupported datatype' );
55 public function validateName( $name, $strict = false ) {
56 if ( !isset( $this->options
[$name] ) ) {
58 throw new MWException( "Invalid option $name" );
66 public function setValue( $name, $value, $force = false ) {
67 $this->validateName( $name, true );
69 if ( !$force && $value === $this->options
[$name]['default'] ) {
70 // null default values as unchanged
71 $this->options
[$name]['value'] = null;
73 $this->options
[$name]['value'] = $value;
77 public function getValue( $name ) {
78 $this->validateName( $name, true );
80 return $this->getValueReal( $this->options
[$name] );
83 protected function getValueReal( $option ) {
84 if ( $option['value'] !== null ) {
85 return $option['value'];
87 return $option['default'];
91 public function reset( $name ) {
92 $this->validateName( $name, true );
93 $this->options
[$name]['value'] = null;
96 public function consumeValue( $name ) {
97 $this->validateName( $name, true );
98 $this->options
[$name]['consumed'] = true;
100 return $this->getValueReal( $this->options
[$name] );
103 public function consumeValues( /*Array*/ $names ) {
106 foreach ( $names as $name ) {
107 $this->validateName( $name, true );
108 $this->options
[$name]['consumed'] = true;
109 $out[] = $this->getValueReal( $this->options
[$name] );
117 public function validateIntBounds( $name, $min, $max ) {
118 $this->validateName( $name, true );
120 if ( $this->options
[$name]['type'] !== self
::INT ) {
121 throw new MWException( "Option $name is not of type int" );
124 $value = $this->getValueReal( $this->options
[$name] );
125 $value = max( $min, min( $max, $value ) );
127 $this->setValue( $name, $value );
130 # Getting the data out for use
132 public function getUnconsumedValues( $all = false ) {
135 foreach ( $this->options
as $name => $data ) {
136 if ( !$data['consumed'] ) {
137 if ( $all ||
$data['value'] !== null ) {
138 $values[$name] = $this->getValueReal( $data );
146 public function getChangedValues() {
149 foreach ( $this->options
as $name => $data ) {
150 if ( $data['value'] !== null ) {
151 $values[$name] = $data['value'];
158 public function getAllValues() {
161 foreach ( $this->options
as $name => $data ) {
162 $values[$name] = $this->getValueReal( $data );
170 public function fetchValuesFromRequest( WebRequest
$r, $values = false ) {
172 $values = array_keys( $this->options
);
175 foreach ( $values as $name ) {
176 $default = $this->options
[$name]['default'];
177 $type = $this->options
[$name]['type'];
181 $value = $r->getBool( $name, $default ); break;
183 $value = $r->getInt( $name, $default ); break;
185 $value = $r->getText( $name, $default ); break;
187 $value = $r->getIntOrNull( $name ); break;
189 throw new MWException( 'Unsupported datatype' );
192 if ( $value !== null ) {
193 $this->options
[$name]['value'] = $value === $default ?
null : $value;
198 /* ArrayAccess methods */
199 public function offsetExists( $name ) {
200 return isset( $this->options
[$name] );
203 public function offsetGet( $name ) {
204 return $this->getValue( $name );
207 public function offsetSet( $name, $value ) {
208 $this->setValue( $name, $value );
211 public function offsetUnset( $name ) {
212 $this->delete( $name );