ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
LanguageTag.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21namespace ILIAS\Data;
22
27use InvalidArgumentException;
31use Closure;
32
39abstract class LanguageTag
40{
41 abstract public function value(): string;
42
43 public function __toString(): string
44 {
45 return $this->value();
46 }
47
48 public static function fromString(string $string): static
49 {
50 $brick = new Brick();
51 return $brick->apply(self::definition($brick), $string)->except(static fn (): Result => (
52 new Error('Given string is no valid language tag.')
53 ))->value();
54 }
55
59 private static function definition(Brick $brick): Closure
60 {
61 $extlang = $brick->sequence([
62 $brick->repeat(3, 3, $brick->alpha()),
63 $brick->repeat(0, 2, $brick->sequence(['-', $brick->repeat(3, 3, $brick->alpha())])),
64 ]);
65
66 $language = $brick->either([
67 $brick->sequence([
68 'lang' => $brick->repeat(2, 3, $brick->alpha()),
69 $brick->repeat(0, 1, $brick->sequence(['-', 'extlang' => $extlang])),
70 ]),
71 $brick->sequence(['lang' => $brick->repeat(4, 4, $brick->alpha())]),
72 $brick->sequence(['lang' => $brick->repeat(5, 8, $brick->alpha())]),
73 ]);
74
75 $script = $brick->repeat(4, 4, $brick->alpha());
76
77 $region = $brick->either([
78 $brick->repeat(2, 2, $brick->alpha()),
79 $brick->repeat(3, 3, $brick->digit()),
80 ]);
81
82 $alphanum = $brick->either([$brick->alpha(), $brick->digit()]);
83
84 $variant = $brick->either([
85 $brick->repeat(5, 8, $alphanum),
86 $brick->sequence([$brick->digit(), $brick->repeat(3, 3, $alphanum)])
87 ]);
88
89 $singleton = $brick->either([
90 $brick->digit(),
91 $brick->range(0x41, 0x57),
92 $brick->range(0x59, 0x5A),
93 $brick->range(0x61, 0x77),
94 $brick->range(0x79, 0x7A),
95 ]);
96
97 $extension = $brick->sequence([
98 $singleton,
99 $brick->repeat(1, null, $brick->sequence(['-', $brick->repeat(2, 8, $alphanum)])),
100 ]);
101
102 $privateuse = $brick->sequence([
103 'x',
104 $brick->repeat(1, null, $brick->sequence(['-', $brick->repeat(1, 8, $alphanum)]))
105 ]);
106
107 $new = static fn (string $class) => new Custom(static fn (string $arg) => new $class($arg));
108
109 $privateuse = $brick->transformation($new(PrivateUse::class), $privateuse);
110
111 $irregular = $brick->either([
112 'en-GB-oed',
113 'i-ami',
114 'i-bnn',
115 'i-default',
116 'i-enochian',
117 'i-hak',
118 'i-klingon',
119 'i-lux',
120 'i-mingo',
121 'i-navajo',
122 'i-pwn',
123 'i-tao',
124 'i-tay',
125 'i-tsu',
126 'sgn-BE-FR',
127 'sgn-BE-NL',
128 'sgn-CH-DE',
129 ]);
130
131 $regular = $brick->either([
132 'art-lojban',
133 'cel-gaulish',
134 'no-bok',
135 'no-nyn',
136 'zh-guoyu',
137 'zh-hakka',
138 'zh-min',
139 'zh-min-nan',
140 'zh-xiang',
141 ]);
142
143 $grandfathered = $brick->either([
144 $brick->transformation($new(Irregular::class), $irregular),
145 $brick->transformation($new(Regular::class), $regular)
146 ]);
147
148 $langtag = $brick->transformation(
149 new Custom(static fn (array $from): Standard => new Standard(
150 $from['language']['lang'],
151 $from['language']['extlang'] ?? null,
152 $from['script'] ?? null,
153 $from['region'] ?? null,
154 $from['variant'] ?? null,
155 $from['extension'] ?? null,
156 $from['privateuse'] ?? null,
157 )),
158 $brick->sequence([
159 'language' => $language,
160 $brick->repeat(0, 1, $brick->sequence(['-', 'script' => $script])),
161 $brick->repeat(0, 1, $brick->sequence(['-', 'region' => $region])),
162 $brick->repeat(0, null, $brick->sequence(['-', 'variant' => $variant])),
163 $brick->repeat(0, null, $brick->sequence(['-', 'extension' => $extension])),
164 $brick->repeat(0, 1, $brick->sequence(['-', 'privateuse' => $privateuse])),
165 ])
166 );
167
168 return $brick->either([$langtag, $privateuse, $grandfathered]);
169 }
170}
This class represents a valid language tag that should be used instead of plain strings.
Definition: LanguageTag.php:40
static fromString(string $string)
Definition: LanguageTag.php:48
static definition(Brick $brick)
This definition is directly translated from the ABNF definition on https://www.ietf....
Definition: LanguageTag.php:59
Transform values according to custom configuration.
@phpstan-type Continuation Closure(Result<Intermediate>): Result<Intermediate> @phpstan-type Parser C...
Definition: Brick.php:35
sequence(array $parsers)
Definition: Brick.php:103
repeat(int $min, ?int $max, $parse)
Definition: Brick.php:114
range(int $start, int $end)
Definition: Brick.php:68
transformation(Transformation $transformation, Closure $parse)
Definition: Brick.php:130
either(array $parsers)
Definition: Brick.php:94
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:29