Passed
Push — main ( 72d047...e456c4 )
by Thierry
02:43
created

TemplateEngine   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 24
c 0
b 0
f 0
dl 0
loc 95
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A render() 0 26 4
A addNamespace() 0 5 1
A renderTemplate() 0 13 1
A pagination() 0 3 1
1
<?php
2
3
/**
4
 * TemplateEngine.php - Template engine
5
 *
6
 * Generate templates with template vars.
7
 *
8
 * @package jaxon-core
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2022 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
14
15
namespace Jaxon\Utils\Template;
16
17
use function trim;
18
use function rtrim;
19
use function substr;
20
use function strrpos;
21
use function ob_start;
22
use function ob_get_clean;
23
use function call_user_func;
24
25
class TemplateEngine
26
{
27
    /**
28
     * The namespaces
29
     *
30
     * @var array   $aNamespaces
31
     */
32
    protected $aNamespaces;
33
34
    /**
35
     * Add a namespace to the template system
36
     *
37
     * @param string $sNamespace The namespace name
38
     * @param string $sDirectory The namespace directory
39
     * @param string $sExtension The extension to append to template names
40
     *
41
     * @return void
42
     */
43
    public function addNamespace(string $sNamespace, string $sDirectory, string $sExtension = '')
44
    {
45
        $this->aNamespaces[$sNamespace] = [
46
            'directory' => rtrim(trim($sDirectory), "/\\") . DIRECTORY_SEPARATOR,
47
            'extension' => $sExtension,
48
        ];
49
    }
50
51
    /**
52
     * Set a new directory for pagination templates
53
     *
54
     * @param string $sDirectory The directory path
55
     *
56
     * @return void
57
     */
58
    public function pagination(string $sDirectory)
59
    {
60
        $this->aNamespaces['pagination']['directory'] = rtrim(trim($sDirectory), "/\\") . DIRECTORY_SEPARATOR;
61
    }
62
63
    /**
64
     * Render a template
65
     *
66
     * @param string $sPath The path to the template
67
     * @param array $aVars The template vars
68
     *
69
     * @return string
70
     */
71
    private function renderTemplate(string $sPath, array $aVars): string
72
    {
73
        // Make the template vars available in a Context object.
74
        $xContext = new Context($this, $aVars);
75
        // Render the template
76
        $cRenderer = function() use($sPath) {
77
            ob_start();
78
            include($sPath);
79
            return ob_get_clean();
80
        };
81
        // Call the closure in the context of the Context object.
82
        // So the keyword '$this' in the template will refer to the $xContext object.
83
        return call_user_func($cRenderer->bindTo($xContext));
84
    }
85
86
    /**
87
     * Render a template
88
     *
89
     * @param string $sTemplate The name of template to be rendered
90
     * @param array $aVars The template vars
91
     *
92
     * @return string
93
     */
94
    public function render(string $sTemplate, array $aVars = []): string
95
    {
96
        $sTemplate = trim($sTemplate);
97
        // Get the namespace name
98
        $sNamespace = '';
99
        $nSeparatorPosition = strrpos($sTemplate, '::');
100
        if($nSeparatorPosition !== false)
101
        {
102
            $sNamespace = substr($sTemplate, 0, $nSeparatorPosition);
103
            $sTemplate = substr($sTemplate, $nSeparatorPosition + 2);
104
        }
105
        // The default namespace is 'jaxon'
106
        if(!($sNamespace = trim($sNamespace)))
107
        {
108
            $sNamespace = 'jaxon';
109
        }
110
        // Check if the namespace is defined
111
        if(!isset($this->aNamespaces[$sNamespace]))
112
        {
113
            return '';
114
        }
115
        $aNamespace = $this->aNamespaces[$sNamespace];
116
        // Get the template path
117
        $sTemplatePath = $aNamespace['directory'] . $sTemplate . $aNamespace['extension'];
118
        // Render the template
119
        return $this->renderTemplate($sTemplatePath, $aVars);
120
    }
121
}
122