* New helper class for dealing with forms
[lhc/web/wiklou.git] / includes / FormOptions.php
1 <?php
2 /**
3 * Helper class to keep track of options when mixing links and form elements.
4 *
5 * @author Niklas Laxström
6 * @copyright Copyright © 2008, Niklas Laxström
7 */
8
9 class FormOptions {
10 const AUTO = -1; //! Automatically detects simple data types
11 const STRING = 0;
12 const INT = 1;
13 const BOOL = 2;
14 const INTNULL = 3; //! Useful for namespace selector
15
16 protected $options = array();
17
18 # Setting up
19
20 public function add( $name, $default, $type = self::AUTO ) {
21 $option = array();
22 $option['default'] = $default;
23 $option['value'] = null;
24 $option['consumed'] = false;
25
26 if ( $type !== self::AUTO ) {
27 $option['type'] = $type;
28 } else {
29 $option['type'] = self::guessType( $default );
30 }
31
32 $this->options[$name] = $option;
33 }
34
35 public static function guessType( $data ) {
36 if ( is_bool($data) ) {
37 return self::BOOL;
38 } elseif( is_int($data) ) {
39 return self::INT;
40 } elseif( is_string($data) ) {
41 return self::STRING;
42 } else {
43 throw new MWException( 'Unsupported datatype' );
44 }
45 }
46
47 # Handling values
48
49 public function validateName( $name, $strict = false ) {
50 if ( !isset($this->options[$name]) ) {
51 if ( $strict ) {
52 throw new MWException( "Invalid option $name" );
53 } else {
54 return false;
55 }
56 }
57 return true;
58 }
59
60 public function setValue( $name, $value, $force = false ) {
61 $this->validateName( $name, true );
62 if ( !$force && $value === $this->options[$name]['default'] ) {
63 // null default values as unchanged
64 $this->options[$name]['value'] = null;
65 } else {
66 $this->options[$name]['value'] = $value;
67 }
68 }
69
70 public function getValue( $name ) {
71 $this->validateName( $name, true );
72 return $this->getValueReal( $this->options[$name] );
73 }
74
75 protected function getValueReal( $option ) {
76 if ( $option['value'] !== null ) {
77 return $option['value'];
78 } else {
79 return $option['default'];
80 }
81 }
82
83 public function consumeValue( $name ) {
84 $this->validateName( $name, true );
85 $this->options[$name]['consumed'] = true;
86 return $this->getValueReal( $this->options[$name] );
87 }
88
89 public function consumeValues( /*Array*/ $names ) {
90 $out = array();
91 foreach ( $names as $name ) {
92 $this->validateName( $name, true );
93 $this->options[$name]['consumed'] = true;
94 $out[] = $this->getValueReal( $this->options[$name] );
95 }
96 return $out;
97 }
98
99 # Validating values
100
101 public function validateIntBounds( $name, $min, $max ) {
102 $this->validateName( $name, true );
103
104 if ( $this->options[$name]['type'] !== self::INT )
105 throw new MWException( "Option $name is not of type int" );
106
107 $value = $this->getValueReal( $this->options[$name] );
108 $value = max( $min, min( $max, $value ) );
109
110 $this->setValue( $name, $value );
111 }
112
113 # Getting the data out for use
114
115 public function getUnconsumedValues( $all = false ) {
116 $values = array();
117 foreach ( $this->options as $name => $data ) {
118 if ( !$data['consumed'] ) {
119 if ( $all || $data['value'] !== null ) {
120 $values[$name] = $this->getValueReal( $data );
121 }
122 }
123 }
124 return $values;
125 }
126
127 public function getChangedValues() {
128 $values = array();
129 foreach ( $this->options as $name => $data ) {
130 if ( $data['value'] !== null ) {
131 $values[$name] = $data['value'];
132 }
133 }
134 return $values;
135 }
136
137 # Reading values
138
139 public function fetchValuesFromRequest( WebRequest $r ) {
140 foreach ( array_keys($this->options) as $name ) {
141 $default = $this->options[$name]['default'];
142 $type = $this->options[$name]['type'];
143
144 switch( $type ) {
145 case self::BOOL:
146 $value = $r->getBool( $name, $default ); break;
147 case self::INT:
148 $value = $r->getInt( $name, $default ); break;
149 case self::STRING:
150 $value = $r->getText( $name, $default ); break;
151 case self::INTNULL:
152 $value = $r->getIntOrNull( $name ); break;
153 default:
154 throw new MWException( 'Unsupported datatype' );
155 }
156
157 if ( $value !== $default && $value != null ) {
158 $this->options[$name]['value'] = $value;
159 }
160 }
161 }
162
163 }