Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
LanguageTag
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
2 / 2
11
100.00% covered (success)
100.00%
1 / 1
 validate
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
10
 createRandom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace Apie\IanaValueObjects\LanguageTag;
3
4use Apie\Core\Attributes\ExampleValue;
5use Apie\Core\Attributes\FakeMethod;
6use Apie\Core\Identifiers\Identifier;
7use Apie\Core\Lists\IdentifierList;
8use Apie\Core\ValueObjects\Exceptions\InvalidStringForValueObjectException;
9use Apie\Core\ValueObjects\Interfaces\StringValueObjectInterface;
10use Apie\Core\ValueObjects\IsStringValueObject;
11use Apie\Core\ValueObjects\SingleLetter;
12use Faker\Generator;
13
14#[FakeMethod('createRandom')]
15#[ExampleValue('nl')]
16#[ExampleValue('en-US')]
17class LanguageTag implements StringValueObjectInterface
18{
19    use IsStringValueObject;
20
21    private static array $resolvedLanguageSubtags = [];
22
23    public static function validate(string $input): void
24    {
25        if (!isset(self::$resolvedLanguageSubtags[$input])) {
26            $split = explode('-', $input);
27            $language = [Language::fromNative(array_shift($split))];
28            $classes = [
29                    LanguageExtlang::class,
30                    LanguageScript::class,
31                    LanguageRegion::class,
32                    LanguageVariant::class,
33                ];
34            while (!empty($split)) {
35                $subtag = array_shift($split);
36                
37                while (!empty($classes)) {
38                    $class = array_shift($classes);
39                    try {
40                        $language[] = $class::fromNative($subtag);
41                        if (in_array($class, [LanguageExtlang::class, LanguageVariant::class])) {
42                            array_unshift($classes, $class);
43                        }
44                        continue 2;
45                    } catch (\Throwable) {
46                        // ignore
47                    }
48                }
49
50                // parse the extensions
51                try {
52                    $singleton = SingleLetter::fromNative($subtag);
53                    $extensions = [];
54
55                    while (!empty($split)) {
56                        $subtag = array_shift($split);
57                        try {
58                            if (strlen($subtag) === 1) {
59                                array_unshift($split, $subtag);
60                                
61                                break;
62                            }
63                            $extensions[] = Identifier::fromNative($subtag);
64                        } catch (\Throwable $err) {
65                            throw new InvalidStringForValueObjectException(
66                                $input,
67                                (new \ReflectionClass(static::class)),
68                                $err
69                            );
70                        }
71                    }
72                    $language[] = new LanguageExtension($singleton, new IdentifierList($extensions));
73                    break;
74                } catch (\Throwable) {
75                    // ignore
76                }
77
78                throw new InvalidStringForValueObjectException(
79                    $input,
80                    (new \ReflectionClass(static::class))
81                );
82            }
83            self::$resolvedLanguageSubtags[$input] = $language;
84        }
85    }
86
87    public static function createRandom(Generator $factory): self
88    {
89        return new LanguageTag($factory->languageCode());
90    }
91}