Completed
Push — master ( 636da2...53dbd4 )
by Alex
08:34
created

HtmlTemplate::setPageVarFromBlock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
namespace Mezon\HtmlTemplate;
3
4
use Mezon\Conf\Conf;
5
use Mezon\TemplateEngine\TemplateEngine;
6
7
/**
8
 * Class HtmlTemplate
9
 *
10
 * @package Mezon
11
 * @subpackage HtmlTemplate
12
 * @author Dodonov A.A.
13
 * @version v.1.0 (2019/08/07)
14
 * @copyright Copyright (c) 2019, aeon.org
15
 */
16
17
/**
18
 * Template class
19
 *
20
 * @author Dodonov A.A.
21
 */
22
class HtmlTemplate
23
{
24
25
    /**
26
     * Loaded template content
27
     */
28
    private $template = false;
29
30
    /**
31
     * Loaded resources
32
     */
33
    private $resources = null;
34
35
    /**
36
     * Path to the template folder
37
     *
38
     * @var array
39
     */
40
    private $paths = false;
41
42
    /**
43
     * Page blocks
44
     *
45
     * @var array
46
     */
47
    private $blocks = [];
48
49
    /**
50
     * Page variables
51
     *
52
     * @var array
53
     */
54
    private $pageVars = [];
55
56
    /**
57
     * Template сonstructor
58
     *
59
     * @param string|array $path
60
     *            Path to template
61
     * @param string $template
62
     *            Page layout
63
     * @param array $blocks
64
     *            Page blocks
65
     */
66
    public function __construct($path, string $template = 'index', array $blocks = [])
67
    {
68
        if (is_string($path)) {
69
            $this->paths = [
70
                $path
71
            ];
72
        } elseif (is_array($path)) {
0 ignored issues
show
introduced by
The condition is_array($path) is always true.
Loading history...
73
            $this->paths = $path;
74
        } else {
75
            throw (new \Exception('Invalid type for $path parameter'));
76
        }
77
78
        $this->resetLayout($template);
79
80
        $this->blocks = [];
81
82
        foreach ($blocks as $blockName) {
83
            $this->addBlock($blockName);
84
        }
85
86
        // output all blocks in one place
87
        // but each block can be inserted in {$blockName} places
88
        $this->setPageVar('content-blocks', implode('', $this->blocks));
89
    }
90
91
    /**
92
     * Method adds paths to the setup ones
93
     *
94
     * @param array $paths
95
     *            paths to directories with the template's static content
96
     */
97
    public function addPaths(array $paths): void
98
    {
99
        $this->paths = array_merge($paths, $this->paths);
100
    }
101
102
    /**
103
     * Resetting paths
104
     *
105
     * @param array $paths
106
     */
107
    public function setPaths(array $paths): void
108
    {
109
        $this->paths = $paths;
110
    }
111
112
    /**
113
     * Method returns all setup puths of the template
114
     *
115
     * @return array
116
     */
117
    public function getPaths(): array
118
    {
119
        return $this->paths;
120
    }
121
122
    /**
123
     * Setting page variables
124
     *
125
     * @param string $var
126
     *            Variable name
127
     * @param mixed $value
128
     *            Variable value
129
     */
130
    public function setPageVar(string $var, $value): void
131
    {
132
        $this->pageVars[$var] = $value;
133
    }
134
135
    /**
136
     * Method sets multiple variables
137
     *
138
     * @param array $vars
139
     */
140
    public function setPageVars(array $vars): void
141
    {
142
        foreach ($vars as $var => $value) {
143
            $this->setPageVar($var, $value);
144
        }
145
    }
146
147
    /**
148
     * Getting page var
149
     *
150
     * @param string $var
151
     *            variable name
152
     * @return mixed variable value, or exception if the variable was not found
153
     */
154
    public function getPageVar(string $var)
155
    {
156
        if (isset($this->pageVars[$var]) === false) {
157
            throw (new \Exception('Template variable ' . $var . ' was not set'));
158
        }
159
160
        return $this->pageVars[$var];
161
    }
162
163
    /**
164
     * Setting page variables from file's content
165
     *
166
     * @param string $var
167
     *            variable name
168
     * @param mixed $path
169
     *            path to file
170
     */
171
    public function setPageVarFromFile(string $var, string $path): void
172
    {
173
        $this->setPageVar($var, file_get_contents($path));
174
    }
175
176
    /**
177
     * Setting page variables from block
178
     *
179
     * @param string $var
180
     *            variable name
181
     * @param mixed $blockName
182
     *            block name
183
     */
184
    public function setPageVarFromBlock(string $var, string $blockName): void
185
    {
186
        $this->setPageVar($var, $this->getBlock($blockName));
187
    }
188
189
    /**
190
     * Compiling the page with it's variables
191
     *
192
     * @param string $content
193
     *            Compiling content
194
     */
195
    public function compilePageVars(string &$content): void
196
    {
197
        foreach ($this->pageVars as $key => $value) {
198
            if (is_array($value) === false && is_object($value) === false) {
199
                // only scalars can be substituted in this way
200
                $content = str_replace('{' . $key . '}', $value, $content);
0 ignored issues
show
Bug introduced by
$value of type object is incompatible with the type string|string[] expected by parameter $replace of str_replace(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

200
                $content = str_replace('{' . $key . '}', /** @scrutinizer ignore-type */ $value, $content);
Loading history...
201
            }
202
        }
203
204
        $content = TemplateEngine::unwrapBlocks($content, $this->pageVars);
205
206
        $content = TemplateEngine::compileSwitch($content);
207
    }
208
209
    /**
210
     * Checking if the file exists
211
     *
212
     * @param string $fileSubPath
213
     *            file sub path
214
     * @return bool true if the file exists, false otherwise
215
     */
216
    protected function fileExists(string $fileSubPath): bool
217
    {
218
        foreach ($this->paths as $path) {
219
            if (file_exists(rtrim($path, '/\\') . '/' . trim($fileSubPath, '/\\'))) {
220
                return true;
221
            }
222
        }
223
224
        return false;
225
    }
226
227
    /**
228
     * Getting content of the file
229
     *
230
     * @param string $fileSubPath
231
     *            file sub path
232
     * @return string file content
233
     */
234
    protected function fileGetContents(string $fileSubPath): string
235
    {
236
        foreach ($this->paths as $path) {
237
            $finalPath = rtrim($path, '/\\') . '/' . trim($fileSubPath, '/\\');
238
            if (file_exists($finalPath)) {
239
                return file_get_contents($finalPath);
240
            }
241
        }
242
        // @codeCoverageIgnoreStart
243
        return '';
244
    }
245
246
    // @codeCoverageIgnoreEnd
247
248
    /**
249
     * Method resets layout
250
     *
251
     * @param string $template
252
     *            Template name
253
     */
254
    public function resetLayout(string $template): void
255
    {
256
        $template .= '.html';
257
258
        if ($this->fileExists($template)) {
259
            $this->template = $this->fileGetContents($template);
260
        } elseif ($this->fileExists('Res/Templates/' . $template)) {
261
            $this->template = $this->fileGetContents('Res/Templates/' . $template);
262
        } else {
263
            throw (new \Exception(
264
                'Template file ' . $template . ' on the paths ' . implode(', ', $this->paths) . ' was not found',
265
                - 1));
266
        }
267
    }
268
269
    /**
270
     * Method returns compiled page resources
271
     *
272
     * @return string Compiled resources includers
273
     */
274
    private function _getResources(): string
275
    {
276
        $content = '';
277
278
        if ($this->resources !== null) {
279
            $cssFiles = $this->resources->getCssFiles();
280
            foreach ($cssFiles as $cSSFile) {
281
                $content .= '
282
        <link href="' . $cSSFile . '" rel="stylesheet" type="text/css">';
283
            }
284
285
            $jsFiles = $this->resources->getJsFiles();
286
            foreach ($jsFiles as $jSFile) {
287
                $content .= '
288
        <script src="' . $jSFile . '"></script>';
289
            }
290
        }
291
292
        return $content;
293
    }
294
295
    /**
296
     * Compile template
297
     *
298
     * @return string Compiled template
299
     */
300
    public function compile(): string
301
    {
302
        $this->setPageVar('resources', $this->_getResources());
303
        $this->setPageVar('mezon-http-path', Conf::getConfigValue('@mezon-http-path'));
304
        $this->setPageVar('service-http-path', Conf::getConfigValue('@service-http-path'));
305
        if (isset($_SERVER['HTTP_HOST'])) {
306
            $this->setPageVar('host', $_SERVER['HTTP_HOST']);
307
        }
308
309
        foreach ($this->blocks as $blockName => $block) {
310
            $this->setPageVar($blockName, $block);
311
        }
312
313
        $this->compilePageVars($this->template);
0 ignored issues
show
Bug introduced by
$this->template of type boolean is incompatible with the type string expected by parameter $content of Mezon\HtmlTemplate\HtmlTemplate::compilePageVars(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

313
        $this->compilePageVars(/** @scrutinizer ignore-type */ $this->template);
Loading history...
314
315
        $this->template = preg_replace('/\{[a-zA-z0-9\-]*\}/', '', $this->template);
316
317
        return $this->template;
318
    }
319
320
    /**
321
     * Does block exist
322
     *
323
     * @param string $blockName
324
     *            block name
325
     * @return bool does block exist?
326
     */
327
    public function blockExists(string $blockName): bool
328
    {
329
        if ($this->fileExists('Res/Blocks/' . $blockName . '.tpl')) {
330
            return true;
331
        } elseif ($this->fileExists('Blocks/' . $blockName . '.tpl')) {
332
            return true;
333
        } else {
334
            return false;
335
        }
336
    }
337
338
    /**
339
     * Method returns block's content
340
     *
341
     * @param string $blockName
342
     * @return string block's content
343
     */
344
    protected function readBlock(string $blockName): string
345
    {
346
        if ($this->fileExists('Res/Blocks/' . $blockName . '.tpl')) {
347
            $blockContent = $this->fileGetContents('Res/Blocks/' . $blockName . '.tpl');
348
        } elseif ($this->fileExists('Blocks/' . $blockName . '.tpl')) {
349
            $blockContent = $this->fileGetContents('Blocks/' . $blockName . '.tpl');
350
        } else {
351
            throw (new \Exception('Block ' . $blockName . ' was not found', - 1));
352
        }
353
354
        return $blockContent;
355
    }
356
357
    /**
358
     * Method adds block to page
359
     *
360
     * @param string $blockName
361
     *            Name of the additing block
362
     */
363
    public function addBlock(string $blockName): void
364
    {
365
        $this->blocks[$blockName] = $this->readBlock($blockName);
366
    }
367
368
    /**
369
     * Method returns block's content
370
     *
371
     * @param string $blockName
372
     * @return string block's content
373
     */
374
    public function getBlock(string $blockName): string
375
    {
376
        return $this->readBlock($blockName);
377
    }
378
379
    /**
380
     * Method sets template resources
381
     *
382
     * @param TemplateResources $resources
383
     *            resources
384
     */
385
    public function setResources(TemplateResources $resources): void
386
    {
387
        $this->resources = $resources;
388
    }
389
}
390