PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.14.3
GiveWP – Donation Plugin and Fundraising Platform v4.14.3
4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 All 253 releases
give / src / DonationForms / resources / app / utilities / ConvertFieldAPIRulesToJoi.ts
ConvertFieldAPIRulesToJoi.ts
176 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import Joi, {AnySchema, ObjectSchema} from 'joi';
2 import {BasicCondition, Field, Form, isField} from '@givewp/forms/types';
3 import {__, sprintf} from '@wordpress/i18n';
4 import conditionOperatorFunctions from '@givewp/forms/app/utilities/conditionOperatorFunctions';
5
6 /**
7 * @since 3.0.0
8 */
9 const requiredMessage = sprintf(
10 /* translators: base error message */
11 __('This is a required field', 'give'),
12 `{#label}`
13 );
14
15 /**
16 * @since 3.0.0
17 */
18 export default function getJoiRulesForForm(form: Form): ObjectSchema {
19 const joiRules = form.reduceNodes(
20 (rules, field: Field) => {
21 rules[field.name] = getJoiRulesForField(field);
22
23 return rules;
24 },
25 {},
26 isField
27 );
28
29 return Joi.object(joiRules).messages({
30 'string.base': requiredMessage,
31 'string.empty': requiredMessage,
32 'any.required': requiredMessage,
33 'number.base': requiredMessage,
34 'object.base': requiredMessage,
35 });
36 }
37
38 /**
39 * @since 3.0.0
40 */
41 function getJoiRulesForField(field: Field): AnySchema {
42 let rules: AnySchema = convertFieldAPIRulesToJoi(field.validationRules);
43
44 if (field.label) {
45 rules = rules.label(field.label);
46 }
47
48 return rules;
49 }
50
51 /**
52 * @since 4.13.1 account for custom rules with only excludeUnless property
53 * @since 4.13.0 add support for optional false values
54 * @since 3.0.0
55 */
56 function convertFieldAPIRulesToJoi(rules): AnySchema {
57 let joiRules;
58 const ruleKeys = Object.keys(rules);
59
60 if (ruleKeys.length === 0 || (ruleKeys.length === 1 && 'excludeUnless' in rules)) {
61 return Joi.any();
62 }
63
64 if (rules.hasOwnProperty('numeric') || rules.hasOwnProperty('integer')) {
65 joiRules = Joi.number();
66
67 if (rules.hasOwnProperty('integer')) {
68 joiRules = joiRules.integer();
69 }
70 } else if (rules.hasOwnProperty('boolean')) {
71 joiRules = Joi.boolean();
72 } else if (rules.hasOwnProperty('array')) {
73 joiRules = Joi.array();
74 } else if (rules.hasOwnProperty('file')) {
75 joiRules = Joi.object();
76 } else if (rules.hasOwnProperty('dateTime')) {
77 joiRules = Joi.date();
78 } else {
79 joiRules = Joi.string();
80
81 if (rules.hasOwnProperty('email')) {
82 joiRules = joiRules.email({tlds: false});
83 }
84
85 if (rules.hasOwnProperty('alpha')) {
86 joiRules = joiRules.alpha();
87 }
88
89 if (rules.hasOwnProperty('alphanum')) {
90 joiRules = joiRules.alphanum();
91 }
92 }
93
94 if (rules.hasOwnProperty('number') || !rules.hasOwnProperty('boolean')) {
95 if (rules.hasOwnProperty('min')) {
96 joiRules = joiRules.min(rules.min);
97 }
98
99 if (rules.hasOwnProperty('max')) {
100 joiRules = joiRules.max(rules.max);
101 }
102 }
103
104 if (rules.required) {
105 if (rules.hasOwnProperty('excludeUnless')) {
106 /**
107 * This applies requirements to a field if the field is not being excluded by its conditions. It only
108 * supports basic conditions at this time, but could be expanded to support more complex conditions.
109 *
110 * Note that this unsets the value if the field conditions are not met.
111 */
112 joiRules = joiRules.custom((value, helpers) => {
113 const formValues = helpers.state.ancestors[0];
114
115 const passesConditions = rules.excludeUnless.every((condition: BasicCondition) => {
116 return conditionOperatorFunctions[condition.comparisonOperator](
117 formValues[condition.field],
118 condition.value
119 );
120 });
121
122 if (passesConditions && (value === '' || value === null)) {
123 return helpers.error('required');
124 } else if (!passesConditions) {
125 return undefined;
126 }
127
128 return value;
129 }, 'exclude unless validation');
130 } else {
131 joiRules = joiRules.required();
132 }
133 } else {
134 joiRules = joiRules.optional().allow('', null, false);
135 }
136
137 joiRules = getJoiRulesForAmountField(rules, joiRules);
138
139 return joiRules;
140 }
141
142 /**
143 * @since 3.0.0
144 */
145 function getJoiRulesForAmountField(rules, joiRules): AnySchema {
146 if (rules.hasOwnProperty('donationType')) {
147 joiRules = Joi.allow('single', 'subscription').only().required();
148 }
149
150 if (rules.hasOwnProperty('subscriptionPeriod')) {
151 joiRules = Joi.when('donationType', {
152 is: 'subscription',
153 then: Joi.allow('day', 'week', 'quarter', 'month', 'year').only().required(),
154 otherwise: Joi.optional(),
155 });
156 }
157
158 if (rules.hasOwnProperty('subscriptionFrequency')) {
159 joiRules = Joi.when('donationType', {
160 is: 'subscription',
161 then: Joi.number().integer().required(),
162 otherwise: Joi.optional(),
163 });
164 }
165
166 if (rules.hasOwnProperty('subscriptionInstallments')) {
167 joiRules = Joi.when('donationType', {
168 is: 'subscription',
169 then: Joi.number().integer().required(),
170 otherwise: Joi.optional(),
171 });
172 }
173
174 return joiRules;
175 }
176