PluginProbe
The Innovative Form Builder – IvyForms / 0.8
The Innovative Form Builder – IvyForms v0.8
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 1.2 1.3
ivyforms / backend / src / Services / Entry / Managers / EntryFieldValueManager.php

EntryFieldValueManager.php in The Innovative Form Builder – IvyForms 0.8, at backend/src/Services/Entry/Managers/EntryFieldValueManager.php

246 lines 8.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\Services\Entry\Managers;
4
5 // phpcs:disable PSR1.Files.SideEffects
6 if (!defined('ABSPATH')) {
7 exit; // Exit if accessed directly
8 }
9
10 use IvyForms\Common\Helpers\DateTimeHelper\DateTimeHelper;
11 use IvyForms\Common\Helpers\EntryHelper;
12 use IvyForms\Services\Field\FieldService;
13
14 /**
15 * Handles field value formatting and resolution.
16 * Responsible for converting field values for display and processing submission data.
17 */
18 class EntryFieldValueManager
19 {
20 private FieldService $fieldService;
21
22 public function __construct(FieldService $fieldService)
23 {
24 $this->fieldService = $fieldService;
25 }
26
27 /**
28 * Format entry fields with values converted for frontend display.
29 * (e.g., timestamp → HH:MM for time fields)
30 *
31 * @param array<int, array<string, mixed>> $entryFields
32 * @param bool $skipFormatting
33 * @return array<int, array<string, mixed>>
34 * @SuppressWarnings(PHPMD)
35 */
36 public function formatForFrontend(array $entryFields, bool $skipFormatting = false): array
37 {
38 $fieldsById = $this->buildFieldsMap($entryFields);
39
40 // Format each entry field value based on field type
41 foreach ($entryFields as &$entryField) {
42 $fieldId = (int)$entryField['fieldId'];
43 if (!isset($fieldsById[$fieldId])) {
44 continue;
45 }
46
47 $field = $fieldsById[$fieldId];
48 $fieldType = strtolower($field->getType());
49 $value = $entryField['fieldValue'];
50
51 $entryField['fieldValue'] = $this->formatFieldValue($fieldType, $value, $skipFormatting);
52 }
53
54 return $entryFields;
55 }
56
57 /**
58 * Resolve the value for a field based on its type and parent/child relationship.
59 *
60 * @param object $field
61 * @param array<mixed> $submissionData
62 * @param array<int, array<int>> $parentChildrenMap
63 * @param array<int, string|null> $parentSubfieldKeys
64 * @return mixed
65 */
66 public function resolveFieldValue(
67 object $field,
68 array $submissionData,
69 array $parentChildrenMap,
70 array $parentSubfieldKeys
71 ) {
72 $fieldId = $field->getId();
73 $fieldType = $field->getType();
74 $parentId = method_exists($field, 'getParentId') ? $field->getParentId() : null;
75
76 $parentValue = $this->getParentSubfieldValue($fieldId, $parentId, $submissionData, $parentSubfieldKeys);
77 if ($parentValue !== null) {
78 return $parentValue;
79 }
80
81 /**
82 * Filters the resolved field value before standard processing.
83 * Allows field-type-specific value resolution (e.g., password hashing).
84 *
85 * @since 0.1.0
86 *
87 * @param mixed|null $value The resolved value (null to continue with default processing).
88 * @param object $field The field object.
89 * @param mixed[] $submissionData The submission data array.
90 * @param mixed[] $parentChildrenMap Map of parent to children field relationships.
91 * @param mixed[] $parentSubfieldKeys Map of parent subfield keys.
92 * @return mixed The resolved field value or null to continue default processing.
93 */
94 $customValue = apply_filters(
95 'ivyforms/entry/field/resolve_value',
96 null,
97 $field,
98 $submissionData,
99 $parentChildrenMap,
100 $parentSubfieldKeys
101 );
102
103 /**
104 * Filters the resolved field value for a specific field type.
105 * Allows dynamic hook registration per field type (e.g., 'ivyforms/entry/field/resolve_value/password').
106 *
107 * @since 0.1.0
108 *
109 * @param mixed|null $value The resolved value (null to continue with default processing).
110 * @param object $field The field object.
111 * @param mixed[] $submissionData The submission data array.
112 * @param mixed[] $parentChildrenMap Map of parent to children field relationships.
113 * @param mixed[] $parentSubfieldKeys Map of parent subfield keys.
114 * @return mixed The resolved field value or null to continue default processing.
115 */
116 $customValue = apply_filters(
117 "ivyforms/entry/field/resolve_value/{$fieldType}",
118 $customValue,
119 $field,
120 $submissionData,
121 $parentChildrenMap,
122 $parentSubfieldKeys
123 );
124
125 if ($customValue !== null) {
126 return $customValue;
127 }
128
129 if (in_array($fieldType, ['name', 'address'], true) && ($parentId === null || $parentId === 0)) {
130 return $this->getCompoundFieldValue($fieldId, $parentChildrenMap, $parentSubfieldKeys, $submissionData);
131 }
132
133 if ($fieldType === 'time') {
134 $value = EntryHelper::getDefaultFieldValue($fieldId, $submissionData);
135 return DateTimeHelper::normalizeTimeValue($value);
136 }
137
138 if ($fieldType === 'date') {
139 $value = EntryHelper::getDefaultFieldValue($fieldId, $submissionData);
140 return DateTimeHelper::normalizeDateValue($value);
141 }
142
143 return EntryHelper::getDefaultFieldValue($fieldId, $submissionData);
144 }
145
146 /**
147 * Build a map of field entities indexed by field ID.
148 *
149 * @param array<int, array<string, mixed>> $entryFields
150 * @return array<int, object>
151 */
152 private function buildFieldsMap(array $entryFields): array
153 {
154 // Extract unique field IDs from entry fields
155 $fieldIds = array_unique(array_column($entryFields, 'fieldId'));
156 if (empty($fieldIds)) {
157 return [];
158 }
159
160 // Single query to load only needed fields
161 return $this->fieldService->getFieldsByIds($fieldIds);
162 }
163
164 /**
165 * Format field value based on field type.
166 *
167 * @param string $fieldType
168 * @param mixed $value
169 * @param bool $skipFormatting
170 * @return mixed
171 * @SuppressWarnings(PHPMD)
172 */
173 private function formatFieldValue(string $fieldType, $value, bool $skipFormatting = false)
174 {
175 // Convert timestamp to HH:MM format for time fields
176 if ($fieldType === 'time' && is_numeric($value)) {
177 $value = DateTimeHelper::timestampToTime((int)$value);
178 }
179
180 // Convert timestamp to date format for date fields
181 if ($fieldType === 'date' && is_numeric($value)) {
182 $value = DateTimeHelper::timestampToDate((int)$value);
183 }
184
185 /**
186 * Filters the formatted field value for frontend display.
187 * Allows field-type-specific formatting.
188 *
189 * @since 0.1.0
190 *
191 * @param mixed $value The field value to format.
192 * @param string $fieldType The field type (lowercase).
193 * @return mixed The formatted field value.
194 */
195 $value = apply_filters('ivyforms/entry/field/format_value', $value, $fieldType);
196
197 /**
198 * Filters the formatted field value for a specific field type.
199 * Allows dynamic hook registration per field type.
200 *
201 * @since 0.1.0
202 *
203 * @param mixed $value The field value to format.
204 * @param bool $skipFormatting Whether the field value should be formatted.
205 * @return mixed The formatted field value.
206 */
207 return apply_filters("ivyforms/entry/field/format_value/{$fieldType}", $value, $skipFormatting);
208 }
209
210 /**
211 * Get the value of a parent subfield.
212 *
213 * @param int $fieldId
214 * @param int|null $parentId
215 * @param array<int|string, mixed> $submissionData
216 * @param array<int, string|null> $parentSubfieldKeys
217 * @return mixed|null
218 */
219 private function getParentSubfieldValue(
220 int $fieldId,
221 ?int $parentId,
222 array $submissionData,
223 array $parentSubfieldKeys
224 ) {
225 return EntryHelper::getParentSubfieldValue($fieldId, $parentId, $submissionData, $parentSubfieldKeys);
226 }
227
228 /**
229 * Get the compound field value by combining child field values.
230 *
231 * @param int $fieldId
232 * @param array<int, array<int>> $parentChildrenMap
233 * @param array<int, string|null> $parentSubfieldKeys
234 * @param array<int|string, mixed> $submissionData
235 * @return string
236 */
237 private function getCompoundFieldValue(
238 int $fieldId,
239 array $parentChildrenMap,
240 array $parentSubfieldKeys,
241 array $submissionData
242 ): string {
243 return EntryHelper::getCompoundFieldValue($fieldId, $parentChildrenMap, $parentSubfieldKeys, $submissionData);
244 }
245 }
246