## Apache Zeta Components Manual :: File Source for input_form.php

## Source for file input_form.php

Documentation is available at input_form.php

1. <?php
2. /**
3. *
4. * Licensed to the Apache Software Foundation (ASF) under one
5. * or more contributor license agreements. See the NOTICE file
6. * distributed with this work for additional information
7. * regarding copyright ownership. The ASF licenses this file
8. * to you under the Apache License, Version 2.0 (the
9. * "License"); you may not use this file except in compliance
10. * with the License. You may obtain a copy of the License at
11. *
12. * http://www.apache.org/licenses/LICENSE-2.0
13. *
14. * Unless required by applicable law or agreed to in writing,
15. * software distributed under the License is distributed on an
16. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17. * KIND, either express or implied. See the License for the
18. * specific language governing permissions and limitations
19. * under the License.
20. *
21. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
22. * @version //autogentag//
23. * @filesource
24. * @package UserInput
25. */
27. /**
28. * Provides access to form variables.
29. *
30. * This class allows you to retrieve input variables from the request in a safe
31. * way, by applying filters to allow only wanted data into your application. It
32. * works by passing an array that describes your form definition to the
33. * constructor of the class. The constructor will then initialize the class
34. * with properties that contain the value of your request's input fields.
35. *
36. * Example:
37. * <code>
38. * <?php
39. * if ( ezcInputForm::hasGetData() )
40. * {
41. * $definition = array(
42. * 'fieldname' => new ezcInputFormDefinitionElement(
43. * ezcInputFormDefinitionElement::REQUIRED, 'filtername'
44. * ),
45. * 'textfield' => new ezcInputFormDefinitionElement(
46. * ezcInputFormDefinitionElement::OPTIONAL, 'string'
47. * ),
48. * 'integer1' => new ezcInputFormDefinitionElement(
49. * ezcInputFormDefinitionElement::REQUIRED, 'int',
50. * array( 'min_range' => 0, 'max_range' => 42 )
51. * ),
52. * 'xmlfield' => new ezcInputFormDefinitionElement(
53. * ezcInputFormDefinitionElement::REQUIRED, 'unsafe_raw'
54. * ),
55. * 'special' => new ezcInputFormDefinitionElement(
56. * ezcInputFormDefinitionElement::OPTIONAL, 'callback',
57. * array( 'ezcInputFilter', 'special' )
58. * ),
59. * );
60. * $form = new ezcInputForm( INPUT_GET, $definition );
61. * if ( $form->hasInputField( 'textfield' ) ) // check for optional field
62. * {
63. * $text = $form->textfield;
64. * }
65. *
66. * try
67. * {
68. * $xml = $form->xmlfield; // Uses dynamic properties through __get().
69. * $field = $form->fieldname;
70. * $int = $form->integer1;
71. * }
72. * catch ( ezcInputFormException $e )
73. * {
74. * // one of the required fields didn't have valid data.
75. * $invalidProperties = $form->getInvalidProperties();
76. *
77. * // Retrieve RAW data for invalid properties so that we can fill in the
78. * // forms online with this RAW data again - Make sure to escape it on
79. * // output though, but that should be done for all data anyway.
80. * if ( in_array( 'xmlfield', $invalidProperties ) )
81. * {
82. * $xml = $form->getUnsafeRawData( 'xmlfield' );
83. * }
84. * }
85. *
86. * // Checking optional fields
87. * foreach ( $form->getOptionalProperties() as $property )
88. * {
89. * $name = "property_{$property}";
90. * if ( $form->hasValidData( $property ) )
91. * {
92. * $$name = $form->$property;
93. * }
94. * }
95. * }
96. * ?>
97. * </code>
98. *
99. * @property-read string $formFields
100. * There is a read-only property for each field that is defined
101. * as input field.
102. *
103. * @package UserInput
104. * @version //autogentag//
105. * @mainclass
106. */
107. class ezcInputForm
108. {
109. /**
110. * @var VALID is used in the $properties array to record whether the data
111. * in a specific input variable contained valid data according
112. * to the filter.
113. */
114. const VALID = 0;
116. /**
117. * @var INVALID is used in the $properties array to record whether the data
118. * in a specific input variable contained valid data according
119. * to the filter.
120. */
121. const INVALID = 1;
123. const DEF_NO_ARRAY = 1;
124. const DEF_EMPTY = 2;
125. const DEF_ELEMENT_NO_DEFINITION_ELEMENT = 3;
126. const DEF_NOT_REQUIRED_OR_OPTIONAL = 5;
127. const DEF_WRONG_FLAGS_TYPE = 6;
128. const DEF_UNSUPPORTED_FILTER = 7;
129. const DEF_FIELD_NAME_BROKEN = 8;
131. /**
132. * Contains the definition for this form (as passed in the constructor).
133. * @var array(string=>ezcInputFormDefinitionElement)
134. */
135. private $definition;
137. /**
138. * Contains a list of all retrieved properties and their status. The key
139. * for each array element is the field name, and the value associated with
140. * this key is one of the constants VALID or INVALID.
141. * @var array
142. */
143. private $properties;
145. /**
146. * Contains the values of the input variables. The key for each array
147. * element is the field name, and the value associated with this key is the
148. * property's value. This array does not have an entry for input fields
149. * that do not have valid data.
150. * @var array
151. */
152. protected $propertyValues ;
154. /**
155. * Contains the input source to be used.
156. * @var int
157. */
158. private $inputSource;
160. /**
161. * Whether all the input elements are valid
162. */
163. private $allElementsValid;
165. /**
166. * Constructs a new ezcInputForm for $inputSource with $definition.
167. *
168. * This method constructs a new ezcInputForm with three parameters. The
169. * $inputSource parameter selects the input source and should be one of the
170. * constants INPUT_GET, INPUT_POST or INPUT_COOKIE. The $definition
171. * parameter is an array of ezcInputFormDefinitionElement items and
172. * determines which input variables make up this form (see the example at
173. * the top of this class). The last parameter, $characterEncoding is the
174. * character encoding to use while retrieving input variable data. This
175. * parameter has currently no function as it will depend on PHP 6
176. * functionality which does not exist yet in the input filter extension.
177. *
178. * @throws ezcInputFormVariableMissingException when one of the required
179. * input variables is missing.
180. * @throws ezcInputFormInvalidDefinitionException when the definition array
181. * is invalid or when the input source was invalid.
182. *
183. * @param int $inputSource
184. * @param array(ezcInputFormDefinitionElement) $definition
185. * @param string $characterEncoding
186. */
187. public function __construct ( $inputSource, $definition, $characterEncoding = null )
188. {
189. if ( ( $returnValue = ezcInputForm :: validateDefinition ( $definition ) ) !== true )
190. {
191. throw new ezcInputFormInvalidDefinitionException ( $returnValue[1] );
192. }
193. $this->definition = $definition;
194. $this->inputSource = $inputSource;
196. $this->parseInput();
197. }
199. /**
200. * Returns whether there is GET data available
201. *
202. * @return bool True if there is GET data available
203. */
204. static public function hasGetData ()
205. {
206. return count ( $_GET ) > 0;
207. }
209. /**
210. * Returns whether there is POST data available
211. *
212. * @return bool True if there is POST data available
213. */
214. static public function hasPostData ()
215. {
216. return count ( $_POST ) > 0;
217. }
219. /**
220. * Parses the input according to the definition array.
221. *
222. * @throws ezcInputFormInvalidDefinitionException when one of the required
223. * input variables is missing or when the input source was invalid.
224. */
225. private function parseInput()
226. {
227. $this->allElementsValid = true;
229. if ( ! in_array ( $this->inputSource, array( INPUT_GET, INPUT_POST, INPUT_COOKIE ) ) )
230. {
231. throw new ezcInputFormWrongInputSourceException ( $this->inputSource );
232. }
234. foreach ( $this->definition as $elementName => $inputElement )
235. {
236. $hasVariable = filter_has_var ( $this->inputSource, $elementName );
237. if ( ! $hasVariable )
238. {
239. if ( $inputElement->type === ezcInputFormDefinitionElement ::REQUIRED )
240. {
241. throw new ezcInputFormVariableMissingException ( $elementName );
242. }
243. else
244. {
245. $this->properties[$elementName] = ezcInputForm ::INVALID;
246. $this->allElementsValid = false;
247. continue;
248. }
249. }
251. $flags = FILTER_NULL_ON_FAILURE | $inputElement->flags;
252. $value = filter_input ( $this->inputSource, $elementName, filter_id ( $inputElement->filterName ), array( 'options' => $inputElement->options, 'flags' => $flags ) );
254. if ( $value !== null )
255. {
256. $this->properties[$elementName] = ezcInputForm ::VALID;
257. $this-> propertyValues [$elementName] = $value;
258. }
259. else
260. {
261. $this->properties[$elementName] = ezcInputForm ::INVALID;
262. $this->allElementsValid = false;
263. }
264. }
265. }
267. /**
268. * Validates the definition array $definition.
269. *
270. * Before reading the values from the input source, the definition array
271. * can be validated by this method to check whether all necessary
272. * elements are correctly formed.
273. *
274. * With the following code you can check whether the definition is valid:
275. * <code>
276. * <?php
277. * if ( ( $returnValue = ezcInputForm::validateDefinition( $definition ) ) !== true )
278. * {
279. * // do something with the error type and error message in $returnValue
280. * }
281. * else
282. * {
283. * // the definition was correct
284. * }
285. * ?>
286. * </code>
287. *
288. * @param array $definition
289. * @return array|boolIf the definition is correct the method returns
290. * boolean true. When an error is found the function
291. * returns an array where the first element is the type,
292. * and the second element the error message.
293. */
294. static public function validateDefinition ( $definition )
295. {
296. // The definition parameter should be an array
297. if ( ! is_array ( $definition ) )
298. {
299. return array( ezcInputForm ::DEF_NO_ARRAY, "The definition array is not an array" );
300. }
302. // There should be atleast one element
303. if ( count ( $definition ) === 0 )
304. {
305. return array( ezcInputForm ::DEF_EMPTY, "The definition array is empty" );
306. }
308. foreach ( $definition as $name => $element )
309. {
310. // Each element should be an ezcInputFormDefinitionElement
311. if ( !$element instanceof ezcInputFormDefinitionElement )
312. {
313. return array( ezcInputForm ::DEF_ELEMENT_NO_DEFINITION_ELEMENT, "The definition for element '{$name}' is not an ezcInputFormDefinitionElement" );
314. }
316. // The first value in an element should be REQUIRED or OPTIONAL
317. if ( ! in_array ( $element->type, array( ezcInputFormDefinitionElement ::OPTIONAL, ezcInputFormDefinitionElement ::REQUIRED ), true ) )
318. {
319. return array( ezcInputForm ::DEF_NOT_REQUIRED_OR_OPTIONAL, "The first element definition for element '{$name}' is not ezcInputFormDefinitionElement::OPTIONAL or ezcInputFormDefinitionElement::REQUIRED" );
320. }
322. // The options should either be an array, a string, or an int
323. if ( $element->options !== null )
324. {
325. $filterOptionsType = gettype ( $element->options );
326. if ( ! in_array ( $filterOptionsType, array( 'integer', 'string', 'array' ) ) )
327. {
328. return array( ezcInputForm ::DEF_WRONG_FLAGS_TYPE, "The options to the definition for element '{$name}' is not of type integer, string or array" );
329. }
331. // A callback filter should have the form "string" or "array(string, string)"
332. if ( $element->filterName == 'callback' )
333. {
334. if ( $filterOptionsType == 'integer' )
335. {
336. return array( ezcInputForm ::DEF_WRONG_FLAGS_TYPE, "The callback filter for element '{$name}' should not be an integer" );
337. }
338. if ( $filterOptionsType == 'array' )
339. {
340. if ( count ( $element->options ) != 2 )
341. {
342. return array( ezcInputForm ::DEF_WRONG_FLAGS_TYPE, "The array parameter for the callback filter for element '{$name}' should have exactly two elements" );
343. }
344. if ( gettype ( $element->options[0] ) != 'string' || gettype ( $element->options[1] ) != 'string' )
345. {
346. return array( ezcInputForm ::DEF_WRONG_FLAGS_TYPE, "The array elements for the callback filter for element '{$name}' should both be a string" );
347. }
348. }
349. }
350. }
352. // The options should either be an int
353. if ( $element->flags !== null )
354. {
355. if ( gettype ( $element->flags ) !== 'integer' )
356. {
357. return array( ezcInputForm ::DEF_WRONG_FLAGS_TYPE, "The flags to the definition for element '{$name}' is not of type integer, string or array" );
358. }
359. }
361. // The filter should be an existing filter
362. if ( ! in_array ( $element->filterName, filter_list () ) )
363. {
364. $filters = join ( ', ', filter_list () );
365. return array( ezcInputForm ::DEF_UNSUPPORTED_FILTER, "The filter '{$element->filterName}' for element '{$name}' does not exist. Pick one of: $filters

" );
- }
- // The input field name should have a sane format
- if ( gettype ( $name ) != 'string' )
- {
- return array( ezcInputForm ::DEF_FIELD_NAME_BROKEN, "The element name '{$name}' is not a string" );
- }
- if (! preg_match ( '@^[a-z][a-z0-9_]*$@i', $name ) )
- {
- return array( ezcInputForm ::DEF_FIELD_NAME_BROKEN, "The element name '{$name}' has an unsupported format. It should start with an a-z and followed by a-z0-9_" );
- }
- }
- return true;
- }
- /**
- * This function is called when a variable is assigned to a magic property.
- *
- * When the value of a property is requested this function checks with the
- * $properties array whether it contains valid data or not. If there is no
- * valid data, the UserInputInValidData exception is thrown, otherwise the
- * function returns the value associated with the input variable.
- *
- * @throws ezcInputFormInvalidDataException when trying to read a property
- * which has no valid data.
- * @throws ezcInputFormUnknownFieldException when a property is being
- * accessed which is not defined in the definition array.
- *
- * @param string $propertyName
- * @return mixed The value of the input variable.
- * @ignore
- */
- public function __get( $propertyName )
- {
- if ( isset( $this->properties[$propertyName] ) )
- {
- if ( $this->properties[$propertyName] === ezcInputForm ::VALID )
- {
- return $this-> propertyValues [$propertyName];
- }
- else
- {
- throw new ezcInputFormNoValidDataException ( $propertyName );
- }
- }
- throw new ezcInputFormUnknownFieldException ( $propertyName );
- }
- /**
- * Returns whether a magic property was is used on a magic property.
- *
- * This method checks whether a magic property exists and returns true of
- * it does and false if it doesn't. The list of properties which exist is
- * determined by the $definition array that was passed to the constructor.
- *
- * @param string $propertyName
- * @return bool Whether the $propertyName exists or not.
- * @ignore
- */
- public function __isset( $propertyName )
- {
- return isset( $this->properties[$propertyName] );
- }
- /**
- * Sets a new magic property.
- *
- * This function is called when one of the magic properties was assigned a
- * new value. As all magic properties are read-only for this class, all
- * that this function does is return the exception
- * ezcBasePropertyReadOnlyException.
- *
- * @throws ezcBasePropertyPermissionException for every call to this
- * function.
- * @param string $propertyName
- * @param mixed $newValue
- * @ignore
- */
- public function __set( $propertyName, $newValue )
- {
- throw new ezcBasePropertyPermissionException ( $propertyName, ezcBasePropertyPermissionException ::READ );
- }
- /**
- * Returns whether the optional field $fieldName exists.
- *
- * @param string $fieldName
- * @return bool true if the input field was available and false otherwise.
- */
- public function hasInputField ( $fieldName )
- {
- if ( isset( $this->properties[$fieldName] ) )
- {
- return true;
- }
- return false;
- }
- /**
- * Returns whether the filters for required field $fieldName returned valid data.
- *
- * @param string $fieldName
- * @return bool true if the input field was available and false otherwise.
- */
- public function hasValidData ( $fieldName )
- {
- if ( isset( $this->properties[$fieldName] ) && $this->properties[$fieldName] === ezcInputForm ::VALID )
- {
- return true;
- }
- return false;
- }
- /**
- * Returns RAW input variable values for invalid field $fieldName.
- *
- * The return value of this function can be used to prefill forms on the
- * next request. It will only work for invalid input fields, as for valid
- * input fields you should never have to get to the original RAW data. In
- * the case a $fieldName is passed that has valid data, an
- * ezcInputFormException will be thrown.
- *
- * @throws ezcInputFormValidDataException when trying to get unsafe raw
- * data from a input field with valid data.
- * @throws ezcInputFormFieldNotFoundException when trying to get data from a
- * property that does not exist.
- * @param string $fieldName
- * @return string The original RAW data of the specified input field.
- */
- public function getUnsafeRawData ( $fieldName )
- {
- if ( isset( $this->properties[$fieldName] ) )
- {
- if ( $this->properties[$fieldName] === ezcInputForm ::VALID )
- {
- throw new ezcInputFormValidDataAvailableException ( $fieldName );
- }
- else
- {
- if ( filter_has_var ( $this->inputSource, $fieldName ) )
- {
- return filter_input ( $this->inputSource, $fieldName, FILTER_UNSAFE_RAW );
- }
- else
- {
- throw new ezcInputFormFieldNotFoundException ( $fieldName );
- }
- }
- }
- throw new ezcInputFormUnknownFieldException ( $fieldName );
- }
- /**
- * Returns a list with all optional properties.
- * @return array(string)
- */
- public function getOptionalProperties ()
- {
- $properties = array();
- foreach ( $this->definition as $fieldName => $fieldDefinition )
- {
- if ( $fieldDefinition->type === ezcInputFormDefinitionElement ::OPTIONAL )
- {
- $properties[] = $fieldName;
- }
- }
- return $properties;
- }
- /**
- * Returns a list with all required properties.
- * @return array(string)
- */
- public function getRequiredProperties ()
- {
- $properties = array();
- foreach ( $this->definition as $fieldName => $fieldDefinition )
- {
- if ( $fieldDefinition->type === ezcInputFormDefinitionElement ::REQUIRED )
- {
- $properties[] = $fieldName;
- }
- }
- return $properties;
- }
- /**
- * Returns a list with all properties that have valid data.
- * @return array(string)
- */
- public function getValidProperties ()
- {
- $properties = array();
- foreach ( $this->properties as $fieldName => $fieldStatus )
- {
- if ( $fieldStatus === ezcInputForm ::VALID )
- {
- $properties[] = $fieldName;
- }
- }
- return $properties;
- }
- /**
- * Returns a list with all properties having invalid data.
- * @return array(string)
- */
- public function getInvalidProperties ()
- {
- $properties = array();
- foreach ( $this->properties as $fieldName => $fieldStatus )
- {
- if ( $fieldStatus === ezcInputForm ::INVALID )
- {
- $properties[] = $fieldName;
- }
- }
- return $properties;
- }
- /**
- * Returns whether all the input elements were valid or not.
- *
- * @return bool
- */
- public function isValid ()
- {
- return $this->allElementsValid;
- }
- }
- ?>
Documentation generated by phpDocumentor 1.4.3