# ivyforms/0.4/backend/src/Common/Helpers/Helper.php

The Innovative Form Builder – IvyForms, version 0.4. 101 lines.

- Page: https://pluginprobe.com/plugins/ivyforms/0.4/code/backend/src/Common/Helpers/Helper.php
- Raw: https://pluginprobe.com/plugins/ivyforms/0.4/raw/backend/src/Common/Helpers/Helper.php
- Modified: 2025-09-25T14:53:02+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/ivyforms/0.4/code/backend/src/Common/Helpers/Helper.php#L10-L20`.

```php
<?php

namespace IvyForms\Common\Helpers;

// phpcs:disable PSR1.Files.SideEffects
use IvyForms\Common\Exceptions\ValidationException;
use IvyForms\Entity\FieldOptions\FieldOptions;
use IvyForms\Factory\FieldOptions\FieldOptionsFactory;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

/**
 * General helper utilities related to Field processing.
 */
class Helper
{
    /**
     * Resolve parentId using fieldIndex -> parentId map if needed.
     *
     * @param array<string,mixed> $data Passed by reference; parentId modified in place.
     * @param array<int,int> $parentMap Map of fieldIndex => newly created parent field id.
     */
    public static function resolveParentId(array &$data, array $parentMap): void
    {
        if (!array_key_exists('parentId', $data)) {
            return;
        }
        $pid = $data['parentId'];
        $needsResolve = ($pid === 0 || $pid === '0' || $pid === null);
        if ($needsResolve && isset($data['fieldIndex']) && isset($parentMap[$data['fieldIndex']])) {
            $data['parentId'] = $parentMap[$data['fieldIndex']];
        }
    }

    /**
     * Partition field options into new, update, and submitted IDs.
     *
     * @param array<string, mixed> $fieldData
     * @param array<int> $existingOptionIds
     * @return array{
     *   newOptions: array<int, FieldOptions>,
     *   updateOptions: array<int, FieldOptions>,
     *   submittedOptionIds: array<int, int>
     * }
     * @throws ValidationException
     */
    public static function partitionFieldOptions(array $fieldData, array $existingOptionIds): array
    {
        $newOptions = [];
        $updateOptions = [];
        $submittedOptionIds = [];
        foreach ($fieldData['fieldOptions'] as $optionData) {
            $option = FieldOptionsFactory::create($optionData);
            if (
                isset($optionData['id']) && $optionData['id'] > 0
                && in_array($optionData['id'], $existingOptionIds, true)
            ) {
                $updateOptions[] = $option;
                $submittedOptionIds[] = $optionData['id'];
                continue;
            }
            $newOptions[] = $option;
        }
        return [
            'newOptions' => $newOptions,
            'updateOptions' => $updateOptions,
            'submittedOptionIds' => $submittedOptionIds,
        ];
    }

    /**
     * Batch process field options: add new, update existing, delete orphaned.
     *
     * @param int $fieldId
     * @param array<string, mixed> $fieldData
     * @param object $fieldOptionsService
     * @param object $fieldOptionsRepository
     * @return void
     * @throws ValidationException
     */
    public static function batchProcessFieldOptions(
        int $fieldId,
        array $fieldData,
        object $fieldOptionsService,
        object $fieldOptionsRepository
    ): void {
        $existingOptions = $fieldOptionsService->getByFieldId($fieldId);
        $existingOptionIds = array_map(fn($opt) => $opt->getId(), $existingOptions);
        $partition = self::partitionFieldOptions($fieldData, $existingOptionIds);
        $newOptionIds = $fieldOptionsService->addOptions($partition['newOptions']);
        $fieldOptionsService->updateOptions($partition['updateOptions']);
        $submittedOptionIds = array_merge($partition['submittedOptionIds'], $newOptionIds);
        $orphanedOptionIds = array_diff($existingOptionIds, $submittedOptionIds);
        if (!empty($orphanedOptionIds)) {
            $fieldOptionsRepository->deleteByOptionIds($orphanedOptionIds);
        }
    }
}

```
