Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
TreeSelectTransformer
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
4 / 4
22
100.00% covered (success)
100.00%
1 / 1
 supports
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 transformRead
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 transformWrite
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 parseItems
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Engine\Application\Transformer;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Engine\Domain\Model\FieldMetadata;
12
13/**
14 * TreeSelect UiType Transformer.
15 *
16 * Handles UiType: tree_select.
17 * Normalizes, validates, and serializes hierarchical folder/category node path selections.
18 *
19 * @package App\Core\Engine\Application\Transformer
20 */
21final class TreeSelectTransformer implements UiTypeTransformerInterface
22{
23    /** {@inheritdoc} */
24    public function supports(string $uitypeName): bool
25    {
26        return in_array($uitypeName, ['tree_select', 'tree_categories', 'hierarchical_tree'], true);
27    }
28
29    /** {@inheritdoc} */
30    public function transformRead(mixed $rawValue, FieldMetadata $field): string
31    {
32        if ($rawValue === null || $rawValue === '') {
33            return '[]';
34        }
35
36        $items = $this->parseItems($rawValue);
37        if (empty($items)) {
38            return '[]';
39        }
40
41        $encoded = json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
42
43        return $encoded !== false ? $encoded : '[]';
44    }
45
46    /** {@inheritdoc} */
47    public function transformWrite(mixed $inputValue, FieldMetadata $field): mixed
48    {
49        if ($inputValue === null || $inputValue === '' || $inputValue === '[]') {
50            return null;
51        }
52
53        $items = $this->parseItems($inputValue);
54        if (empty($items)) {
55            return null;
56        }
57
58        $encoded = json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
59
60        return $encoded !== false ? $encoded : null;
61    }
62
63    /**
64     * Parses raw input into a sanitized, unique array of string values.
65     *
66     * @param mixed $value Raw input value.
67     * @return array<int, string> Sanitized list of category path keys.
68     */
69    private function parseItems(mixed $value): array
70    {
71        $rawArray = [];
72
73        if (is_array($value)) {
74            $rawArray = $value;
75        } elseif (is_string($value)) {
76            $trimmed = trim($value);
77            if ($trimmed === '' || $trimmed === '[]') {
78                return [];
79            }
80            $decoded = json_decode($trimmed, true);
81            if (is_array($decoded)) {
82                $rawArray = $decoded;
83            } else {
84                $rawArray = [$trimmed];
85            }
86        }
87
88        $clean = [];
89        foreach ($rawArray as $item) {
90            if (is_scalar($item)) {
91                $strVal = trim((string) $item);
92                if ($strVal !== '' && !in_array($strVal, $clean, true)) {
93                    $clean[] = $strVal;
94                }
95            }
96        }
97
98        return $clean;
99    }
100}