PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
← All changes | backend/src/Common/Helpers/FieldHelper.php +115 -8 0.6 → 1.5 View file →
@@ -1,17 +1,13 @@
1 1 <?php
2 2
3 3 namespace IvyForms\Common\Helpers;
4 4
5 -// phpcs:disable PSR1.Files.SideEffects
6 -if (!defined('ABSPATH')) {
7 - exit; // Exit if accessed directly
8 -}
9 -
10 5 use IvyForms\Common\Exceptions\ValidationException;
11 6 use IvyForms\Entity\FieldOptions\FieldOptions;
12 7 use IvyForms\Factory\FieldOptions\FieldOptionsFactory;
13 8 use IvyForms\Repository\FieldOptions\FieldOptionsRepositoryInterface;
9 +use IvyForms\Services\Media\ImageService;
14 10
15 11 /**
16 12 * General helper utilities related to Field processing.
17 13 */
@@ -29,15 +25,40 @@
29 25 return;
30 26 }
31 27
32 28 $parentId = $data['parentId'];
33 - $needsResolve = ($parentId === 0 || $parentId === '0' || $parentId === null);
34 - if ($needsResolve && isset($data['fieldIndex']) && isset($parentMap[$data['fieldIndex']])) {
35 - $data['parentId'] = $parentMap[$data['fieldIndex']];
29 +
30 + //parentId is 0 or null → use current field's fieldIndex
31 + if (($parentId === 0 || $parentId === '0' || $parentId === null) && isset($data['fieldIndex'])) {
32 + $parentIndex = $data['fieldIndex'];
33 + if (isset($parentMap[$parentIndex])) {
34 + $data['parentId'] = $parentMap[$parentIndex];
35 + }
36 + return;
36 37 }
38 +
39 + //parentId is numeric → use it as parent's fieldIndex
40 + if (is_numeric($parentId)) {
41 + if (isset($parentMap[$parentId])) {
42 + $data['parentId'] = $parentMap[$parentId];
43 + }
44 + }
37 45 }
38 46
39 47 /**
48 + * Remap parentId for duplicated field using old-to-new field ID map.
49 + *
50 + * @param array<string,mixed> $fieldData Passed by reference; parentId modified in place.
51 + * @param array<int,int> $fieldIdMap Map of old field ID => new field ID.
52 + */
53 + public static function remapParentIdForDuplication(array &$fieldData, array $fieldIdMap): void
54 + {
55 + if ($fieldData['parentId'] !== null && isset($fieldIdMap[$fieldData['parentId']])) {
56 + $fieldData['parentId'] = $fieldIdMap[$fieldData['parentId']];
57 + }
58 + }
59 +
60 + /**
40 61 * Partition field options into new, update, and submitted IDs.
41 62 *
42 63 * @param array<string, mixed> $fieldData
43 64 * @param array<int> $existingOptionIds
@@ -69,6 +90,92 @@
69 90 'newOptions' => $newOptions,
70 91 'updateOptions' => $updateOptions,
71 92 'submittedOptionIds' => $submittedOptionIds,
72 93 ];
94 + }
95 +
96 + /**
97 + * Check if a field type has options (radio, checkbox, select, multi-select).
98 + *
99 + * @param string $fieldType
100 + * @return bool
101 + */
102 + public static function fieldTypeHasOptions(string $fieldType): bool
103 + {
104 + return in_array($fieldType, ['radio', 'checkbox', 'select', 'multi-select', 'product', 'rating'], true);
105 + }
106 +
107 + /**
108 + * Check if a field type is a security/CAPTCHA field.
109 + *
110 + * Security fields are used for bot/spam protection and should be excluded
111 + * from stored entries, integration payloads, placeholder lists, and any
112 + * other processing that targets user-submitted data.
113 + *
114 + * @param string $fieldType
115 + * @return bool
116 + */
117 + public static function isSecurityField(string $fieldType): bool
118 + {
119 + return in_array($fieldType, ['recaptcha', 'turnstile', 'hcaptcha'], true);
120 + }
121 +
122 + /**
123 + * Duplicate field options from one field to another.
124 + *
125 + * @param int $oldFieldId
126 + * @param int $newFieldId
127 + * @param FieldOptionsRepositoryInterface $repository
128 + * @return void
129 + * @throws ValidationException
130 + */
131 + public static function duplicateFieldOptions(
132 + int $oldFieldId,
133 + int $newFieldId,
134 + FieldOptionsRepositoryInterface $repository
135 + ): void {
136 + $options = $repository->getByFieldId($oldFieldId);
137 + foreach ($options as $option) {
138 + $optionData = $option->toArray();
139 + unset($optionData['id']);
140 + $optionData['fieldId'] = $newFieldId;
141 + $repository->add(FieldOptionsFactory::create($optionData));
142 + }
143 + }
144 +
145 + /**
146 + * Process htmlContent to upload base64 images
147 + *
148 + * @param array<string, mixed> $fieldData Passed by reference; htmlContent modified in place
149 + * @param ImageService $imageService
150 + * @return void
151 + */
152 + public static function processFieldHtmlContent(array &$fieldData, ImageService $imageService): void
153 + {
154 + if (!empty($fieldData['htmlContent'])) {
155 + $processedContent = $imageService->processImagesInContent(
156 + $fieldData['htmlContent'],
157 + 'field'
158 + );
159 + $fieldData['htmlContent'] = $processedContent;
160 + }
161 + }
162 +
163 + /**
164 + * Upload base64 images in rich text default values before form save.
165 + *
166 + * @param array<string, mixed> $fieldData Passed by reference; defaultValue modified in place
167 + * @param ImageService $imageService
168 + * @return void
169 + */
170 + public static function processRichTextDefaultValue(array &$fieldData, ImageService $imageService): void
171 + {
172 + if (($fieldData['type'] ?? '') !== 'rich_text' || empty($fieldData['defaultValue'])) {
173 + return;
174 + }
175 +
176 + $fieldData['defaultValue'] = $imageService->processImagesInContent(
177 + (string) $fieldData['defaultValue'],
178 + 'field'
179 + );
73 180 }
74 181 }