Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.10% covered (success)
93.10%
27 / 29
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
MultiUserReferenceTransformer
92.86% covered (success)
92.86%
26 / 28
80.00% covered (warning)
80.00%
4 / 5
22.18
0.00% covered (danger)
0.00%
0 / 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%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 transformWrite
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 parseInputList
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
6
 sanitizeReferenceItem
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
5.93
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;
12use App\Shared\Utils\JsonArrayHelper;
13
14/**
15 * Multi-User Reference UiType Transformer.
16 *
17 * Handles UiType: multi_user_reference.
18 * Read: formats JSON-stored user IDs into comma-separated display values or badges.
19 * Write: sanitizes and encodes user ID array into JSON for database storage.
20 *
21 * @package App\Core\Engine\Application\Transformer
22 */
23final class MultiUserReferenceTransformer implements UiTypeTransformerInterface
24{
25    /** {@inheritdoc} */
26    public function supports(string $uitypeName): bool
27    {
28        return $uitypeName === 'multi_user_reference';
29    }
30
31    /** {@inheritdoc} */
32    public function transformRead(mixed $rawValue, FieldMetadata $field): string
33    {
34        $ids = JsonArrayHelper::toIntList($rawValue);
35        if ($ids !== []) {
36            return implode(', ', $ids);
37        }
38
39        return is_string($rawValue) && $rawValue !== '' && $rawValue !== '[]'
40            ? $rawValue
41            : '';
42    }
43
44    /** {@inheritdoc} */
45    public function transformWrite(mixed $inputValue, FieldMetadata $field): ?string
46    {
47        $rawList = $this->parseInputList($inputValue);
48        if ($rawList === null) {
49            return null;
50        }
51
52        $sanitized = [];
53        foreach ($rawList as $item) {
54            $parsed = $this->sanitizeReferenceItem(trim((string)$item));
55            if ($parsed !== null) {
56                $sanitized[] = $parsed;
57            }
58        }
59
60        return $sanitized !== [] ? (string) json_encode(array_values(array_unique($sanitized))) : null;
61    }
62
63    /**
64     * Parses input into list of raw reference items.
65     *
66     * @param mixed $inputValue Raw input value.
67     * @return array<mixed>|null List of items or null if empty.
68     */
69    private function parseInputList(mixed $inputValue): ?array
70    {
71        if (is_array($inputValue)) {
72            return $inputValue;
73        }
74
75        if (is_string($inputValue) && $inputValue !== '' && $inputValue !== '[]') {
76            $decoded = json_decode($inputValue, true);
77            return is_array($decoded) ? $decoded : explode(',', $inputValue);
78        }
79
80        return null;
81    }
82
83    /**
84     * Sanitizes a single reference string (e.g. user ID or structure node prefix).
85     *
86     * @param string $itemStr Trimmed reference string.
87     * @return string|int|null Sanitized reference token or null.
88     */
89    private function sanitizeReferenceItem(string $itemStr): string|int|null
90    {
91        if (str_starts_with($itemStr, 'struct_')) {
92            $sid = (int)substr($itemStr, 7);
93            return $sid > 0 ? 'struct_' . $sid : null;
94        }
95
96        if (is_numeric($itemStr) && (int)$itemStr > 0) {
97            return (int)$itemStr;
98        }
99
100        return null;
101    }
102}