PluginProbe
The Innovative Form Builder – IvyForms / 0.8.2
The Innovative Form Builder – IvyForms v0.8.2
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 / Repository / Field / FieldRepository.php

FieldRepository.php in The Innovative Form Builder – IvyForms 0.8.2, at backend/src/Repository/Field/FieldRepository.php

370 lines 15.5 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\Repository\Field;
9
10 // phpcs:disable PSR1.Files.SideEffects
11 if (!defined('ABSPATH')) {
12 exit; // Exit if accessed directly
13 }
14
15 use IvyForms\Common\Exceptions\InvalidArgumentException;
16 use IvyForms\Common\Exceptions\QueryExecutionException;
17 use IvyForms\Entity\Field\Field;
18 use IvyForms\Factory\Field\FieldFactory;
19 use IvyForms\Repository\AbstractRepository;
20 use IvyForms\Services\Translations\BackendStrings;
21
22 /**
23 * Class FieldRepository
24 *
25 * @package IvyForms\Repository\Field
26 */
27 class FieldRepository extends AbstractRepository implements FieldRepositoryInterface
28 {
29 public const FACTORY = FieldFactory::class;
30
31 /**
32 * Add field to the database
33 *
34 * @param Field $entity
35 *
36 * @return int
37 *
38 * @throws QueryExecutionException
39 */
40 public function add($entity): int
41 {
42
43 $data = $entity->toArray();
44
45 $result = $this->wpdb->insert(
46 $this->table,
47 [
48 'fieldIndex' => $data['fieldIndex'],
49 'formId' => $data['formId'],
50 'type' => $data['type'],
51 'label' => $data['label'],
52 'required' => (int)$data['required'],
53 'defaultValue' => $data['defaultValue'],
54 'placeholder' => $data['placeholder'],
55 'position' => $data['position'],
56 'rowIndex' => $data['rowIndex'] ?? 0,
57 'columnIndex' => $data['columnIndex'] ?? 0,
58 'width' => $data['width'] ?? 100,
59 'parentId' => $data['parentId'] ?? null,
60 'settings' => json_encode(
61 /**
62 * Allows modification of the settings data before saving to database.
63 * @since 0.1.0
64 *
65 * @param mixed[] $settings The current settings array.
66 * @param mixed[] $data The full field data array.
67 * @param Field $entity The Field entity instance.
68 * @return mixed[] The modified settings array.
69 */
70 apply_filters(
71 'ivyforms/repository/field/settings',
72 [
73 'hideLabel' => (int)$data['hideLabel'],
74 'readOnly' => (int)$data['readOnly'],
75 'description' => $data['description'],
76 'requiredMessage' => $data['requiredMessage'],
77 'cssClasses' => $data['cssClasses'],
78 'limitMaxLength' => (int)$data['limitMaxLength'],
79 'maxLength' => $data['maxLength'],
80 'labelPosition' => $data['labelPosition'],
81 'noDuplicates' => (int)$data['noDuplicates'],
82 'shuffleOptions' => (int)$data['shuffleOptions'],
83 'showValues' => (int)$data['showValues'],
84 'enableSearch' => (int)$data['enableSearch'],
85 'rows' => (int)$data['rows'],
86 'confirmFieldEnabled' => (int)($data['confirmFieldEnabled'] ?? 0),
87 'confirmFieldLabel' => $data['confirmFieldLabel'] ?? '',
88 'confirmFieldPlaceholder' => $data['confirmFieldPlaceholder'] ?? '',
89 'confirmFieldHideLabel' => (int)($data['confirmFieldHideLabel'] ?? 0),
90 'phoneFormat' => $data['phoneFormat'],
91 'phoneAutoDetect' => $data['phoneAutoDetect'],
92 'minValue' => isset($data['minValue'])
93 ? (float)$data['minValue'] : null,
94 'maxValue' => isset($data['maxValue'])
95 ? (float)$data['maxValue'] : null,
96 'step' => (float)$data['step'],
97 'numberFormat' => $data['numberFormat'] ?? '',
98 'visible' => (int)$data['visible'],
99 'inputPrefix' => $data['inputPrefix'] ?? '',
100 'inputSuffix' => $data['inputSuffix'] ?? '',
101 'timeFieldType' => $data['timeFieldType'] ?? '',
102 'timeFormat' => $data['timeFormat'] ?? '',
103 'dateFieldType' => $data['dateFieldType'] ?? '',
104 'dateFormat' => $data['dateFormat'] ?? '',
105 'minDateValue' => $data['minDateValue'] ?? '',
106 'maxDateValue' => $data['maxDateValue'] ?? '',
107 'showRatingText' => (int)($data['showRatingText'] ?? 0),
108 'ratingIcon' => $data['ratingIcon'] ?? 'star',
109 ],
110 $data,
111 $entity
112 )
113 ),
114 'dateCreated' => current_time('mysql')
115 ],
116 ['%d', '%d', '%s', '%s', '%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d', '%s', '%s']
117 );
118
119 if ($result === false) {
120 throw new QueryExecutionException(
121 BackendStrings::getExceptionStrings()['unable_to_add_data'] . __CLASS__
122 );
123 }
124
125 return $this->wpdb->insert_id;
126 }
127
128 /**
129 * Update field in the database
130 *
131 * @param int $id
132 * @param Field $entity
133 *
134 * @return bool
135 *
136 * @throws QueryExecutionException
137 */
138 public function update(int $id, $entity): bool
139 {
140
141 $data = $entity->toArray();
142
143 $result = $this->wpdb->update(
144 $this->table,
145 [
146 'fieldIndex' => $data['fieldIndex'],
147 'formId' => $data['formId'],
148 'type' => $data['type'],
149 'label' => $data['label'],
150 'required' => (int)$data['required'],
151 'defaultValue' => $data['defaultValue'],
152 'placeholder' => $data['placeholder'],
153 'position' => $data['position'],
154 'rowIndex' => $data['rowIndex'] ?? 0,
155 'columnIndex' => $data['columnIndex'] ?? 0,
156 'width' => $data['width'] ?? 100,
157 'parentId' => $data['parentId'] ?? null,
158 'settings' => json_encode(
159 /**
160 * Allows modification of the settings data before updating database.
161 * @since 0.1.0
162 *
163 * @param mixed[] $settings The current settings array.
164 * @param mixed[] $data The full field data array.
165 * @param Field $entity The Field entity instance.
166 * @return mixed[] The modified settings array.
167 */
168 apply_filters(
169 'ivyforms/repository/field/settings',
170 [
171 'hideLabel' => (int)$data['hideLabel'],
172 'readOnly' => (int)$data['readOnly'],
173 'description' => $data['description'],
174 'requiredMessage' => $data['requiredMessage'],
175 'cssClasses' => $data['cssClasses'],
176 'limitMaxLength' => (int)$data['limitMaxLength'],
177 'maxLength' => $data['maxLength'],
178 'labelPosition' => $data['labelPosition'],
179 'noDuplicates' => (int)$data['noDuplicates'],
180 'shuffleOptions' => (int)$data['shuffleOptions'],
181 'showValues' => (int)$data['showValues'],
182 'enableSearch' => (int)$data['enableSearch'],
183 'rows' => (int)$data['rows'],
184 'confirmFieldEnabled' => (int)($data['confirmFieldEnabled'] ?? 0),
185 'confirmFieldLabel' => $data['confirmFieldLabel'] ?? '',
186 'confirmFieldPlaceholder' => $data['confirmFieldPlaceholder'] ?? '',
187 'confirmFieldHideLabel' => (int)($data['confirmFieldHideLabel'] ?? 0),
188 'phoneFormat' => $data['phoneFormat'],
189 'phoneAutoDetect' => $data['phoneAutoDetect'],
190 'minValue' => isset($data['minValue'])
191 ? (float)$data['minValue'] : null,
192 'maxValue' => isset($data['maxValue'])
193 ? (float)$data['maxValue'] : null,
194 'step' => (float)$data['step'],
195 'numberFormat' => $data['numberFormat'] ?? '',
196 'visible' => array_key_exists('visible', $data) ? (int)$data['visible'] : 1,
197 'inputPrefix' => $data['inputPrefix'] ?? '',
198 'inputSuffix' => $data['inputSuffix'] ?? '',
199 'timeFieldType' => $data['timeFieldType'] ?? '',
200 'timeFormat' => $data['timeFormat'] ?? '',
201 'dateFieldType' => $data['dateFieldType'] ?? '',
202 'dateFormat' => $data['dateFormat'] ?? '',
203 'minDateValue' => $data['minDateValue'] ?? '',
204 'maxDateValue' => $data['maxDateValue'] ?? '',
205 'showRatingText' => (int)($data['showRatingText'] ?? 0),
206 'ratingIcon' => $data['ratingIcon'] ?? 'star',
207 ],
208 $data,
209 $entity
210 )
211 ),
212 ],
213 ['id' => $data['id']],
214 ['%d', '%d', '%s', '%s', '%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d', '%s'],
215 ['%d']
216 );
217
218 if ($result === false) {
219 throw new QueryExecutionException(BackendStrings::getAllFormsStrings()['unable_to_save_data'] . __CLASS__);
220 }
221
222 return $result;
223 }
224
225 /**
226 * Get fields by form ID
227 *
228 * @param int $id
229 *
230 * @return mixed[]
231 * @throws QueryExecutionException
232 */
233 public function getFieldsById(int $id): array
234 {
235 $rows = $this->wpdb->get_results(
236 $this->wpdb->prepare(
237 $this->selectQuery() . " WHERE $this->table.formId = %d ORDER BY $this->table.position ASC",
238 $id
239 ),
240 ARRAY_A
241 );
242 if ($rows === false) {
243 throw new QueryExecutionException(
244 BackendStrings::getExceptionStrings()['unable_find_by_id'] . __CLASS__
245 );
246 }
247 $result = [];
248 foreach ($rows as $row) {
249 if (array_key_exists('parentId', $row)) {
250 $row['parentId'] = $row['parentId'] !== null ? (int)$row['parentId'] : null;
251 }
252 $result[] = call_user_func([static::FACTORY, 'create'], $row);
253 }
254 return $result;
255 }
256
257 /**
258 * Get multiple fields by their IDs in a single query.
259 *
260 * @param int[] $fieldIds
261 * @return array<int, object> Indexed by field ID
262 * @throws QueryExecutionException
263 */
264 public function getFieldsByIds(array $fieldIds): array
265 {
266 if (empty($fieldIds)) {
267 return [];
268 }
269
270 $fieldIds = array_map('intval', $fieldIds);
271 $placeholders = implode(',', array_fill(0, count($fieldIds), '%d'));
272 $rows = $this->wpdb->get_results(
273 $this->wpdb->prepare(
274 $this->selectQuery() . " WHERE $this->table.id IN ($placeholders) ORDER BY $this->table.position ASC",
275 ...$fieldIds
276 ),
277 ARRAY_A
278 );
279
280 if ($rows === false) {
281 throw new QueryExecutionException(
282 BackendStrings::getExceptionStrings()['unable_find_by_id'] . __CLASS__
283 );
284 }
285
286 $result = [];
287 foreach ($rows as $row) {
288 if (array_key_exists('parentId', $row)) {
289 $row['parentId'] = $row['parentId'] !== null ? (int)$row['parentId'] : null;
290 }
291 $field = call_user_func([static::FACTORY, 'create'], $row);
292 $result[$field->getId()] = $field;
293 }
294
295 return $result;
296 }
297
298 /**
299 * Delete multiple fields by their IDs in bulk, and their field options.
300 *
301 * @param array<int> $ids
302 * @return int Number of deleted fields
303 * @throws QueryExecutionException
304 */
305 public function deleteMany(array $ids): int
306 {
307 if (empty($ids)) {
308 return 0;
309 }
310 $placeholders = implode(',', array_fill(0, count($ids), '%d'));
311 $deleteFieldsQuery = "DELETE FROM {$this->table} WHERE id IN ($placeholders)";
312 $result = $this->wpdb->query($this->wpdb->prepare($deleteFieldsQuery, ...$ids));
313 if ($result === false) {
314 throw new QueryExecutionException(
315 sprintf(
316 BackendStrings::getExceptionStrings()['failed_delete_by_ids'],
317 implode(', ', $ids),
318 $this->table
319 )
320 );
321 }
322 return $result;
323 }
324
325 /**
326 * Delete multiple fields by foreign key values (formId), and their field options.
327 *
328 * @param array<int> $formIds
329 * @param string $foreignColumn
330 * @return int Number of deleted fields
331 * @throws QueryExecutionException
332 */
333 public function deleteManyByForeignKeyValues(array $formIds, string $foreignColumn = 'formId'): int
334 {
335 if (empty($formIds)) {
336 return 0;
337 }
338 $formIds = array_map('intval', $formIds);
339 $placeholders = implode(',', array_fill(0, count($formIds), '%d'));
340 $deleteFieldsQuery = "DELETE FROM {$this->table} WHERE {$foreignColumn} IN ($placeholders)";
341 $result = $this->wpdb->query($this->wpdb->prepare($deleteFieldsQuery, ...$formIds));
342 if ($result === false) {
343 throw new QueryExecutionException(
344 BackendStrings::getExceptionStrings()['failed_delete_by_foreign_keys']
345 );
346 }
347 return $result;
348 }
349
350 /**
351 * Delete fields by a single foreign key value (formId), and their field options.
352 *
353 * @param int $formId
354 * @param string $foreignColumn
355 * @return int Number of deleted fields
356 * @throws QueryExecutionException
357 */
358 public function deleteOneByForeignKeyValue(int $formId, string $foreignColumn = 'formId'): int
359 {
360 $deleteFieldsQuery = "DELETE FROM {$this->table} WHERE {$foreignColumn} = %d";
361 $result = $this->wpdb->query($this->wpdb->prepare($deleteFieldsQuery, $formId));
362 if ($result === false) {
363 throw new QueryExecutionException(
364 BackendStrings::getExceptionStrings()['failed_delete_by_foreign_key']
365 );
366 }
367 return $result;
368 }
369 }
370