11import { isNil , get , set } from 'min-dash' ;
22import { countDecimals } from '../render/components/util/numberFieldUtil' ;
33import Big from 'big.js' ;
4+ import { clone } from '../util' ;
5+ import { wrapObjectKeysWithUnderscores } from '../util/simple' ;
46
57const EMAIL_PATTERN = / ^ [ a - z A - Z 0 - 9 . ! # $ % & ' * + / = ? ^ _ ` { | } ~ - ] + @ [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] { 0 , 61 } [ a - z A - Z 0 - 9 ] ) ? (?: \. [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] { 0 , 61 } [ a - z A - Z 0 - 9 ] ) ? ) * $ / ;
68const PHONE_PATTERN = / ( \+ | 0 0 ) ( 2 9 7 | 9 3 | 2 4 4 | 1 2 6 4 | 3 5 8 | 3 5 5 | 3 7 6 | 9 7 1 | 5 4 | 3 7 4 | 1 6 8 4 | 1 2 6 8 | 6 1 | 4 3 | 9 9 4 | 2 5 7 | 3 2 | 2 2 9 | 2 2 6 | 8 8 0 | 3 5 9 | 9 7 3 | 1 2 4 2 | 3 8 7 | 5 9 0 | 3 7 5 | 5 0 1 | 1 4 4 1 | 5 9 1 | 5 5 | 1 2 4 6 | 6 7 3 | 9 7 5 | 2 6 7 | 2 3 6 | 1 | 6 1 | 4 1 | 5 6 | 8 6 | 2 2 5 | 2 3 7 | 2 4 3 | 2 4 2 | 6 8 2 | 5 7 | 2 6 9 | 2 3 8 | 5 0 6 | 5 3 | 5 9 9 9 | 6 1 | 1 3 4 5 | 3 5 7 | 4 2 0 | 4 9 | 2 5 3 | 1 7 6 7 | 4 5 | 1 8 0 9 | 1 8 2 9 | 1 8 4 9 | 2 1 3 | 5 9 3 | 2 0 | 2 9 1 | 2 1 2 | 3 4 | 3 7 2 | 2 5 1 | 3 5 8 | 6 7 9 | 5 0 0 | 3 3 | 2 9 8 | 6 9 1 | 2 4 1 | 4 4 | 9 9 5 | 4 4 | 2 3 3 | 3 5 0 | 2 2 4 | 5 9 0 | 2 2 0 | 2 4 5 | 2 4 0 | 3 0 | 1 4 7 3 | 2 9 9 | 5 0 2 | 5 9 4 | 1 6 7 1 | 5 9 2 | 8 5 2 | 5 0 4 | 3 8 5 | 5 0 9 | 3 6 | 6 2 | 4 4 | 9 1 | 2 4 6 | 3 5 3 | 9 8 | 9 6 4 | 3 5 4 | 9 7 2 | 3 9 | 1 8 7 6 | 4 4 | 9 6 2 | 8 1 | 7 6 | 7 7 | 2 5 4 | 9 9 6 | 8 5 5 | 6 8 6 | 1 8 6 9 | 8 2 | 3 8 3 | 9 6 5 | 8 5 6 | 9 6 1 | 2 3 1 | 2 1 8 | 1 7 5 8 | 4 2 3 | 9 4 | 2 6 6 | 3 7 0 | 3 5 2 | 3 7 1 | 8 5 3 | 5 9 0 | 2 1 2 | 3 7 7 | 3 7 3 | 2 6 1 | 9 6 0 | 5 2 | 6 9 2 | 3 8 9 | 2 2 3 | 3 5 6 | 9 5 | 3 8 2 | 9 7 6 | 1 6 7 0 | 2 5 8 | 2 2 2 | 1 6 6 4 | 5 9 6 | 2 3 0 | 2 6 5 | 6 0 | 2 6 2 | 2 6 4 | 6 8 7 | 2 2 7 | 6 7 2 | 2 3 4 | 5 0 5 | 6 8 3 | 3 1 | 4 7 | 9 7 7 | 6 7 4 | 6 4 | 9 6 8 | 9 2 | 5 0 7 | 6 4 | 5 1 | 6 3 | 6 8 0 | 6 7 5 | 4 8 | 1 7 8 7 | 1 9 3 9 | 8 5 0 | 3 5 1 | 5 9 5 | 9 7 0 | 6 8 9 | 9 7 4 | 2 6 2 | 4 0 | 7 | 2 5 0 | 9 6 6 | 2 4 9 | 2 2 1 | 6 5 | 5 0 0 | 4 7 7 9 | 6 7 7 | 2 3 2 | 5 0 3 | 3 7 8 | 2 5 2 | 5 0 8 | 3 8 1 | 2 1 1 | 2 3 9 | 5 9 7 | 4 2 1 | 3 8 6 | 4 6 | 2 6 8 | 1 7 2 1 | 2 4 8 | 9 6 3 | 1 6 4 9 | 2 3 5 | 2 2 8 | 6 6 | 9 9 2 | 6 9 0 | 9 9 3 | 6 7 0 | 6 7 6 | 1 8 6 8 | 2 1 6 | 9 0 | 6 8 8 | 8 8 6 | 2 5 5 | 2 5 6 | 3 8 0 | 5 9 8 | 1 | 9 9 8 | 3 9 0 6 6 9 8 | 3 7 9 | 1 7 8 4 | 5 8 | 1 2 8 4 | 1 3 4 0 | 8 4 | 6 7 8 | 6 8 1 | 6 8 5 | 9 6 7 | 2 7 | 2 6 0 | 2 6 3 ) ( 9 [ 9 7 6 ] \d | 8 [ 9 8 7 5 3 0 ] \d | 6 [ 9 8 7 ] \d | 5 [ 9 0 ] \d | 4 2 \d | 3 [ 8 7 5 ] \d | 2 [ 9 8 6 5 4 3 2 1 ] \d | 9 [ 8 5 4 3 2 1 0 ] | 8 [ 6 4 2 1 ] | 6 [ 6 5 4 3 2 1 0 ] | 5 [ 8 7 6 5 4 3 2 1 ] | 4 [ 9 8 7 6 5 4 3 1 0 ] | 3 [ 9 6 4 3 2 1 0 ] | 2 [ 7 0 ] | 7 | 1 ) \d { 4 , 20 } $ / ;
79
8- const VALIDATE_FEEL_PROPERTIES = [
10+ const PRECOMPUTE_FEEL_PROPERTIES = [
11+ 'custom' ,
912 'min' ,
1013 'max' ,
1114 'minLength' ,
@@ -75,7 +78,7 @@ export class Validator {
7578 return errors ;
7679 }
7780
78- const evaluatedValidation = evaluateFEELValues (
81+ const evaluatedValidation = precomputeFEELValues (
7982 validate ,
8083 this . _expressionLanguage ,
8184 this . _conditionChecker ,
@@ -144,6 +147,20 @@ export class Validator {
144147 ] ;
145148 }
146149
150+ if ( 'custom' in evaluatedValidation && value && evaluatedValidation . custom . length ) {
151+ const { custom } = evaluatedValidation ;
152+ custom . forEach ( customValidation => {
153+ const { condition, message } = customValidation ;
154+
155+ if ( condition && ! evaluateExpression ( condition , this . _expressionLanguage , this . _conditionChecker , this . _form , { value } ) ) {
156+ errors = [
157+ ...errors ,
158+ message
159+ ] ;
160+ }
161+ } ) ;
162+ }
163+
147164 return errors ;
148165 }
149166}
@@ -153,35 +170,29 @@ Validator.$inject = [ 'expressionLanguage', 'conditionChecker', 'form' ];
153170
154171// helpers //////////
155172
156- /**
157- * Helper function to evaluate optional FEEL validation values.
158- */
159- function evaluateFEELValues ( validate , expressionLanguage , conditionChecker , form ) {
160-
161- const evaluatedValidate = { ...validate } ;
162-
163- VALIDATE_FEEL_PROPERTIES . forEach ( property => {
164- const path = property . split ( '.' ) ;
173+ function precomputeFEELValues ( _validate , expressionLanguage , conditionChecker , form ) {
165174
166- const value = get ( evaluatedValidate , path ) ;
175+ const validate = clone ( _validate ) ;
167176
168- // mirroring FEEL evaluation of our hooks
169- if ( ! expressionLanguage || ! expressionLanguage . isExpression ( value ) ) {
170- return value ;
177+ PRECOMPUTE_FEEL_PROPERTIES . forEach ( propertyPath => {
178+ const value = get ( validate , propertyPath . split ( '.' ) ) ;
179+ const evaluatedValue = evaluateExpression ( value , expressionLanguage , conditionChecker , form ) ;
180+ if ( evaluatedValue ) {
181+ set ( validate , propertyPath . split ( '.' ) , evaluatedValue ) ;
171182 }
183+ } ) ;
172184
173- const { initialData, data } = form . _getState ( ) ;
174-
175- const newData = conditionChecker ? conditionChecker . applyConditions ( data , data ) : data ;
176- const filteredData = { ...initialData , ...newData } ;
185+ return validate ;
186+ }
177187
178- const evaluatedValue = expressionLanguage . evaluate ( value , filteredData ) ;
188+ function evaluateExpression ( expression , expressionLanguage , conditionChecker , form , additionalContext = { } ) {
189+ if ( ! expressionLanguage || ! expressionLanguage . isExpression ( expression ) ) {
190+ return expression ;
191+ }
179192
180- // replace validate property with evaluated value
181- if ( evaluatedValue ) {
182- set ( evaluatedValidate , path , evaluatedValue ) ;
183- }
184- } ) ;
193+ const { initialData, data } = form . _getState ( ) ;
194+ const filteredData = conditionChecker ? conditionChecker . applyConditions ( data , data ) : data ;
195+ const expressionContext = { ...additionalContext , ...initialData , ...filteredData , ...wrapObjectKeysWithUnderscores ( additionalContext ) } ;
185196
186- return evaluatedValidate ;
197+ return expressionLanguage . evaluate ( expression , expressionContext ) ;
187198}
0 commit comments