PluginProbe
The Innovative Form Builder – IvyForms / 1.4.1
The Innovative Form Builder – IvyForms v1.4.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 / Factory / Form / FormFactory.php

FormFactory.php in The Innovative Form Builder – IvyForms 1.4.1, at backend/src/Factory/Form/FormFactory.php

253 lines 8.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * @copyright © Melograno Venture Studio. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace IvyForms\Factory\Form;
9
10 use IvyForms\Common\Exceptions\ValidationException;
11 use IvyForms\Common\Helpers\Helper;
12 use IvyForms\Common\Sanitizer\Sanitizer;
13 use IvyForms\Entity\Form\Form as FormEntity;
14 use IvyForms\ValueObjects\Form\Form;
15 use IvyForms\ValueObjects\Form\IntegrationSettings;
16 use IvyForms\ValueObjects\Form\PaymentSettings;
17 use IvyForms\ValueObjects\Form\FormMetadata;
18 use IvyForms\ValueObjects\Form\FormSettings;
19 use IvyForms\ValueObjects\Form\StyleSettings;
20 use IvyForms\Services\Translations\BackendStrings;
21
22 /**
23 * Class FormFactory
24 *
25 * @package IvyForms\Factory\Form
26 */
27 class FormFactory
28 {
29 /**
30 * Top-level keys owned by Lite; anything else in $data is extension data (e.g. Pro settings).
31 *
32 * @var list<string>
33 */
34 private const KNOWN_FORM_DATA_KEYS = [
35 'id',
36 'name',
37 'author',
38 'starred',
39 'published',
40 'dateCreated',
41 'dateEdited',
42 'fields',
43 'description',
44 'formType',
45 'showTitle',
46 'showDescription',
47 'storeEntries',
48 'integrationSettings',
49 'styleSettings',
50 'formActionButtons',
51 'pages',
52 'progressIndicator',
53 'paymentSettings',
54 'settings',
55 'confirmationId',
56 ];
57
58 /**
59 * @param array<string, mixed> $data
60 *
61 * @return FormEntity
62 *
63 * @throws ValidationException
64 */
65 public static function create(array $data): FormEntity
66 {
67 $settings = isset($data['settings']) ? json_decode($data['settings'], true) : [];
68 if (!is_array($settings)) {
69 $settings = [];
70 }
71
72 /**
73 * @param array<string, mixed> $data
74 * @param array<string, mixed> $settings
75 * @return array<string, mixed>
76 */
77 $data = apply_filters('ivyforms/form/factory/extract_settings', $data, $settings);
78
79 $integrationSettings = Helper::parseToArray($data['integrationSettings']);
80 $pages = $data['pages'] ?? null;
81 $progressIndicator = $data['progressIndicator'] ?? null;
82 $rawStyleSettings = isset($data['styleSettings']) ? Helper::parseToArray($data['styleSettings']) : null;
83 $styleSettings = new StyleSettings(is_array($rawStyleSettings) ? $rawStyleSettings : null);
84
85 if (!empty($settings)) {
86 $data['showTitle'] = $settings['showTitle'] ?? true;
87 $data['showDescription'] = $settings['showDescription'] ?? false;
88 $data['storeEntries'] = !isset($settings['storeEntries']) || (bool)$settings['storeEntries'];
89 $data['formActionButtons'] = $settings['formActionButtons'] ?? [
90 'submitButtonSettings' => [
91 'label' => BackendStrings::getCommonStrings()['submit'],
92 'position' => 'default'
93 ]
94 ];
95
96 // Prefer values from decoded settings, fallback to top-level API payload.
97 $pages = array_key_exists('pages', $settings)
98 ? $settings['pages']
99 : ($data['pages'] ?? null);
100 $progressIndicator = array_key_exists('progressIndicator', $settings)
101 ? $settings['progressIndicator']
102 : ($data['progressIndicator'] ?? null);
103 }
104
105 // Process extensible form options via one universal Pro hook.
106 $formOptions = [
107 'pages' => $pages,
108 'progressIndicator' => $progressIndicator,
109 ];
110
111 $formOptions = apply_filters('ivyforms/process/form_options', $formOptions, $data['id'] ?? 0);
112
113 $data['pages'] = $formOptions['pages'] ?? null;
114 $data['progressIndicator'] = $formOptions['progressIndicator'] ?? null;
115
116 // Process form action buttons via Pro hook if available
117 // This runs for both database-loaded and API-submitted formActionButtons
118 if (isset($data['formActionButtons'])) {
119 $data['formActionButtons'] = apply_filters(
120 'ivyforms/process/form_action_buttons',
121 $data['formActionButtons'],
122 $data['id'] ?? 0
123 );
124 } else {
125 // Set default if not provided
126 $data['formActionButtons'] = [
127 'submitButtonSettings' => [
128 'label' => BackendStrings::getCommonStrings()['submit'],
129 'position' => 'default'
130 ]
131 ];
132 }
133
134 if (empty($data['fields']) && isset($data['pages']) && is_array($data['pages'])) {
135 $allFields = [];
136 foreach ($data['pages'] as $page) {
137 if (isset($page['fields']) && is_array($page['fields'])) {
138 foreach ($page['fields'] as $field) {
139 $allFields[] = $field;
140 }
141 }
142 }
143 if (!empty($allFields)) {
144 $data['fields'] = $allFields;
145 }
146 }
147
148 $paymentRaw = null;
149 if (isset($data['paymentSettings']) && is_array($data['paymentSettings'])) {
150 $paymentRaw = $data['paymentSettings'];
151 } elseif (!empty($settings['paymentSettings']) && is_array($settings['paymentSettings'])) {
152 $paymentRaw = $settings['paymentSettings'];
153 }
154
155 $resolvedFormType = Sanitizer::sanitizeFormType($data['formType'] ?? Sanitizer::FORM_TYPE_CLASSIC);
156
157 $formObject = new Form(
158 $data['id'] ?? 0,
159 $data['name'] ?? '',
160 $data['description'] ?? '',
161 new FormMetadata(
162 $data['author'] ?? '',
163 $data['starred'] ?? false,
164 $data['published'] ?? true,
165 isset($data['dateCreated']) ? (string)$data['dateCreated'] : null,
166 isset($data['dateEdited']) ? (string)$data['dateEdited'] : null
167 ),
168 new FormSettings(
169 $data['showTitle'] ?? true,
170 $data['showDescription'] ?? false,
171 isset($data['storeEntries']) ? (bool)$data['storeEntries'] : true
172 ),
173 $data['fields'] ?? [],
174 new IntegrationSettings($integrationSettings),
175 $data['pages'] ?? null,
176 $data['progressIndicator'] ?? null,
177 $styleSettings,
178 $data['formActionButtons'] ?? null,
179 $resolvedFormType,
180 new PaymentSettings($paymentRaw)
181 );
182
183 $form = new FormEntity($formObject);
184
185 if (isset($data['id'])) {
186 $form->setId($data['id']);
187 }
188
189 if (isset($data['name'])) {
190 $form->setName($data['name']);
191 }
192
193 if (isset($data['author'])) {
194 $form->setAuthor($data['author']);
195 }
196
197 if (isset($data['starred'])) {
198 $form->setStarred($data['starred']);
199 }
200
201 if (isset($data['published'])) {
202 $form->setPublished($data['published']);
203 }
204
205 if (isset($data['description'])) {
206 $form->setDescription($data['description']);
207 }
208
209 if (isset($data['fields'])) {
210 $form->setFields($data['fields']);
211 }
212
213 if (isset($data['showTitle'])) {
214 $form->setTitleVisible($data['showTitle']);
215 }
216
217 if (isset($data['showDescription'])) {
218 $form->setDescriptionVisible($data['showDescription']);
219 }
220
221 if (isset($data['storeEntries'])) {
222 $form->setStoreEntries($data['storeEntries']);
223 }
224
225 if (isset($data['pages'])) {
226 $form->setPages($data['pages']);
227 }
228
229 if (isset($data['progressIndicator'])) {
230 $form->setProgressIndicator($data['progressIndicator']);
231 }
232
233 if (isset($data['formActionButtons'])) {
234 $form->setFormActionButtons($data['formActionButtons']);
235 }
236
237 $form->setExtensionData(self::extractExtensionData($data));
238
239 return $form;
240 }
241
242 /**
243 * Keys in $data that are not owned by Lite (e.g. Pro form settings in REST / settings JSON).
244 *
245 * @param array<string, mixed> $data
246 * @return array<string, mixed>
247 */
248 private static function extractExtensionData(array $data): array
249 {
250 return array_diff_key($data, array_flip(self::KNOWN_FORM_DATA_KEYS));
251 }
252 }
253