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

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

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