PluginProbe
The Innovative Form Builder – IvyForms / 1.1
The Innovative Form Builder – IvyForms v1.1
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
ivyforms / backend / src / Common / Helpers / FieldHelper.php

FieldHelper.php in The Innovative Form Builder – IvyForms 1.1, at backend/src/Common/Helpers/FieldHelper.php

163 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace IvyForms\Common\Helpers;
4
5 use IvyForms\Common\Exceptions\ValidationException;
6 use IvyForms\Entity\FieldOptions\FieldOptions;
7 use IvyForms\Factory\FieldOptions\FieldOptionsFactory;
8 use IvyForms\Repository\FieldOptions\FieldOptionsRepositoryInterface;
9 use IvyForms\Services\Media\ImageService;
10
11 /**
12 * General helper utilities related to Field processing.
13 */
14 class FieldHelper
15 {
16 /**
17 * Resolve parentId using fieldIndex -> parentId map if needed.
18 *
19 * @param array<string,mixed> $data Passed by reference; parentId modified in place.
20 * @param array<int,int> $parentMap Map of fieldIndex => newly created parent field id.
21 */
22 public static function resolveParentId(array &$data, array $parentMap): void
23 {
24 if (!array_key_exists('parentId', $data)) {
25 return;
26 }
27
28 $parentId = $data['parentId'];
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;
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 }
45 }
46
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 /**
61 * Partition field options into new, update, and submitted IDs.
62 *
63 * @param array<string, mixed> $fieldData
64 * @param array<int> $existingOptionIds
65 * @return array{
66 * newOptions: array<int, FieldOptions>,
67 * updateOptions: array<int, FieldOptions>,
68 * submittedOptionIds: array<int, int>
69 * }
70 * @throws ValidationException
71 */
72 public static function partitionFieldOptions(array $fieldData, array $existingOptionIds): array
73 {
74 $newOptions = [];
75 $updateOptions = [];
76 $submittedOptionIds = [];
77 foreach ($fieldData['fieldOptions'] as $optionData) {
78 $option = FieldOptionsFactory::create($optionData);
79 if (
80 isset($optionData['id']) && $optionData['id'] > 0
81 && in_array($optionData['id'], $existingOptionIds, true)
82 ) {
83 $updateOptions[] = $option;
84 $submittedOptionIds[] = $optionData['id'];
85 continue;
86 }
87 $newOptions[] = $option;
88 }
89 return [
90 'newOptions' => $newOptions,
91 'updateOptions' => $updateOptions,
92 'submittedOptionIds' => $submittedOptionIds,
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'], 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