Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.14% covered (success)
97.14%
34 / 35
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
PolymorphicRelationTransformer
97.06% covered (success)
97.06%
33 / 34
83.33% covered (warning)
83.33%
5 / 6
27
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%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 transformWrite
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 normalizeStringWriteValue
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
4.13
 parse
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 parseString
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
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 * Polymorphic Multi-Target Relation UiType Transformer.
15 *
16 * Handles UiType: relation_polymorphic (ID: 7008).
17 * Stores relation references in 'module_name:record_id' format (e.g. 'companies:15').
18 *
19 * @package App\Core\Engine\Application\Transformer
20 */
21final class PolymorphicRelationTransformer implements UiTypeTransformerInterface
22{
23    /**
24     * {@inheritdoc}
25     */
26    public function supports(string $uitypeName): bool
27    {
28        return $uitypeName === 'relation_polymorphic';
29    }
30
31    /**
32     * {@inheritdoc}
33     */
34    public function transformRead(mixed $rawValue, FieldMetadata $field): string
35    {
36        if ($rawValue === null || $rawValue === '') {
37            return '';
38        }
39
40        if (is_array($rawValue)) {
41            $mod = (string) ($rawValue['module'] ?? '');
42            $id = (int) ($rawValue['id'] ?? 0);
43            return $mod !== '' && $id > 0 ? "{$mod}:{$id}" : '';
44        }
45
46        return (string) $rawValue;
47    }
48
49    /**
50     * {@inheritdoc}
51     */
52    public function transformWrite(mixed $inputValue, FieldMetadata $field): mixed
53    {
54        if ($inputValue === null || $inputValue === '') {
55            return null;
56        }
57
58        if (is_array($inputValue)) {
59            $mod = trim((string) ($inputValue['module'] ?? ''));
60            $id = (int) ($inputValue['id'] ?? 0);
61            return ($mod !== '' && $id > 0) ? "{$mod}:{$id}" : null;
62        }
63
64        return $this->normalizeStringWriteValue(trim((string) $inputValue));
65    }
66
67    /**
68     * Normalizes string form of polymorphic relation input.
69     */
70    private function normalizeStringWriteValue(string $strVal): string|int|null
71    {
72        if ($strVal === '') {
73            return null;
74        }
75        if (preg_match('/^[\w-]+:\d+$/', $strVal)) {
76            return $strVal;
77        }
78        return is_numeric($strVal) ? (int) $strVal : null;
79    }
80
81    /**
82     * Parses raw polymorphic relation value into module and id components.
83     *
84     * @param mixed $value Raw database or form value.
85     * @return array{module: string, id: int}|null Parsed components or null.
86     */
87    public static function parse(mixed $value): ?array
88    {
89        if ($value === null || $value === '') {
90            return null;
91        }
92
93        if (is_array($value) && !empty($value['module']) && !empty($value['id'])) {
94            return [
95                'module' => (string) $value['module'],
96                'id' => (int) $value['id'],
97            ];
98        }
99
100        return self::parseString((string) $value);
101    }
102
103    /**
104     * Parses "module:id" colon-delimited string.
105     *
106     * @return array{module: string, id: int}|null
107     */
108    private static function parseString(string $str): ?array
109    {
110        if (!str_contains($str, ':')) {
111            return null;
112        }
113
114        $parts = explode(':', $str, 2);
115        $mod = trim($parts[0]);
116        $id = (int) $parts[1];
117
118        return ($mod !== '' && $id > 0) ? ['module' => $mod, 'id' => $id] : null;
119    }
120}