Passed
Push — master ( 8f302d...636da2 )
by Alex
21:26
created

HtmlTemplate::setResources()   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 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
     * Compiling the page with it's variables
178
     *
179
     * @param string $content
180
     *            Compiling content
181
     */
182
    public function compilePageVars(string &$content): void
183
    {
184
        foreach ($this->pageVars as $key => $value) {
185
            if (is_array($value) === false && is_object($value) === false) {
186
                // only scalars can be substituted in this way
187
                $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

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

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