Passed
Push — develop ( 03421b...c9efed )
by steve
39:12 queued 25:46
created

Field::validate()   C

Complexity

Conditions 12
Paths 12

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 19.5936

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 12
eloc 25
c 2
b 0
f 1
nc 12
nop 0
dl 0
loc 41
ccs 15
cts 24
cp 0.625
crap 19.5936
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.newicon.net/neon
4
 * @copyright Copyright (c) 2016 Newicon Ltd
5
 * @license http://www.newicon.net/neon/license
6
 */
7
8
namespace neon\core\form\fields;
9
10
11
use InvalidArgumentException;
12
use Neon;
13
use neon\core\form\Deprecated;
14
use neon\core\form\exceptions\InvalidNameFormat;
15
use neon\core\form\Form;
16
use neon\core\form\FormField;
17
use neon\core\form\interfaces\IField;
18
use neon\core\form\Model;
0 ignored issues
show
Bug introduced by
The type neon\core\form\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use neon\core\grid\query\IQuery;
20
use neon\core\helpers\Arr;
21
use neon\core\helpers\Html;
22
use neon\core\traits\PropertiesTrait;
23
use yii\base\NotSupportedException;
24
use yii\base\UnknownPropertyException;
25
26
/**
27
 * Class Field
28
 * @package neon\core\forms
29
 * @property string $name
30
 * @property Model $model
31
 * @property array $options
32
 * @property string $hint
33
 * @property string $label
34
 * @property string $value
35
 * @property Form $form
36
 */
37
class Field extends FormField implements IField
38
{
39
	use PropertiesTrait;
40
41
	/**
42
	 * @var array the default options for the input tags. The parameter passed to individual input methods
43
	 * (e.g. [[textInput()]]) will be merged with this property when rendering the input tag.
44
	 *
45
	 * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
46
	 *
47
	 * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
48
	 */
49
	public $inputOptions = [];
50
51
	public $readOnly = false;
52
53
	public $printOnly = false;
54
55
	public $mapField = false;
56
57
	public $showIf = [];
58
59
	public $placeholderLabel = false;
60
61
	/**
62
	 * Get the parent form that this item belongs to
63
	 * @return Form
64
	 */
65 36
	public function getForm()
66
	{
67 36
		$form = parent::getForm();
68 36
		if ($form === null) {
69
			throw new InvalidArgumentException('The field must have a form object defined. This happens when the field is added to a form object');
70
		}
71 36
		return $form;
72
	}
73
74
	/**
75
	 * @var array the default options for the error tags. The parameter passed to [[error()]] will be
76
	 * merged with this property when rendering the error tag.
77
	 * The following special options are recognized:
78
	 *
79
	 * - tag: the tag name of the container element. Defaults to "div".
80
	 * - encode: whether to encode the error output. Defaults to true.
81
	 *
82
	 * If you set a custom `id` for the error element, you may need to adjust the [[$selectors]] accordingly.
83
	 *
84
	 * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
85
	 */
86
	public $errorOptions = ['class' => 'help-block', 'tag' => 'span'];
87
	/**
88
	 * @var array the default options for the label tags. The parameter passed to [[label()]] will be
89
	 * merged with this property when rendering the label tag.
90
	 * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
91
	 */
92
	public $labelAttributes = ['class' => 'control-label from-group__label'];
93
	/**
94
	 * @var array the default options for the hint tags. The parameter passed to [[hint()]] will be
95
	 * merged with this property when rendering the hint tag.
96
	 * The following special options are recognized:
97
	 *
98
	 * - tag: the tag name of the container element. Defaults to "div".
99
	 *
100
	 * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
101
	 */
102
	public $hintOptions = ['class' => 'hint-block hint-top'];
103
	/**
104
	 * @var bool whether to enable client-side data validation.
105
	 * If not set, it will take the value of [[ActiveForm::enableClientValidation]].
106
	 */
107
	public $enableClientValidation;
108
	/**
109
	 * @var bool whether to enable AJAX-based data validation.
110
	 * If not set, it will take the value of [[ActiveForm::enableAjaxValidation]].
111
	 */
112
	public $enableAjaxValidation;
113
	/**
114
	 * @var bool whether to enable AJAX-based form submission
115
	 */
116
	public $enableAjaxSubmission;
117
	/**
118
	 * @var bool whether to perform validation when the value of the input field is changed.
119
	 * If not set, it will take the value of [[ActiveForm::validateOnChange]].
120
	 */
121
	public $validateOnChange;
122
	/**
123
	 * @var bool whether to perform validation when the input field loses focus.
124
	 * If not set, it will take the value of [[ActiveForm::validateOnBlur]].
125
	 */
126
	public $validateOnBlur;
127
	/**
128
	 * @var bool whether to perform validation while the user is typing in the input field.
129
	 * If not set, it will take the value of [[ActiveForm::validateOnType]].
130
	 * @see validationDelay
131
	 */
132
	public $validateOnType;
133
	/**
134
	 * @var int number of milliseconds that the validation should be delayed when the user types in the field
135
	 * and [[validateOnType]] is set true.
136
	 * If not set, it will take the value of [[ActiveForm::validationDelay]].
137
	 */
138
	public $validationDelay;
139
	/**
140
	 * @var array the jQuery selectors for selecting the container, input and error tags.
141
	 * The array keys should be "container", "input", and/or "error", and the array values
142
	 * are the corresponding selectors. For example, `['input' => '#my-input']`.
143
	 *
144
	 * The container selector is used under the context of the form, while the input and the error
145
	 * selectors are used under the context of the container.
146
	 *
147
	 * You normally do not need to set this property as the default selectors should work well for most cases.
148
	 */
149
	public $selectors = [];
150
	/**
151
	 * @var array different parts of the field (e.g. input, label). This will be used together with
152
	 * [[template]] to generate the final field HTML code. The keys are the token names in [[template]],
153
	 * while the values are the corresponding HTML code. Valid tokens include `{input}`, `{label}` and `{error}`.
154
	 * Note that you normally don't need to access this property directly as
155
	 * it is maintained by various methods of this class.
156
	 */
157
	public $parts = [];
158
159
	protected $_value = null;
160
	protected $_sanitisedValue = null;
161
	protected $_name;
162
	protected $_hint;
163
	protected $_label = null;
164
	protected $_classLabel;
165
166
	/**
167
	 * By default the form fields will strip tags before setting the fields value
168
	 * you can override this property in child Field classes to allow specific tags
169
	 *
170
	 * @var string|null - default null will remove all tags
171
	 * specify allowed tags for example set this variable to be "<br><a><strong>" to allow all br, a and strong tags
172
	 * ```php
173
	 * protected $allowableTags = "<br><a><strong>"
174
	 * ```
175
	 */
176
	protected $allowableTags = '<br><em><i><u><b><s><mark><strong>';
177
178
	/**
179
	 * @var string the key to use when outputting the fields data
180
	 */
181
	protected $_dataKey;
182
183
	/**
184
	 * Whether this field is required
185
	 * @var bool
186
	 */
187
	protected $_required = false;
188
189
	public $attributes = [];
190
191
	/**
192
	 * Field constructor.
193
	 * @param array|string $name
194
	 * @param array $config
195
	 * @throws InvalidNameFormat
196
	 */
197 114
	public function __construct($name=[], array $config=[])
198
	{
199
		// The $name field can also be a configuration array
200 114
		if (is_array($name)) {
201 40
			$config = $name;
202
		}
203
		// if a name has been specified then add this to the config
204 74
		elseif (is_string($name)) {
0 ignored issues
show
introduced by
The condition is_string($name) is always true.
Loading history...
205 74
			$config['name'] = $name;
206
		}
207
		// -----
208
		// By this point $config should be the required minimum config
209
		// i.e. has a `name` property
210
		// -----
211 114
		if (isset($config['name']))
212 114
			$this->setName($config['name']);
213
214
		// Configure the field - the name property must be set by this point.
215
		// as many configuration options such as adding Validators and attaching
216
		// the file to the form use the name as an index
217 106
		if (!empty($config)) {
218 106
			Neon::configure($this, $config);
219
		}
220
221
		// check the Field has a sensible configuration
222 106
		$this->preInitCheck();
223
224 106
		$this->init();
225 106
	}
226
227
	/**
228
	 * Check the configuration and throw exceptions
229
	 * @throws InvalidArgumentException
230
	 */
231 106
	public function preInitCheck()
232
	{
233
		// check the Field has a sensible configuration
234 106
		if ($this->_name == null) {
235
			throw new InvalidArgumentException('You must set a name property for a form field');
236
		}
237 106
	}
238
239
	/**
240
	 * @inheritdoc
241
	 */
242 100
	public function init()
243 100
	{}
244
245
	/**
246
	 * @inheritdoc
247
	 * @return string
248
	 */
249
	public function run()
250
	{
251
		$this->registerScripts($this->getView());
252
		return Html::tag($this->getComponentName(), '', ['v-bind' => $this->toJson()]);
253
	}
254
255
	/**
256
	 * This function is old - before the form rendering was handled by vue
257
	 * The idea is that is returns just the input field allowing you within a template file
258
	 * to place labels and errors your self.
259
	 * Really you can do this by simply hiding elements in css rather than changing the forms
260
	 * output html.  Therefore this function could apply a class or have an option instructing vue
261
	 * to hide the labels and errors etc.
262
	 */
263
	public function getFieldHtml()
264
	{
265
		return $this->run();
266
	}
267
268
	/**
269
	 * Set the js/html component name
270
	 * defaults to the class name with dashes instead of backslashes
271
	 * @param string $value
272
	 * @return $this
273
	 */
274
	public function setComponentName($value)
275
	{
276
		$this->_componentName = $value;
277
		return $this;
278
	}
279
280
	/**
281
	 * Get the js/html component name for this field
282
	 * @return mixed|null
283
	 */
284
	public function getComponentName()
285
	{
286
		if ($this->_componentName === null)
287
			$this->_componentName = str_replace('\\', '-', get_class($this));
288
		return $this->_componentName;
289
	}
290
291
	/**
292
	 * @var string - component name
293
	 * @see setComponentName
294
	 * @see getComponentName
295
	 */
296
	protected $_componentName = null;
297
298
	/**
299
	 * @inheritdoc
300
	 */
301
	public function registerScripts($view)
302
	{
303
	}
304
305
	/**
306
	 * Used when outputting form data via the getData method. Sets the key in the output array for this fields data
307
	 * If not specified will return the fields name as the key for the data
308
	 * @see \neon\core\form\Form::getData()
309
	 * @return mixed
310
	 */
311 58
	public function getDataKey()
312
	{
313 58
		if ($this->_dataKey === null)
314 58
			return $this->getName();
315 4
		return $this->_dataKey;
316
	}
317
318
	/**
319
	 * Set the data key
320
	 *
321
	 * @param string $key
322
	 *
323
	 * @return $this is a chainable method
324
	 */
325 4
	public function setDataKey($key)
326
	{
327 4
		$this->_dataKey = $key;
328 4
		return $this;
329
	}
330
331
	/**
332
	 * This function represents the formatted data of the fields value
333
	 * the getValue represents the field value in the context of the input control and may have different formatting to
334
	 * the data wished to be returned by the form.
335
	 * Override this function in children Field type classes to change the output
336
	 * This function is called when the parent forms getData function is called
337
	 *
338
	 * @return mixed
339
	 */
340 30
	public function getData()
341
	{
342 30
		return $this->getValue();
343
	}
344
345
	/**
346
	 * @inheritdoc
347
	 */
348 98
	public function getValue()
349
	{
350
		// return sanitised data only
351 98
		if ($this->_sanitisedValue === null)
352 98
			$this->_sanitisedValue = $this->sanitiseInput($this->getUnsafeValue());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getUnsafeValue() targeting neon\core\form\fields\Field::getUnsafeValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
353 98
		return $this->_sanitisedValue;
354
	}
355
356
	/**
357
	 * Gets the raw, unsanitised value as posted by the user input
358
	 * @return null
359
	 */
360 98
	protected function getUnsafeValue()
361
	{
362 98
		return $this->_value;
363
	}
364
365
	/**
366
	 * @inheritdoc
367
	 */
368 88
	public function setValue($value)
369
	{
370 88
		$this->_value = $value;
371
		// note that data needs to be sanitised if we are going to use it
372 88
		$this->_sanitisedValue = null;
373 88
		return $this;
374
	}
375
376
	/**
377
	 * @inheritdoc
378
	 */
379 4
	public function setValueFromDb($value)
380
	{
381 4
		$this->setValue($value);
382
		// database data should have already been sanitised
383 4
		$this->_sanitisedValue = $value;
384 4
		return $this;
385
	}
386
387
	/**
388
	 * Sanitise the value
389
	 * @param string $value
390
	 * @return string sanitised
391
	 */
392 98
	protected function sanitiseInput($value)
393
	{
394 98
		if (empty($value))
395 26
			return $value;
396
397 78
		profile_begin('form sanitise');
398 78
		$sanitise = Html::sanitise($value, $this->allowableTags);
399 78
		profile_end('form sanitise');
400 78
		return $sanitise;
401
	}
402
403
	/**
404
	 * Purify the value - it is run through HTMLPurifier and then strip tags
405
	 * @param string $value
406
	 * @return string sanitised
407
	 */
408
	protected function purifyInput($value)
409
	{
410
		if (empty($value))
411
			return $value;
412
413
		profile_begin('form purify');
414
		$sanitise = Html::purify($value, $this->allowableTags);
415
		profile_end('form purify');
416
		return $sanitise;
417
	}
418
419
	/**
420
	 * @inheritdoc
421
	 */
422 12
	public function getHint()
423
	{
424 12
		return $this->_hint;
425
	}
426
427
	/**
428
	 * @inheritdoc
429
	 */
430 4
	public function setHint($hint)
431
	{
432 4
		$this->_hint = $hint;
433 4
		return $this;
434
	}
435
436
	/**
437
	 * Set the placeholder text for the field
438
	 *
439
	 * @param $placeholder
440
	 *
441
	 * @return $this
442
	 */
443 4
	public function setPlaceholder($placeholder)
444
	{
445 4
		$this->_placeholder = $placeholder;
446 4
		return $this;
447
	}
448
449
	protected $_placeholder = '';
450
451
	/**
452
	 * Get the string placeholder
453
	 * @return string
454
	 */
455 12
	public function getPlaceholder()
456
	{
457 12
		return $this->_placeholder;
458
	}
459
460
	/**
461
	 * Get an option from the internal options array
462
	 *
463
	 * @param string $name the option key to look up
464
	 * @param mixed  $default value to return if there is no options with the key of $name
465
	 *
466
	 * @return mixed
467
	 */
468
	public function getOption($name, $default = '')
469
	{
470
		return array_key_exists($name, $this->inputOptions) ? $this->inputOptions[$name] : $default;
471
	}
472
473
	/**
474
	 * @inheritdoc
475
	 */
476 2
	public function isForm()
477
	{
478 2
		return false;
479
	}
480
481
	/**
482
	 * @inheritdoc
483
	 */
484 14
	public function getLabel()
485
	{
486 14
		return $this->_label;
487
	}
488
489
	/**
490
	 * @inheritdoc
491
	 */
492 6
	public function setLabel($label)
493
	{
494 6
		$this->_label = $label;
495 6
		return $this;
496
	}
497
498
	/**
499
	 * @inheritdoc
500
	 */
501 12
	public function getClassLabel()
502
	{
503 12
		return $this->_classLabel;
504
	}
505
506
	/**
507
	 * @inheritdoc
508
	 */
509 4
	public function setClassLabel($label)
510
	{
511 4
		$this->_classLabel = $label;
512 4
		return $this;
513
	}
514
515
	/**
516
	 * Get the html for the field label
517
	 *
518
	 * @return string will return an empty string if no label is specified
519
	 */
520
	public function getLabelHtml()
521
	{
522
		return $this->getLabel() ? Html::activeLabel($this->getForm(), $this->getName(), $this->labelAttributes ) : '';
0 ignored issues
show
Bug introduced by
$this->getForm() of type neon\core\form\Form is incompatible with the type yii\base\Model expected by parameter $model of yii\helpers\BaseHtml::activeLabel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

522
		return $this->getLabel() ? Html::activeLabel(/** @scrutinizer ignore-type */ $this->getForm(), $this->getName(), $this->labelAttributes ) : '';
Loading history...
523
	}
524
525
	/**
526
	 * Render the hint HTML
527
	 *
528
	 * @return string html
529
	 */
530
	public function getHintHtml()
531
	{
532
		$tag = Arr::remove($this->hintOptions, 'tag', 'div');
533
		return Html::tag($tag, $this->getHint(), $this->hintOptions);
534
	}
535
536
	/**
537
	 * @return string html representing the error
538
	 */
539
	public function getErrorHtml()
540
	{
541
		$error = $this->getFirstError();
542
		if ($error === '')
543
			return '';
544
		$options = $this->errorOptions;
545
		$tag = Arr::remove($options, 'tag', 'div');
546
		$encode = Arr::remove($options, 'encode', true);
547
		return Html::tag($tag, $encode ? Html::encode($error) : $error, $options);
548
	}
549
550
	/**
551
	 * @return array of options for the field, this is usually piped into the html render functions within the Html
552
	 * helper class which typically calle \neon\core\helpers\Html::renderTagAttributes()
553
	 */
554
	public function getOptions()
555
	{
556
		return $this->inputOptions;
557
	}
558
559
	/**
560
	 * set options for the field - will merge by the default options
561
	 *
562
	 * @param array   $options
563
	 * @param bool $replace by default options are merged if you wish to overwrite all options set this to true
564
	 *
565
	 * @return $this - is chainable method
566
	 */
567
	public function setOptions($options, $replace = false)
568
	{
569
		if (!$replace) {
570
			$options = Arr::merge($this->inputOptions, $options);
571
		}
572
		// TODO - consolidate on inputOptions or attributes?
573
		// inputOptions came before, but
574
		// attributes is the terminology used in Form.php
575
		$this->inputOptions = $options;
576
		$this->attributes = $options;
577
		return $this;
578
	}
579
580
	/**
581
	 * Returns the JS options for the field.
582
	 * Ugly Yii function
583
	 *
584
	 * @return array the JS options
585
	 */
586
	public function getClientOptions()
587
	{
588
		$options = [];
589
		// only get the options that are different from the default ones (set in yii.activeForm.js)
590
		return array_diff_assoc($options, [
591
			'validateOnChange' => true,
592
			'validateOnBlur' => true,
593
			'encodeError' => true,
594
			'error' => '.help-block',
595
		]);
596
	}
597
598
	/**
599
	 * @inheritdoc
600
	 */
601 36
	public function validate()
602
	{
603 36
		$validators = $this->getValidators();
604 36
		if (count($validators)==0)
605
			return true;
606
607 36
		$isEmpty = empty($this->getValue());
608 36
		$hasErrors = $this->hasError();
609 36
		$form = $this->getForm();
610 36
		$attribute = $this->getName();
611 36
		$unsafeValue = $this->getUnsafeValue();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $unsafeValue is correct as $this->getUnsafeValue() targeting neon\core\form\fields\Field::getUnsafeValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
612
613 36
		foreach ($validators as $validator) {
614
			// see if we can skip this validator
615 36
			if (($validator->skipOnEmpty && $isEmpty) || ($validator->skipOnError && $hasErrors)) {
616 2
				continue;
617
			}
618
619
			// ok - now apply the validator
620
			try {
621 36
				if ($validator->when == null || call_user_func($validator->when, $form, $attribute)) {
622 36
					if (!$validator->validate($unsafeValue, $error)) {
623 36
						$this->addError($error);
624
					}
625
				}
626
			} catch (NotSupportedException $e) {
627
				try {
628
					// in this case we need to try validateAttribute which will set
629
					// the error back on this field via the form addError method
630
					$validator->validateAttribute($form, $attribute);
0 ignored issues
show
Bug introduced by
$form of type neon\core\form\Form is incompatible with the type yii\base\Model expected by parameter $model of yii\validators\Validator::validateAttribute(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

630
					$validator->validateAttribute(/** @scrutinizer ignore-type */ $form, $attribute);
Loading history...
631
				} catch (UnknownPropertyException $e) {
632
					throw new UnknownPropertyException(
633
						'You are using a validator ' . get_class($validator) . ' that has a when clause or needs to use validateAttribute. '
634
						. 'This requires you to have <br><br>'
635
						. 'public function get' . ucfirst($attribute) . "<br>{ <br>&nbsp;&nbsp;return \$this->getField(&quot;$attribute&quot;)->getValue()); <br>}"
636
						. '<br><br>on the form. You may also need the equivalent set' . ucfirst($attribute) . ' method. <br>Error was ' . $e->getMessage());
637
				}
638
			}
639
		}
640
641 36
		return !$this->hasError();
642
	}
643
644
	/**
645
	 * @return array
646
	 * @deprecated use getProperties()
647
	 * @alias getProperties
648
	 */
649
	public function fields()
650
	{
651
		return $this->getProperties();
652
	}
653
654
	/**
655
	 * Return a list of properties that are serializable
656
	 * Each property should be accessible via $object->{propertyName}
657
	 * @return array
658
	 */
659 12
	public function getProperties()
660
	{
661
		return [
662 12
			'class', 'classLabel', 'id', 'name', 'label', 'hint', 'value',
663
			'required', 'dataKey', 'validators', 'placeholder', 'deleted',
664
			'order', 'mapField', 'errors', 'visible', 'inline', 'readOnly',
665
			'attributes', 'printOnly', 'showIf', 'placeholderLabel', 'enableClientValidation'
666
		];
667
	}
668
669
	/**
670
	 * @return array
671
	 */
672
	public function getPropertiesToSave()
673
	{
674
		$props = $this->toArray();
675
		Arr::remove($props, 'id');
676
		return $props;
677
	}
678
679
	/**
680
	 * Get the full class name
681
	 * @return string
682
	 */
683 12
	public function getClass()
684
	{
685 12
		return get_class($this);
686
	}
687
688
	/* ============================================================================================
689
	 * Phoebe and Daedalus specific functions
690
	 * ============================================================================================
691
	 */
692
693
	/**
694
	 * The DDS data type to store the value of the field
695
	 * @var string
696
	 */
697
	public $ddsDataType = 'textshort';
698
699
	/**
700
	 * Get the definition of a field for external storage
701
	 * Override this to remove anything that shouldn't make it
702
	 * as part of the definition
703
	 * @return array [
704
	 *   name - the field name
705
	 *   dataType - the daedalus data type
706
	 *   label - a label for the field
707
	 *   description - a user facing description for the field
708
	 *   choices - the set of associated choice (if any)
709
	 *   linkClass - the type of class linked to (if any)
710
	 *   mapField - whether or not this is a field used in maps
711
	 *   widget - a serialised definition of the widget
712
	 * ]
713
	 */
714 6
	public function exportDefinition()
715
	{
716
		$fieldDefinition = [
717 6
			'memberRef' => $this->getName(),
718 6
			'name' => $this->getName(),
719 6
			'dataType' => $this->ddsDataType,
720 6
			'label' => $this->getLabel(),
721 6
			'description' => $this->getHint(),
722 6
			'choices' => $this->extractChoices(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->extractChoices() targeting neon\core\form\fields\Field::extractChoices() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
723 6
			'linkClass' => $this->extractLinkClass(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->extractLinkClass() targeting neon\core\form\fields\Field::extractLinkClass() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
724 6
			'mapField' => $this->mapField,
725 6
			'deleted' => $this->deleted,
726
			// we must ensure that fields used for form state between requests 
727
			// are not permanently stored in the definition
728 6
			'definition' => $this->toArray(['errors'])
729
		];
730
731 6
		return $fieldDefinition;
732
	}
733
734
	/**
735
	 * extract the choice for a particular field.
736
	 * Override this if you need to provide that functionality
737
	 * @return null|array  an array of [key=>value] pairs
738
	 */
739 6
	protected function extractChoices()
740
	{
741 6
		return null;
742
	}
743
744
	/**
745
	 * extract the link class for a particular field
746
	 * Override this if you need to provide that functionality
747
	 * @return null|string  the link class
748
	 */
749 6
	protected function extractLinkClass()
750
	{
751 6
		return null;
752
	}
753
754
	// TODO: remove the need for this function!
755
	public function getDdsName()
756
	{
757
		return preg_replace('/[^a-z0-9_]/', '', strtolower(preg_replace('/ +/', '_', $this->getName())));
758
	}
759
760
// endregion
761
762
	/**
763
	 * Get a displayable representation of the fields value to be output to html
764
	 * @return string
765
	 */
766
	public function getValueDisplay($context='')
767
	{
768
		return Html::encode($this->getValue());
769
	}
770
771
// region: Filter Field
772
// ============================================================================
773
774
	/**
775
	 * @inheritdoc
776
	 */
777
	public function getFilterField()
778
	{
779
		$field = $this->toArray();
780
		return Arr::except($field, ['name', 'label', 'hint', 'placeholderLabel']);
781
	}
782
783
	/**
784
	 * @inheritdoc
785
	 */
786
	public function processAsFilter(IQuery $query, $searchData=null)
787
	{
788
		$searchData = ($searchData === null) ? $this->getValue() : $searchData;
789
		// Note: we can not use empty here
790
		// empty will return true for '0' meaning filtering for booleans
791
		// false passed over request (particularly for checkboxes) becomes '0'
792
		$query->where($this->getDataKey(), '=', $searchData);
793
	}
794
// endregion
795
796
	/**
797
	 * Whether this field represents a valid input field and will appear in data output
798
	 * Headings and section fields will not be inputs and therefore not clutter up data output
799
	 * @return bool
800
	 */
801 48
	public function getIsInput()
802
	{
803 48
		return !($this->ddsDataType === null);
804
	}
805
806
	/**
807
	 * Reset the form field's value
808
	 * @return $this;
809
	 */
810
	public function reset()
811
	{
812
		$this->_value = null;
813
		$this->_sanitisedValue = null;
814
		return $this;
815
	}
816
817
	/**
818
	 * @inheritdoc
819
	 */
820
	public function getComponentDetails()
821
	{
822
		if (get_class() == get_called_class()) {
823
			return false;
824
		}
825
		return [
826
			'icon' => 'fa fa-cubes',
827
			'order' => 1000
828
		];
829
	}
830
831
832
	/**
833
	 * !!!!!!!!!!!!!!!!!!
834
	 * !!! DEPRECATED !!!
835
	 * !!!!!!!!!!!!!!!!!!
836
	 *
837
	 * Saves the current field object as a member of the DDS class
838
	 * The DDS class can be specified by the $classType param,
839
	 * if not defined it will use the parent form's' name as the classType
840
	 *
841
	 * @param string|null $classType
842
	 * @param array|null $ddsMembers if not specified it will look up the members of the classType
843
	 * @deprecated
844
	 */
845
	public function ddsSaveDefinition($classType=null, $ddsMembers=null)
846
	{
847
		Deprecated::ddsSaveDefinitionField($this, $classType, $ddsMembers);
0 ignored issues
show
Deprecated Code introduced by
The function neon\core\form\Deprecate...dsSaveDefinitionField() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

847
		/** @scrutinizer ignore-deprecated */ Deprecated::ddsSaveDefinitionField($this, $classType, $ddsMembers);
Loading history...
848
	}
849
}
850