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