PluginProbe
The Innovative Form Builder – IvyForms / 0.6.1-backup
The Innovative Form Builder – IvyForms v0.6.1-backup
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.6.1-backup, at backend/src/Repository/Field/FieldRepository.php

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