22namespace PHPForm \Forms ;
33
44use ArrayAccess ;
5- use Iterator ;
65use Countable ;
6+ use InvalidArgumentException ;
7+ use Iterator ;
8+ use UnexpectedValueException ;
79
810use Fleshgrinder \Core \Formatter ;
911
@@ -17,40 +19,78 @@ abstract class Form implements ArrayAccess, Iterator, Countable
1719 const PREFIX_TEMPLATE = '{prefix}-{field_name} ' ;
1820 const NON_FIELD_ERRORS = '__all__ ' ;
1921
22+ /**
23+ * List of form errors.
24+ * @var array
25+ */
2026 private $ form_errors = null ;
27+
28+ /**
29+ * Array of bounded field to cache propose.
30+ * @var array
31+ */
32+ private $ bound_fields_cache = array ();
33+
34+ /**
35+ * Indicates if there's data bounded to form.
36+ * @var boolean
37+ */
2138 private $ is_bound = false ;
39+
40+ /**
41+ * Prefix to be used in form names.
42+ * @var string
43+ */
44+ protected $ prefix = null ;
45+
46+ /**
47+ * Fields declared to this form.
48+ * @var array
49+ */
2250 protected $ fields = array ();
51+
52+ /**
53+ * Cleaned values after validation.
54+ * @var array
55+ */
2356 protected $ cleaned_data = array ();
2457
25- public function __construct (array $ data = null , array $ files = null , string $ prefix = null )
58+ /**
59+ * Constructor method
60+ * @param array $args Arguments
61+ */
62+ public function __construct (array $ args = array ())
2663 {
27- $ this ->is_bound = !is_null ($ data ) or !is_null ($ files );
28- $ this ->data = $ data ;
29- $ this ->files = $ files ;
30- $ this ->prefix = $ prefix ;
64+ $ this ->data = array_key_exists ('data ' , $ args ) ? $ args ['data ' ] : null ;
65+ $ this ->files = array_key_exists ('files ' , $ args ) ? $ args ['files ' ] : null ;
66+ $ this ->prefix = array_key_exists ('prefix ' , $ args ) ? $ args ['prefix ' ] : $ this ->prefix ;
67+ $ this ->initial = array_key_exists ('initial ' , $ args ) ? $ args ['initial ' ] : array ();
68+
69+ $ this ->is_bound = !is_null ($ this ->data ) or !is_null ($ this ->files );
3170 $ this ->fields = $ this ::setFields ();
3271 }
3372
3473 /**
3574 * Method to be redefined with form fields
36- *
3775 * @return array Desired fields for this form.
3876 */
3977 protected static function setFields ()
4078 {
4179 return array ();
4280 }
4381
82+ /**
83+ * Return if form is bounded or not.
84+ * @return boolean
85+ */
4486 public function isBound ()
4587 {
4688 return $ this ->is_bound ;
4789 }
4890
4991 /**
5092 * Special method to make errors accessible as a attribute.
51- *
52- * @param string Attribute name.
53- *
93+ * @param string $name Attribute name.
5494 * @return mixed
5595 */
5696 public function __get (string $ name )
@@ -68,9 +108,7 @@ public function __get(string $name)
68108
69109 /**
70110 * Add a prefix to a name.
71- *
72- * @param string Field name.
73- *
111+ * @param string $field_name Field name.
74112 * @return string
75113 */
76114 public function addPrefix (string $ field_name )
@@ -86,8 +124,9 @@ public function addPrefix(string $field_name)
86124 }
87125
88126 /**
89- * @param mixed
90- * @param string
127+ * Add error to specific $field_name, if null, define to NON_FIELD_ERRORS.
128+ * @param mixed $error
129+ * @param string $field_name
91130 */
92131 protected function addError ($ error , string $ field_name = null )
93132 {
@@ -157,7 +196,6 @@ private function cleanForm()
157196
158197 /**
159198 * Redefine if need to validate crossfields.
160- *
161199 * @return array Cleaned data
162200 */
163201 protected function clean ()
@@ -166,12 +204,42 @@ protected function clean()
166204 }
167205
168206 /**
169- * @param string Field name
207+ * Return cleaned data values.
208+ * @return array Cleaned data
209+ */
210+ public function getCleanedData ()
211+ {
212+ return $ this ->cleaned_data ;
213+ }
214+
215+ /**
216+ * Return cleaned field value.
217+ * @param string $field_name Name of field.
218+ * @return string Cleaned field value.
219+ */
220+ public function getCleanedField (string $ field_name )
221+ {
222+ return isset ($ this ->cleaned_data [$ field_name ]) ? $ this ->cleaned_data [$ field_name ] : null ;
223+ }
224+
225+ /**
226+ * Check if field has error on it.
227+ * @param string $field_name Name of field to check
228+ * @return boolean
229+ */
230+ public function hasError ($ field_name )
231+ {
232+ return array_key_exists ($ field_name , $ this ->errors );
233+ }
234+
235+ /**
236+ * Return all errors associated to $field_name.
237+ * @param string $field_name Field name
170238 * @return ErrorList
171239 */
172240 public function getFieldErrors (string $ field_name )
173241 {
174- if (!array_key_exists ( $ field_name , $ this ->errors )) {
242+ if (!$ this ->hasError ( $ field_name )) {
175243 return new ErrorList ();
176244 }
177245
@@ -180,12 +248,11 @@ public function getFieldErrors(string $field_name)
180248
181249 /**
182250 * Return errors not associated with any field.
183- *
184251 * @return ErrorList
185252 */
186253 public function getNonFieldErrors ()
187254 {
188- if (!array_key_exists ($ this ::NON_FIELD_ERRORS , $ this -> errors )) {
255+ if (!$ this -> hasError ($ this ::NON_FIELD_ERRORS )) {
189256 return new ErrorList ();
190257 }
191258
@@ -194,14 +261,22 @@ public function getNonFieldErrors()
194261
195262 /**
196263 * Check if form is valid.
197- *
198264 * @return bool
199265 */
200266 public function isValid ()
201267 {
202268 return $ this ->is_bound and !count ($ this ->errors );
203269 }
204270
271+ /**
272+ * Check if form is valid.
273+ * @return bool
274+ */
275+ public function getInitialForField ($ field , $ field_name )
276+ {
277+ return isset ($ this ->initial [$ field_name ]) ? $ this ->initial [$ field_name ] : $ field ->getInitial ();
278+ }
279+
205280 /**
206281 * Implementation of ArrayAccess interface to provide accessing objects as arrays.
207282 */
@@ -224,10 +299,25 @@ public function offsetUnset($offset)
224299 unset($ this ->fields [$ offset ]);
225300 }
226301
302+ /**
303+ * @throws UnexpectedValueException
304+ * @return BoundField
305+ */
227306 public function offsetGet ($ offset )
228307 {
229308 $ field = isset ($ this ->fields [$ offset ]) ? $ this ->fields [$ offset ] : null ;
230- return new BoundField ($ this , $ field , $ offset );
309+
310+ if (is_null ($ field )) {
311+ $ choices = implode (", " , array_keys ($ this ->fields ));
312+ $ class_name = get_called_class ();
313+ throw new UnexpectedValueException ("Field ' $ offset' not found in $ class_name. Choices are: $ choices " , 1 );
314+ }
315+
316+ if (!isset ($ this ->bound_fields_cache [$ offset ])) {
317+ $ this ->bound_fields_cache [$ offset ] = new BoundField ($ this , $ field , $ offset );
318+ }
319+
320+ return $ this ->bound_fields_cache [$ offset ];
231321 }
232322
233323 /**
0 commit comments