PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.7.1
GiveWP – Donation Plugin and Fundraising Platform v4.7.1
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 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / FormMigration / Steps / FormFieldManager.php
give / src / FormMigration / Steps Last commit date
FormFields 2 years ago FormTemplate 2 years ago ActiveCampaign.php 2 years ago ConstantContact.php 2 years ago ConvertKit.php 2 years ago CurrencySwitcher.php 2 years ago DonationGoal.php 2 years ago DonationOptions.php 2 years ago DoubleTheDonation.php 2 years ago EmailSettings.php 2 years ago FeeRecovery.php 2 years ago FormExcerpt.php 2 years ago FormFeaturedImage.php 2 years ago FormFieldManager.php 2 years ago FormFields.php 2 years ago FormGrid.php 2 years ago FormMeta.php 2 years ago FormTaxonomies.php 1 year ago FormTitle.php 2 years ago FundsAndDesignations.php 2 years ago GiftAid.php 2 years ago Mailchimp.php 2 years ago MigrateMeta.php 2 years ago OfflineDonations.php 2 years ago PaymentGateways.php 2 years ago PdfSettings.php 2 years ago PerFormGateways.php 2 years ago RazorpayPerFormSettings.php 1 year ago RecurringDonationOptions.php 2 years ago TermsAndConditions.php 2 years ago
FormFieldManager.php
474 lines
1 <?php
2
3 namespace Give\FormMigration\Steps;
4
5 use Give\FormMigration\Contracts\FormMigrationStep;
6 use Give\Framework\Blocks\BlockModel;
7
8 class FormFieldManager extends FormMigrationStep
9 {
10
11 /** @var array {0: BlockCollection, 1: string, 2: string|null} */
12 private $inserter;
13
14 /** @var array {fieldName: {field: array, block: BlockModel}} */
15 private $fieldBlockRelationships = [];
16
17 /**
18 * Suppressed settings for all fields:
19 * - "field_width" (Field Width)
20 * - "css" (CSS Class Name)
21 *
22 * @since 3.0.0 added support for conditions based on Donation Amount.
23 * @since 3.0.0
24 */
25 public function process()
26 {
27 $formFields = $this->formV2->getFormFields();
28
29 if (!$formFields) {
30 return;
31 }
32
33 $this->fieldBlockRelationships['give-amount'] = [
34 'field' => [], // This is a core field and doesn't have any FFM settings.
35 'block' => $this->fieldBlocks->findByName('givewp/donation-amount'),
36 ];
37
38 $this->inserter = $this->getInitialInserter();
39
40 $map = [
41 'checkbox' => [$this, 'addMultiSelectField'],
42 'date' => [$this, 'addDateField'],
43 'select' => [$this, 'addDropdownField'],
44 'email' => [$this, 'addEmailField'],
45 'file_upload' => [$this, 'addFileUploadField'],
46 'hidden' => [$this, 'addHiddenField'],
47 'html' => [$this, 'addHtmlField'],
48 'multiselect' => [$this, 'addMultiSelectField'],
49 'phone' => [$this, 'addPhoneField'],
50 'radio' => [$this, 'addRadioField'],
51 'text' => [$this, 'addTextField'],
52 'textarea' => [$this, 'addTextareaField'],
53 'url' => [$this, 'addUrlField'],
54 ];
55
56 foreach ($formFields as $field) {
57 if ($field['input_type'] === 'section') {
58 $this->addSection($field);
59 continue;
60 }
61
62 if (!array_key_exists($field['input_type'], $map) || !$field['name']) {
63 continue;
64 }
65
66 $method = $map[$field['input_type']];
67
68 $block = $this->applyCommonAttributes($method($field), $field);
69 $this->fieldBlockRelationships[$field['name']] = [
70 'field' => $field,
71 'block' => $block
72 ];
73 $this->insertBlock($block);
74 }
75
76 $this->mapConditionalLogicToBlocks();
77 }
78
79 /**
80 * Suppressed settings for the Date field:
81 * - "time" (Enable time input)
82 * - "format_time" (Time Format)
83 *
84 * @since 3.0.0
85 */
86 private function addDateField($field): BlockModel
87 {
88 $dateFormatOrder = [
89 'yyyy' => strpos(strtolower($field['format']), 'y'),
90 'mm' => strpos(strtolower($field['format']), 'm'),
91 'dd' => strpos(strtolower($field['format']), 'd'),
92 ];
93 asort($dateFormatOrder);
94 $dateFormat = implode('/', array_keys($dateFormatOrder));
95
96 return BlockModel::make([
97 'name' => 'givewp-form-field-manager/date',
98 'attributes' => [
99 'dateFormat' => $dateFormat,
100 ]
101 ]);
102 }
103
104 /**
105 * Suppressed settings for the Dropdown field:
106 * - "first" (Select Text)
107 *
108 * @since 3.0.0
109 */
110 private function addDropdownField($field): BlockModel
111 {
112 $options = array_map(function ($option) use ($field) {
113 return [
114 'label' => $option,
115 'value' => '',
116 'checked' => array_key_exists('selected', $field) && $option === $field['selected'],
117 ];
118 }, array_filter($field['options']));
119
120 return BlockModel::make([
121 'name' => 'givewp-form-field-manager/dropdown',
122 'attributes' => [
123 'options' => $options,
124 ]
125 ]);
126 }
127
128 /**
129 * Suppressed settings for the Email field:
130 * - "maxlength" (Max Length)
131 *
132 * @since 3.0.0
133 */
134 private function addEmailField($field): BlockModel
135 {
136 return BlockModel::make([
137 'name' => 'givewp-form-field-manager/email',
138 ]);
139 }
140
141 /**
142 * Suppressed settings for the File Upload field:
143 * - "count" (Max. files)
144 *
145 * @since 3.0.0
146 */
147 private function addFileUploadField($field): BlockModel
148 {
149 $allowedFileTypes = array_map(function ($type) {
150 switch ($type) {
151 case 'images':
152 return 'image';
153 default:
154 return $type;
155 }
156 }, $field['extension']);
157
158 return BlockModel::make([
159 'name' => 'givewp-form-field-manager/file-upload',
160 'attributes' => [
161 'maxFileSize' => $field['max_size'],
162 'allowedFileTypes' => $allowedFileTypes,
163 ]
164 ]);
165 }
166
167 /**
168 * @since 3.0.0
169 */
170 private function addHiddenField($field): BlockModel
171 {
172 return BlockModel::make([
173 'name' => 'givewp-form-field-manager/hidden',
174 ]);
175 }
176
177 /**
178 * @since 3.0.0
179 */
180
181 private function addHtmlField($field): BlockModel
182 {
183 return BlockModel::make([
184 'name' => 'givewp-form-field-manager/html',
185 'attributes' => [
186 'htmlCode' => $field['html'],
187 ]
188 ]);
189 }
190
191 /**
192 * Suppressed settings for the Dropdown field:
193 * - "first" (Select Text)
194 *
195 * @since 3.0.0
196 */
197 private function addMultiSelectField($field): BlockModel
198 {
199 $fieldType = $field['template'] === 'checkbox_field' ? 'checkbox' : 'dropdown';
200 $options = array_map(function ($option) use ($field) {
201 return [
202 'label' => $option,
203 'value' => '',
204 'checked' => array_key_exists('selected', $field) && in_array($option, (array)$field['selected'], true),
205 ];
206 }, array_filter($field['options']));
207
208 return BlockModel::make([
209 'name' => 'givewp-form-field-manager/multi-select',
210 'attributes' => [
211 'fieldType' => $fieldType,
212 'options' => $options,
213 ]
214 ]);
215 }
216
217 /**
218 * @since 3.0.0
219 */
220
221 private function addPhoneField($field): BlockModel
222 {
223 $phoneFormat = $field['format'] === 'domestic' ? 'domestic' : 'unformatted';
224
225 return BlockModel::make([
226 'name' => 'givewp-form-field-manager/phone',
227 'attributes' => [
228 'phoneFormat' => $phoneFormat,
229 ]
230 ]);
231 }
232
233 /**
234 * @since 3.0.0
235 */
236
237 private function addRadioField($field): BlockModel
238 {
239 $options = array_map(function ($option) use ($field) {
240 return [
241 'label' => $option,
242 'value' => '',
243 'checked' => array_key_exists('selected', $field) && $option === $field['selected'],
244 ];
245 }, array_filter($field['options']));
246
247 return BlockModel::make([
248 'name' => 'givewp-form-field-manager/radio',
249 'attributes' => [
250 'options' => $options,
251 ]
252 ]);
253 }
254
255 /**
256 * Suppressed settings for the Text field:
257 * - "maxlength" (Max Length)
258 *
259 * @since 3.0.0
260 */
261 private function addTextField($field): BlockModel
262 {
263 return BlockModel::make([
264 'name' => 'givewp/text',
265 ]);
266 }
267
268 /**
269 * Suppressed settings for the Textarea field:
270 * - "cols" (Columns)
271 *
272 * @since 3.0.0
273 */
274 private function addTextareaField($field): BlockModel
275 {
276 return BlockModel::make([
277 'name' => 'givewp-form-field-manager/textarea',
278 'attributes' => [
279 'rows' => $field['rows'],
280 ],
281 ]);
282 }
283
284 /**
285 * Suppressed settings for the Text field:
286 * - "maxlength" (Max Length)
287 *
288 * @since 3.0.0
289 */
290 private function addUrlField($field): BlockModel
291 {
292 return BlockModel::make([
293 'name' => 'givewp-form-field-manager/url',
294 ]);
295 }
296
297 /**
298 * @since 3.0.0
299 */
300
301 private function addSection($field): void
302 {
303 $block = BlockModel::make([
304 'name' => 'givewp/section',
305 'attributes' => [
306 'title' => $field['label'],
307 'description' => ''
308 ]
309 ]);
310
311 list($blockCollection, $method) = $this->inserter;
312 $this->inserter = [$block->innerBlocks, 'append'];
313 $found = $this->fieldBlocks->findParentByBlockCollection($blockCollection);
314
315 if (!$found) {
316 $this->fieldBlocks->append($block);
317 return;
318 }
319
320 list($parentBlock, $parentBlockIndex) = $found;
321
322 if ($method === 'insertBefore') {
323 $this->fieldBlocks->insertBefore(
324 $parentBlock->name,
325 $block,
326 $parentBlockIndex
327 );
328 } else {
329 $this->fieldBlocks->insertAfter(
330 $parentBlock->name,
331 $block,
332 $parentBlockIndex
333 );
334 }
335 }
336
337 /**
338 * @since 3.0.0
339 */
340
341 private function getInitialInserter(): array
342 {
343 $placement = $this->formV2->getFormFieldsPlacement();
344
345 switch ($placement) {
346 case 'give_before_donation_levels':
347 $parentBlock = BlockModel::make([
348 'name' => 'givewp/section',
349 ]);
350 $this->fieldBlocks->prepend($parentBlock);
351 return [$parentBlock->innerBlocks, 'append'];
352 case 'give_payment_mode_top':
353 return [$this->fieldBlocks, 'insertBefore', 'givewp/donation-summary'];
354 case 'give_payment_mode_bottom':
355 $parentBlock = $this->fieldBlocks->findParentByChildName('givewp/donation-summary');
356 return [$parentBlock->innerBlocks, 'append'];
357 case 'give_donation_form_before_personal_info':
358 return [$this->fieldBlocks, 'insertBefore', 'givewp/donor-name'];
359 case 'give_donation_form_after_personal_info':
360 $parentBlock = $this->fieldBlocks->findParentByChildName('givewp/donor-name');
361 return [$parentBlock->innerBlocks, 'append'];
362 case 'give_donation_form_before_cc_form':
363 return [$this->fieldBlocks, 'insertBefore', 'givewp/payment-gateways'];
364 case 'give_donation_form_bottom':
365 case 'give_donation_form_after_cc_form':
366 $parentBlock = $this->fieldBlocks->findParentByChildName('givewp/payment-gateways');
367 return [$parentBlock->innerBlocks, 'append'];
368 case 'give_donation_form_top':
369 case 'give_after_donation_levels':
370 default:
371 $parentBlock = $this->fieldBlocks->findParentByChildName('givewp/donation-amount');
372 return [$parentBlock->innerBlocks, 'append'];
373 }
374 }
375
376 /**
377 * @since 3.0.0
378 */
379
380 private function applyCommonAttributes($block, $field): BlockModel
381 {
382 $protectedFieldNames = [
383 'donation-amount',
384 'donor-name',
385 'email',
386 ];
387
388 if (in_array($field['name'], $protectedFieldNames, true)) {
389 $field['name'] .= '_1';
390 }
391
392 $block->setAttribute('fieldName', $field['name']);
393 $block->setAttribute('displayInAdmin', true);
394 $block->setAttribute('displayInReceipt', true);
395 $block->setAttribute('emailTag', "meta_donation_{$field['name']}");
396 $block->setAttribute('metaUUID', $block->clientId);
397
398 if (array_key_exists('required', $field)) {
399 $block->setAttribute('isRequired', $field['required'] === 'yes');
400 }
401
402 if (array_key_exists('label', $field)) {
403 $block->setAttribute('label', $field['label']);
404 }
405
406 if (array_key_exists('placeholder', $field)) {
407 $block->setAttribute('placeholder', $field['placeholder']);
408 }
409
410 if (array_key_exists('help', $field)) {
411 $block->setAttribute('description', $field['help']);
412 }
413
414 if (array_key_exists('default', $field)) {
415 $block->setAttribute('defaultValue', $field['default']);
416 }
417
418 return $block;
419 }
420
421 /**
422 * @since 3.0.0
423 */
424
425 private function insertBlock($block): void
426 {
427 list($blockCollection, $method, $target) = array_pad($this->inserter, 3, null);
428 call_user_func_array([$blockCollection, $method], array_filter([$target, $block]));
429 }
430
431 /**
432 * @since 3.0.0 Fixed missing conditionalLogic attribute on custom fields.
433 * @since 3.0.0
434 */
435 private function mapConditionalLogicToBlocks(): void
436 {
437 foreach ($this->fieldBlockRelationships as $item) {
438 ['field' => $field, 'block' => $block] = $item;
439
440 // Initialize conditional logic support for custom fields.
441 // The `conditionalLogic` attribute is used to signal support for conditional logic.
442 $block->setAttribute('conditionalLogic', [
443 'enabled' => give_is_setting_enabled($field['control_field_visibility']),
444 'action' => 'show',
445 'boolean' => 'and',
446 'rules' => [],
447 ]);
448
449 if (!array_key_exists('control_field_visibility', $field)) {
450 continue;
451 }
452
453 if(!isset($this->fieldBlockRelationships[$field['controller_field_name']])) {
454 continue;
455 }
456
457 $referenceBlock = $this->fieldBlockRelationships[$field['controller_field_name']]['block'];
458
459 $block->setAttribute('conditionalLogic', [
460 'enabled' => true,
461 'action' => 'show',
462 'boolean' => 'and',
463 'rules' => [
464 [
465 'field' => $referenceBlock->clientId,
466 'operator' => $field['controller_field_operator'],
467 'value' => $field['controller_field_value'],
468 ],
469 ],
470 ]);
471 }
472 }
473 }
474