Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.08% covered (warning)
73.08%
38 / 52
60.00% covered (warning)
60.00%
9 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslationStringPrefix
73.08% covered (warning)
73.08%
38 / 52
60.00% covered (warning)
60.00%
9 / 15
51.98
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
 getBoundedContextId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResourceIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSimplifications
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 getSpecifity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 withoutBoundedContextId
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 withBoundedContextId
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 withoutResourceIdentifier
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 withResourceIdentifier
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRegularExpression
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toNative
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 fromNative
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
4.01
 createFromTranslation
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2namespace Apie\Core\Translator\ValueObjects;
3
4use Apie\Core\Attributes\Description;
5use Apie\Core\Attributes\ExampleValue;
6use Apie\Core\BoundedContext\BoundedContextId;
7use Apie\Core\Identifiers\SnakeCaseSlug;
8use Apie\Core\Translator\Lists\TranslationStringPrefixSet;
9use Apie\Core\ValueObjects\Exceptions\InvalidStringForValueObjectException;
10use Apie\Core\ValueObjects\Interfaces\HasRegexValueObjectInterface;
11use Apie\Core\ValueObjects\Interfaces\ValueObjectInterface;
12use Apie\Core\ValueObjects\Utils;
13
14#[Description('prefix of a Apie translation string. It includes the trailing dot!')]
15#[ExampleValue('apie.bounded.test.')]
16#[ExampleValue('apie.bounded.test.resource.user.')]
17#[ExampleValue('apie.')]
18#[ExampleValue('apie.resource.user.')]
19final class TranslationStringPrefix implements HasRegexValueObjectInterface
20{
21    public function __construct(
22        private ?BoundedContextId $boundedContextId = null,
23        private ?SnakeCaseSlug $resourceIdentifier = null,
24    ) {
25    }
26
27    public function getBoundedContextId(): ?BoundedContextId
28    {
29        return $this->boundedContextId;
30    }
31
32    public function getResourceIdentifier(): ?SnakeCaseSlug
33    {
34        return $this->resourceIdentifier;
35    }
36
37    public function getSimplifications(): TranslationStringPrefixSet
38    {
39        $list = [];
40        if ($this->boundedContextId !== null) {
41            $list[] = new static(null, $this->resourceIdentifier);
42            if ($this->resourceIdentifier !== null) {
43                $list[] = new static($this->boundedContextId, null);
44            }
45        } elseif ($this->resourceIdentifier !== null) {
46            $list[] = new static();
47        }
48        return new TranslationStringPrefixSet($list);
49    }
50
51    final public function getSpecifity(): int
52    {
53        return ($this->boundedContextId ? 2 : 0) + ($this->resourceIdentifier ? 4 : 0);
54    }
55
56    public function withoutBoundedContextId(): static
57    {
58        if ($this->boundedContextId === null) {
59            return $this;
60        }
61
62        return new TranslationStringPrefix(null, $this->resourceIdentifier);
63    }
64
65    public function withBoundedContextId(BoundedContextId $boundedContextId): static
66    {
67        if ($this->boundedContextId?->toNative() === $boundedContextId->toNative()) {
68            return $this;
69        }
70
71        return new TranslationStringPrefix($boundedContextId, $this->resourceIdentifier);
72    }
73
74    public function withoutResourceIdentifier(): static
75    {
76        if ($this->resourceIdentifier === null) {
77            return $this;
78        }
79
80        return new TranslationStringPrefix($this->boundedContextId, null);
81    }
82
83    public function withResourceIdentifier(SnakeCaseSlug $resourceIdentifier): static
84    {
85        if ($this->resourceIdentifier?->toNative() === $resourceIdentifier->toNative()) {
86            return $this;
87        }
88
89        return new TranslationStringPrefix($this->boundedContextId, $resourceIdentifier);
90    }
91
92
93    public function __toString(): string
94    {
95        return $this->toNative();
96    }
97
98    public function jsonSerialize(): mixed
99    {
100        return $this->toNative();
101    }
102
103    public static function getRegularExpression(): string
104    {
105        return '/^apie\.(bounded\.([a-z][a-z0-9]*)\.)?(resource\.([a-z0-9]+(_[a-z0-9]+)*)\.)?$/';
106    }
107
108    public function toNative(): string
109    {
110        $resourceSection = $this->resourceIdentifier ? ('resource.' . $this->resourceIdentifier . '.') : '';
111        if ($this->boundedContextId === null) {
112            return 'apie.' . $resourceSection;
113        }
114        return 'apie.bounded.' .  $this->boundedContextId . '.' . $resourceSection;
115    }
116
117    public static function fromNative(mixed $input): ValueObjectInterface
118    {
119        $input = Utils::toString($input);
120        if (preg_match(
121            '/^apie\.(bounded\.(?<bounded>[a-z][a-z0-9]*)\.)?(resource\.(?<resource>[a-z0-9]+(_[a-z0-9]+)*)\.)?$/',
122            $input,
123            $matches
124        )) {
125            return new TranslationStringPrefix(
126                empty($matches['bounded']) ? null : BoundedContextId::fromNative($matches['bounded']),
127                empty($matches['resource']) ? null : SnakeCaseSlug::fromNative($matches['resource'])
128            );
129        }
130        throw new InvalidStringForValueObjectException($input, new \ReflectionClass(static::class));
131    }
132
133    public static function createFromTranslation(string $translationString): TranslationStringPrefix
134    {
135        if (preg_match(
136            '/^apie\.(bounded\.(?<bounded>[a-z][a-z0-9]*)\.)?(resource\.(?<resource>[a-z0-9]+(_[a-z0-9]+)*)\.)?/',
137            $translationString,
138            $matches
139        )) {
140            return new TranslationStringPrefix(
141                empty($matches['bounded']) ? null : BoundedContextId::fromNative($matches['bounded']),
142                empty($matches['resource']) ? null : SnakeCaseSlug::fromNative($matches['resource'])
143            );
144        }
145        throw new InvalidStringForValueObjectException($translationString, new \ReflectionClass(static::class));
146    }
147
148}