forked from scandio/lmvc-modules
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAbstractForm.php
176 lines (158 loc) · 4.96 KB
/
AbstractForm.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?php
namespace Scandio\lmvc\modules\form;
use Scandio\lmvc\LVC;
use Scandio\lmvc\utils\string\StringUtils;
/**
* Form Validator class
* Create a class extending from AbstractForm and define the form fields as
* public members. Write your own validator methods and use their camelCased
* validator string as method name.
*
* class MyForm extends AbstractForm {
*
* public myField = array(
* 'my-validator' = array(
* 'message' = 'my error message for %s'
* )
* );
*
* public function myValidator($name) {
* if ($this->request->$name != 'LVC') {
* $this->setError($name);
* }
* }
* }
*
* In an action you can use it like validate(self::request());
*/
abstract class AbstractForm
{
/**
* @var null|\stdClass hidden member for internal use
*/
private $__formdata = null;
/**
* reads the form members and fills __formdata
*/
public function __construct()
{
$this->__formdata = new \stdClass();
$this->__formdata->fields = $this->getFormdataFields();
unset($this->__formdata->fields['__formdata']);
}
/**
* fetches the form fields by reflecting upon the instance
*/
public function getFormdataFields()
{
$reflection = new \ReflectionClass(get_class($this));
$potentialFields = $reflection->getDefaultProperties();
$fields = [];
foreach ($potentialFields as $name => $potentialField) {
if ( is_array($potentialField) ) {
$fields[$name] = $potentialField;
}
}
return $fields;
}
/**
* validates the whole form from the request array
*
* @param array $request the form request from LVC
* @param array $params optional additional parameters
*/
public function validate($request, $params = array())
{
$this->__formdata->request = $request;
$this->__formdata->params = $params;
foreach ($this->__formdata->fields as $property => $propertyValue) {
foreach ($propertyValue as $validator => $params) {
$this->__formdata->validator = $validator;
$validationInfo = $this->getValidationInfo($validator);
if (!is_null($validationInfo)) {
$camelCasedMethod = $validationInfo['method'];
$this->$camelCasedMethod($property, $validationInfo['rule']);
}
}
}
}
/**
* checks which validator message is the one to be called
*
* @param string $validator validator name
* @return array|null name and rule for validator method
*/
private function getValidationInfo($validator)
{
$newValidator = $validator;
$rule = array();
while (!method_exists($this, StringUtils::camelCaseFrom($newValidator))) {
$dashPos = strrpos($newValidator, '-');
if ($dashPos > 0) {
$rule[] = substr($newValidator, $dashPos + 1);
$newValidator = substr($newValidator, 0, $dashPos);
} else {
error_log('LMVC -- Undefined validator in ' . get_class($this));
return null;
}
}
return array(
'method' => StringUtils::camelCaseFrom($newValidator),
'rule' => implode('-', array_reverse($rule))
);
}
/**
* return the array of errors
*
* @return array associative array [field][validator] that contains the message
*/
public function getErrors()
{
return $this->__formdata->errors;
}
/**
* @return bool whether the form is valid
*/
public function isValid()
{
return !$this->hasErrors();
}
/**
* @return bool whether the form has errors
*/
public function hasErrors()
{
return is_array($this->__formdata->errors);
}
/**
* validator methods sets an error with the method
*
* @param string $name name of the form field
* @param array $params optional list of parameters if message uses sprintf variables
* @param null $message alternative message to overwrite the original message
*/
public function setError($name, $params = array(), $message = null)
{
if (empty($message)) {
$message = $this->__formdata->fields[$name][$this->__formdata->validator]['message'];
}
if (count($params) > 0) {
$message = call_user_func_array('sprintf', array_merge((array)$message, $params));
}
$this->__formdata->errors[$name][$this->__formdata->validator] = $message;
}
/**
* @return object the request from LVC
*/
protected function request()
{
return $this->__formdata->request;
}
/**
* @return array the params from a validation call
*/
protected function params()
{
return $this->__formdata->params;
}
}