PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0.1
GiveWP – Donation Plugin and Fundraising Platform v4.18.0.1
4.18.0.1 4.18.0 4.17.0 4.16.9 4.16.8.1 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 All 258 releases
← All changes | src/DonationForms/resources/app/utilities/ConvertFieldAPIRulesToJoi.ts +54 -8 4.16.2 → 4.18.0.1 View file →
@@ -1,6 +1,6 @@
1 1 import Joi, {AnySchema, ObjectSchema} from 'joi';
2 -import {BasicCondition, Field, Form, isField} from '@givewp/forms/types';
2 +import {AmountField, BasicCondition, Field, Form, isField} from '@givewp/forms/types';
3 3 import {__, sprintf} from '@wordpress/i18n';
4 4 import conditionOperatorFunctions from '@givewp/forms/app/utilities/conditionOperatorFunctions';
5 5
6 6 /**
@@ -35,12 +35,13 @@
35 35 });
36 36 }
37 37
38 38 /**
39 + * @since 4.16.8 collect the amounts exempt from the minimum and maximum
39 40 * @since 3.0.0
40 41 */
41 42 function getJoiRulesForField(field: Field): AnySchema {
42 - let rules: AnySchema = convertFieldAPIRulesToJoi(field.validationRules);
43 + let rules: AnySchema = convertFieldAPIRulesToJoi(field.validationRules, getExemptAmounts(field));
43 44
44 45 if (field.label) {
45 46 rules = rules.label(field.label);
46 47 }
@@ -48,13 +49,35 @@
48 49 return rules;
49 50 }
50 51
51 52 /**
53 + * The amounts the admin configured on the donation amount field. The custom amount minimum and maximum only
54 + * constrain what a donor types into the custom amount input, so these are always accepted.
55 + *
56 + * @since 4.16.8
57 + */
58 +function getExemptAmounts(field: Field): number[] {
59 + if (field.type !== 'amount') {
60 + return [];
61 + }
62 +
63 + const {levels, allowLevels, fixedAmountValue} = field as AmountField;
64 +
65 + // An unset level or fixed amount reads as 0, which must never be exempt from the minimum.
66 + if (allowLevels) {
67 + return (levels ?? []).map((level) => Number(level.value)).filter((amount) => amount > 0);
68 + }
69 +
70 + return fixedAmountValue > 0 ? [Number(fixedAmountValue)] : [];
71 +}
72 +
73 +/**
74 + * @since 4.16.8 exempt admin-defined amounts from the minimum and maximum
52 75 * @since 4.13.1 account for custom rules with only excludeUnless property
53 76 * @since 4.13.0 add support for optional false values
54 77 * @since 3.0.0
55 78 */
56 -function convertFieldAPIRulesToJoi(rules): AnySchema {
79 +function convertFieldAPIRulesToJoi(rules, exemptAmounts: number[] = []): AnySchema {
57 80 let joiRules;
58 81 const ruleKeys = Object.keys(rules);
59 82
60 83 if (ruleKeys.length === 0 || (ruleKeys.length === 1 && 'excludeUnless' in rules)) {
@@ -91,14 +114,37 @@
91 114 }
92 115 }
93 116
94 117 if (rules.hasOwnProperty('number') || !rules.hasOwnProperty('boolean')) {
95 - if (rules.hasOwnProperty('min')) {
96 - joiRules = joiRules.min(rules.min);
97 - }
118 + const hasMin = rules.hasOwnProperty('min');
119 + const hasMax = rules.hasOwnProperty('max');
98 120
99 - if (rules.hasOwnProperty('max')) {
100 - joiRules = joiRules.max(rules.max);
121 + if (exemptAmounts.length > 0 && (hasMin || hasMax)) {
122 + joiRules = joiRules.custom((value, helpers) => {
123 + const amount = Number(value);
124 +
125 + if (exemptAmounts.includes(amount)) {
126 + return value;
127 + }
128 +
129 + if (hasMin && amount < rules.min) {
130 + return helpers.error('number.min', {limit: rules.min});
131 + }
132 +
133 + if (hasMax && amount > rules.max) {
134 + return helpers.error('number.max', {limit: rules.max});
135 + }
136 +
137 + return value;
138 + }, 'exempt amount range');
139 + } else {
140 + if (hasMin) {
141 + joiRules = joiRules.min(rules.min);
142 + }
143 +
144 + if (hasMax) {
145 + joiRules = joiRules.max(rules.max);
146 + }
101 147 }
102 148 }
103 149
104 150 if (rules.required) {