PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.3
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.3
3.6.0 3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / abilities / class-evf-field-schemas.php
everest-forms / includes / abilities Last commit date
class-evf-abilities-handlers.php 1 month ago class-evf-abilities-registry.php 1 month ago class-evf-abilities.php 1 month ago class-evf-field-schemas.php 1 month ago class-evf-form-builder.php 1 month ago class-evf-mcp-server.php 1 month ago
class-evf-field-schemas.php
234 lines
1 <?php
2 /**
3 * Field-type schemas + addon hint registry.
4 *
5 * The Abilities API needs to validate field definitions before persisting them
6 * to a form. This class is the source of truth for:
7 *
8 * 1. Which keys a field type accepts (label, required, choices, etc.)
9 * 2. Per-type defaults applied when the caller omits something.
10 * 3. Which Everest Forms addon ships a given field type, so we can produce
11 * "you need to install/activate addon X" errors when the LLM asks for a
12 * type that isn't registered on this site.
13 *
14 * The runtime check for whether a type is *currently usable* still goes
15 * through `evf()->form_fields->form_fields` — this class only adds metadata
16 * and friendly errors on top of that.
17 *
18 * @package EverestForms\Abilities
19 */
20
21 defined( 'ABSPATH' ) || exit;
22
23 /**
24 * Field schemas.
25 */
26 class EVF_Field_Schemas {
27
28 /**
29 * Common keys every field accepts. Type-specific keys layer on top.
30 *
31 * @var string[]
32 */
33 const COMMON_KEYS = array(
34 'label',
35 'description',
36 'required',
37 'placeholder',
38 'default_value',
39 'css',
40 'label_hide',
41 'meta-key',
42 );
43
44 /**
45 * Type -> addon slug map. Used to emit a friendly error when a requested
46 * field type isn't registered (e.g. "needs the Survey, Polls and Quiz
47 * addon"). Missing entries default to "Everest Forms PRO".
48 *
49 * @return array<string, array{addon: string, plugin: string}>
50 */
51 public static function addon_hints() {
52 return array(
53 // Survey, Polls & Quiz.
54 'likert' => array( 'addon' => 'Survey, Polls and Quiz', 'plugin' => 'everest-forms-survey-polls-quiz/everest-forms-survey-polls-quiz.php' ),
55 'scale-rating' => array( 'addon' => 'Survey, Polls and Quiz', 'plugin' => 'everest-forms-survey-polls-quiz/everest-forms-survey-polls-quiz.php' ),
56 'yes-no' => array( 'addon' => 'Survey, Polls and Quiz', 'plugin' => 'everest-forms-survey-polls-quiz/everest-forms-survey-polls-quiz.php' ),
57
58 // PRO field types.
59 'address' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
60 'color' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
61 'country' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
62 'credit-card' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
63 'file-upload' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
64 'image-upload' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
65 'lookup' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
66 'password' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
67 'phone' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
68 'privacy-policy' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
69 'range-slider' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
70 'rating' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
71 'signature' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
72 'wysiwyg' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
73
74 // Payments (PRO).
75 'payment-single' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
76 'payment-checkbox' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
77 'payment-radio' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
78 'payment-quantity' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
79 'payment-coupon' => array( 'addon' => 'Coupons (PRO)', 'plugin' => 'everest-forms-coupons/everest-forms-coupons.php' ),
80 'payment-subtotal' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
81 'payment-total' => array( 'addon' => 'Everest Forms PRO', 'plugin' => 'everest-forms-pro/everest-forms-pro.php' ),
82
83 // Captcha.
84 'captcha' => array( 'addon' => 'Captcha', 'plugin' => 'everest-forms-captcha/everest-forms-captcha.php' ),
85 'recaptcha' => array( 'addon' => 'Captcha', 'plugin' => 'everest-forms-captcha/everest-forms-captcha.php' ),
86 'hcaptcha' => array( 'addon' => 'Captcha', 'plugin' => 'everest-forms-captcha/everest-forms-captcha.php' ),
87 'turnstile' => array( 'addon' => 'Captcha', 'plugin' => 'everest-forms-captcha/everest-forms-captcha.php' ),
88
89 // Repeater.
90 'repeater' => array( 'addon' => 'Repeater Fields', 'plugin' => 'everest-forms-repeater-fields/everest-forms-repeater-fields.php' ),
91 );
92 }
93
94 /**
95 * Per-type extra accepted keys + per-type defaults.
96 *
97 * Schema shape: [ type => [ 'extra_keys' => [...], 'defaults' => [...], 'requires_choices' => bool ] ].
98 *
99 * @return array
100 */
101 public static function type_schemas() {
102 return array(
103 'text' => array(),
104 'textarea' => array( 'extra_keys' => array( 'limit_count', 'limit_mode' ) ),
105 'email' => array( 'extra_keys' => array( 'confirmation' ) ),
106 'url' => array(),
107 'number' => array( 'extra_keys' => array( 'min_value', 'max_value', 'step' ) ),
108 'phone' => array( 'extra_keys' => array( 'format' ) ),
109 'first-name' => array( 'extra_keys' => array( 'sublabels' ) ),
110 'last-name' => array( 'extra_keys' => array( 'sublabels' ) ),
111 'select' => array( 'extra_keys' => array( 'choices', 'multiple_choices' ), 'requires_choices' => true ),
112 'radio' => array( 'extra_keys' => array( 'choices' ), 'requires_choices' => true ),
113 'checkbox' => array( 'extra_keys' => array( 'choices' ), 'requires_choices' => true ),
114 'date-time' => array( 'extra_keys' => array( 'datetime_format', 'date_format', 'time_format' ) ),
115 'hidden' => array(),
116 'html' => array( 'extra_keys' => array( 'code' ) ),
117 'divider' => array(),
118 'title' => array( 'extra_keys' => array( 'subtitle' ) ),
119 'address' => array( 'extra_keys' => array( 'address_scheme' ) ),
120 'country' => array( 'extra_keys' => array( 'choices' ) ),
121 'file-upload' => array( 'extra_keys' => array( 'extensions', 'max_size', 'multiple_upload' ) ),
122 'image-upload'=> array( 'extra_keys' => array( 'extensions', 'max_size', 'multiple_upload' ) ),
123 'rating' => array( 'extra_keys' => array( 'rating_scale', 'rating_icon' ) ),
124 'range-slider'=> array( 'extra_keys' => array( 'min_value', 'max_value', 'step' ) ),
125 'signature' => array(),
126 'likert' => array( 'extra_keys' => array( 'rows', 'columns', 'single_row' ), 'requires_choices' => false ),
127 'scale-rating'=> array( 'extra_keys' => array( 'rating_scale' ) ),
128 'yes-no' => array(),
129 'password' => array( 'extra_keys' => array( 'confirmation' ) ),
130 'wysiwyg' => array(),
131 );
132 }
133
134 /**
135 * Convenience: full schema for one type, merging common keys + type extras.
136 *
137 * @param string $type Field type id.
138 * @return array|null Null when the type isn't known here (still may be runtime-registered).
139 */
140 public static function for_type( $type ) {
141 $type = (string) $type;
142 $schemas = self::type_schemas();
143 if ( ! isset( $schemas[ $type ] ) ) {
144 return null;
145 }
146 $entry = $schemas[ $type ];
147 $extra_keys = isset( $entry['extra_keys'] ) ? (array) $entry['extra_keys'] : array();
148 return array(
149 'type' => $type,
150 'accepted_keys' => array_values( array_unique( array_merge( self::COMMON_KEYS, $extra_keys ) ) ),
151 'requires_choices' => ! empty( $entry['requires_choices'] ),
152 'addon' => self::addon_for( $type ),
153 );
154 }
155
156 /**
157 * Addon hint for a type, or null if it ships with core.
158 *
159 * @param string $type Field type id.
160 * @return array|null
161 */
162 public static function addon_for( $type ) {
163 $hints = self::addon_hints();
164 return isset( $hints[ $type ] ) ? $hints[ $type ] : null;
165 }
166
167 /**
168 * Setting keys that depend on a specific addon being active to actually
169 * do anything.
170 *
171 * Writing `enable_save_and_continue: "1"` on a form whose Save and Continue
172 * addon is inactive is a silent footgun: the option lands in post_content,
173 * but the addon's hooks aren't loaded so the feature doesn't actually work.
174 * The builder uses this map to short-circuit such writes with the same
175 * structured-error envelope used for addon-gated field types.
176 *
177 * Only "boolean toggle" keys are listed — settings that are no-ops without
178 * a specific addon. Generic configuration keys (e.g. text overrides on
179 * an addon's confirmation message) are NOT gated, because writing them is
180 * harmless even if the addon is inactive.
181 *
182 * @return array<string, array{addon: string, plugin: string}>
183 */
184 public static function setting_addon_hints() {
185 return array(
186 'enable_save_and_continue' => array(
187 'addon' => 'Save and Continue',
188 'plugin' => 'everest-forms-save-and-continue/everest-forms-save-and-continue.php',
189 ),
190 'enable_calculation' => array(
191 'addon' => 'Calculations',
192 'plugin' => 'everest-forms-calculations/everest-forms-calculations.php',
193 ),
194 'pdf_enabled' => array(
195 'addon' => 'PDF Submission',
196 'plugin' => 'everest-forms-pdf-submission/everest-forms-pdf-submission.php',
197 ),
198 'pdf_submission' => array(
199 'addon' => 'PDF Submission',
200 'plugin' => 'everest-forms-pdf-submission/everest-forms-pdf-submission.php',
201 ),
202 'enable_send_pdf_dropbox' => array(
203 'addon' => 'PDF Submission',
204 'plugin' => 'everest-forms-pdf-submission/everest-forms-pdf-submission.php',
205 ),
206 'enable_send_pdf_google_drive' => array(
207 'addon' => 'PDF Submission',
208 'plugin' => 'everest-forms-pdf-submission/everest-forms-pdf-submission.php',
209 ),
210 );
211 }
212
213 /**
214 * Set of field type ids currently registered at runtime, derived from the
215 * EVF Fields registry. This is the authoritative "is this type usable now"
216 * check; addon_hints() is only metadata for nicer errors.
217 *
218 * @return array<string, true>
219 */
220 public static function registered_types() {
221 $out = array();
222 $registry = function_exists( 'evf' ) ? evf()->form_fields : null;
223 $groups = ( is_object( $registry ) && isset( $registry->form_fields ) ) ? (array) $registry->form_fields : array();
224 foreach ( $groups as $fields ) {
225 foreach ( (array) $fields as $field ) {
226 if ( is_object( $field ) && isset( $field->type ) ) {
227 $out[ $field->type ] = true;
228 }
229 }
230 }
231 return $out;
232 }
233 }
234