Completed
Push — master ( 5d53c5...860d57 )
by Alex
09:53 queued 01:42
created

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

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

295
        $this->compilePageVars(/** @scrutinizer ignore-type */ $this->template);
Loading history...
296
297
        $this->template = preg_replace('/\{[a-zA-z0-9\-]*\}/', '', $this->template);
298
299
        return $this->template;
300
    }
301
302
    /**
303
     * Method returns block's content
304
     *
305
     * @param string $blockName
306
     * @return string block's content
307
     */
308
    protected function readBlock(string $blockName): string
309
    {
310
        if ($this->fileExists('res/blocks/' . $blockName . '.tpl')) {
311
            $blockContent = $this->fileGetContents('res/blocks/' . $blockName . '.tpl');
312
        } elseif ($this->fileExists('blocks/' . $blockName . '.tpl')) {
313
            $blockContent = $this->fileGetContents('blocks/' . $blockName . '.tpl');
314
        } else {
315
            throw (new \Exception('Block ' . $blockName . ' was not found', - 1));
316
        }
317
318
        return $blockContent;
319
    }
320
321
    /**
322
     * Method adds block to page
323
     *
324
     * @param string $blockName
325
     *            Name of the additing block
326
     */
327
    public function addBlock(string $blockName): void
328
    {
329
        $this->blocks[$blockName] = $this->readBlock($blockName);
330
    }
331
332
    /**
333
     * Method returns block's content
334
     *
335
     * @param string $blockName
336
     * @return string block's content
337
     */
338
    public function getBlock(string $blockName): string
339
    {
340
        return $this->readBlock($blockName);
341
    }
342
}
343