This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Proengsoft\JsValidation; |
||
4 | |||
5 | use Illuminate\Contracts\Validation\Factory as ValidationFactory; |
||
6 | use Illuminate\Foundation\Http\FormRequest as IlluminateFormRequest; |
||
7 | use Illuminate\Support\Arr; |
||
8 | use Illuminate\Validation\Validator; |
||
9 | use Proengsoft\JsValidation\Javascript\JavascriptValidator; |
||
10 | use Proengsoft\JsValidation\Javascript\MessageParser; |
||
11 | use Proengsoft\JsValidation\Javascript\RuleParser; |
||
12 | use Proengsoft\JsValidation\Javascript\ValidatorHandler; |
||
13 | use Proengsoft\JsValidation\Remote\FormRequest; |
||
14 | use Proengsoft\JsValidation\Support\DelegatedValidator; |
||
15 | use Proengsoft\JsValidation\Support\ValidationRuleParserProxy; |
||
16 | |||
17 | class JsValidatorFactory |
||
18 | { |
||
19 | const ASTERISK = '__asterisk__'; |
||
20 | |||
21 | /** |
||
22 | * The application instance. |
||
23 | * |
||
24 | * @var \Illuminate\Container\Container |
||
25 | */ |
||
26 | protected $app; |
||
27 | |||
28 | /** |
||
29 | * Configuration options. |
||
30 | * |
||
31 | * @var array |
||
32 | */ |
||
33 | protected $options; |
||
34 | |||
35 | /** |
||
36 | * Create a new Validator factory instance. |
||
37 | 84 | * |
|
38 | * @param \Illuminate\Container\Container $app |
||
39 | 84 | * @param array $options |
|
40 | 84 | */ |
|
41 | 84 | public function __construct($app, array $options = []) |
|
42 | { |
||
43 | $this->app = $app; |
||
44 | $this->setOptions($options); |
||
45 | } |
||
46 | |||
47 | 84 | /** |
|
48 | * @param $options |
||
49 | 84 | * @return void |
|
50 | 84 | */ |
|
51 | 84 | protected function setOptions($options) |
|
52 | { |
||
53 | 84 | $options['disable_remote_validation'] = empty($options['disable_remote_validation']) ? false : $options['disable_remote_validation']; |
|
54 | 84 | $options['view'] = empty($options['view']) ? 'jsvalidation:bootstrap' : $options['view']; |
|
55 | $options['form_selector'] = empty($options['form_selector']) ? 'form' : $options['form_selector']; |
||
56 | |||
57 | $this->options = $options; |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * Creates JsValidator instance based on rules and message arrays. |
||
62 | * |
||
63 | * @param array $rules |
||
64 | * @param array $messages |
||
65 | 48 | * @param array $customAttributes |
|
66 | * @param null|string $selector |
||
67 | 48 | * @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
|
68 | */ |
||
69 | 48 | public function make(array $rules, array $messages = [], array $customAttributes = [], $selector = null) |
|
70 | { |
||
71 | $validator = $this->getValidatorInstance($rules, $messages, $customAttributes); |
||
72 | |||
73 | return $this->validator($validator, $selector); |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Get the validator instance for the request. |
||
78 | * |
||
79 | * @param array $rules |
||
80 | 72 | * @param array $messages |
|
81 | * @param array $customAttributes |
||
82 | 72 | * @return \Illuminate\Validation\Validator |
|
83 | */ |
||
84 | 72 | protected function getValidatorInstance(array $rules, array $messages = [], array $customAttributes = []) |
|
85 | 72 | { |
|
86 | 72 | $factory = $this->app->make(ValidationFactory::class); |
|
87 | |||
88 | 72 | $data = $this->getValidationData($rules, $customAttributes); |
|
89 | $validator = $factory->make($data, $rules, $messages, $customAttributes); |
||
90 | $validator->addCustomAttributes($customAttributes); |
||
91 | |||
92 | return $validator; |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Gets fake data when validator has wildcard rules. |
||
97 | 72 | * |
|
98 | * @param array $rules |
||
99 | * @param array $customAttributes |
||
100 | 48 | * @return array |
|
101 | 72 | */ |
|
102 | protected function getValidationData(array $rules, array $customAttributes = []) |
||
103 | 72 | { |
|
104 | $attributes = array_filter(array_keys($rules), function ($attribute) { |
||
105 | 24 | return $attribute !== '' && mb_strpos($attribute, '*') !== false; |
|
106 | }); |
||
107 | 24 | ||
108 | 72 | $attributes = array_merge(array_keys($customAttributes), $attributes); |
|
109 | $data = array_reduce($attributes, function ($data, $attribute) { |
||
110 | 72 | // Prevent wildcard rule being removed as an implicit attribute (not present in the data). |
|
111 | $attribute = str_replace('*', self::ASTERISK, $attribute); |
||
112 | |||
113 | Arr::set($data, $attribute, true); |
||
114 | |||
115 | return $data; |
||
116 | }, []); |
||
117 | |||
118 | return $data; |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | 24 | * Creates JsValidator instance based on FormRequest. |
|
123 | * |
||
124 | 24 | * @param $formRequest |
|
125 | 12 | * @param null|string $selector |
|
126 | * @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
||
127 | * |
||
128 | 24 | * @throws \Illuminate\Contracts\Container\BindingResolutionException |
|
129 | */ |
||
130 | 24 | public function formRequest($formRequest, $selector = null) |
|
131 | { |
||
132 | 24 | if (! is_object($formRequest)) { |
|
133 | $formRequest = $this->createFormRequest($formRequest); |
||
134 | 24 | } |
|
135 | |||
136 | if ($formRequest instanceof FormRequest) { |
||
137 | return $this->newFormRequestValidator($formRequest, $selector); |
||
138 | 24 | } |
|
139 | |||
140 | return $this->oldFormRequestValidator($formRequest, $selector); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Create form request validator. |
||
145 | 12 | * |
|
146 | * @param FormRequest $formRequest |
||
147 | 12 | * @param string $selector |
|
148 | 12 | * @return JavascriptValidator |
|
149 | 12 | */ |
|
150 | 12 | private function newFormRequestValidator($formRequest, $selector) |
|
151 | { |
||
152 | // Replace all rules with Noop rules which are checked client-side and always valid to true. |
||
153 | 12 | // This is important because jquery-validation expects fields under validation to have rules present. For |
|
154 | // example, if you mark a field as invalid without a defined rule, then unhighlight won't be called. |
||
155 | $rules = method_exists($formRequest, 'rules') ? $formRequest->rules() : []; |
||
0 ignored issues
–
show
|
|||
156 | foreach ($rules as $key => $value) { |
||
157 | $rules[$key] = 'proengsoft_noop'; |
||
158 | } |
||
159 | |||
160 | // This rule controls AJAX validation of all fields. |
||
161 | $rules['proengsoft_jsvalidation'] = RuleParser::FORM_REQUEST_RULE_NAME; |
||
162 | |||
163 | $baseValidator = $this->getValidatorInstance($rules); |
||
164 | 12 | ||
165 | return $this->validator($baseValidator, $selector); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Create a form request validator instance. |
||
170 | 12 | * |
|
171 | * @param IlluminateFormRequest $formRequest |
||
172 | 12 | * @param string $selector |
|
173 | 12 | * @return JavascriptValidator |
|
174 | */ |
||
175 | 12 | private function oldFormRequestValidator($formRequest, $selector) |
|
176 | 12 | { |
|
177 | $rules = method_exists($formRequest, 'rules') ? $this->app->call([$formRequest, 'rules']) : []; |
||
178 | 12 | ||
179 | 12 | $validator = $this->getValidatorInstance($rules, $formRequest->messages(), $formRequest->attributes()); |
|
180 | 12 | ||
181 | 12 | $jsValidator = $this->validator($validator, $selector); |
|
182 | |||
183 | 12 | if (method_exists($formRequest, 'withJsValidator')) { |
|
184 | $formRequest->withJsValidator($jsValidator); |
||
185 | } |
||
186 | |||
187 | return $jsValidator; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * @param string|array $class |
||
192 | * @return array |
||
193 | 72 | */ |
|
194 | protected function parseFormRequestName($class) |
||
195 | 72 | { |
|
196 | $params = []; |
||
197 | if (is_array($class)) { |
||
198 | $params = empty($class[1]) ? $params : $class[1]; |
||
199 | $class = $class[0]; |
||
200 | } |
||
201 | |||
202 | return [$class, $params]; |
||
203 | } |
||
204 | |||
205 | 72 | /** |
|
206 | * Creates and initializes an Form Request instance. |
||
207 | 72 | * |
|
208 | 72 | * @param string $class |
|
209 | 72 | * @return IlluminateFormRequest |
|
210 | * |
||
211 | 72 | * @throws \Illuminate\Contracts\Container\BindingResolutionException |
|
212 | 72 | */ |
|
213 | 72 | protected function createFormRequest($class) |
|
214 | { |
||
215 | 72 | /* |
|
216 | * @var $formRequest \Illuminate\Foundation\Http\FormRequest |
||
217 | 72 | * @var $request Request |
|
218 | */ |
||
219 | 72 | [$class, $params] = $this->parseFormRequestName($class); |
|
0 ignored issues
–
show
|
|||
220 | |||
221 | $request = $this->app->__get('request'); |
||
222 | $formRequest = $this->app->build($class, $params); |
||
0 ignored issues
–
show
The call to
Container::build() has too many arguments starting with $params .
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 ![]() |
|||
223 | |||
224 | if ($session = $request->getSession()) { |
||
225 | $formRequest->setLaravelSession($session); |
||
226 | } |
||
227 | 72 | $formRequest->setUserResolver($request->getUserResolver()); |
|
228 | $formRequest->setRouteResolver($request->getRouteResolver()); |
||
229 | 72 | $formRequest->setContainer($this->app); |
|
230 | 72 | $formRequest->query = $request->query; |
|
231 | 12 | ||
232 | return $formRequest; |
||
233 | } |
||
234 | 72 | ||
235 | 12 | /** |
|
236 | * Creates JsValidator instance based on Validator. |
||
237 | * |
||
238 | 72 | * @param \Illuminate\Validation\Validator $validator |
|
239 | * @param null|string $selector |
||
240 | * @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
||
241 | */ |
||
242 | public function validator(Validator $validator, $selector = null) |
||
243 | { |
||
244 | return $this->jsValidator($validator, $selector); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Creates JsValidator instance based on Validator. |
||
249 | * |
||
250 | * @param \Illuminate\Validation\Validator $validator |
||
251 | * @param null|string $selector |
||
252 | * @return \Proengsoft\JsValidation\Javascript\JavascriptValidator |
||
253 | */ |
||
254 | protected function jsValidator(Validator $validator, $selector = null) |
||
255 | { |
||
256 | $remote = ! $this->options['disable_remote_validation']; |
||
257 | $view = $this->options['view']; |
||
258 | $selector = is_null($selector) ? $this->options['form_selector'] : $selector; |
||
259 | $ignore = $this->options['ignore']; |
||
260 | |||
261 | $delegated = new DelegatedValidator($validator, new ValidationRuleParserProxy($validator->getData())); |
||
262 | $rules = new RuleParser($delegated, $this->getSessionToken()); |
||
263 | $messages = new MessageParser($delegated, isset($this->options['escape']) ? $this->options['escape'] : false); |
||
264 | |||
265 | $jsValidator = new ValidatorHandler($rules, $messages); |
||
266 | |||
267 | return new JavascriptValidator($jsValidator, compact('view', 'selector', 'remote', 'ignore')); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Get and encrypt token from session store. |
||
272 | * |
||
273 | * @return null|string |
||
274 | */ |
||
275 | protected function getSessionToken() |
||
276 | { |
||
277 | $token = null; |
||
278 | if ($session = $this->app->__get('session')) { |
||
279 | $token = $session->token(); |
||
280 | } |
||
281 | |||
282 | if ($encrypter = $this->app->__get('encrypter')) { |
||
283 | $token = $encrypter->encrypt($token); |
||
284 | } |
||
285 | |||
286 | return $token; |
||
287 | } |
||
288 | } |
||
289 |
If you implement
__call
and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.This is often the case, when
__call
is implemented by a parent class and only the child class knows which methods exist: