Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
48.48% covered (danger)
48.48%
16 / 33
54.55% covered (warning)
54.55%
6 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
FormName
48.48% covered (danger)
48.48%
16 / 33
54.55% covered (warning)
54.55%
6 / 11
56.51
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromNative
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 hasChildFormFieldName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChildFormFieldName
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 createChildForm
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toNative
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toValidationErrorKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPrototypeName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createTranslationString
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 __toString
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 createSchema
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2namespace Apie\HtmlBuilders\ValueObjects;
3
4use Apie\Core\Attributes\SchemaMethod;
5use Apie\Core\BoundedContext\BoundedContextId;
6use Apie\Core\Exceptions\InvalidTypeException;
7use Apie\Core\Identifiers\SnakeCaseSlug;
8use Apie\Core\Translator\ValueObjects\TranslationString;
9use Apie\Core\ValueObjects\Interfaces\ValueObjectInterface;
10use Apie\HtmlBuilders\Exceptions\EmptyFormNameException;
11use ReflectionClass;
12use Stringable;
13
14#[SchemaMethod('createSchema')]
15final class FormName implements ValueObjectInterface, Stringable
16{
17    /** @var array<int, string> */
18    private array $internal = [];
19
20    public function __construct(string... $parts)
21    {
22        $this->internal = $parts;
23    }
24
25    /**
26     * @return static
27     */
28    public static function fromNative(mixed $input): self
29    {
30        if (is_string($input) && str_starts_with($input, 'form[')) {
31            // remove 'form['
32            $input = preg_replace('/^form\[/', '', $input);
33            // remove trailing ']'
34            $input = preg_replace('/\]$/', '', $input);
35            $input = str_replace('][', ',', $input);
36            return new static(...explode(',', $input));
37        }
38        if (is_iterable($input)) {
39            return new static(...$input);
40        }
41        throw new InvalidTypeException($input, 'string|array');
42    }
43
44    public function hasChildFormFieldName(): bool
45    {
46        return !empty($this->internal);
47    }
48
49    public function getChildFormFieldName(): string
50    {
51        if (empty($this->internal)) {
52            throw new EmptyFormNameException();
53        }
54        return end($this->internal);
55    }
56
57    public function createChildForm(string $formFieldName): self
58    {
59        return new self(...[...$this->internal, $formFieldName]);
60    }
61
62    /**
63     * @return array<string|int, string>
64     */
65    public function toNative(): array
66    {
67        return $this->internal;
68    }
69
70    public function toValidationErrorKey(): string
71    {
72        return implode('.', $this->internal);
73    }
74
75    public function getPrototypeName(): string
76    {
77        return '__' . end($this->internal);
78    }
79
80    /**
81     * @param ReflectionClass<object> $class
82     */
83    public function createTranslationString(ReflectionClass $class, ?BoundedContextId $boundedContextId = null): TranslationString
84    {
85        $suffix = '.'
86            . SnakeCaseSlug::fromClass($class)
87            . '.properties.'
88            . strtolower(implode('.', $this->internal));
89        if ($boundedContextId === null) {
90            return new TranslationString('apie.resource' . $suffix);
91        }
92        return new TranslationString('apie.bounded.' .  $boundedContextId . $suffix);
93    }
94
95    public function __toString(): string
96    {
97        if (empty($this->internal)) {
98            return 'form';
99        }
100        return 'form[' . implode('][', $this->internal) . ']';
101    }
102
103    /**
104     * @return array<string, mixed>
105     */
106    public static function createSchema(): array
107    {
108        return [
109            'type' => 'array',
110            'items' => [
111                'type' => 'string',
112            ]
113        ];
114    }
115}