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 | * Part of the Joomla Framework Form Package |
||
4 | * |
||
5 | * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved. |
||
6 | * @license GNU General Public License version 2 or later; see LICENSE |
||
7 | */ |
||
8 | |||
9 | namespace Joomla\Form; |
||
10 | |||
11 | use Joomla\Filter; |
||
12 | use Joomla\Uri\Uri; |
||
13 | use Joomla\Language\Language; |
||
14 | use Joomla\Language\Text; |
||
15 | use Joomla\Filesystem\Path; |
||
16 | use Joomla\Registry\Registry; |
||
17 | use Joomla\Utilities\ArrayHelper; |
||
18 | |||
19 | /** |
||
20 | * Form Class for the Joomla Framework. |
||
21 | * |
||
22 | * This class implements a robust API for constructing, populating, filtering, and validating forms. |
||
23 | * It uses XML definitions to construct form fields and a variety of field and rule classes to |
||
24 | * render and validate the form. |
||
25 | * |
||
26 | * @link http://www.w3.org/TR/html4/interact/forms.html |
||
27 | * @link http://www.w3.org/TR/html5/forms.html |
||
28 | * @since 1.0 |
||
29 | * @deprecated The joomla/form package is deprecated |
||
30 | */ |
||
31 | class Form |
||
32 | { |
||
33 | /** |
||
34 | * The Registry data store for form fields during display. |
||
35 | * |
||
36 | * @var object |
||
37 | * @since 1.0 |
||
38 | */ |
||
39 | protected $data; |
||
40 | |||
41 | /** |
||
42 | * The form object errors array. |
||
43 | * |
||
44 | * @var array |
||
45 | * @since 1.0 |
||
46 | */ |
||
47 | protected $errors = array(); |
||
48 | |||
49 | /** |
||
50 | * The name of the form instance. |
||
51 | * |
||
52 | * @var string |
||
53 | * @since 1.0 |
||
54 | */ |
||
55 | protected $name; |
||
56 | |||
57 | /** |
||
58 | * The form object options for use in rendering and validation. |
||
59 | * |
||
60 | * @var array |
||
61 | * @since 1.0 |
||
62 | */ |
||
63 | protected $options = array(); |
||
64 | |||
65 | /** |
||
66 | * The form XML definition. |
||
67 | * |
||
68 | * @var \SimpleXMLElement |
||
69 | * @since 1.0 |
||
70 | */ |
||
71 | protected $xml; |
||
72 | |||
73 | /** |
||
74 | * Form instances. |
||
75 | * |
||
76 | * @var array |
||
77 | * @since 1.0 |
||
78 | */ |
||
79 | protected static $forms = array(); |
||
80 | |||
81 | /** |
||
82 | * Method to instantiate the form object. |
||
83 | * |
||
84 | * @param string $name The name of the form. |
||
85 | * @param array $options An array of form options. |
||
86 | * |
||
87 | * @since 1.0 |
||
88 | */ |
||
89 | public function __construct($name, array $options = array()) |
||
90 | { |
||
91 | // Set the name for the form. |
||
92 | $this->name = $name; |
||
93 | |||
94 | // Initialise the Registry data. |
||
95 | $this->data = new Registry; |
||
96 | |||
97 | // Set the options if specified. |
||
98 | $this->options['control'] = isset($options['control']) ? $options['control'] : false; |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Method to bind data to the form. |
||
103 | * |
||
104 | * @param mixed $data An array or object of data to bind to the form. |
||
105 | * |
||
106 | * @return boolean True on success. |
||
107 | * |
||
108 | * @since 1.0 |
||
109 | */ |
||
110 | public function bind($data) |
||
111 | { |
||
112 | // Make sure there is a valid Form XML document. |
||
113 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
114 | { |
||
115 | return false; |
||
116 | } |
||
117 | |||
118 | // The data must be an object or array. |
||
119 | if (!is_object($data) && !is_array($data)) |
||
120 | { |
||
121 | return false; |
||
122 | } |
||
123 | |||
124 | // Convert the object to an array. |
||
125 | if ($data instanceof Registry) |
||
126 | { |
||
127 | $data = $data->toArray(); |
||
128 | } |
||
129 | elseif (is_object($data)) |
||
130 | { |
||
131 | $data = (array) $data; |
||
132 | } |
||
133 | |||
134 | // Process the input data. |
||
135 | foreach ($data as $k => $v) |
||
136 | { |
||
137 | if ($this->findField($k)) |
||
138 | { |
||
139 | // If the field exists set the value. |
||
140 | $this->data->set($k, $v); |
||
141 | } |
||
142 | elseif (is_object($v) || ArrayHelper::isAssociative($v)) |
||
143 | { |
||
144 | // If the value is an object or an associative array hand it off to the recursive bind level method. |
||
145 | $this->bindLevel($k, $v); |
||
146 | } |
||
147 | } |
||
148 | |||
149 | return true; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Method to bind data to the form for the group level. |
||
154 | * |
||
155 | * @param string $group The dot-separated form group path on which to bind the data. |
||
156 | * @param mixed $data An array or object of data to bind to the form for the group level. |
||
157 | * |
||
158 | * @return void |
||
159 | * |
||
160 | * @since 1.0 |
||
161 | */ |
||
162 | protected function bindLevel($group, $data) |
||
163 | { |
||
164 | // Ensure the input data is an array. |
||
165 | settype($data, 'array'); |
||
166 | |||
167 | // Process the input data. |
||
168 | foreach ($data as $k => $v) |
||
169 | { |
||
170 | if ($this->findField($k, $group)) |
||
171 | { |
||
172 | // If the field exists set the value. |
||
173 | $this->data->set($group . '.' . $k, $v); |
||
174 | } |
||
175 | elseif (is_object($v) || ArrayHelper::isAssociative($v)) |
||
176 | { |
||
177 | // If the value is an object or an associative array, hand it off to the recursive bind level method |
||
178 | $this->bindLevel($group . '.' . $k, $v); |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Method to filter the form data. |
||
185 | * |
||
186 | * @param array $data An array of field values to filter. |
||
187 | * @param string $group The dot-separated form group path on which to filter the fields. |
||
188 | * |
||
189 | * @return mixed Array or false. |
||
190 | * |
||
191 | * @since 1.0 |
||
192 | */ |
||
193 | public function filter($data, $group = null) |
||
194 | { |
||
195 | // Make sure there is a valid Form XML document. |
||
196 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
197 | { |
||
198 | return false; |
||
199 | } |
||
200 | |||
201 | $input = new Registry($data); |
||
202 | $output = new Registry; |
||
203 | |||
204 | // Get the fields for which to filter the data. |
||
205 | $fields = $this->findFieldsByGroup($group); |
||
206 | |||
207 | if (!$fields) |
||
208 | { |
||
209 | // PANIC! |
||
210 | return false; |
||
211 | } |
||
212 | |||
213 | // Filter the fields. |
||
214 | foreach ($fields as $field) |
||
215 | { |
||
216 | $name = (string) $field['name']; |
||
217 | |||
218 | // Get the field groups for the element. |
||
219 | $attrs = $field->xpath('ancestor::fields[@name]/@name'); |
||
220 | $groups = array_map('strval', $attrs ? $attrs : array()); |
||
221 | $group = implode('.', $groups); |
||
222 | |||
223 | // Get the field value from the data input. |
||
224 | if ($group) |
||
225 | { |
||
226 | // Filter the value if it exists. |
||
227 | if ($input->exists($group . '.' . $name)) |
||
228 | { |
||
229 | $output->set($group . '.' . $name, $this->filterField($field, $input->get($group . '.' . $name, (string) $field['default']))); |
||
230 | } |
||
231 | } |
||
232 | else |
||
233 | { |
||
234 | // Filter the value if it exists. |
||
235 | if ($input->exists($name)) |
||
236 | { |
||
237 | $output->set($name, $this->filterField($field, $input->get($name, (string) $field['default']))); |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | |||
242 | return $output->toArray(); |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Return all errors, if any. |
||
247 | * |
||
248 | * @return array Array of error messages or RuntimeException objects. |
||
249 | * |
||
250 | * @since 1.0 |
||
251 | */ |
||
252 | public function getErrors() |
||
253 | { |
||
254 | return $this->errors; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Method to get a form field represented as a Field object. |
||
259 | * |
||
260 | * @param string $name The name of the form field. |
||
261 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
262 | * @param mixed $value The optional value to use as the default for the field. |
||
263 | * |
||
264 | * @return mixed The Field object for the field or boolean false on error. |
||
265 | * |
||
266 | * @since 1.0 |
||
267 | */ |
||
268 | public function getField($name, $group = null, $value = null) |
||
269 | { |
||
270 | // Make sure there is a valid Form XML document. |
||
271 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
272 | { |
||
273 | return false; |
||
274 | } |
||
275 | |||
276 | // Attempt to find the field by name and group. |
||
277 | $element = $this->findField($name, $group); |
||
278 | |||
279 | // If the field element was not found return false. |
||
280 | if (!$element) |
||
281 | { |
||
282 | return false; |
||
283 | } |
||
284 | |||
285 | return $this->loadField($element, $group, $value); |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Method to get an attribute value from a field XML element. If the attribute doesn't exist or |
||
290 | * is null then the optional default value will be used. |
||
291 | * |
||
292 | * @param string $name The name of the form field for which to get the attribute value. |
||
293 | * @param string $attribute The name of the attribute for which to get a value. |
||
294 | * @param mixed $default The optional default value to use if no attribute value exists. |
||
295 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
296 | * |
||
297 | * @return mixed The attribute value for the field. |
||
298 | * |
||
299 | * @since 1.0 |
||
300 | * @throws \UnexpectedValueException |
||
301 | */ |
||
302 | public function getFieldAttribute($name, $attribute, $default = null, $group = null) |
||
303 | { |
||
304 | // Make sure there is a valid Form XML document. |
||
305 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
306 | { |
||
307 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
308 | } |
||
309 | |||
310 | // Find the form field element from the definition. |
||
311 | $element = $this->findField($name, $group); |
||
312 | |||
313 | // If the element exists and the attribute exists for the field return the attribute value. |
||
314 | if (($element instanceof \SimpleXMLElement) && ((string) $element[$attribute])) |
||
315 | { |
||
316 | return (string) $element[$attribute]; |
||
317 | } |
||
318 | else |
||
319 | // Otherwise return the given default value. |
||
320 | { |
||
321 | return $default; |
||
322 | } |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Method to get an array of FormField objects in a given fieldset by name. If no name is |
||
327 | * given then all fields are returned. |
||
328 | * |
||
329 | * @param string $set The optional name of the fieldset. |
||
330 | * |
||
331 | * @return array The array of FormField objects in the fieldset. |
||
332 | * |
||
333 | * @since 1.0 |
||
334 | */ |
||
335 | View Code Duplication | public function getFieldset($set = null) |
|
0 ignored issues
–
show
|
|||
336 | { |
||
337 | $fields = array(); |
||
338 | |||
339 | // Get all of the field elements in the fieldset. |
||
340 | if ($set) |
||
0 ignored issues
–
show
The expression
$set of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
341 | { |
||
342 | $elements = $this->findFieldsByFieldset($set); |
||
343 | } |
||
344 | else |
||
345 | // Get all fields. |
||
346 | { |
||
347 | $elements = $this->findFieldsByGroup(); |
||
348 | } |
||
349 | |||
350 | // If no field elements were found return empty. |
||
351 | if (empty($elements)) |
||
352 | { |
||
353 | return $fields; |
||
354 | } |
||
355 | |||
356 | // Build the result array from the found field elements. |
||
357 | foreach ($elements as $element) |
||
358 | { |
||
359 | // Get the field groups for the element. |
||
360 | $attrs = $element->xpath('ancestor::fields[@name]/@name'); |
||
361 | $groups = array_map('strval', $attrs ? $attrs : array()); |
||
362 | $group = implode('.', $groups); |
||
363 | |||
364 | // If the field is successfully loaded add it to the result array. |
||
365 | if ($field = $this->loadField($element, $group)) |
||
366 | { |
||
367 | $fields[$field->id] = $field; |
||
368 | } |
||
369 | } |
||
370 | |||
371 | return $fields; |
||
372 | } |
||
373 | |||
374 | /** |
||
375 | * Method to get an array of fieldset objects optionally filtered over a given field group. |
||
376 | * |
||
377 | * @param string $group The dot-separated form group path on which to filter the fieldsets. |
||
378 | * |
||
379 | * @return array The array of fieldset objects. |
||
380 | * |
||
381 | * @since 1.0 |
||
382 | */ |
||
383 | public function getFieldsets($group = null) |
||
384 | { |
||
385 | $fieldsets = array(); |
||
386 | $sets = array(); |
||
387 | |||
388 | // Make sure there is a valid Form XML document. |
||
389 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
390 | { |
||
391 | return $fieldsets; |
||
392 | } |
||
393 | |||
394 | if ($group) |
||
0 ignored issues
–
show
The expression
$group of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
395 | { |
||
396 | // Get the fields elements for a given group. |
||
397 | $elements = &$this->findGroup($group); |
||
398 | |||
399 | View Code Duplication | foreach ($elements as &$element) |
|
0 ignored issues
–
show
The expression
$elements of type false|array is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
400 | { |
||
401 | // Get an array of <fieldset /> elements and fieldset attributes within the fields element. |
||
402 | if ($tmp = $element->xpath('descendant::fieldset[@name] | descendant::field[@fieldset]/@fieldset')) |
||
403 | { |
||
404 | $sets = array_merge($sets, (array) $tmp); |
||
405 | } |
||
406 | } |
||
407 | } |
||
408 | else |
||
409 | { |
||
410 | // Get an array of <fieldset /> elements and fieldset attributes. |
||
411 | $sets = $this->xml->xpath('//fieldset[@name] | //field[@fieldset]/@fieldset'); |
||
412 | } |
||
413 | |||
414 | // If no fieldsets are found return empty. |
||
415 | if (empty($sets)) |
||
416 | { |
||
417 | return $fieldsets; |
||
418 | } |
||
419 | |||
420 | // Process each found fieldset. |
||
421 | foreach ($sets as $set) |
||
422 | { |
||
423 | // Are we dealing with a fieldset element? |
||
424 | if ((string) $set['name']) |
||
425 | { |
||
426 | // Only create it if it doesn't already exist. |
||
427 | if (empty($fieldsets[(string) $set['name']])) |
||
428 | { |
||
429 | // Build the fieldset object. |
||
430 | $fieldset = (object) array('name' => '', 'label' => '', 'description' => ''); |
||
431 | |||
432 | foreach ($set->attributes() as $name => $value) |
||
433 | { |
||
434 | $fieldset->$name = (string) $value; |
||
435 | } |
||
436 | |||
437 | // Add the fieldset object to the list. |
||
438 | $fieldsets[$fieldset->name] = $fieldset; |
||
439 | } |
||
440 | } |
||
441 | else |
||
442 | // Must be dealing with a fieldset attribute. |
||
443 | { |
||
444 | // Only create it if it doesn't already exist. |
||
445 | if (empty($fieldsets[(string) $set])) |
||
446 | { |
||
447 | // Attempt to get the fieldset element for data (throughout the entire form document). |
||
448 | $tmp = $this->xml->xpath('//fieldset[@name="' . (string) $set . '"]'); |
||
449 | |||
450 | // If no element was found, build a very simple fieldset object. |
||
451 | if (empty($tmp)) |
||
452 | { |
||
453 | $fieldset = (object) array('name' => (string) $set, 'label' => '', 'description' => ''); |
||
454 | } |
||
455 | else |
||
456 | // Build the fieldset object from the element. |
||
457 | { |
||
458 | $fieldset = (object) array('name' => '', 'label' => '', 'description' => ''); |
||
459 | |||
460 | foreach ($tmp[0]->attributes() as $name => $value) |
||
461 | { |
||
462 | $fieldset->$name = (string) $value; |
||
463 | } |
||
464 | } |
||
465 | |||
466 | // Add the fieldset object to the list. |
||
467 | $fieldsets[$fieldset->name] = $fieldset; |
||
468 | } |
||
469 | } |
||
470 | } |
||
471 | |||
472 | return $fieldsets; |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * Method to get the form control. This string serves as a container for all form fields. For |
||
477 | * example, if there is a field named 'foo' and a field named 'bar' and the form control is |
||
478 | * empty the fields will be rendered like: <input name="foo" /> and <input name="bar" />. If |
||
479 | * the form control is set to 'joomla' however, the fields would be rendered like: |
||
480 | * <input name="joomla[foo]" /> and <input name="joomla[bar]" />. |
||
481 | * |
||
482 | * @return string The form control string. |
||
483 | * |
||
484 | * @since 1.0 |
||
485 | */ |
||
486 | public function getFormControl() |
||
487 | { |
||
488 | return (string) $this->options['control']; |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Method to get an array of FormField objects in a given field group by name. |
||
493 | * |
||
494 | * @param string $group The dot-separated form group path for which to get the form fields. |
||
495 | * @param boolean $nested True to also include fields in nested groups that are inside of the |
||
496 | * group for which to find fields. |
||
497 | * |
||
498 | * @return array The array of FormField objects in the field group. |
||
499 | * |
||
500 | * @since 1.0 |
||
501 | */ |
||
502 | View Code Duplication | public function getGroup($group, $nested = false) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
503 | { |
||
504 | $fields = array(); |
||
505 | |||
506 | // Get all of the field elements in the field group. |
||
507 | $elements = $this->findFieldsByGroup($group, $nested); |
||
508 | |||
509 | // If no field elements were found return empty. |
||
510 | if (empty($elements)) |
||
511 | { |
||
512 | return $fields; |
||
513 | } |
||
514 | |||
515 | // Build the result array from the found field elements. |
||
516 | foreach ($elements as $element) |
||
517 | { |
||
518 | // Get the field groups for the element. |
||
519 | $attrs = $element->xpath('ancestor::fields[@name]/@name'); |
||
520 | $groups = array_map('strval', $attrs ? $attrs : array()); |
||
521 | $group = implode('.', $groups); |
||
522 | |||
523 | // If the field is successfully loaded add it to the result array. |
||
524 | if ($field = $this->loadField($element, $group)) |
||
525 | { |
||
526 | $fields[$field->id] = $field; |
||
527 | } |
||
528 | } |
||
529 | |||
530 | return $fields; |
||
531 | } |
||
532 | |||
533 | /** |
||
534 | * Method to get a form field markup for the field input. |
||
535 | * |
||
536 | * @param string $name The name of the form field. |
||
537 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
538 | * @param mixed $value The optional value to use as the default for the field. |
||
539 | * |
||
540 | * @return string The form field markup. |
||
541 | * |
||
542 | * @since 1.0 |
||
543 | */ |
||
544 | public function getInput($name, $group = null, $value = null) |
||
545 | { |
||
546 | // Attempt to get the form field. |
||
547 | if ($field = $this->getField($name, $group, $value)) |
||
548 | { |
||
549 | return $field->input; |
||
550 | } |
||
551 | |||
552 | return ''; |
||
553 | } |
||
554 | |||
555 | /** |
||
556 | * Method to get the label for a field input. |
||
557 | * |
||
558 | * @param string $name The name of the form field. |
||
559 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
560 | * |
||
561 | * @return string The form field label. |
||
562 | * |
||
563 | * @since 1.0 |
||
564 | */ |
||
565 | public function getLabel($name, $group = null) |
||
566 | { |
||
567 | // Attempt to get the form field. |
||
568 | if ($field = $this->getField($name, $group)) |
||
569 | { |
||
570 | return $field->label; |
||
571 | } |
||
572 | |||
573 | return ''; |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Method to get the form name. |
||
578 | * |
||
579 | * @return string The name of the form. |
||
580 | * |
||
581 | * @since 1.0 |
||
582 | */ |
||
583 | public function getName() |
||
584 | { |
||
585 | return $this->name; |
||
586 | } |
||
587 | |||
588 | /** |
||
589 | * Method to get the value of a field. |
||
590 | * |
||
591 | * @param string $name The name of the field for which to get the value. |
||
592 | * @param string $group The optional dot-separated form group path on which to get the value. |
||
593 | * @param mixed $default The optional default value of the field value is empty. |
||
594 | * |
||
595 | * @return mixed The value of the field or the default value if empty. |
||
596 | * |
||
597 | * @since 1.0 |
||
598 | */ |
||
599 | public function getValue($name, $group = null, $default = null) |
||
600 | { |
||
601 | // If a group is set use it. |
||
602 | if ($group) |
||
0 ignored issues
–
show
The expression
$group of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
603 | { |
||
604 | $return = $this->data->get($group . '.' . $name, $default); |
||
605 | } |
||
606 | else |
||
607 | { |
||
608 | $return = $this->data->get($name, $default); |
||
609 | } |
||
610 | |||
611 | return $return; |
||
612 | } |
||
613 | |||
614 | /** |
||
615 | * Method to load the form description from an XML string or object. |
||
616 | * |
||
617 | * The replace option works per field. If a field being loaded already exists in the current |
||
618 | * form definition then the behavior or load will vary depending upon the replace flag. If it |
||
619 | * is set to true, then the existing field will be replaced in its exact location by the new |
||
620 | * field being loaded. If it is false, then the new field being loaded will be ignored and the |
||
621 | * method will move on to the next field to load. |
||
622 | * |
||
623 | * @param string $data The name of an XML string or object. |
||
624 | * @param string $replace Flag to toggle whether form fields should be replaced if a field |
||
625 | * already exists with the same group/name. |
||
626 | * @param string $xpath An optional xpath to search for the fields. |
||
627 | * |
||
628 | * @return boolean True on success, false otherwise. |
||
629 | * |
||
630 | * @since 1.0 |
||
631 | */ |
||
632 | public function load($data, $replace = true, $xpath = false) |
||
633 | { |
||
634 | // If the data to load isn't already an XML element or string return false. |
||
635 | if ((!($data instanceof \SimpleXMLElement)) && (!is_string($data))) |
||
636 | { |
||
637 | return false; |
||
638 | } |
||
639 | |||
640 | // Attempt to load the XML if a string. |
||
641 | if (is_string($data)) |
||
642 | { |
||
643 | try |
||
644 | { |
||
645 | $data = new \SimpleXMLElement($data); |
||
646 | } |
||
647 | catch (\Exception $e) |
||
648 | { |
||
649 | return false; |
||
650 | } |
||
651 | |||
652 | // Make sure the XML loaded correctly. |
||
653 | if (!$data) |
||
654 | { |
||
655 | return false; |
||
656 | } |
||
657 | } |
||
658 | |||
659 | // If we have no XML definition at this point let's make sure we get one. |
||
660 | if (empty($this->xml)) |
||
661 | { |
||
662 | // If no XPath query is set to search for fields, and we have a <form />, set it and return. |
||
663 | if (!$xpath && ($data->getName() == 'form')) |
||
0 ignored issues
–
show
The expression
$xpath of type false|string is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
664 | { |
||
665 | $this->xml = $data; |
||
666 | |||
667 | // Synchronize any paths found in the load. |
||
668 | $this->syncPaths(); |
||
669 | |||
670 | return true; |
||
671 | } |
||
672 | else |
||
673 | // Create a root element for the form. |
||
674 | { |
||
675 | $this->xml = new \SimpleXMLElement('<form></form>'); |
||
676 | } |
||
677 | } |
||
678 | |||
679 | // Get the XML elements to load. |
||
680 | $elements = array(); |
||
681 | |||
682 | if ($xpath) |
||
0 ignored issues
–
show
The expression
$xpath of type false|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
683 | { |
||
684 | $elements = $data->xpath($xpath); |
||
685 | } |
||
686 | elseif ($data->getName() == 'form') |
||
687 | { |
||
688 | $elements = $data->children(); |
||
689 | } |
||
690 | |||
691 | // If there is nothing to load return true. |
||
692 | if (empty($elements)) |
||
693 | { |
||
694 | return true; |
||
695 | } |
||
696 | |||
697 | // Load the found form elements. |
||
698 | foreach ($elements as $element) |
||
699 | { |
||
700 | // Get an array of fields with the correct name. |
||
701 | $fields = $element->xpath('descendant-or-self::field'); |
||
702 | |||
703 | foreach ($fields as $field) |
||
704 | { |
||
705 | // Get the group names as strings for ancestor fields elements. |
||
706 | $attrs = $field->xpath('ancestor::fields[@name]/@name'); |
||
707 | $groups = array_map('strval', $attrs ? $attrs : array()); |
||
708 | |||
709 | // Check to see if the field exists in the current form. |
||
710 | if ($current = $this->findField((string) $field['name'], implode('.', $groups))) |
||
711 | { |
||
712 | // If set to replace found fields, replace the data and remove the field so we don't add it twice. |
||
713 | if ($replace) |
||
714 | { |
||
715 | $olddom = dom_import_simplexml($current); |
||
716 | $loadeddom = dom_import_simplexml($field); |
||
717 | $addeddom = $olddom->ownerDocument->importNode($loadeddom); |
||
718 | $olddom->parentNode->replaceChild($addeddom, $olddom); |
||
719 | $loadeddom->parentNode->removeChild($loadeddom); |
||
720 | } |
||
721 | else |
||
722 | { |
||
723 | unset($field); |
||
724 | } |
||
725 | } |
||
726 | } |
||
727 | |||
728 | // Merge the new field data into the existing XML document. |
||
729 | self::addNode($this->xml, $element); |
||
730 | } |
||
731 | |||
732 | // Synchronize any paths found in the load. |
||
733 | $this->syncPaths(); |
||
734 | |||
735 | return true; |
||
736 | } |
||
737 | |||
738 | /** |
||
739 | * Method to load the form description from an XML file. |
||
740 | * |
||
741 | * The reset option works on a group basis. If the XML file references |
||
742 | * groups that have already been created they will be replaced with the |
||
743 | * fields in the new XML file unless the $reset parameter has been set |
||
744 | * to false. |
||
745 | * |
||
746 | * @param string $file The filesystem path of an XML file. |
||
747 | * @param string $reset Flag to toggle whether form fields should be replaced if a field |
||
748 | * already exists with the same group/name. |
||
749 | * @param string $xpath An optional xpath to search for the fields. |
||
750 | * |
||
751 | * @return boolean True on success, false otherwise. |
||
752 | * |
||
753 | * @since 1.0 |
||
754 | */ |
||
755 | public function loadFile($file, $reset = true, $xpath = false) |
||
756 | { |
||
757 | // Check to see if the path is an absolute path. |
||
758 | if (!is_file($file)) |
||
759 | { |
||
760 | // Not an absolute path so let's attempt to find one using JPath. |
||
761 | $file = Path::find(FormHelper::addFormPath(), strtolower($file) . '.xml'); |
||
762 | |||
763 | // If unable to find the file return false. |
||
764 | if (!$file) |
||
0 ignored issues
–
show
The expression
$file of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
765 | { |
||
766 | return false; |
||
767 | } |
||
768 | } |
||
769 | |||
770 | // Attempt to load the XML file. |
||
771 | $xml = simplexml_load_file($file); |
||
772 | |||
773 | return $this->load($xml, $reset, $xpath); |
||
774 | } |
||
775 | |||
776 | /** |
||
777 | * Method to remove a field from the form definition. |
||
778 | * |
||
779 | * @param string $name The name of the form field for which remove. |
||
780 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
781 | * |
||
782 | * @return boolean True on success. |
||
783 | * |
||
784 | * @since 1.0 |
||
785 | * @throws \UnexpectedValueException |
||
786 | */ |
||
787 | View Code Duplication | public function removeField($name, $group = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
788 | { |
||
789 | // Make sure there is a valid Form XML document. |
||
790 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
791 | { |
||
792 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
793 | } |
||
794 | |||
795 | // Find the form field element from the definition. |
||
796 | $element = $this->findField($name, $group); |
||
797 | |||
798 | // If the element exists remove it from the form definition. |
||
799 | if ($element instanceof \SimpleXMLElement) |
||
800 | { |
||
801 | $dom = dom_import_simplexml($element); |
||
802 | $dom->parentNode->removeChild($dom); |
||
803 | } |
||
804 | |||
805 | return true; |
||
806 | } |
||
807 | |||
808 | /** |
||
809 | * Method to remove a group from the form definition. |
||
810 | * |
||
811 | * @param string $group The dot-separated form group path for the group to remove. |
||
812 | * |
||
813 | * @return boolean True on success. |
||
814 | * |
||
815 | * @since 1.0 |
||
816 | * @throws \UnexpectedValueException |
||
817 | */ |
||
818 | public function removeGroup($group) |
||
819 | { |
||
820 | // Make sure there is a valid Form XML document. |
||
821 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
822 | { |
||
823 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
824 | } |
||
825 | |||
826 | // Get the fields elements for a given group. |
||
827 | $elements = &$this->findGroup($group); |
||
828 | |||
829 | foreach ($elements as &$element) |
||
0 ignored issues
–
show
The expression
$elements of type false|array is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
830 | { |
||
831 | $dom = dom_import_simplexml($element); |
||
832 | $dom->parentNode->removeChild($dom); |
||
833 | } |
||
834 | |||
835 | return true; |
||
836 | } |
||
837 | |||
838 | /** |
||
839 | * Method to reset the form data store and optionally the form XML definition. |
||
840 | * |
||
841 | * @param boolean $xml True to also reset the XML form definition. |
||
842 | * |
||
843 | * @return boolean True on success. |
||
844 | * |
||
845 | * @since 1.0 |
||
846 | */ |
||
847 | public function reset($xml = false) |
||
848 | { |
||
849 | unset($this->data); |
||
850 | $this->data = new Registry; |
||
851 | |||
852 | if ($xml) |
||
853 | { |
||
854 | unset($this->xml); |
||
855 | $this->xml = new \SimpleXMLElement('<form></form>'); |
||
856 | } |
||
857 | |||
858 | return true; |
||
859 | } |
||
860 | |||
861 | /** |
||
862 | * Method to set a field XML element to the form definition. If the replace flag is set then |
||
863 | * the field will be set whether it already exists or not. If it isn't set, then the field |
||
864 | * will not be replaced if it already exists. |
||
865 | * |
||
866 | * @param \SimpleXMLElement $element The XML element object representation of the form field. |
||
867 | * @param string $group The optional dot-separated form group path on which to set the field. |
||
868 | * @param boolean $replace True to replace an existing field if one already exists. |
||
869 | * |
||
870 | * @return boolean True on success. |
||
871 | * |
||
872 | * @since 1.0 |
||
873 | * @throws \UnexpectedValueException |
||
874 | */ |
||
875 | public function setField(\SimpleXMLElement $element, $group = null, $replace = true) |
||
876 | { |
||
877 | // Make sure there is a valid Form XML document. |
||
878 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
879 | { |
||
880 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
881 | } |
||
882 | |||
883 | // Find the form field element from the definition. |
||
884 | $old = $this->findField((string) $element['name'], $group); |
||
885 | |||
886 | // If an existing field is found and replace flag is false do nothing and return true. |
||
887 | if (!$replace && !empty($old)) |
||
888 | { |
||
889 | return true; |
||
890 | } |
||
891 | |||
892 | // If an existing field is found and replace flag is true remove the old field. |
||
893 | if ($replace && !empty($old) && ($old instanceof \SimpleXMLElement)) |
||
894 | { |
||
895 | $dom = dom_import_simplexml($old); |
||
896 | $dom->parentNode->removeChild($dom); |
||
897 | } |
||
898 | |||
899 | // If no existing field is found find a group element and add the field as a child of it. |
||
900 | if ($group) |
||
0 ignored issues
–
show
The expression
$group of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
901 | { |
||
902 | // Get the fields elements for a given group. |
||
903 | $fields = &$this->findGroup($group); |
||
904 | |||
905 | // If an appropriate fields element was found for the group, add the element. |
||
906 | if (isset($fields[0]) && ($fields[0] instanceof \SimpleXMLElement)) |
||
907 | { |
||
908 | self::addNode($fields[0], $element); |
||
909 | } |
||
910 | } |
||
911 | else |
||
912 | { |
||
913 | // Set the new field to the form. |
||
914 | self::addNode($this->xml, $element); |
||
915 | } |
||
916 | |||
917 | // Synchronize any paths found in the load. |
||
918 | $this->syncPaths(); |
||
919 | |||
920 | return true; |
||
921 | } |
||
922 | |||
923 | /** |
||
924 | * Method to set an attribute value for a field XML element. |
||
925 | * |
||
926 | * @param string $name The name of the form field for which to set the attribute value. |
||
927 | * @param string $attribute The name of the attribute for which to set a value. |
||
928 | * @param mixed $value The value to set for the attribute. |
||
929 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
930 | * |
||
931 | * @return boolean True on success. |
||
932 | * |
||
933 | * @since 1.0 |
||
934 | * @throws \UnexpectedValueException |
||
935 | */ |
||
936 | View Code Duplication | public function setFieldAttribute($name, $attribute, $value, $group = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
937 | { |
||
938 | // Make sure there is a valid Form XML document. |
||
939 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
940 | { |
||
941 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
942 | } |
||
943 | |||
944 | // Find the form field element from the definition. |
||
945 | $element = $this->findField($name, $group); |
||
946 | |||
947 | // If the element doesn't exist return false. |
||
948 | if (!($element instanceof \SimpleXMLElement)) |
||
949 | { |
||
950 | return false; |
||
951 | } |
||
952 | else |
||
953 | // Otherwise set the attribute and return true. |
||
954 | { |
||
955 | $element[$attribute] = $value; |
||
956 | |||
957 | // Synchronize any paths found in the load. |
||
958 | $this->syncPaths(); |
||
959 | |||
960 | return true; |
||
961 | } |
||
962 | } |
||
963 | |||
964 | /** |
||
965 | * Method to set some field XML elements to the form definition. If the replace flag is set then |
||
966 | * the fields will be set whether they already exists or not. If it isn't set, then the fields |
||
967 | * will not be replaced if they already exist. |
||
968 | * |
||
969 | * @param array &$elements The array of XML element object representations of the form fields. |
||
970 | * @param string $group The optional dot-separated form group path on which to set the fields. |
||
971 | * @param boolean $replace True to replace existing fields if they already exist. |
||
972 | * |
||
973 | * @return boolean True on success. |
||
974 | * |
||
975 | * @since 1.0 |
||
976 | * @throws \UnexpectedValueException |
||
977 | */ |
||
978 | public function setFields(&$elements, $group = null, $replace = true) |
||
979 | { |
||
980 | // Make sure there is a valid Form XML document. |
||
981 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
982 | { |
||
983 | throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); |
||
984 | } |
||
985 | |||
986 | // Make sure the elements to set are valid. |
||
987 | foreach ($elements as $element) |
||
988 | { |
||
989 | if (!($element instanceof \SimpleXMLElement)) |
||
990 | { |
||
991 | throw new \UnexpectedValueException(sprintf('$element not SimpleXMLElement in %s::setFields', get_class($this))); |
||
992 | } |
||
993 | } |
||
994 | |||
995 | // Set the fields. |
||
996 | $return = true; |
||
997 | |||
998 | foreach ($elements as $element) |
||
999 | { |
||
1000 | if (!$this->setField($element, $group, $replace)) |
||
1001 | { |
||
1002 | $return = false; |
||
1003 | } |
||
1004 | } |
||
1005 | |||
1006 | // Synchronize any paths found in the load. |
||
1007 | $this->syncPaths(); |
||
1008 | |||
1009 | return $return; |
||
1010 | } |
||
1011 | |||
1012 | /** |
||
1013 | * Method to set the value of a field. If the field does not exist in the form then the method |
||
1014 | * will return false. |
||
1015 | * |
||
1016 | * @param string $name The name of the field for which to set the value. |
||
1017 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
1018 | * @param mixed $value The value to set for the field. |
||
1019 | * |
||
1020 | * @return boolean True on success. |
||
1021 | * |
||
1022 | * @since 1.0 |
||
1023 | */ |
||
1024 | public function setValue($name, $group = null, $value = null) |
||
1025 | { |
||
1026 | // If the field does not exist return false. |
||
1027 | if (!$this->findField($name, $group)) |
||
1028 | { |
||
1029 | return false; |
||
1030 | } |
||
1031 | |||
1032 | // If a group is set use it. |
||
1033 | if ($group) |
||
0 ignored issues
–
show
The expression
$group of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1034 | { |
||
1035 | $this->data->set($group . '.' . $name, $value); |
||
1036 | } |
||
1037 | else |
||
1038 | { |
||
1039 | $this->data->set($name, $value); |
||
1040 | } |
||
1041 | |||
1042 | return true; |
||
1043 | } |
||
1044 | |||
1045 | /** |
||
1046 | * Method to validate form data. |
||
1047 | * |
||
1048 | * Validation warnings will be pushed into Form::errors and should be |
||
1049 | * retrieved with Form::getErrors() when validate returns boolean false. |
||
1050 | * |
||
1051 | * @param array $data An array of field values to validate. |
||
1052 | * @param string $group The optional dot-separated form group path on which to filter the |
||
1053 | * fields to be validated. |
||
1054 | * |
||
1055 | * @return mixed True on success. |
||
1056 | * |
||
1057 | * @since 1.0 |
||
1058 | */ |
||
1059 | public function validate($data, $group = null) |
||
1060 | { |
||
1061 | // Make sure there is a valid Form XML document. |
||
1062 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1063 | { |
||
1064 | return false; |
||
1065 | } |
||
1066 | |||
1067 | $return = true; |
||
1068 | |||
1069 | // Create an input registry object from the data to validate. |
||
1070 | $input = new Registry($data); |
||
1071 | |||
1072 | // Get the fields for which to validate the data. |
||
1073 | $fields = $this->findFieldsByGroup($group); |
||
1074 | |||
1075 | if (!$fields) |
||
1076 | { |
||
1077 | // PANIC! |
||
1078 | return false; |
||
1079 | } |
||
1080 | |||
1081 | // Validate the fields. |
||
1082 | foreach ($fields as $field) |
||
1083 | { |
||
1084 | $value = null; |
||
0 ignored issues
–
show
$value is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
1085 | $name = (string) $field['name']; |
||
1086 | |||
1087 | // Get the group names as strings for ancestor fields elements. |
||
1088 | $attrs = $field->xpath('ancestor::fields[@name]/@name'); |
||
1089 | $groups = array_map('strval', $attrs ? $attrs : array()); |
||
1090 | $group = implode('.', $groups); |
||
1091 | |||
1092 | // Get the value from the input data. |
||
1093 | if ($group) |
||
1094 | { |
||
1095 | $value = $input->get($group . '.' . $name); |
||
1096 | } |
||
1097 | else |
||
1098 | { |
||
1099 | $value = $input->get($name); |
||
1100 | } |
||
1101 | |||
1102 | // Validate the field. |
||
1103 | $valid = $this->validateField($field, $group, $value, $input); |
||
1104 | |||
1105 | // Check for an error. |
||
1106 | if ($valid instanceof \Exception) |
||
1107 | { |
||
1108 | array_push($this->errors, $valid); |
||
1109 | $return = false; |
||
1110 | } |
||
1111 | } |
||
1112 | |||
1113 | return $return; |
||
1114 | } |
||
1115 | |||
1116 | /** |
||
1117 | * Method to apply an input filter to a value based on field data. |
||
1118 | * |
||
1119 | * @param string $element The XML element object representation of the form field. |
||
1120 | * @param mixed $value The value to filter for the field. |
||
1121 | * |
||
1122 | * @return mixed The filtered value. |
||
1123 | * |
||
1124 | * @since 1.0 |
||
1125 | */ |
||
1126 | protected function filterField($element, $value) |
||
1127 | { |
||
1128 | // Make sure there is a valid SimpleXMLElement. |
||
1129 | if (!($element instanceof \SimpleXMLElement)) |
||
1130 | { |
||
1131 | return false; |
||
1132 | } |
||
1133 | |||
1134 | // Get the field filter type. |
||
1135 | $filter = (string) $element['filter']; |
||
1136 | |||
1137 | // Process the input value based on the filter. |
||
1138 | $return = null; |
||
1139 | |||
1140 | switch (strtoupper($filter)) |
||
1141 | { |
||
1142 | // Do nothing, thus leaving the return value as null. |
||
1143 | case 'UNSET': |
||
1144 | break; |
||
1145 | |||
1146 | // No Filter. |
||
1147 | case 'RAW': |
||
1148 | $return = $value; |
||
1149 | break; |
||
1150 | |||
1151 | // Filter the input as an array of integers. |
||
1152 | case 'INT_ARRAY': |
||
1153 | // Make sure the input is an array. |
||
1154 | if (is_object($value)) |
||
1155 | { |
||
1156 | $value = get_object_vars($value); |
||
1157 | } |
||
1158 | |||
1159 | $value = is_array($value) ? $value : array($value); |
||
1160 | |||
1161 | $value = ArrayHelper::toInteger($value); |
||
1162 | $return = $value; |
||
1163 | break; |
||
1164 | |||
1165 | // Filter safe HTML. |
||
1166 | case 'SAFEHTML': |
||
1167 | $filterInput = new Filter\InputFilter(null, null, 1, 1); |
||
0 ignored issues
–
show
null is of type null , but the function expects a array .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
1168 | $return = $filterInput->clean($value, 'string'); |
||
1169 | break; |
||
1170 | |||
1171 | // Ensures a protocol is present in the saved field. Only use when |
||
1172 | // the only permitted protocols requre '://'. See Rule\Url for list of these. |
||
1173 | |||
1174 | case 'URL': |
||
1175 | if (empty($value)) |
||
1176 | { |
||
1177 | return false; |
||
1178 | } |
||
1179 | |||
1180 | $filterInput = new Filter\InputFilter; |
||
1181 | $value = $filterInput->clean($value, 'html'); |
||
1182 | $value = trim($value); |
||
1183 | |||
1184 | // Check for a protocol |
||
1185 | $protocol = parse_url($value, PHP_URL_SCHEME); |
||
1186 | |||
1187 | // If there is no protocol and the relative option is not specified, |
||
1188 | // we assume that it is an external URL and prepend http://. |
||
1189 | if (($element['type'] == 'url' && !$protocol && !$element['relative']) |
||
0 ignored issues
–
show
The expression
$protocol of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1190 | || (!$element['type'] == 'url' && !$protocol)) |
||
0 ignored issues
–
show
The expression
$protocol of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1191 | { |
||
1192 | $protocol = 'http'; |
||
1193 | |||
1194 | // If it looks like an internal link, then add the root. |
||
1195 | if (substr($value, 0) == 'index.php') |
||
1196 | { |
||
1197 | $value = Uri::root() . $value; |
||
0 ignored issues
–
show
The method
root() does not seem to exist on object<Joomla\Uri\Uri> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
1198 | } |
||
1199 | |||
1200 | // Otherwise we treat it is an external link. |
||
1201 | // Put the url back together. |
||
1202 | $value = $protocol . '://' . $value; |
||
1203 | } |
||
1204 | |||
1205 | // If relative URLS are allowed we assume that URLs without protocols are internal. |
||
1206 | elseif (!$protocol && $element['relative']) |
||
0 ignored issues
–
show
The expression
$protocol of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1207 | { |
||
1208 | $host = Uri::getInstance('SERVER')->gethost(); |
||
0 ignored issues
–
show
The method
getInstance() does not seem to exist on object<Joomla\Uri\Uri> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
1209 | |||
1210 | // If it starts with the host string, just prepend the protocol. |
||
1211 | if (substr($value, 0) == $host) |
||
1212 | { |
||
1213 | $value = 'http://' . $value; |
||
1214 | } |
||
1215 | else |
||
1216 | // Otherwise prepend the root. |
||
1217 | { |
||
1218 | $value = Uri::root() . $value; |
||
0 ignored issues
–
show
The method
root() does not seem to exist on object<Joomla\Uri\Uri> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||
1219 | } |
||
1220 | } |
||
1221 | |||
1222 | $return = $value; |
||
1223 | break; |
||
1224 | |||
1225 | case 'TEL': |
||
1226 | $value = trim($value); |
||
1227 | |||
1228 | // Does it match the NANP pattern? |
||
1229 | if (preg_match('/^(?:\+?1[-. ]?)?\(?([2-9][0-8][0-9])\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/', $value) == 1) |
||
1230 | { |
||
1231 | $number = (string) preg_replace('/[^\d]/', '', $value); |
||
1232 | |||
1233 | if (substr($number, 0, 1) == 1) |
||
1234 | { |
||
1235 | $number = substr($number, 1); |
||
1236 | } |
||
1237 | |||
1238 | if (substr($number, 0, 2) == '+1') |
||
1239 | { |
||
1240 | $number = substr($number, 2); |
||
1241 | } |
||
1242 | |||
1243 | $result = '1.' . $number; |
||
1244 | } |
||
1245 | elseif (preg_match('/^\+(?:[0-9] ?){6,14}[0-9]$/', $value) == 1) |
||
1246 | // If not, does it match ITU-T? |
||
1247 | { |
||
1248 | $countrycode = substr($value, 0, strpos($value, ' ')); |
||
1249 | $countrycode = (string) preg_replace('/[^\d]/', '', $countrycode); |
||
1250 | $number = strstr($value, ' '); |
||
1251 | $number = (string) preg_replace('/[^\d]/', '', $number); |
||
1252 | $result = $countrycode . '.' . $number; |
||
1253 | } |
||
1254 | elseif (preg_match('/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/', $value) == 1) |
||
1255 | // If not, does it match EPP? |
||
1256 | { |
||
1257 | if (strstr($value, 'x')) |
||
1258 | { |
||
1259 | $xpos = strpos($value, 'x'); |
||
1260 | $value = substr($value, 0, $xpos); |
||
1261 | } |
||
1262 | |||
1263 | $result = str_replace('+', '', $value); |
||
1264 | } |
||
1265 | elseif (preg_match('/[0-9]{1,3}\.[0-9]{4,14}$/', $value) == 1) |
||
1266 | // Maybe it is already ccc.nnnnnnn? |
||
1267 | { |
||
1268 | $result = $value; |
||
1269 | } |
||
1270 | else |
||
1271 | // If not, can we make it a string of digits? |
||
1272 | { |
||
1273 | $value = (string) preg_replace('/[^\d]/', '', $value); |
||
1274 | |||
1275 | if ($value != null && strlen($value) <= 15) |
||
1276 | { |
||
1277 | $length = strlen($value); |
||
1278 | |||
1279 | // If it is fewer than 13 digits assume it is a local number |
||
1280 | if ($length <= 12) |
||
1281 | { |
||
1282 | $result = '.' . $value; |
||
1283 | } |
||
1284 | else |
||
1285 | { |
||
1286 | // If it has 13 or more digits let's make a country code. |
||
1287 | $cclen = $length - 12; |
||
1288 | $result = substr($value, 0, $cclen) . '.' . substr($value, $cclen); |
||
1289 | } |
||
1290 | } |
||
1291 | else |
||
1292 | // If not let's not save anything. |
||
1293 | { |
||
1294 | $result = ''; |
||
1295 | } |
||
1296 | } |
||
1297 | |||
1298 | $return = $result; |
||
1299 | |||
1300 | break; |
||
1301 | |||
1302 | default: |
||
1303 | // Check for a callback filter. |
||
1304 | if (strpos($filter, '::') !== false && is_callable(explode('::', $filter))) |
||
1305 | { |
||
1306 | $return = call_user_func(explode('::', $filter), $value); |
||
1307 | } |
||
1308 | elseif (function_exists($filter)) |
||
1309 | // Filter using a callback function if specified. |
||
1310 | { |
||
1311 | $return = call_user_func($filter, $value); |
||
1312 | } |
||
1313 | else |
||
1314 | // Filter using InputFilter. All HTML code is filtered by default. |
||
1315 | { |
||
1316 | $filterInput = new Filter\InputFilter; |
||
1317 | $return = $filterInput->clean($value, $filter); |
||
1318 | } |
||
1319 | break; |
||
1320 | } |
||
1321 | |||
1322 | return $return; |
||
1323 | } |
||
1324 | |||
1325 | /** |
||
1326 | * Method to get a form field represented as an XML element object. |
||
1327 | * |
||
1328 | * @param string $name The name of the form field. |
||
1329 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
1330 | * |
||
1331 | * @return mixed The XML element object for the field or boolean false on error. |
||
1332 | * |
||
1333 | * @since 1.0 |
||
1334 | */ |
||
1335 | protected function findField($name, $group = null) |
||
1336 | { |
||
1337 | $element = false; |
||
1338 | $fields = array(); |
||
1339 | |||
1340 | // Make sure there is a valid Form XML document. |
||
1341 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1342 | { |
||
1343 | return false; |
||
1344 | } |
||
1345 | |||
1346 | // Let's get the appropriate field element based on the method arguments. |
||
1347 | if ($group) |
||
0 ignored issues
–
show
The expression
$group of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
1348 | { |
||
1349 | // Get the fields elements for a given group. |
||
1350 | $elements = &$this->findGroup($group); |
||
1351 | |||
1352 | // Get all of the field elements with the correct name for the fields elements. |
||
1353 | View Code Duplication | foreach ($elements as $element) |
|
0 ignored issues
–
show
The expression
$elements of type false|array is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1354 | { |
||
1355 | // If there are matching field elements add them to the fields array. |
||
1356 | if ($tmp = $element->xpath('descendant::field[@name="' . $name . '"]')) |
||
1357 | { |
||
1358 | $fields = array_merge($fields, $tmp); |
||
1359 | } |
||
1360 | } |
||
1361 | |||
1362 | // Make sure something was found. |
||
1363 | if (!$fields) |
||
0 ignored issues
–
show
The expression
$fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
1364 | { |
||
1365 | return false; |
||
1366 | } |
||
1367 | |||
1368 | // Use the first correct match in the given group. |
||
1369 | $groupNames = explode('.', $group); |
||
1370 | |||
1371 | View Code Duplication | foreach ($fields as &$field) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1372 | { |
||
1373 | // Get the group names as strings for ancestor fields elements. |
||
1374 | $attrs = $field->xpath('ancestor::fields[@name]/@name'); |
||
1375 | $names = array_map('strval', $attrs ? $attrs : array()); |
||
1376 | |||
1377 | // If the field is in the exact group use it and break out of the loop. |
||
1378 | if ($names == (array) $groupNames) |
||
1379 | { |
||
1380 | $element = &$field; |
||
1381 | break; |
||
1382 | } |
||
1383 | } |
||
1384 | } |
||
1385 | else |
||
1386 | { |
||
1387 | // Get an array of fields with the correct name. |
||
1388 | $fields = $this->xml->xpath('//field[@name="' . $name . '"]'); |
||
1389 | |||
1390 | // Make sure something was found. |
||
1391 | if (!$fields) |
||
0 ignored issues
–
show
The expression
$fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
1392 | { |
||
1393 | return false; |
||
1394 | } |
||
1395 | |||
1396 | // Search through the fields for the right one. |
||
1397 | foreach ($fields as &$field) |
||
1398 | { |
||
1399 | // If we find an ancestor fields element with a group name then it isn't what we want. |
||
1400 | if ($field->xpath('ancestor::fields[@name]')) |
||
1401 | { |
||
1402 | continue; |
||
1403 | } |
||
1404 | else |
||
1405 | // Found it! |
||
1406 | { |
||
1407 | $element = &$field; |
||
1408 | break; |
||
1409 | } |
||
1410 | } |
||
1411 | } |
||
1412 | |||
1413 | return $element; |
||
1414 | } |
||
1415 | |||
1416 | /** |
||
1417 | * Method to get an array of <field /> elements from the form XML document which are |
||
1418 | * in a specified fieldset by name. |
||
1419 | * |
||
1420 | * @param string $name The name of the fieldset. |
||
1421 | * |
||
1422 | * @return mixed Boolean false on error or array of SimpleXMLElement objects. |
||
1423 | * |
||
1424 | * @since 1.0 |
||
1425 | */ |
||
1426 | protected function &findFieldsByFieldset($name) |
||
1427 | { |
||
1428 | $false = false; |
||
1429 | |||
1430 | // Make sure there is a valid Form XML document. |
||
1431 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1432 | { |
||
1433 | return $false; |
||
1434 | } |
||
1435 | |||
1436 | /* |
||
1437 | * Get an array of <field /> elements that are underneath a <fieldset /> element |
||
1438 | * with the appropriate name attribute (unless they are the decendents |
||
1439 | * of another <field /> element for some reaon), and also any <field /> elements |
||
1440 | * with the appropriate fieldset attribute. |
||
1441 | */ |
||
1442 | $fields = $this->xml->xpath('//fieldset[@name="' . $name . '"]//field[not(ancestor::field)] | //field[@fieldset="' . $name . '"]'); |
||
1443 | |||
1444 | return $fields; |
||
1445 | } |
||
1446 | |||
1447 | /** |
||
1448 | * Method to get an array of <field /> elements from the form XML document which are |
||
1449 | * in a control group by name. |
||
1450 | * |
||
1451 | * @param mixed $group The optional dot-separated form group path on which to find the fields. |
||
1452 | * Null will return all fields. False will return fields not in a group. |
||
1453 | * @param boolean $nested True to also include fields in nested groups that are inside of the |
||
1454 | * group for which to find fields. |
||
1455 | * |
||
1456 | * @return mixed Boolean false on error or array of SimpleXMLElement objects. |
||
1457 | * |
||
1458 | * @since 1.0 |
||
1459 | */ |
||
1460 | protected function &findFieldsByGroup($group = null, $nested = false) |
||
1461 | { |
||
1462 | $false = false; |
||
1463 | $fields = array(); |
||
1464 | |||
1465 | // Make sure there is a valid Form XML document. |
||
1466 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1467 | { |
||
1468 | return $false; |
||
1469 | } |
||
1470 | |||
1471 | // Get only fields in a specific group? |
||
1472 | if ($group) |
||
1473 | { |
||
1474 | // Get the fields elements for a given group. |
||
1475 | $elements = &$this->findGroup($group); |
||
1476 | |||
1477 | // Get all of the field elements for the fields elements. |
||
1478 | foreach ($elements as $element) |
||
0 ignored issues
–
show
The expression
$elements of type false|array is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
1479 | { |
||
1480 | // If there are field elements add them to the return result. |
||
1481 | if ($tmp = $element->xpath('descendant::field')) |
||
1482 | { |
||
1483 | // If we also want fields in nested groups then just merge the arrays. |
||
1484 | if ($nested) |
||
1485 | { |
||
1486 | $fields = array_merge($fields, $tmp); |
||
1487 | } |
||
1488 | else |
||
1489 | // If we want to exclude nested groups then we need to check each field. |
||
1490 | { |
||
1491 | $groupNames = explode('.', $group); |
||
1492 | |||
1493 | View Code Duplication | foreach ($tmp as $field) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1494 | { |
||
1495 | // Get the names of the groups that the field is in. |
||
1496 | $attrs = $field->xpath('ancestor::fields[@name]/@name'); |
||
1497 | $names = array_map('strval', $attrs ? $attrs : array()); |
||
1498 | |||
1499 | // If the field is in the specific group then add it to the return list. |
||
1500 | if ($names == (array) $groupNames) |
||
1501 | { |
||
1502 | $fields = array_merge($fields, array($field)); |
||
1503 | } |
||
1504 | } |
||
1505 | } |
||
1506 | } |
||
1507 | } |
||
1508 | } |
||
1509 | elseif ($group === false) |
||
1510 | { |
||
1511 | // Get only field elements not in a group. |
||
1512 | $fields = $this->xml->xpath('descendant::fields[not(@name)]/field | descendant::fields[not(@name)]/fieldset/field '); |
||
1513 | } |
||
1514 | else |
||
1515 | { |
||
1516 | // Get an array of all the <field /> elements. |
||
1517 | $fields = $this->xml->xpath('//field'); |
||
1518 | } |
||
1519 | |||
1520 | return $fields; |
||
1521 | } |
||
1522 | |||
1523 | /** |
||
1524 | * Method to get a form field group represented as an XML element object. |
||
1525 | * |
||
1526 | * @param string $group The dot-separated form group path on which to find the group. |
||
1527 | * |
||
1528 | * @return mixed An array of XML element objects for the group or boolean false on error. |
||
1529 | * |
||
1530 | * @since 1.0 |
||
1531 | */ |
||
1532 | protected function &findGroup($group) |
||
1533 | { |
||
1534 | $false = false; |
||
1535 | $groups = array(); |
||
1536 | $tmp = array(); |
||
1537 | |||
1538 | // Make sure there is a valid Form XML document. |
||
1539 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1540 | { |
||
1541 | return $false; |
||
1542 | } |
||
1543 | |||
1544 | // Make sure there is actually a group to find. |
||
1545 | $group = explode('.', $group); |
||
1546 | |||
1547 | if (!empty($group)) |
||
1548 | { |
||
1549 | // Get any fields elements with the correct group name. |
||
1550 | $elements = $this->xml->xpath('//fields[@name="' . (string) $group[0] . '"]'); |
||
1551 | |||
1552 | // Check to make sure that there are no parent groups for each element. |
||
1553 | foreach ($elements as $element) |
||
1554 | { |
||
1555 | if (!$element->xpath('ancestor::fields[@name]')) |
||
1556 | { |
||
1557 | $tmp[] = $element; |
||
1558 | } |
||
1559 | } |
||
1560 | |||
1561 | // Iterate through the nested groups to find any matching form field groups. |
||
1562 | for ($i = 1, $n = count($group); $i < $n; $i++) |
||
1563 | { |
||
1564 | // Initialise some loop variables. |
||
1565 | $validNames = array_slice($group, 0, $i + 1); |
||
1566 | $current = $tmp; |
||
1567 | $tmp = array(); |
||
1568 | |||
1569 | // Check to make sure that there are no parent groups for each element. |
||
1570 | foreach ($current as $element) |
||
1571 | { |
||
1572 | // Get any fields elements with the correct group name. |
||
1573 | $children = $element->xpath('descendant::fields[@name="' . (string) $group[$i] . '"]'); |
||
1574 | |||
1575 | // For the found fields elements validate that they are in the correct groups. |
||
1576 | View Code Duplication | foreach ($children as $fields) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1577 | { |
||
1578 | // Get the group names as strings for ancestor fields elements. |
||
1579 | $attrs = $fields->xpath('ancestor-or-self::fields[@name]/@name'); |
||
1580 | $names = array_map('strval', $attrs ? $attrs : array()); |
||
1581 | |||
1582 | // If the group names for the fields element match the valid names at this |
||
1583 | // level add the fields element. |
||
1584 | if ($validNames == $names) |
||
1585 | { |
||
1586 | $tmp[] = $fields; |
||
1587 | } |
||
1588 | } |
||
1589 | } |
||
1590 | } |
||
1591 | |||
1592 | // Only include valid XML objects. |
||
1593 | foreach ($tmp as $element) |
||
1594 | { |
||
1595 | if ($element instanceof \SimpleXMLElement) |
||
1596 | { |
||
1597 | $groups[] = $element; |
||
1598 | } |
||
1599 | } |
||
1600 | } |
||
1601 | |||
1602 | return $groups; |
||
1603 | } |
||
1604 | |||
1605 | /** |
||
1606 | * Method to load, setup and return a FormField object based on field data. |
||
1607 | * |
||
1608 | * @param string $element The XML element object representation of the form field. |
||
1609 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
1610 | * @param mixed $value The optional value to use as the default for the field. |
||
1611 | * |
||
1612 | * @return mixed The FormField object for the field or boolean false on error. |
||
1613 | * |
||
1614 | * @since 1.0 |
||
1615 | */ |
||
1616 | protected function loadField($element, $group = null, $value = null) |
||
1617 | { |
||
1618 | // Make sure there is a valid SimpleXMLElement. |
||
1619 | if (!($element instanceof \SimpleXMLElement)) |
||
1620 | { |
||
1621 | return false; |
||
1622 | } |
||
1623 | |||
1624 | // Get the field type. |
||
1625 | $type = $element['type'] ? (string) $element['type'] : 'text'; |
||
1626 | |||
1627 | // Load the Field object for the field. |
||
1628 | $field = FormHelper::loadFieldType($type); |
||
0 ignored issues
–
show
The method
Joomla\Form\FormHelper::loadFieldType() has been deprecated with message: 2.0 Field objects should be autoloaded
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1629 | |||
1630 | // If the object could not be loaded, get a text field object. |
||
1631 | if ($field === false) |
||
1632 | { |
||
1633 | $field = FormHelper::loadFieldType('text'); |
||
0 ignored issues
–
show
The method
Joomla\Form\FormHelper::loadFieldType() has been deprecated with message: 2.0 Field objects should be autoloaded
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1634 | |||
1635 | if ($field === false) |
||
1636 | { |
||
1637 | return false; |
||
1638 | } |
||
1639 | } |
||
1640 | |||
1641 | /* |
||
1642 | * Get the value for the form field if not set. |
||
1643 | * Default to the translated version of the 'default' attribute |
||
1644 | * if 'translate_default' attribute if set to 'true' or '1' |
||
1645 | * else the value of the 'default' attribute for the field. |
||
1646 | */ |
||
1647 | if ($value === null) |
||
1648 | { |
||
1649 | $default = (string) $element['default']; |
||
1650 | |||
1651 | if (($translate = $element['translate_default']) && ((string) $translate == 'true' || (string) $translate == '1')) |
||
1652 | { |
||
1653 | $lang = Language::getInstance(); |
||
0 ignored issues
–
show
The method
Joomla\Language\Language::getInstance() has been deprecated with message: 2.0 Use LanguageFactory::getLanguage() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1654 | |||
1655 | if ($lang->hasKey($default)) |
||
1656 | { |
||
1657 | $debug = $lang->setDebug(false); |
||
1658 | $default = Text::_($default); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1659 | $lang->setDebug($debug); |
||
1660 | } |
||
1661 | else |
||
1662 | { |
||
1663 | $default = Text::_($default); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1664 | } |
||
1665 | } |
||
1666 | |||
1667 | $value = $this->getValue((string) $element['name'], $group, $default); |
||
1668 | } |
||
1669 | |||
1670 | // Setup the Field object. |
||
1671 | $field->setForm($this); |
||
1672 | |||
1673 | if ($field->setup($element, $value, $group)) |
||
1674 | { |
||
1675 | return $field; |
||
1676 | } |
||
1677 | else |
||
1678 | { |
||
1679 | return false; |
||
1680 | } |
||
1681 | } |
||
1682 | |||
1683 | /** |
||
1684 | * Method to synchronize any field, form or rule paths contained in the XML document. |
||
1685 | * |
||
1686 | * @return boolean True on success. |
||
1687 | * |
||
1688 | * @since 1.0 |
||
1689 | * @todo Maybe we should receive all addXXXpaths attributes at once? |
||
1690 | */ |
||
1691 | protected function syncPaths() |
||
1692 | { |
||
1693 | // Make sure there is a valid Form XML document. |
||
1694 | if (!($this->xml instanceof \SimpleXMLElement)) |
||
1695 | { |
||
1696 | return false; |
||
1697 | } |
||
1698 | |||
1699 | // Get any addfieldpath attributes from the form definition. |
||
1700 | $paths = $this->xml->xpath('//*[@addfieldpath]/@addfieldpath'); |
||
1701 | $paths = array_map('strval', $paths ? $paths : array()); |
||
1702 | |||
1703 | // Add the field paths. |
||
1704 | View Code Duplication | foreach ($paths as $path) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1705 | { |
||
1706 | $path = JPATH_ROOT . '/' . ltrim($path, '/\\'); |
||
1707 | FormHelper::addFieldPath($path); |
||
0 ignored issues
–
show
The method
Joomla\Form\FormHelper::addFieldPath() has been deprecated with message: 2.0 Field objects should be autoloaded
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1708 | } |
||
1709 | |||
1710 | // Get any addformpath attributes from the form definition. |
||
1711 | $paths = $this->xml->xpath('//*[@addformpath]/@addformpath'); |
||
1712 | $paths = array_map('strval', $paths ? $paths : array()); |
||
1713 | |||
1714 | // Add the form paths. |
||
1715 | View Code Duplication | foreach ($paths as $path) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1716 | { |
||
1717 | $path = JPATH_ROOT . '/' . ltrim($path, '/\\'); |
||
1718 | FormHelper::addFormPath($path); |
||
1719 | } |
||
1720 | |||
1721 | // Get any addrulepath attributes from the form definition. |
||
1722 | $paths = $this->xml->xpath('//*[@addrulepath]/@addrulepath'); |
||
1723 | $paths = array_map('strval', $paths ? $paths : array()); |
||
1724 | |||
1725 | // Add the rule paths. |
||
1726 | View Code Duplication | foreach ($paths as $path) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1727 | { |
||
1728 | $path = JPATH_ROOT . '/' . ltrim($path, '/\\'); |
||
1729 | FormHelper::addRulePath($path); |
||
0 ignored issues
–
show
The method
Joomla\Form\FormHelper::addRulePath() has been deprecated with message: 2.0 Rule objects should be autoloaded
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1730 | } |
||
1731 | |||
1732 | return true; |
||
1733 | } |
||
1734 | |||
1735 | /** |
||
1736 | * Method to validate a Field object based on field data. |
||
1737 | * |
||
1738 | * @param \SimpleXMLElement $element The XML element object representation of the form field. |
||
1739 | * @param string $group The optional dot-separated form group path on which to find the field. |
||
1740 | * @param mixed $value The optional value to use as the default for the field. |
||
1741 | * @param Registry $input An optional Registry object with the entire data set to validate |
||
1742 | * against the entire form. |
||
1743 | * |
||
1744 | * @return mixed Boolean true if field value is valid, Exception on failure. |
||
1745 | * |
||
1746 | * @since 1.0 |
||
1747 | * @throws \InvalidArgumentException |
||
1748 | * @throws \UnexpectedValueException |
||
1749 | */ |
||
1750 | protected function validateField(\SimpleXMLElement $element, $group = null, $value = null, Registry $input = null) |
||
1751 | { |
||
1752 | $valid = true; |
||
1753 | |||
1754 | // Check if the field is required. |
||
1755 | $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); |
||
1756 | |||
1757 | if ($required) |
||
1758 | { |
||
1759 | // If the field is required and the value is empty return an error message. |
||
1760 | if (($value === '') || ($value === null)) |
||
1761 | { |
||
1762 | View Code Duplication | if ($element['label']) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1763 | { |
||
1764 | $message = Text::_($element['label']); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1765 | } |
||
1766 | else |
||
1767 | { |
||
1768 | $message = Text::_($element['name']); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1769 | } |
||
1770 | |||
1771 | $message = Text::sprintf('JLIB_FORM_VALIDATE_FIELD_REQUIRED', $message); |
||
1772 | |||
1773 | return new \RuntimeException($message); |
||
1774 | } |
||
1775 | } |
||
1776 | |||
1777 | // Get the field validation rule. |
||
1778 | if ($type = (string) $element['validate']) |
||
1779 | { |
||
1780 | // Load the Rule object for the field. |
||
1781 | $rule = FormHelper::loadRuleType($type); |
||
0 ignored issues
–
show
The method
Joomla\Form\FormHelper::loadRuleType() has been deprecated with message: 2.0 Rule objects should be autoloaded
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1782 | |||
1783 | // If the object could not be loaded return an error message. |
||
1784 | if ($rule === false) |
||
1785 | { |
||
1786 | throw new \UnexpectedValueException(sprintf('%s::validateField() rule `%s` missing.', get_class($this), $type)); |
||
1787 | } |
||
1788 | |||
1789 | // Run the field validation rule test. |
||
1790 | $valid = $rule->test($element, $value, $group, $input, $this); |
||
1791 | |||
1792 | // Check for an error in the validation test. |
||
1793 | if ($valid instanceof \Exception) |
||
1794 | { |
||
1795 | return $valid; |
||
1796 | } |
||
1797 | } |
||
1798 | |||
1799 | // Check if the field is valid. |
||
1800 | if ($valid === false) |
||
1801 | { |
||
1802 | // Does the field have a defined error message? |
||
1803 | $message = (string) $element['message']; |
||
1804 | |||
1805 | if ($message) |
||
1806 | { |
||
1807 | $message = Text::_($element['message']); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1808 | |||
1809 | return new \UnexpectedValueException($message); |
||
1810 | } |
||
1811 | View Code Duplication | else |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1812 | { |
||
1813 | $message = Text::_($element['label']); |
||
0 ignored issues
–
show
The method
Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
1814 | $message = Text::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', $message); |
||
1815 | |||
1816 | return new \UnexpectedValueException($message); |
||
1817 | } |
||
1818 | } |
||
1819 | |||
1820 | return true; |
||
1821 | } |
||
1822 | |||
1823 | /** |
||
1824 | * Method to get an instance of a form. |
||
1825 | * |
||
1826 | * @param string $name The name of the form. |
||
1827 | * @param string $data The name of an XML file or string to load as the form definition. |
||
1828 | * @param array $options An array of form options. |
||
1829 | * @param string $replace Flag to toggle whether form fields should be replaced if a field |
||
1830 | * already exists with the same group/name. |
||
1831 | * @param string $xpath An optional xpath to search for the fields. |
||
1832 | * |
||
1833 | * @return Form Instance of this class. |
||
1834 | * |
||
1835 | * @since 1.0 |
||
1836 | * @throws \InvalidArgumentException if no data provided. |
||
1837 | * @throws \RuntimeException if the form could not be loaded. |
||
1838 | */ |
||
1839 | public static function getInstance($name, $data = null, $options = array(), $replace = true, $xpath = false) |
||
1840 | { |
||
1841 | // Reference to array with form instances |
||
1842 | $forms = &self::$forms; |
||
1843 | |||
1844 | // Only instantiate the form if it does not already exist. |
||
1845 | if (!isset($forms[$name])) |
||
1846 | { |
||
1847 | $data = trim($data); |
||
1848 | |||
1849 | if (empty($data)) |
||
1850 | { |
||
1851 | throw new \InvalidArgumentException(sprintf('%s(name, *%s*)', __METHOD__, gettype($data))); |
||
1852 | } |
||
1853 | |||
1854 | // Instantiate the form. |
||
1855 | $forms[$name] = new self($name, $options); |
||
0 ignored issues
–
show
The class
Joomla\Form\Form has been deprecated with message: The joomla/form package is deprecated
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead. ![]() |
|||
1856 | |||
1857 | // Load the data. |
||
1858 | if (substr(trim($data), 0, 1) == '<') |
||
1859 | { |
||
1860 | View Code Duplication | if ($forms[$name]->load($data, $replace, $xpath) == false) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1861 | { |
||
1862 | throw new \RuntimeException(__METHOD__ . ' could not load form'); |
||
1863 | } |
||
1864 | } |
||
1865 | View Code Duplication | else |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1866 | { |
||
1867 | if ($forms[$name]->loadFile($data, $replace, $xpath) == false) |
||
0 ignored issues
–
show
|
|||
1868 | { |
||
1869 | throw new \RuntimeException(__METHOD__ . ' could not load file'); |
||
1870 | } |
||
1871 | } |
||
1872 | } |
||
1873 | |||
1874 | return $forms[$name]; |
||
1875 | } |
||
1876 | |||
1877 | /** |
||
1878 | * Adds a new child SimpleXMLElement node to the source. |
||
1879 | * |
||
1880 | * @param \SimpleXMLElement $source The source element on which to append. |
||
1881 | * @param \SimpleXMLElement $new The new element to append. |
||
1882 | * |
||
1883 | * @return void |
||
1884 | * |
||
1885 | * @since 1.0 |
||
1886 | */ |
||
1887 | protected static function addNode(\SimpleXMLElement $source, \SimpleXMLElement $new) |
||
1888 | { |
||
1889 | // Add the new child node. |
||
1890 | $node = $source->addChild($new->getName(), trim($new)); |
||
1891 | |||
1892 | // Add the attributes of the child node. |
||
1893 | foreach ($new->attributes() as $name => $value) |
||
1894 | { |
||
1895 | $node->addAttribute($name, $value); |
||
1896 | } |
||
1897 | |||
1898 | // Add any children of the new node. |
||
1899 | foreach ($new->children() as $child) |
||
1900 | { |
||
1901 | self::addNode($node, $child); |
||
1902 | } |
||
1903 | } |
||
1904 | |||
1905 | /** |
||
1906 | * Update the attributes of a child node |
||
1907 | * |
||
1908 | * @param \SimpleXMLElement $source The source element on which to append the attributes |
||
1909 | * @param \SimpleXMLElement $new The new element to append |
||
1910 | * |
||
1911 | * @return void |
||
1912 | * |
||
1913 | * @since 1.0 |
||
1914 | */ |
||
1915 | protected static function mergeNode(\SimpleXMLElement $source, \SimpleXMLElement $new) |
||
1916 | { |
||
1917 | // Update the attributes of the child node. |
||
1918 | View Code Duplication | foreach ($new->attributes() as $name => $value) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1919 | { |
||
1920 | if (isset($source[$name])) |
||
1921 | { |
||
1922 | $source[$name] = (string) $value; |
||
1923 | } |
||
1924 | else |
||
1925 | { |
||
1926 | $source->addAttribute($name, $value); |
||
1927 | } |
||
1928 | } |
||
1929 | } |
||
1930 | |||
1931 | /** |
||
1932 | * Merges new elements into a source <fields> element. |
||
1933 | * |
||
1934 | * @param \SimpleXMLElement $source The source element. |
||
1935 | * @param \SimpleXMLElement $new The new element to merge. |
||
1936 | * |
||
1937 | * @return void |
||
1938 | * |
||
1939 | * @since 1.0 |
||
1940 | */ |
||
1941 | protected static function mergeNodes(\SimpleXMLElement $source, \SimpleXMLElement $new) |
||
1942 | { |
||
1943 | // The assumption is that the inputs are at the same relative level. |
||
1944 | // So we just have to scan the children and deal with them. |
||
1945 | |||
1946 | // Update the attributes of the child node. |
||
1947 | View Code Duplication | foreach ($new->attributes() as $name => $value) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1948 | { |
||
1949 | if (isset($source[$name])) |
||
1950 | { |
||
1951 | $source[$name] = (string) $value; |
||
1952 | } |
||
1953 | else |
||
1954 | { |
||
1955 | $source->addAttribute($name, $value); |
||
1956 | } |
||
1957 | } |
||
1958 | |||
1959 | foreach ($new->children() as $child) |
||
1960 | { |
||
1961 | $type = $child->getName(); |
||
1962 | $name = $child['name']; |
||
1963 | |||
1964 | // Does this node exist? |
||
1965 | $fields = $source->xpath($type . '[@name="' . $name . '"]'); |
||
1966 | |||
1967 | if (empty($fields)) |
||
1968 | { |
||
1969 | // This node does not exist, so add it. |
||
1970 | self::addNode($source, $child); |
||
1971 | } |
||
1972 | else |
||
1973 | { |
||
1974 | // This node does exist. |
||
1975 | switch ($type) |
||
1976 | { |
||
1977 | case 'field': |
||
1978 | self::mergeNode($fields[0], $child); |
||
1979 | break; |
||
1980 | |||
1981 | default: |
||
1982 | self::mergeNodes($fields[0], $child); |
||
1983 | break; |
||
1984 | } |
||
1985 | } |
||
1986 | } |
||
1987 | } |
||
1988 | } |
||
1989 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.