1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Proengsoft\JsValidation; |
4
|
|
|
|
5
|
|
|
use Illuminate\Contracts\Validation\Factory as ValidationFactory; |
6
|
|
|
use Illuminate\Support\Arr; |
7
|
|
|
use Illuminate\Validation\Validator; |
8
|
|
|
use Proengsoft\JsValidation\Javascript\JavascriptValidator; |
9
|
|
|
use Proengsoft\JsValidation\Javascript\MessageParser; |
10
|
|
|
use Proengsoft\JsValidation\Javascript\RuleParser; |
11
|
|
|
use Proengsoft\JsValidation\Javascript\ValidatorHandler; |
12
|
|
|
use Proengsoft\JsValidation\Support\DelegatedValidator; |
13
|
|
|
use Proengsoft\JsValidation\Support\ValidationRuleParserProxy; |
14
|
|
|
|
15
|
|
|
class JsValidatorFactory |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* The application instance. |
19
|
|
|
* |
20
|
|
|
* @var \Illuminate\Container\Container |
21
|
|
|
*/ |
22
|
|
|
protected $app; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Configuration options. |
26
|
|
|
* |
27
|
|
|
* @var array |
28
|
|
|
*/ |
29
|
|
|
protected $options; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Create a new Validator factory instance. |
33
|
|
|
* |
34
|
|
|
* @param \Illuminate\Container\Container $app |
35
|
|
|
* @param array $options |
36
|
|
|
*/ |
37
|
84 |
|
public function __construct($app, array $options = []) |
38
|
|
|
{ |
39
|
84 |
|
$this->app = $app; |
40
|
84 |
|
$this->setOptions($options); |
41
|
84 |
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @param $options |
45
|
|
|
* @return void |
46
|
|
|
*/ |
47
|
84 |
|
protected function setOptions($options) |
48
|
|
|
{ |
49
|
84 |
|
$options['disable_remote_validation'] = empty($options['disable_remote_validation']) ? false : $options['disable_remote_validation']; |
50
|
84 |
|
$options['view'] = empty($options['view']) ? 'jsvalidation:bootstrap' : $options['view']; |
51
|
84 |
|
$options['form_selector'] = empty($options['form_selector']) ? 'form' : $options['form_selector']; |
52
|
|
|
|
53
|
84 |
|
$this->options = $options; |
54
|
84 |
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Creates JsValidator instance based on rules and message arrays. |
58
|
|
|
* |
59
|
|
|
* @param array $rules |
60
|
|
|
* @param array $messages |
61
|
|
|
* @param array $customAttributes |
62
|
|
|
* @param null|string $selector |
63
|
|
|
* @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
64
|
|
|
*/ |
65
|
48 |
|
public function make(array $rules, array $messages = [], array $customAttributes = [], $selector = null) |
66
|
|
|
{ |
67
|
48 |
|
$validator = $this->getValidatorInstance($rules, $messages, $customAttributes); |
68
|
|
|
|
69
|
48 |
|
return $this->validator($validator, $selector); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Get the validator instance for the request. |
74
|
|
|
* |
75
|
|
|
* @param array $rules |
76
|
|
|
* @param array $messages |
77
|
|
|
* @param array $customAttributes |
78
|
|
|
* @return \Illuminate\Validation\Validator |
79
|
|
|
*/ |
80
|
72 |
|
protected function getValidatorInstance(array $rules, array $messages = [], array $customAttributes = []) |
81
|
|
|
{ |
82
|
72 |
|
$factory = $this->app->make(ValidationFactory::class); |
83
|
|
|
|
84
|
72 |
|
$data = $this->getValidationData($rules, $customAttributes); |
85
|
72 |
|
$validator = $factory->make($data, $rules, $messages, $customAttributes); |
86
|
72 |
|
$validator->addCustomAttributes($customAttributes); |
87
|
|
|
|
88
|
72 |
|
return $validator; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Gets fake data when validator has wildcard rules. |
93
|
|
|
* |
94
|
|
|
* @param array $rules |
95
|
|
|
* @return array |
96
|
|
|
*/ |
97
|
72 |
|
protected function getValidationData(array $rules, array $customAttributes = []) |
98
|
|
|
{ |
99
|
|
|
$attributes = array_filter(array_keys($rules), function ($attribute) { |
100
|
48 |
|
return $attribute !== '' && mb_strpos($attribute, '*') !== false; |
101
|
72 |
|
}); |
102
|
|
|
|
103
|
72 |
|
$attributes = array_merge(array_keys($customAttributes), $attributes); |
104
|
|
|
$data = array_reduce($attributes, function ($data, $attribute) { |
105
|
24 |
|
Arr::set($data, $attribute, true); |
106
|
|
|
|
107
|
24 |
|
return $data; |
108
|
72 |
|
}, []); |
109
|
|
|
|
110
|
72 |
|
return $data; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Creates JsValidator instance based on FormRequest. |
115
|
|
|
* |
116
|
|
|
* @param $formRequest |
117
|
|
|
* @param null $selector |
118
|
|
|
* @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
119
|
|
|
* |
120
|
|
|
* @throws \Illuminate\Contracts\Container\BindingResolutionException |
121
|
|
|
*/ |
122
|
24 |
|
public function formRequest($formRequest, $selector = null) |
123
|
|
|
{ |
124
|
24 |
|
if (! is_object($formRequest)) { |
125
|
12 |
|
$formRequest = $this->createFormRequest($formRequest); |
126
|
|
|
} |
127
|
|
|
|
128
|
24 |
|
$rules = method_exists($formRequest, 'rules') ? $formRequest->rules() : []; |
129
|
|
|
|
130
|
24 |
|
$validator = $this->getValidatorInstance($rules, $formRequest->messages(), $formRequest->attributes()); |
131
|
|
|
|
132
|
24 |
|
$jsValidator = $this->validator($validator, $selector); |
133
|
|
|
|
134
|
24 |
|
if (method_exists($formRequest, 'withJsValidator')) { |
135
|
|
|
$formRequest->withJsValidator($jsValidator); |
136
|
|
|
} |
137
|
|
|
|
138
|
24 |
|
return $jsValidator; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @param string|array $class |
143
|
|
|
* @return array |
144
|
|
|
*/ |
145
|
12 |
|
protected function parseFormRequestName($class) |
146
|
|
|
{ |
147
|
12 |
|
$params = []; |
148
|
12 |
|
if (is_array($class)) { |
149
|
12 |
|
$params = empty($class[1]) ? $params : $class[1]; |
150
|
12 |
|
$class = $class[0]; |
151
|
|
|
} |
152
|
|
|
|
153
|
12 |
|
return [$class, $params]; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Creates and initializes an Form Request instance. |
158
|
|
|
* |
159
|
|
|
* @param string $class |
160
|
|
|
* @return \Illuminate\Foundation\Http\FormRequest |
161
|
|
|
* |
162
|
|
|
* @throws \Illuminate\Contracts\Container\BindingResolutionException |
163
|
|
|
*/ |
164
|
12 |
|
protected function createFormRequest($class) |
165
|
|
|
{ |
166
|
|
|
/* |
167
|
|
|
* @var $formRequest \Illuminate\Foundation\Http\FormRequest |
168
|
|
|
* @var $request Request |
169
|
|
|
*/ |
170
|
12 |
|
list($class, $params) = $this->parseFormRequestName($class); |
171
|
|
|
|
172
|
12 |
|
$request = $this->app->__get('request'); |
173
|
12 |
|
$formRequest = $this->app->build($class, $params); |
|
|
|
|
174
|
|
|
|
175
|
12 |
|
if ($session = $request->getSession()) { |
176
|
12 |
|
$formRequest->setLaravelSession($session); |
177
|
|
|
} |
178
|
12 |
|
$formRequest->setUserResolver($request->getUserResolver()); |
179
|
12 |
|
$formRequest->setRouteResolver($request->getRouteResolver()); |
180
|
12 |
|
$formRequest->setContainer($this->app); |
181
|
12 |
|
$formRequest->query = $request->query; |
182
|
|
|
|
183
|
12 |
|
return $formRequest; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Creates JsValidator instance based on Validator. |
188
|
|
|
* |
189
|
|
|
* @param \Illuminate\Validation\Validator $validator |
190
|
|
|
* @param null|string $selector |
191
|
|
|
* @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
192
|
|
|
*/ |
193
|
72 |
|
public function validator(Validator $validator, $selector = null) |
194
|
|
|
{ |
195
|
72 |
|
return $this->jsValidator($validator, $selector); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Creates JsValidator instance based on Validator. |
200
|
|
|
* |
201
|
|
|
* @param \Illuminate\Validation\Validator $validator |
202
|
|
|
* @param null|string $selector |
203
|
|
|
* @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
204
|
|
|
*/ |
205
|
72 |
|
protected function jsValidator(Validator $validator, $selector = null) |
206
|
|
|
{ |
207
|
72 |
|
$remote = ! $this->options['disable_remote_validation']; |
208
|
72 |
|
$view = $this->options['view']; |
209
|
72 |
|
$selector = is_null($selector) ? $this->options['form_selector'] : $selector; |
210
|
|
|
|
211
|
72 |
|
$delegated = new DelegatedValidator($validator, new ValidationRuleParserProxy($validator->getData())); |
212
|
72 |
|
$rules = new RuleParser($delegated, $this->getSessionToken()); |
213
|
72 |
|
$messages = new MessageParser($delegated, isset($this->options['escape']) ? $this->options['escape'] : false); |
214
|
|
|
|
215
|
72 |
|
$jsValidator = new ValidatorHandler($rules, $messages); |
216
|
|
|
|
217
|
72 |
|
$manager = new JavascriptValidator($jsValidator, compact('view', 'selector', 'remote')); |
218
|
|
|
|
219
|
72 |
|
return $manager; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Get and encrypt token from session store. |
224
|
|
|
* |
225
|
|
|
* @return null|string |
226
|
|
|
*/ |
227
|
72 |
|
protected function getSessionToken() |
228
|
|
|
{ |
229
|
72 |
|
$token = null; |
230
|
72 |
|
if ($session = $this->app->__get('session')) { |
231
|
12 |
|
$token = $session->token(); |
232
|
|
|
} |
233
|
|
|
|
234
|
72 |
|
if ($encrypter = $this->app->__get('encrypter')) { |
235
|
12 |
|
$token = $encrypter->encrypt($token); |
236
|
|
|
} |
237
|
|
|
|
238
|
72 |
|
return $token; |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.