PluginProbe
The Innovative Form Builder – IvyForms / 1.1
The Innovative Form Builder – IvyForms v1.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 / ValueObjects / Field / Field.php

Field.php in The Innovative Form Builder – IvyForms 1.1, at backend/src/ValueObjects/Field/Field.php

528 lines 12.6 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\ValueObjects\Field;
9
10 use IvyForms\Common\Exceptions\ValidationException;
11 use IvyForms\Services\Translations\BackendStrings;
12
13 /**
14 * Class Field
15 *
16 * @SuppressWarnings(PHPMD)
17 * @package IvyForms\ValueObjects\Field
18 */
19 final class Field
20 {
21 /**
22 * @var int
23 */
24 public int $id;
25 /**
26 * @var int
27 */
28 public int $formId;
29 /**
30 * @var int
31 */
32 public int $fieldIndex;
33 /**
34 * @var string
35 */
36 public string $type;
37 /**
38 * @var int
39 */
40 public int $position;
41 /**
42 * @var int Row index for grid layout (0-based)
43 */
44 public int $rowIndex;
45 /**
46 * @var int Column index within row (0-based, max 4 for 5 fields per row)
47 */
48 public int $columnIndex;
49 /**
50 * @var int Field width percentage (20, 25, 33, 50, or 100)
51 */
52 public int $width;
53 /**
54 * @var int|null
55 */
56 public ?int $parentId;
57 /**
58 * @var string|null Page ID for multi-page forms
59 */
60 public ?string $pageId;
61 /**
62 * @var FieldGeneralSettings
63 */
64 public FieldGeneralSettings $generalSettings;
65 /**
66 * @var FieldOptions
67 */
68 public FieldOptions $fieldOptions;
69 /**
70 * @var int Number of rows (for textarea fields)
71 */
72 public int $rows;
73 /** @var bool */
74 public bool $confirmFieldEnabled;
75 /** @var string */
76 public string $confirmFieldLabel;
77 /** @var string */
78 public string $confirmFieldPlaceholder;
79 /** @var bool */
80 public bool $confirmFieldHideLabel;
81 /**
82 * @var FieldAdvancedSettings
83 */
84 public FieldAdvancedSettings $advancedSettings;
85 /**
86 * @var array<string, mixed> Additional properties from Pro plugin
87 */
88 private array $additionalProperties = [];
89
90 /**
91 * Field constructor.
92 * @SuppressWarnings(PHPMD)
93 *
94 * @param int $id
95 * @param int $formId
96 * @param int $fieldIndex
97 * @param string $type
98 * @param int $position
99 * @param int|null $parentId
100 * @param FieldGeneralSettings $generalSettings
101 * @param FieldOptions $fieldOptions
102 * @param FieldAdvancedSettings $advancedSettings
103 * @param int $rows
104 * @param int $rowIndex
105 * @param int $columnIndex
106 * @param int $width
107 * @param string|null $pageId
108 *
109 * @throws ValidationException
110 */
111 public function __construct(
112 int $id,
113 int $formId,
114 int $fieldIndex,
115 string $type,
116 int $position,
117 FieldGeneralSettings $generalSettings,
118 FieldOptions $fieldOptions,
119 FieldAdvancedSettings $advancedSettings,
120 ?int $parentId = null,
121 int $rows = 0,
122 int $rowIndex = 0,
123 int $columnIndex = 0,
124 int $width = 100,
125 ?string $pageId = null
126 ) {
127 $this->id = $this->validateId($id);
128 $this->formId = $this->validateId($formId);
129 $this->fieldIndex = $this->validateId($fieldIndex);
130 $this->type = $this->validateString($type, 50, 'type');
131 $this->position = $this->validatePosition($position);
132 $this->rowIndex = $this->validateRowIndex($rowIndex);
133 $this->columnIndex = $this->validateColumnIndex($columnIndex);
134 $this->width = $this->validateWidth($width);
135 $this->parentId = $this->validateParentId($parentId);
136 $this->pageId = $pageId;
137 $this->generalSettings = $generalSettings;
138 $this->fieldOptions = $fieldOptions;
139 $this->advancedSettings = $advancedSettings;
140 $this->rows = $this->validateRows($rows);
141
142 /**
143 * Allows initialization of additional properties for the Field value object.
144 * @since 0.1.0
145 *
146 * @param mixed[] $additionalProperties The current list of additional properties.
147 * @param Field $field The Field value object instance.
148 * @return mixed[] The modified list of additional properties.
149 */
150 $this->additionalProperties =
151 apply_filters('ivyforms/field/value_object/init_additional_properties', [], $this);
152 }
153
154 /**
155 * Set an additional property
156 *
157 * @param string $key
158 * @param mixed $value
159 *
160 * @return void
161 */
162 public function setAdditionalProperty(string $key, $value): void
163 {
164 foreach ($this->additionalProperties as &$property) {
165 if (array_key_exists($key, $property)) {
166 $property[$key] = $value; // update existing
167 return;
168 }
169 }
170
171 // if not found, append new key-value pair
172 $this->additionalProperties[] = [$key => $value];
173 }
174
175 /**
176 * Get an additional property
177 *
178 * @param string $key
179 * @return mixed|null The value of the additional property, or null if not found
180 */
181 public function getAdditionalProperty(string $key)
182 {
183 foreach ($this->additionalProperties as $property) {
184 if (array_key_exists($key, $property)) {
185 return $property[$key];
186 }
187 }
188 return null;
189 }
190
191 /**
192 * Get all additional properties
193 *
194 * @return array<string, mixed> The additional properties
195 */
196 public function getAllAdditionalProperties(): array
197 {
198 return $this->additionalProperties;
199 }
200
201 /**
202 * Validates the ID.
203 *
204 * @param int $id
205 *
206 * @return int
207 * @throws ValidationException
208 */
209 public function validateId(int $id): int
210 {
211 if ($id < 0) {
212 throw new ValidationException(BackendStrings::getExceptionStrings()['id_positive_integer']);
213 }
214 return $id;
215 }
216
217 /**
218 * Validates parent id which can be null or non-negative int.
219 *
220 * @param int|null $parentId
221 *
222 * @return int|null
223 * @throws ValidationException
224 */
225 private function validateParentId(?int $parentId): ?int
226 {
227 if ($parentId === null) {
228 return null;
229 }
230 if ($parentId < 0) {
231 throw new ValidationException(BackendStrings::getExceptionStrings()['parentId_positive_integer']);
232 }
233 return $parentId;
234 }
235
236 /**
237 * Validates a string value.
238 *
239 * @param string $value
240 * @param int $maxLength
241 * @param string $fieldName
242 *
243 * @return string
244 *
245 * @throws ValidationException
246 */
247 private function validateString(string $value, int $maxLength, string $fieldName): string
248 {
249 if (strlen($value) > $maxLength) {
250 throw new ValidationException(
251 sprintf(
252 /* translators: 1: String value, 2: String max length. */
253 esc_html__('%1$s must be at most %2$d characters.', 'ivyforms'),
254 esc_html($fieldName),
255 $maxLength
256 )
257 );
258 }
259 return $value;
260 }
261
262 /**
263 * Validates the position.
264 *
265 * @param int $value
266 *
267 * @return int
268 *
269 * @throws ValidationException
270 */
271 private function validatePosition(int $value): int
272 {
273 if ($value < 0) {
274 throw new ValidationException(
275 BackendStrings::getExceptionStrings()['position_non_negative']
276 );
277 }
278 return $value;
279 }
280
281 /**
282 * Validates the row index.
283 *
284 * @param int $value
285 *
286 * @return int
287 *
288 * @throws ValidationException
289 */
290 private function validateRowIndex(int $value): int
291 {
292 if ($value < 0) {
293 throw new ValidationException(
294 BackendStrings::getExceptionStrings()['row_index_non_negative']
295 );
296 }
297 return $value;
298 }
299
300 /**
301 * Validates the column index (0-4 for max 5 fields per row).
302 *
303 * @param int $value
304 *
305 * @return int
306 *
307 * @throws ValidationException
308 */
309 private function validateColumnIndex(int $value): int
310 {
311 if ($value < 0 || $value > 4) {
312 throw new ValidationException(
313 BackendStrings::getExceptionStrings()['column_index_range']
314 );
315 }
316 return $value;
317 }
318
319 /**
320 * Validates the width percentage.
321 *
322 * @param int $value
323 *
324 * @return int
325 *
326 * @throws ValidationException
327 */
328 private function validateWidth(int $value): int
329 {
330 if ($value < 20 || $value > 100) {
331 throw new ValidationException(
332 BackendStrings::getExceptionStrings()['width_range']
333 );
334 }
335 return $value;
336 }
337
338 /**
339 * Validate rows.
340 *
341 * @param int $rows
342 * @return int
343 * @throws ValidationException
344 */
345 private function validateRows(int $rows): int
346 {
347 if ($rows < 0) {
348 throw new ValidationException(
349 BackendStrings::getExceptionStrings()['rows_non_negative']
350 );
351 }
352 return $rows;
353 }
354
355 /**
356 * Get the form ID.
357 *
358 * @return int
359 */
360 public function getFormId(): int
361 {
362 return $this->formId;
363 }
364
365 /**
366 * Get the field ID.
367 *
368 * @return int
369 */
370 public function getId(): int
371 {
372 return $this->id;
373 }
374
375 /**
376 * Get the field index.
377 *
378 * @return int
379 */
380 public function getIndex(): int
381 {
382 return $this->fieldIndex;
383 }
384
385 /**
386 * Get the field type.
387 *
388 * @return string
389 */
390 public function getType(): string
391 {
392 return $this->type;
393 }
394
395 /**
396 * Get the field position.
397 *
398 * @return int
399 */
400 public function getPosition(): int
401 {
402 return $this->position;
403 }
404
405 /**
406 * Get the row index.
407 *
408 * @return int
409 */
410 public function getRowIndex(): int
411 {
412 return $this->rowIndex;
413 }
414
415 /**
416 * Get the column index.
417 *
418 * @return int
419 */
420 public function getColumnIndex(): int
421 {
422 return $this->columnIndex;
423 }
424
425 /**
426 * Get the field width percentage.
427 *
428 * @return int
429 */
430 public function getWidth(): int
431 {
432 return $this->width;
433 }
434
435 /**
436 * Get the parent field id.
437 *
438 * @return int|null
439 */
440 public function getParentId(): ?int
441 {
442 return $this->parentId;
443 }
444
445 /**
446 * Get the general settings object.
447 *
448 * @return FieldGeneralSettings
449 */
450 public function getGeneralSettings(): FieldGeneralSettings
451 {
452 return $this->generalSettings;
453 }
454
455 /**
456 * Get the field options.
457 *
458 * @return FieldOptions
459 */
460 public function getFieldOptions(): FieldOptions
461 {
462 return $this->fieldOptions;
463 }
464
465 /**
466 * Get number of rows.
467 * @return int
468 */
469 public function getRows(): int
470 {
471 return $this->rows;
472 }
473
474 /**
475 * Set number of rows.
476 * @param int $rows
477 */
478 public function setRows(int $rows): void
479 {
480 $this->rows = $rows;
481 }
482
483 /**
484 * Get the general settings object.
485 *
486 * @return FieldAdvancedSettings
487 */
488 public function getAdvancedSettings(): FieldAdvancedSettings
489 {
490 return $this->advancedSettings;
491 }
492
493 /**
494 * Convert the field to an array.
495 *
496 * @return array<string, mixed>
497 */
498 public function toArray(): array
499 {
500 $data = [
501 'id' => $this->id,
502 'formId' => $this->formId,
503 'fieldIndex' => $this->fieldIndex,
504 'type' => $this->type,
505 'position' => $this->position,
506 'rowIndex' => $this->rowIndex,
507 'columnIndex' => $this->columnIndex,
508 'width' => $this->width,
509 'parentId' => $this->parentId,
510 'generalSettings' => $this->generalSettings->toArray(),
511 'fieldOptions' => $this->fieldOptions->toArray(),
512 'rows' => $this->rows,
513 // Advanced options
514 'advancedSettings' => $this->advancedSettings->toArray()
515 ];
516
517 /**
518 * Allows modification of the array representation of the Field value object.
519 * @since 0.1.0
520 *
521 * @param mixed[] $data The current array representation of the Field value object.
522 * @param Field $field The Field value object instance.
523 * @return mixed[] The modified array representation of the Field value object.
524 */
525 return apply_filters('ivyforms/field/value_object/add_to_array_additional_properties', $data, $this);
526 }
527 }
528