Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
84.31% |
43 / 51 |
|
73.33% |
11 / 15 |
CRAP | |
0.00% |
0 / 1 |
View | |
84.31% |
43 / 51 |
|
73.33% |
11 / 15 |
34.71 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
hasData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
removeData | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
addData | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getText | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
5 | |||
setModuleDynamically | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
5 | |||
setThemeDynamically | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
5.02 | |||
getHtml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getNumeric | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getPercentage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getCurrency | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDateTime | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
renderUserName | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package phpOMS\Views |
8 | * @copyright Dennis Eichhorn |
9 | * @license OMS License 2.0 |
10 | * @version 1.0.0 |
11 | * @link https://jingga.app |
12 | */ |
13 | declare(strict_types=1); |
14 | |
15 | namespace phpOMS\Views; |
16 | |
17 | use phpOMS\Localization\L11nManager; |
18 | use phpOMS\Localization\Localization; |
19 | use phpOMS\Localization\Money; |
20 | use phpOMS\Message\RequestAbstract; |
21 | use phpOMS\Message\ResponseAbstract; |
22 | use phpOMS\Module\Exception\InvalidModuleException; |
23 | use phpOMS\Module\Exception\InvalidThemeException; |
24 | use phpOMS\Stdlib\Base\FloatInt; |
25 | |
26 | /** |
27 | * Basic view which can be used as basis for specific implementations. |
28 | * |
29 | * @package phpOMS\Views |
30 | * @license OMS License 2.0 |
31 | * @link https://jingga.app |
32 | * @since 1.0.0 |
33 | */ |
34 | class View extends ViewAbstract |
35 | { |
36 | /** |
37 | * View data. |
38 | * |
39 | * @var array<string, mixed> |
40 | * @since 1.0.0 |
41 | */ |
42 | public array $data = []; |
43 | |
44 | /** |
45 | * View Localization. |
46 | * |
47 | * @var Localization |
48 | * @since 1.0.0 |
49 | */ |
50 | public Localization $l11n; |
51 | |
52 | /** |
53 | * Application. |
54 | * |
55 | * @var L11nManager |
56 | * @since 1.0.0 |
57 | */ |
58 | public L11nManager $l11nManager; |
59 | |
60 | /** |
61 | * Request. |
62 | * |
63 | * @var null|RequestAbstract |
64 | * @since 1.0.0 |
65 | */ |
66 | public ?RequestAbstract $request; |
67 | |
68 | /** |
69 | * Request. |
70 | * |
71 | * @var null|ResponseAbstract |
72 | * @since 1.0.0 |
73 | */ |
74 | public ?ResponseAbstract $response; |
75 | |
76 | /** |
77 | * Theme name. |
78 | * |
79 | * @var null|string |
80 | * @since 1.0.0 |
81 | */ |
82 | public ?string $theme = null; |
83 | |
84 | /** |
85 | * Module name. |
86 | * |
87 | * @var null|string |
88 | * @since 1.0.0 |
89 | */ |
90 | public ?string $module = null; |
91 | |
92 | /** |
93 | * Constructor. |
94 | * |
95 | * @param L11nManager $l11n Localization manager |
96 | * @param RequestAbstract $request Request |
97 | * @param ResponseAbstract $response Request |
98 | * |
99 | * @since 1.0.0 |
100 | */ |
101 | public function __construct(L11nManager $l11n = null, RequestAbstract $request = null, ResponseAbstract $response = null) |
102 | { |
103 | $this->l11nManager = $l11n ?? new L11nManager(); |
104 | $this->request = $request; |
105 | $this->response = $response; |
106 | $this->l11n = $response !== null ? $response->header->l11n : new Localization(); |
107 | } |
108 | |
109 | /** |
110 | * Check if data exists |
111 | * |
112 | * @param string $id Data Id |
113 | * |
114 | * @return bool |
115 | * |
116 | * @since 1.0.0 |
117 | */ |
118 | public function hasData(string $id) : bool |
119 | { |
120 | return isset($this->data[$id]); |
121 | } |
122 | |
123 | /** |
124 | * Get data attached to view |
125 | * |
126 | * @param string $id Data Id |
127 | * |
128 | * @return mixed |
129 | * |
130 | * @since 1.0.0 |
131 | */ |
132 | public function getData(string $id) : mixed |
133 | { |
134 | return $this->data[$id] ?? null; |
135 | } |
136 | |
137 | /** |
138 | * Set data of view |
139 | * |
140 | * @param string $id Data ID |
141 | * @param mixed $data Data |
142 | * |
143 | * @return void |
144 | * |
145 | * @since 1.0.0 |
146 | */ |
147 | public function setData(string $id, mixed $data) : void |
148 | { |
149 | $this->data[$id] = $data; |
150 | } |
151 | |
152 | /** |
153 | * Remove view. |
154 | * |
155 | * @param string $id Data Id |
156 | * |
157 | * @return bool |
158 | * |
159 | * @since 1.0.0 |
160 | */ |
161 | public function removeData(string $id) : bool |
162 | { |
163 | if (isset($this->data[$id])) { |
164 | unset($this->data[$id]); |
165 | |
166 | return true; |
167 | } |
168 | |
169 | return false; |
170 | } |
171 | |
172 | /** |
173 | * Add data to view |
174 | * |
175 | * @param string $id Data ID |
176 | * @param mixed $data Data |
177 | * |
178 | * @return bool |
179 | * |
180 | * @since 1.0.0 |
181 | */ |
182 | public function addData(string $id, mixed $data) : bool |
183 | { |
184 | if (isset($this->data[$id])) { |
185 | return false; |
186 | } |
187 | |
188 | $this->data[$id] = $data; |
189 | |
190 | return true; |
191 | } |
192 | |
193 | /** |
194 | * Get translation. |
195 | * |
196 | * @param string $translation Text |
197 | * @param string $module Module name |
198 | * @param string $theme Theme name |
199 | * |
200 | * @return string |
201 | * |
202 | * @since 1.0.0 |
203 | */ |
204 | public function getText(string $translation, string $module = null, string $theme = null) : string |
205 | { |
206 | if ($module === null && $this->module === null) { |
207 | $this->setModuleDynamically(); |
208 | } |
209 | |
210 | if ($theme === null && $this->theme === null) { |
211 | $this->setThemeDynamically(); |
212 | } |
213 | |
214 | /** @var string $module */ |
215 | $module = $module ?? $this->module; |
216 | /** @var string $theme */ |
217 | $theme = $theme ?? $this->theme; |
218 | |
219 | return $this->l11nManager->getText($this->l11n->language, $module, $theme, $translation); |
220 | } |
221 | |
222 | /** |
223 | * Set the view module dynamically. |
224 | * |
225 | * Sets the view module based on the template path |
226 | * |
227 | * @return void |
228 | * |
229 | * @throws InvalidModuleException throws this exception if no data for the defined module could be found |
230 | * |
231 | * @since 1.0.0 |
232 | */ |
233 | private function setModuleDynamically() : void |
234 | { |
235 | $match = '/Modules/'; |
236 | |
237 | if (($start = \strripos($this->template, $match)) === false) { |
238 | $this->module = '0'; |
239 | } |
240 | |
241 | $start += \strlen($match); |
242 | if (\strlen($this->template) < $start) { |
243 | throw new InvalidModuleException($this->template); |
244 | } |
245 | |
246 | $end = \strpos($this->template, '/', $start); |
247 | if ($end === false) { |
248 | throw new InvalidModuleException($this->template); |
249 | } |
250 | |
251 | $this->module = \substr($this->template, $start, $end - $start); |
252 | |
253 | if ($this->module === false) { |
254 | $this->module = '0'; // @codeCoverageIgnore |
255 | } |
256 | } |
257 | |
258 | /** |
259 | * Set the view theme dynamically. |
260 | * |
261 | * Sets the view theme based on the template path |
262 | * |
263 | * @return void |
264 | * |
265 | * @throws InvalidThemeException throws this exception if no data for the defined theme could be found |
266 | * |
267 | * @since 1.0.0 |
268 | */ |
269 | private function setThemeDynamically() : void |
270 | { |
271 | $match = '/Theme/'; |
272 | |
273 | if (($start = \strripos($this->template, $match)) === false) { |
274 | $this->theme = '0'; |
275 | } |
276 | |
277 | $start += \strlen($match); |
278 | if (\strlen($this->template) < $start) { |
279 | throw new InvalidThemeException($this->template); |
280 | } |
281 | |
282 | $end = \strpos($this->template, '/', $start); |
283 | if ($end === false) { |
284 | throw new InvalidThemeException($this->template); |
285 | } |
286 | |
287 | $this->theme = \substr($this->template, $start, $end - $start); |
288 | |
289 | if ($this->theme === false) { |
290 | $this->theme = '0'; // @codeCoverageIgnore |
291 | } |
292 | } |
293 | |
294 | /** |
295 | * Get translation. |
296 | * |
297 | * @param string $translation Text |
298 | * @param null|string $module Module name |
299 | * @param null|string $theme Theme name |
300 | * |
301 | * @return string |
302 | * |
303 | * @since 1.0.0 |
304 | */ |
305 | public function getHtml(string $translation, string $module = null, string $theme = null) : string |
306 | { |
307 | return \htmlspecialchars($this->getText($translation, $module, $theme)); |
308 | } |
309 | |
310 | /** |
311 | * Print a numeric value |
312 | * |
313 | * @param int|float|FloatInt $numeric Numeric value to print |
314 | * @param null|string $format Format type to use |
315 | * |
316 | * @return string |
317 | * |
318 | * @since 1.0.0 |
319 | */ |
320 | public function getNumeric(int | float | FloatInt $numeric, string $format = null) : string |
321 | { |
322 | return $this->l11nManager->getNumeric($this->l11n, $numeric, $format); |
323 | } |
324 | |
325 | /** |
326 | * Print a percentage value |
327 | * |
328 | * @param float $percentage Percentage value to print |
329 | * @param null|string $format Format type to use |
330 | * |
331 | * @return string |
332 | * |
333 | * @since 1.0.0 |
334 | */ |
335 | public function getPercentage(float $percentage, string $format = null) : string |
336 | { |
337 | return $this->l11nManager->getPercentage($this->l11n, $percentage, $format); |
338 | } |
339 | |
340 | /** |
341 | * Print a currency |
342 | * |
343 | * @param int|float|Money $currency Currency value to print |
344 | * @param null|string $symbol Currency name/symbol |
345 | * @param null|string $format Format type to use |
346 | * @param int $divide Divide currency by divisor |
347 | * |
348 | * @return string |
349 | * |
350 | * @since 1.0.0 |
351 | */ |
352 | public function getCurrency( |
353 | int | float | Money | FloatInt $currency, |
354 | string $symbol = null, |
355 | string $format = null, |
356 | int $divide = 1 |
357 | ) : string |
358 | { |
359 | return $this->l11nManager->getCurrency($this->l11n, $currency, $symbol, $format, $divide); |
360 | } |
361 | |
362 | /** |
363 | * Print a datetime |
364 | * |
365 | * @param null|\DateTimeInterface $datetime DateTime to print |
366 | * @param string $format Format type to use |
367 | * |
368 | * @return string |
369 | * |
370 | * @since 1.0.0 |
371 | */ |
372 | public function getDateTime(\DateTimeInterface $datetime = null, string $format = null) : string |
373 | { |
374 | return $this->l11nManager->getDateTime($this->l11n, $datetime, $format); |
375 | } |
376 | |
377 | /** |
378 | * Render user name based on format |
379 | * |
380 | * @param string $format Format used in printf |
381 | * @param array $names Names to render according to the format |
382 | * |
383 | * @return string |
384 | * |
385 | * @since 1.0.0 |
386 | */ |
387 | public function renderUserName(string $format, array $names) : string |
388 | { |
389 | $name = \preg_replace('/\s+/', ' ', \sprintf($format, ...$names)); |
390 | |
391 | return $name === null ? '' : \trim($name); |
392 | } |
393 | } |