Completed
Push — master ( 3869b5...b1eb47 )
by Alex
03:03
created

HtmlTemplate::getFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 3
nc 3
nop 1
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
        // TODO substitute untill nothing can be substituted
198
        // for example
199
        // while (($tmp = preg_match_count('{mecro-name}', $content))<=$prevCount){
200
        // here do the nextward loop
201
        // $prevCount = $tmp;
202
        // }
203
        foreach ($this->pageVars as $key => $value) {
204
            if (is_array($value) === false && is_object($value) === false) {
205
                // only scalars can be substituted in this way
206
                $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

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

319
        $this->compilePageVars(/** @scrutinizer ignore-type */ $this->template);
Loading history...
320
321
        $this->template = preg_replace('/\{[a-zA-z0-9\-]*\}/', '', $this->template);
322
323
        return $this->template;
324
    }
325
326
    /**
327
     * Does block exist
328
     *
329
     * @param string $blockName
330
     *            block name
331
     * @return bool does block exist?
332
     */
333
    public function blockExists(string $blockName): bool
334
    {
335
        if ($this->fileExists('Res/Blocks/' . $blockName . '.tpl')) {
336
            return true;
337
        } elseif ($this->fileExists('Blocks/' . $blockName . '.tpl')) {
338
            return true;
339
        } else {
340
            return false;
341
        }
342
    }
343
344
    /**
345
     * Method returns block's content
346
     *
347
     * @param string $blockName
348
     * @return string block's content
349
     */
350
    protected function readBlock(string $blockName): string
351
    {
352
        if ($this->fileExists('Res/Blocks/' . $blockName . '.tpl')) {
353
            $blockContent = $this->fileGetContents('Res/Blocks/' . $blockName . '.tpl');
354
        } elseif ($this->fileExists('Blocks/' . $blockName . '.tpl')) {
355
            $blockContent = $this->fileGetContents('Blocks/' . $blockName . '.tpl');
356
        } else {
357
            throw (new \Exception('Block ' . $blockName . ' was not found', - 1));
358
        }
359
360
        return $blockContent;
361
    }
362
363
    /**
364
     * Method adds block to page
365
     *
366
     * @param string $blockName
367
     *            Name of the additing block
368
     */
369
    public function addBlock(string $blockName): void
370
    {
371
        $this->blocks[$blockName] = $this->readBlock($blockName);
372
    }
373
374
    /**
375
     * Method returns block's content
376
     *
377
     * @param string $blockName
378
     * @return string block's content
379
     */
380
    public function getBlock(string $blockName): string
381
    {
382
        return $this->readBlock($blockName);
383
    }
384
385
    /**
386
     * Method returns file data
387
     *
388
     * @param string $filePath
389
     *            path to file
390
     * @return string file content
391
     */
392
    public function getFile(string $filePath): string
393
    {
394
        foreach ($this->paths as $path) {
395
            $fullPath = rtrim($path, '\\/') . '/' . ltrim($filePath, '\\/');
396
397
            if (file_exists($fullPath)) {
398
                return file_get_contents($fullPath);
399
            }
400
        }
401
402
        throw (new \Exception('File "' . $filePath . '" was not found in paths : ' . implode($this->paths)));
403
    }
404
405
    /**
406
     * Method sets template resources
407
     *
408
     * @param TemplateResources $resources
409
     *            resources
410
     */
411
    public function setResources(TemplateResources $resources): void
412
    {
413
        $this->resources = $resources;
414
    }
415
}
416