Skip to content

Commit 6daa207

Browse files
committed
New: Conditional validators. Using the new ValidationOptions->dependsOn() method you can conditionally have a validator apply based on the value of another field, another field having a value at all, or providing your own conditional check function.
DD-2957
1 parent 66dfd78 commit 6daa207

File tree

2 files changed

+128
-35
lines changed

2 files changed

+128
-35
lines changed

Editor/Validate.php

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
<?php
22

33
/**
4-
* DataTables PHP libraries.
5-
*
6-
* PHP libraries for DataTables and DataTables Editor.
7-
*
8-
* @author SpryMedia
9-
* @copyright 2012-2014 SpryMedia ( http://sprymedia.co.uk )
10-
* @license http://editor.datatables.net/license DataTables Editor
4+
* Validation methods for DataTables Editor.
115
*
126
* @see http://editor.datatables.net
137
*/
@@ -131,6 +125,30 @@ public static function __callStatic($name, $arguments)
131125
}
132126
}
133127

128+
/**
129+
* During validation, check if the validator is conditional.
130+
*
131+
* @internal
132+
*
133+
* @param mixed $val Field's value to validate
134+
* @param ValidateOptions|null $opts Validation options
135+
* @param array $data Row's submitted data
136+
* @param array $host Host information
137+
*
138+
* @return bool `true` if there is no condition, or if there is one and the condition
139+
* matches, or `false` if there is a condition and it doesn't match.
140+
*/
141+
public static function _conditional($val, $opts, $data, $host)
142+
{
143+
if ($opts === null) {
144+
// No options, so there can be no condition
145+
return true;
146+
}
147+
148+
// Otherwise, let the options dependency runner return the value
149+
return $opts->runDepends($val, $data, $host);
150+
}
151+
134152
/**
135153
* Extend the options from the user function and the validation function
136154
* with core defaults.
@@ -169,8 +187,15 @@ public static function _extend($userOpts, $prop, $fnOpts)
169187
*
170188
* @internal
171189
*/
172-
public static function _common($val, $opts)
190+
public static function _common($val, $opts, $data, $host)
173191
{
192+
// Check if the validator should be applied. If not, then it will pass (i.e. as if
193+
// there was no validator). If the validator should apply, fall through to the actual
194+
// validator function.
195+
if (Validate::_conditional($val, $opts, $data, $host) === false) {
196+
return true;
197+
}
198+
174199
$optional = $opts->optional();
175200
$empty = $opts->allowEmpty();
176201

@@ -284,7 +309,7 @@ public static function basic($cfg = null)
284309
$opts = ValidateOptions::select($cfg);
285310

286311
return static function ($val, $data, $field, $host) use ($opts) {
287-
$common = Validate::_common($val, $opts);
312+
$common = Validate::_common($val, $opts, $data, $host);
288313

289314
return $common === false ?
290315
$opts->message() :
@@ -318,7 +343,7 @@ public static function required($cfg = null)
318343
$opts->optional(false);
319344

320345
return static function ($val, $data, $field, $host) use ($opts) {
321-
$common = Validate::_common($val, $opts);
346+
$common = Validate::_common($val, $opts, $data, $host);
322347

323348
return $common === false ?
324349
$opts->message() :
@@ -347,7 +372,7 @@ public static function notEmpty($cfg = null)
347372
$opts->allowEmpty(false);
348373

349374
return static function ($val, $data, $field, $host) use ($opts) {
350-
$common = Validate::_common($val, $opts);
375+
$common = Validate::_common($val, $opts, $data, $host);
351376

352377
return $common === false ?
353378
$opts->message() :
@@ -371,7 +396,7 @@ public static function boolean($cfg = null)
371396
$opts = ValidateOptions::select($cfg);
372397

373398
return static function ($val, $data, $field, $host) use ($opts) {
374-
$common = Validate::_common($val, $opts);
399+
$common = Validate::_common($val, $opts, $data, $host);
375400

376401
if ($common !== null) {
377402
return $common === false ?
@@ -408,7 +433,7 @@ public static function numeric($decimal = '.', $cfg = null)
408433
$opts = ValidateOptions::select($cfg);
409434

410435
return static function ($val, $data, $field, $host) use ($opts, $decimal) {
411-
$common = Validate::_common($val, $opts);
436+
$common = Validate::_common($val, $opts, $data, $host);
412437

413438
if ($common !== null) {
414439
return $common === false ?
@@ -447,7 +472,7 @@ public static function minNum($min, $decimal = '.', $cfg = null)
447472
$opts = ValidateOptions::select($cfg);
448473

449474
return static function ($val, $data, $field, $host) use ($opts, $min, $decimal) {
450-
$common = Validate::_common($val, $opts);
475+
$common = Validate::_common($val, $opts, $data, $host);
451476

452477
if ($common !== null) {
453478
return $common === false ?
@@ -492,7 +517,7 @@ public static function maxNum($max, $decimal = '.', $cfg = null)
492517
$opts = ValidateOptions::select($cfg);
493518

494519
return static function ($val, $data, $field, $host) use ($opts, $max, $decimal) {
495-
$common = Validate::_common($val, $opts);
520+
$common = Validate::_common($val, $opts, $data, $host);
496521

497522
if ($common !== null) {
498523
return $common === false ?
@@ -537,7 +562,7 @@ public static function minMaxNum($min, $max, $decimal = '.', $cfg = null)
537562
$opts = ValidateOptions::select($cfg);
538563

539564
return static function ($val, $data, $field, $host) use ($opts, $min, $max, $decimal) {
540-
$common = Validate::_common($val, $opts);
565+
$common = Validate::_common($val, $opts, $data, $host);
541566

542567
if ($common !== null) {
543568
return $common === false ?
@@ -590,7 +615,7 @@ public static function email($cfg = null)
590615
$opts = ValidateOptions::select($cfg);
591616

592617
return static function ($val, $data, $field, $host) use ($opts) {
593-
$common = Validate::_common($val, $opts);
618+
$common = Validate::_common($val, $opts, $data, $host);
594619

595620
if ($common !== null) {
596621
return $common === false ?
@@ -623,7 +648,7 @@ public static function minLen($min, $cfg = null)
623648
$opts = ValidateOptions::select($cfg);
624649

625650
return static function ($val, $data, $field, $host) use ($min, $opts) {
626-
$common = Validate::_common($val, $opts);
651+
$common = Validate::_common($val, $opts, $data, $host);
627652

628653
if ($common !== null) {
629654
return $common === false ?
@@ -660,7 +685,7 @@ public static function maxLen($max, $cfg = null)
660685
$opts = ValidateOptions::select($cfg);
661686

662687
return static function ($val, $data, $field, $host) use ($max, $opts) {
663-
$common = Validate::_common($val, $opts);
688+
$common = Validate::_common($val, $opts, $data, $host);
664689

665690
if ($common !== null) {
666691
return $common === false ?
@@ -695,7 +720,7 @@ public static function minMaxLen($min, $max, $cfg = null)
695720
$opts = ValidateOptions::select($cfg);
696721

697722
return static function ($val, $data, $field, $host) use ($opts, $min, $max) {
698-
$common = Validate::_common($val, $opts);
723+
$common = Validate::_common($val, $opts, $data, $host);
699724

700725
if ($common !== null) {
701726
return $common === false ?
@@ -737,7 +762,7 @@ public static function ip($cfg = null)
737762
$opts = ValidateOptions::select($cfg);
738763

739764
return static function ($val, $data, $field, $host) use ($opts) {
740-
$common = Validate::_common($val, $opts);
765+
$common = Validate::_common($val, $opts, $data, $host);
741766

742767
if ($common !== null) {
743768
return $common === false ?
@@ -767,7 +792,7 @@ public static function url($cfg = null)
767792
$opts = ValidateOptions::select($cfg);
768793

769794
return static function ($val, $data, $field, $host) use ($opts) {
770-
$common = Validate::_common($val, $opts);
795+
$common = Validate::_common($val, $opts, $data, $host);
771796

772797
if ($common !== null) {
773798
return $common === false ?
@@ -800,7 +825,7 @@ public static function xss($cfg = null)
800825
$opts = ValidateOptions::select($cfg);
801826

802827
return static function ($val, $data, $field, $host) use ($opts) {
803-
$common = Validate::_common($val, $opts);
828+
$common = Validate::_common($val, $opts, $data, $host);
804829

805830
if ($common !== null) {
806831
return $common === false ?
@@ -833,7 +858,7 @@ public static function values($values, $cfg = null)
833858
$opts = ValidateOptions::select($cfg);
834859

835860
return static function ($val, $data, $field, $host) use ($values, $opts) {
836-
$common = Validate::_common($val, $opts);
861+
$common = Validate::_common($val, $opts, $data, $host);
837862

838863
if ($common !== null) {
839864
return $common === false ?
@@ -866,7 +891,7 @@ public static function noTags($cfg = null)
866891
$opts = ValidateOptions::select($cfg);
867892

868893
return static function ($val, $data, $field, $host) use ($opts) {
869-
$common = Validate::_common($val, $opts);
894+
$common = Validate::_common($val, $opts, $data, $host);
870895

871896
if ($common !== null) {
872897
return $common === false ?
@@ -902,7 +927,7 @@ public static function dateFormat($format, $cfg = null)
902927
$opts = ValidateOptions::select($cfg);
903928

904929
return static function ($val, $data, $field, $host) use ($format, $opts) {
905-
$common = Validate::_common($val, $opts);
930+
$common = Validate::_common($val, $opts, $data, $host);
906931

907932
if ($common !== null) {
908933
return $common === false ?
@@ -945,7 +970,7 @@ public static function unique($cfg = null, $column = null, $table = null, $db =
945970
$opts = ValidateOptions::select($cfg);
946971

947972
return static function ($val, $data, $field, $host) use ($opts, $column, $table, $db) {
948-
$common = Validate::_common($val, $opts);
973+
$common = Validate::_common($val, $opts, $data, $host);
949974

950975
if ($common !== null) {
951976
return $common === false ?
@@ -1010,7 +1035,7 @@ public static function dbValues($cfg = null, $column = null, $table = null, $db
10101035
$opts = ValidateOptions::select($cfg);
10111036

10121037
return static function ($val, $data, $field, $host) use ($opts, $column, $table, $db, $values) {
1013-
$common = Validate::_common($val, $opts);
1038+
$common = Validate::_common($val, $opts, $data, $host);
10141039

10151040
if ($common !== null) {
10161041
return $common === false ?

Editor/ValidateOptions.php

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
<?php
22

33
/**
4-
* DataTables PHP libraries.
5-
*
6-
* PHP libraries for DataTables and DataTables Editor.
7-
*
8-
* @author SpryMedia
9-
* @copyright 2012-2014 SpryMedia ( http://sprymedia.co.uk )
10-
* @license http://editor.datatables.net/license DataTables Editor
4+
* Validation Options for DataTables Editor.
115
*
126
* @see http://editor.datatables.net
137
*/
@@ -21,10 +15,24 @@
2115
*/
2216
class ValidateOptions extends Ext
2317
{
18+
/** @var bool */
2419
private $_empty = true;
20+
21+
/** @var string */
2522
private $_message = 'Input not valid';
23+
24+
/** @var bool */
2625
private $_optional = true;
2726

27+
/** @var string */
28+
private $_dependsField;
29+
30+
/** @var mixed */
31+
private $_dependsValue;
32+
33+
/** @var callable(mixed, array, array): boolean */
34+
private $_dependsFn;
35+
2836
public function __construct($opts = null)
2937
{
3038
if ($opts) {
@@ -40,6 +48,28 @@ public function __construct($opts = null)
4048
}
4149
}
4250

51+
/**
52+
* Apply a dependency for the validator.
53+
*
54+
* @param callable(mixed, array, array): boolean|string $field Function that performances a
55+
* dependency check, or a field name that this validator depends upon
56+
* @param mixed $value If `$field` is given as a string, this can be a value, or an array of
57+
* values that the field name given needs the value to match.
58+
*
59+
* @return $this Self for chaining
60+
*/
61+
public function dependsOn($field, $value = null)
62+
{
63+
if (is_callable($field)) {
64+
$this->_dependsFn = $field;
65+
} else {
66+
$this->_dependsField = $field;
67+
$this->_dependsValue = $value;
68+
}
69+
70+
return $this;
71+
}
72+
4373
/**
4474
* Get / set the error message to use if validation fails.
4575
*
@@ -108,4 +138,42 @@ public static function select($user)
108138

109139
return new ValidateOptions();
110140
}
141+
142+
/**
143+
* Run the dependency check.
144+
*
145+
* @internal
146+
*
147+
* @param mixed $val Field's value to validate
148+
* @param array $data Row's submitted data
149+
* @param array $host Host information
150+
*
151+
* @return bool `true` if there is no condition, or if there is one and the condition
152+
* matches, or `false` if there is a condition and it doesn't match.
153+
*/
154+
public function runDepends($val, $data, $host)
155+
{
156+
if ($this->_dependsFn !== null) {
157+
// External function - call it
158+
$fn = $this->_dependsFn;
159+
160+
return $fn($val, $data, $host);
161+
} elseif ($this->_dependsField) {
162+
// Get the value that was submitted for the dependent field
163+
$depFieldVal = $this->_readProp($this->_dependsField, $data);
164+
165+
if ($this->_dependsValue !== null) {
166+
// Field and value
167+
return is_array($this->_dependsValue)
168+
? in_array($depFieldVal, $this->_dependsValue)
169+
: ($depFieldVal === $this->_dependsValue);
170+
}
171+
172+
// Just a field - check that the field has a value
173+
return $depFieldVal !== null && $depFieldVal !== '';
174+
}
175+
176+
// Default is to apply the validator
177+
return true;
178+
}
111179
}

0 commit comments

Comments
 (0)