PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.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
← All changes | backend/src/ValueObjects/Field/Field.php +269 -175 0.3.1 → 1.5 View file →
@@ -1,24 +1,20 @@
1 1 <?php
2 2
3 3 /**
4 -* @copyright © TMS-Plugins. All rights reserved.
4 +* @copyright © Melograno Venture Studio. All rights reserved.
5 5 * @licence See LICENCE.md for license details.
6 6 */
7 7
8 8 namespace IvyForms\ValueObjects\Field;
9 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 10 use IvyForms\Common\Exceptions\ValidationException;
11 +use IvyForms\Services\Translations\BackendStrings;
17 12
18 13 /**
19 14 * Class Field
20 15 *
16 + * @SuppressWarnings(PHPMD)
21 17 * @package IvyForms\ValueObjects\Field
22 18 */
23 19 final class Field
24 20 {
@@ -38,47 +34,59 @@
38 34 * @var string
39 35 */
40 36 public string $type;
41 37 /**
42 - * @var string
38 + * @var int
43 39 */
44 - public string $label;
40 + public int $position;
45 41 /**
46 - * @var string
42 + * @var int Row index for grid layout (0-based)
47 43 */
48 - public string $defaultValue;
44 + public int $rowIndex;
49 45 /**
50 - * @var bool
46 + * @var int Column index within row (0-based, max 4 for 5 fields per row)
51 47 */
52 - public bool $required;
48 + public int $columnIndex;
53 49 /**
54 - * @var string
50 + * @var int Field width percentage (20, 25, 33, 50, or 100)
55 51 */
56 - public string $placeholder;
52 + public int $width;
57 53 /**
58 - * @var int
54 + * @var int|null
59 55 */
60 - public int $position;
56 + public ?int $parentId;
61 57 /**
62 - * @var bool
58 + * @var string|null Page ID for multi-page forms
63 59 */
64 - public bool $hideLabel;
60 + public ?string $pageId;
65 61 /**
66 - * @var bool
62 + * @var FieldGeneralSettings
67 63 */
68 - public bool $readOnly;
64 + public FieldGeneralSettings $generalSettings;
69 65 /**
70 - * @var string
66 + * @var FieldOptions
71 67 */
72 - public string $description;
68 + public FieldOptions $fieldOptions;
73 69 /**
74 - * @var string
70 + * @var int Number of rows (for textarea fields)
75 71 */
76 - public string $requiredMessage;
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;
77 81 /**
78 - * @var string
82 + * @var FieldAdvancedSettings
79 83 */
80 - public string $cssClasses;
84 + public FieldAdvancedSettings $advancedSettings;
85 + /**
86 + * @var array<string, mixed> Additional properties from Pro plugin
87 + */
88 + private array $additionalProperties = [];
81 89
82 90 /**
83 91 * Field constructor.
84 92 * @SuppressWarnings(PHPMD)
@@ -86,18 +94,18 @@
86 94 * @param int $id
87 95 * @param int $formId
88 96 * @param int $fieldIndex
89 97 * @param string $type
90 - * @param string $label
91 - * @param string $defaultValue
92 - * @param bool $required
93 - * @param string $placeholder
94 98 * @param int $position
95 - * @param bool $hideLabel
96 - * @param bool $readOnly
97 - * @param string $description
98 - * @param string $requiredMessage
99 - * @param string $cssClasses
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
100 108 *
101 109 * @throws ValidationException
102 110 */
103 111 public function __construct(
@@ -104,36 +112,94 @@
104 112 int $id,
105 113 int $formId,
106 114 int $fieldIndex,
107 115 string $type,
108 - string $label,
109 - string $defaultValue,
110 - bool $required,
111 - string $placeholder,
112 116 int $position,
113 - bool $hideLabel,
114 - bool $readOnly,
115 - string $description = '',
116 - string $requiredMessage = '',
117 - string $cssClasses = ''
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
118 126 ) {
119 - $this->id = $this->validateId($id);
120 - $this->formId = $this->validateId($formId) ;
121 - $this->fieldIndex = $this->validateId($fieldIndex);
122 - $this->type = $this->validateString($type, 50, 'type');
123 - $this->label = $this->validateString($label, 255, 'label');
124 - $this->defaultValue = $this->validateString($defaultValue, 255, 'defaultValue');
125 - $this->required = $this->validateRequired($required);
126 - $this->placeholder = $this->validateString($placeholder, 255, 'placeholder');
127 - $this->position = $this->validatePosition($position);
128 - $this->hideLabel = $this->validateBool($hideLabel);
129 - $this->readOnly = $this->validateBool($readOnly);
130 - $this->description = $this->validateString($description, 255, 'description');
131 - $this->requiredMessage = $this->validateString($requiredMessage, 255, 'requiredMessage');
132 - $this->cssClasses = $this->validateString($cssClasses, 255, 'cssClasses');
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);
133 152 }
134 153
135 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 + /**
136 202 * Validates the ID.
137 203 *
138 204 * @param int $id
139 205 *
@@ -142,14 +208,33 @@
142 208 */
143 209 public function validateId(int $id): int
144 210 {
145 211 if ($id < 0) {
146 - throw new ValidationException("Id must be a positive integer.");
212 + throw new ValidationException(BackendStrings::getExceptionStrings()['id_positive_integer']);
147 213 }
148 214 return $id;
149 215 }
150 216
151 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 + /**
152 237 * Validates a string value.
153 238 *
154 239 * @param string $value
155 240 * @param int $maxLength
@@ -163,9 +248,9 @@
163 248 {
164 249 if (strlen($value) > $maxLength) {
165 250 throw new ValidationException(
166 251 sprintf(
167 - /* translators: 1: String value, 2: String max length. */
252 + /* translators: 1: String value, 2: String max length. */
168 253 esc_html__('%1$s must be at most %2$d characters.', 'ivyforms'),
169 254 esc_html($fieldName),
170 255 $maxLength
171 256 )
@@ -174,22 +259,28 @@
174 259 return $value;
175 260 }
176 261
177 262 /**
178 - * Validates the required field.
263 + * Validates the position.
179 264 *
180 - * @param bool $value
265 + * @param int $value
181 266 *
182 - * @return bool
267 + * @return int
183 268 *
269 + * @throws ValidationException
184 270 */
185 - private function validateRequired(bool $value): bool
271 + private function validatePosition(int $value): int
186 272 {
273 + if ($value < 0) {
274 + throw new ValidationException(
275 + BackendStrings::getExceptionStrings()['position_non_negative']
276 + );
277 + }
187 278 return $value;
188 279 }
189 280
190 281 /**
191 - * Validates the position.
282 + * Validates the row index.
192 283 *
193 284 * @param int $value
194 285 *
195 286 * @return int
@@ -195,29 +286,74 @@
195 286 * @return int
196 287 *
197 288 * @throws ValidationException
198 289 */
199 - private function validatePosition(int $value): int
290 + private function validateRowIndex(int $value): int
200 291 {
201 292 if ($value < 0) {
202 - throw new ValidationException("position must be a non-negative integer.");
293 + throw new ValidationException(
294 + BackendStrings::getExceptionStrings()['row_index_non_negative']
295 + );
203 296 }
204 297 return $value;
205 298 }
206 299
207 300 /**
208 - * Validates a boolean field.
301 + * Validates the column index (0-4 for max 5 fields per row).
209 302 *
210 - * @param bool $value
303 + * @param int $value
211 304 *
212 - * @return bool
305 + * @return int
306 + *
307 + * @throws ValidationException
213 308 */
214 - private function validateBool(bool $value): bool
309 + private function validateColumnIndex(int $value): int
215 310 {
311 + if ($value < 0 || $value > 4) {
312 + throw new ValidationException(
313 + BackendStrings::getExceptionStrings()['column_index_range']
314 + );
315 + }
216 316 return $value;
217 317 }
218 318
219 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 + /**
220 356 * Get the form ID.
221 357 *
222 358 * @return int
223 359 */
@@ -256,48 +392,8 @@
256 392 return $this->type;
257 393 }
258 394
259 395 /**
260 - * Get the field label.
261 - *
262 - * @return string
263 - */
264 - public function getLabel(): string
265 - {
266 - return $this->label;
267 - }
268 -
269 - /**
270 - * Get the default value.
271 - *
272 - * @return string
273 - */
274 - public function getDefaultValue(): string
275 - {
276 - return $this->defaultValue;
277 - }
278 -
279 - /**
280 - * Check if the field is required.
281 - *
282 - * @return bool
283 - */
284 - public function isRequired(): bool
285 - {
286 - return $this->required;
287 - }
288 -
289 - /**
290 - * Get the field placeholder.
291 - *
292 - * @return string
293 - */
294 - public function getPlaceholder(): string
295 - {
296 - return $this->placeholder;
297 - }
298 -
299 - /**
300 396 * Get the field position.
301 397 *
302 398 * @return int
303 399 */
@@ -306,108 +402,96 @@
306 402 return $this->position;
307 403 }
308 404
309 405 /**
310 - * Check if the field label should be hidden.
406 + * Get the row index.
311 407 *
312 - * @return bool
408 + * @return int
313 409 */
314 - public function isLabelHidden(): bool
410 + public function getRowIndex(): int
315 411 {
316 - return $this->hideLabel;
412 + return $this->rowIndex;
317 413 }
318 414
319 415 /**
320 - * Set the hideLabel setting.
416 + * Get the column index.
321 417 *
322 - * @param bool $hideLabel
418 + * @return int
323 419 */
324 - public function setHideLabel(bool $hideLabel): void
420 + public function getColumnIndex(): int
325 421 {
326 - $this->hideLabel = $hideLabel;
422 + return $this->columnIndex;
327 423 }
328 424
329 425 /**
330 - * Check if the field is read-only.
426 + * Get the field width percentage.
331 427 *
332 - * @return bool
428 + * @return int
333 429 */
334 - public function isReadOnly(): bool
430 + public function getWidth(): int
335 431 {
336 - return $this->readOnly;
432 + return $this->width;
337 433 }
338 434
339 435 /**
340 - * Set the readOnly setting.
436 + * Get the parent field id.
341 437 *
342 - * @param bool $readOnly
438 + * @return int|null
343 439 */
344 - public function setReadOnly(bool $readOnly): void
440 + public function getParentId(): ?int
345 441 {
346 - $this->readOnly = $readOnly;
442 + return $this->parentId;
347 443 }
348 444
349 445 /**
350 - * Get the field description.
446 + * Get the general settings object.
351 447 *
352 - * @return string
448 + * @return FieldGeneralSettings
353 449 */
354 - public function getDescription(): string
450 + public function getGeneralSettings(): FieldGeneralSettings
355 451 {
356 - return $this->description;
452 + return $this->generalSettings;
357 453 }
358 454
359 455 /**
360 - * Set the description setting.
456 + * Get the field options.
361 457 *
362 - * @param string $description
458 + * @return FieldOptions
363 459 */
364 - public function setDescription(string $description): void
460 + public function getFieldOptions(): FieldOptions
365 461 {
366 - $this->description = $description;
462 + return $this->fieldOptions;
367 463 }
368 464
369 465 /**
370 - * Get the field required message.
371 - *
372 - * @return string
466 + * Get number of rows.
467 + * @return int
373 468 */
374 - public function getRequiredMessage(): string
469 + public function getRows(): int
375 470 {
376 - return $this->requiredMessage;
471 + return $this->rows;
377 472 }
378 473
379 474 /**
380 - * Set the required message setting.
381 - *
382 - * @param string $requiredMessage
475 + * Set number of rows.
476 + * @param int $rows
383 477 */
384 - public function setRequiredMessage(string $requiredMessage): void
478 + public function setRows(int $rows): void
385 479 {
386 - $this->requiredMessage = $requiredMessage;
480 + $this->rows = $rows;
387 481 }
388 482
389 483 /**
390 - * Get the field CSS classes.
484 + * Get the general settings object.
391 485 *
392 - * @return string
486 + * @return FieldAdvancedSettings
393 487 */
394 - public function getCssClasses(): string
488 + public function getAdvancedSettings(): FieldAdvancedSettings
395 489 {
396 - return $this->cssClasses;
490 + return $this->advancedSettings;
397 491 }
398 492
399 493 /**
400 - * Set the CSS classes setting.
401 - *
402 - * @param string $cssClasses
403 - */
404 - public function setCssClasses(string $cssClasses): void
405 - {
406 - $this->cssClasses = $cssClasses;
407 - }
408 -
409 - /**
410 494 * Convert the field to an array.
411 495 *
412 496 * @return array<string, mixed>
413 497 */
@@ -412,22 +496,32 @@
412 496 * @return array<string, mixed>
413 497 */
414 498 public function toArray(): array
415 499 {
416 - return [
417 - 'id' => $this->getId(),
418 - 'formId' => $this->getFormId(),
419 - 'fieldIndex' => $this->getIndex(),
420 - 'type' => $this->getType(),
421 - 'label' => $this->getLabel(),
422 - 'defaultValue' => $this->getDefaultValue(),
423 - 'required' => $this->isRequired(),
424 - 'placeholder' => $this->getPlaceholder(),
425 - 'position' => $this->getPosition(),
426 - 'hideLabel' => $this->isLabelHidden(),
427 - 'readOnly' => $this->isReadOnly(),
428 - 'description' => $this->getDescription(),
429 - 'requiredMessage' => $this->getRequiredMessage(),
430 - 'cssClasses' => $this->getCssClasses(),
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()
431 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);
432 526 }
433 527 }