Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
87.04% |
47 / 54 |
|
73.33% |
11 / 15 |
CRAP | |
0.00% |
0 / 1 |
ViewAbstract | |
87.04% |
47 / 54 |
|
73.33% |
11 / 15 |
38.82 | |
0.00% |
0 / 1 |
getTemplate | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setTemplate | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
printHtml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
html | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
printCli | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
cli | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
getViews | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getView | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
removeView | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
addView | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
serialize | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
toArray | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
render | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
renderTemplate | |
83.33% |
15 / 18 |
|
0.00% |
0 / 1 |
8.30 | |||
build | |
75.00% |
6 / 8 |
|
0.00% |
0 / 1 |
3.14 | |||
unserialize | n/a |
0 / 0 |
n/a |
0 / 0 |
1 |
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\Contract\RenderableInterface; |
18 | |
19 | /** |
20 | * View Abstract. |
21 | * |
22 | * @package phpOMS\Views |
23 | * @license OMS License 2.0 |
24 | * @link https://jingga.app |
25 | * @since 1.0.0 |
26 | */ |
27 | abstract class ViewAbstract implements RenderableInterface |
28 | { |
29 | /** |
30 | * Base path. |
31 | * |
32 | * @var string |
33 | * @since 1.0.0 |
34 | */ |
35 | protected const BASE_PATH = __DIR__ . '/../..'; |
36 | |
37 | /** |
38 | * Output is buffered |
39 | * |
40 | * @var bool |
41 | * @since 1.0.0 |
42 | */ |
43 | public bool $isBuffered = true; |
44 | |
45 | /** |
46 | * Template. |
47 | * |
48 | * @var string |
49 | * @since 1.0.0 |
50 | */ |
51 | protected string $template = ''; |
52 | |
53 | /** |
54 | * Views. |
55 | * |
56 | * @var \phpOMS\Views\View[] |
57 | * @since 1.0.0 |
58 | */ |
59 | protected array $views = []; |
60 | |
61 | /** |
62 | * Get the template. |
63 | * |
64 | * @return string |
65 | * |
66 | * @since 1.0.0 |
67 | */ |
68 | public function getTemplate() : string |
69 | { |
70 | return $this->template; |
71 | } |
72 | |
73 | /** |
74 | * Set the template. |
75 | * |
76 | * @param string $template View template |
77 | * @param string $extension Extension of the template |
78 | * |
79 | * @return void |
80 | * |
81 | * @since 1.0.0 |
82 | */ |
83 | public function setTemplate(string $template, string $extension = 'tpl.php') : void |
84 | { |
85 | $this->template = self::BASE_PATH . $template . '.' . $extension; |
86 | } |
87 | |
88 | /** |
89 | * Print html output. |
90 | * |
91 | * @param ?string $text Text |
92 | * |
93 | * @return string |
94 | * |
95 | * @since 1.0.0 |
96 | */ |
97 | public function printHtml(?string $text) : string |
98 | { |
99 | return $text === null ? '' : \htmlspecialchars($text); |
100 | } |
101 | |
102 | /** |
103 | * Print html output. |
104 | * |
105 | * @param ?string $text Text |
106 | * |
107 | * @return string |
108 | * |
109 | * @since 1.0.0 |
110 | */ |
111 | public static function html(?string $text) : string |
112 | { |
113 | return $text === null ? '' : \htmlspecialchars($text); |
114 | } |
115 | |
116 | /** |
117 | * Print cli output. |
118 | * |
119 | * @param ?string $text Text |
120 | * |
121 | * @return string |
122 | * |
123 | * @since 1.0.0 |
124 | */ |
125 | public function printCli(?string $text) : string |
126 | { |
127 | return $text === null ? '' : \escapeshellcmd($text); |
128 | } |
129 | |
130 | /** |
131 | * Print cli output. |
132 | * |
133 | * @param ?string $text Text |
134 | * |
135 | * @return string |
136 | * |
137 | * @since 1.0.0 |
138 | */ |
139 | public static function cli(?string $text) : string |
140 | { |
141 | return $text === null ? '' : \escapeshellcmd($text); |
142 | } |
143 | |
144 | /** |
145 | * Returns all views |
146 | * |
147 | * @return View[] |
148 | * |
149 | * @since 1.0.0 |
150 | */ |
151 | public function getViews() : array |
152 | { |
153 | return $this->views; |
154 | } |
155 | |
156 | /** |
157 | * Returns a specific view |
158 | * |
159 | * @param string $id View ID |
160 | * |
161 | * @return false|self |
162 | * |
163 | * @since 1.0.0 |
164 | */ |
165 | public function getView(string $id) : bool | self |
166 | { |
167 | if (!isset($this->views[$id])) { |
168 | return false; |
169 | } |
170 | |
171 | return $this->views[$id]; |
172 | } |
173 | |
174 | /** |
175 | * Remove view bz id |
176 | * |
177 | * @param string $id View ID |
178 | * |
179 | * @return bool |
180 | * |
181 | * @since 1.0.0 |
182 | */ |
183 | public function removeView(string $id) : bool |
184 | { |
185 | if (isset($this->views[$id])) { |
186 | unset($this->views[$id]); |
187 | |
188 | return true; |
189 | } |
190 | |
191 | return false; |
192 | } |
193 | |
194 | /** |
195 | * Add view. |
196 | * |
197 | * @param string $id View ID |
198 | * @param View $view View to add |
199 | * @param bool $overwrite Overwrite existing view |
200 | * |
201 | * @return bool |
202 | * |
203 | * @since 1.0.0 |
204 | */ |
205 | public function addView(string $id, View $view, bool $overwrite = false) : bool |
206 | { |
207 | if ($overwrite || !isset($this->views[$id])) { |
208 | $this->views[$id] = $view; |
209 | |
210 | return true; |
211 | } |
212 | |
213 | return false; |
214 | } |
215 | |
216 | /** |
217 | * Serialize view for rendering. |
218 | * |
219 | * @return string |
220 | * |
221 | * @since 1.0.0 |
222 | */ |
223 | public function serialize() : string |
224 | { |
225 | if (empty($this->template)) { |
226 | return (string) \json_encode($this->toArray()); |
227 | } |
228 | |
229 | return $this->render(); |
230 | } |
231 | |
232 | /** |
233 | * Arrayify view and it's subviews. |
234 | * |
235 | * @return array |
236 | * |
237 | * @since 1.0.0 |
238 | */ |
239 | public function toArray() : array |
240 | { |
241 | $viewArray = []; |
242 | |
243 | if ($this->template !== '') { |
244 | $viewArray[] = $this->render(); |
245 | } |
246 | |
247 | foreach ($this->views as $key => $view) { |
248 | $viewArray[$key] = $view->toArray(); |
249 | } |
250 | |
251 | return $viewArray; |
252 | } |
253 | |
254 | /** |
255 | * Get view/template response. |
256 | * |
257 | * @param mixed ...$data Data to pass to renderer |
258 | * |
259 | * @return string |
260 | * |
261 | * @since 1.0.0 |
262 | */ |
263 | public function render(mixed ...$data) : string |
264 | { |
265 | return $this->renderTemplate($this->template, ...$data); |
266 | } |
267 | |
268 | /** |
269 | * Render a template file |
270 | * |
271 | * @param string $template Template path |
272 | * @param mixed ...$data Data to pass to renderer |
273 | * |
274 | * @return string |
275 | * |
276 | * @since 1.0.0 |
277 | */ |
278 | protected function renderTemplate(string $template, mixed ...$data) : string |
279 | { |
280 | $obLevel = 0; |
281 | $ob = ''; |
282 | |
283 | try { |
284 | $path = $template; |
285 | if (!\is_file($path)) { |
286 | return ''; |
287 | } |
288 | |
289 | if ($this->isBuffered) { |
290 | ++$obLevel; |
291 | \ob_start(); |
292 | } |
293 | |
294 | /** @noinspection PhpIncludeInspection */ |
295 | $includeData = include $path; |
296 | |
297 | if ($this->isBuffered) { |
298 | --$obLevel; |
299 | $ob .= (string) \ob_get_clean(); |
300 | } |
301 | |
302 | if (\is_array($includeData)) { |
303 | $ob .= (string) \json_encode($includeData); |
304 | } |
305 | } catch (\Throwable $_) { |
306 | if ($obLevel > 0 && $this->isBuffered) { |
307 | $ob .= (string) \ob_get_clean(); |
308 | } |
309 | } |
310 | |
311 | return $ob; |
312 | } |
313 | |
314 | /** |
315 | * Very similar to render, except that it executes the template file and returns its response as is. |
316 | * This allows to build the template as any datatype (e.g. pdf). |
317 | * |
318 | * @param mixed ...$data Data to pass to build |
319 | * |
320 | * @return mixed |
321 | * |
322 | * @since 1.0.0 |
323 | */ |
324 | public function build(mixed ...$data) : mixed |
325 | { |
326 | $ob = ''; |
327 | |
328 | try { |
329 | $path = $this->template; |
330 | if (!\is_file($path)) { |
331 | return ''; |
332 | } |
333 | |
334 | /** @noinspection PhpIncludeInspection */ |
335 | $ob = include $path; |
336 | } catch (\Throwable $_) { |
337 | $ob = ''; |
338 | } |
339 | |
340 | return $ob; |
341 | } |
342 | |
343 | /** |
344 | * Unserialize view. |
345 | * |
346 | * @param string $raw Raw data to parse |
347 | * |
348 | * @return void |
349 | * |
350 | * @since 1.0.0 |
351 | * @codeCoverageIgnore |
352 | */ |
353 | public function unserialize(mixed $raw) : void |
354 | { |
355 | } |
356 | } |