1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Charcoal\View\Mustache; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use Traversable; |
7
|
|
|
|
8
|
|
|
// Dependency from 'mustache/mustache' |
9
|
|
|
use Mustache_Engine; |
10
|
|
|
|
11
|
|
|
// Intra-module (`charcoal-view`) depentencies |
12
|
|
|
use Charcoal\View\AbstractEngine; |
13
|
|
|
|
14
|
|
|
use Charcoal\View\Mustache\HelpersInterface; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Mustache view rendering engine. |
18
|
|
|
*/ |
19
|
|
|
class MustacheEngine extends AbstractEngine |
20
|
|
|
{ |
21
|
|
|
const DEFAULT_CACHE_PATH = '../cache/mustache'; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* A collection of helpers. |
25
|
|
|
* |
26
|
|
|
* @var array |
27
|
|
|
*/ |
28
|
|
|
private $helpers = []; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* The renderering framework. |
32
|
|
|
* |
33
|
|
|
* @var Mustache_Engine |
34
|
|
|
*/ |
35
|
|
|
private $mustache; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @return string |
39
|
|
|
*/ |
40
|
|
|
public function type() |
41
|
|
|
{ |
42
|
|
|
return 'mustache'; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Build the Mustache Engine with an array of dependencies. |
47
|
|
|
* |
48
|
|
|
* @param array $data Engine dependencie. |
49
|
|
|
*/ |
50
|
|
|
public function __construct(array $data) |
51
|
|
|
{ |
52
|
|
|
parent::__construct($data); |
53
|
|
|
|
54
|
|
|
if (isset($data['helpers'])) { |
55
|
|
|
$this->setHelpers($data['helpers']); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @return Mustache_Engine |
61
|
|
|
*/ |
62
|
|
|
protected function mustache() |
63
|
|
|
{ |
64
|
|
|
if ($this->mustache === null) { |
65
|
|
|
$this->mustache = $this->createMustache(); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return $this->mustache; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @return Mustache_Engine |
73
|
|
|
*/ |
74
|
|
|
protected function createMustache() |
75
|
|
|
{ |
76
|
|
|
$mustache = new Mustache_Engine([ |
77
|
|
|
'cache' => $this->cache(), |
78
|
|
|
'loader' => $this->loader(), |
79
|
|
|
'partials_loader' => $this->loader(), |
80
|
|
|
'strict_callables' => true, |
81
|
|
|
'helpers' => $this->helpers() |
82
|
|
|
]); |
83
|
|
|
|
84
|
|
|
return $mustache; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Set the engine's cache implementation. |
89
|
|
|
* |
90
|
|
|
* @param mixed $cache A Mustache cache option. |
91
|
|
|
* @return void |
92
|
|
|
*/ |
93
|
|
|
protected function setCache($cache) |
94
|
|
|
{ |
95
|
|
|
/** |
96
|
|
|
* If FALSE is specified, the value is converted to NULL |
97
|
|
|
* because Mustache internally requires NULL to disable the cache. |
98
|
|
|
*/ |
99
|
|
|
if ($cache === false) { |
100
|
|
|
$cache = null; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
parent::setCache($cache); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Set the engine's helpers. |
108
|
|
|
* |
109
|
|
|
* @param array|Traversable|HelpersInterface $helpers Mustache helpers. |
110
|
|
|
* @throws InvalidArgumentException If the given helper(s) are invalid. |
111
|
|
|
* @return MustacheEngine Chainable |
112
|
|
|
*/ |
113
|
|
View Code Duplication |
public function setHelpers($helpers) |
|
|
|
|
114
|
|
|
{ |
115
|
|
|
if ($helpers instanceof HelpersInterface) { |
116
|
|
|
$helpers = $helpers->toArray(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
if (!is_array($helpers) && !$helpers instanceof Traversable) { |
120
|
|
|
throw new InvalidArgumentException(sprintf( |
121
|
|
|
'setHelpers expects an array of helpers, received %s', |
122
|
|
|
(is_object($helpers) ? get_class($helpers) : gettype($helpers)) |
123
|
|
|
)); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$this->helpers = []; |
127
|
|
|
foreach ($helpers as $name => $helper) { |
128
|
|
|
$this->addHelper($name, $helper); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
return $this; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Merge (replacing or adding) the engine's helpers. |
136
|
|
|
* |
137
|
|
|
* @param array|Traversable|HelpersInterface $helpers Mustache helpers. |
138
|
|
|
* @throws InvalidArgumentException If the given helper(s) are invalid. |
139
|
|
|
* @return MustacheEngine Chainable |
140
|
|
|
*/ |
141
|
|
View Code Duplication |
public function mergeHelpers($helpers) |
|
|
|
|
142
|
|
|
{ |
143
|
|
|
if ($helpers instanceof HelpersInterface) { |
144
|
|
|
$helpers = $helpers->toArray(); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
if (!is_array($helpers) && !$helpers instanceof Traversable) { |
148
|
|
|
throw new InvalidArgumentException(sprintf( |
149
|
|
|
'mergeHelpers expects an array of helpers, received %s', |
150
|
|
|
(is_object($helpers) ? get_class($helpers) : gettype($helpers)) |
151
|
|
|
)); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
foreach ($helpers as $name => $helper) { |
155
|
|
|
$this->addHelper($name, $helper); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return $this; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Add a helper. |
163
|
|
|
* |
164
|
|
|
* @param string $name The tag name. |
165
|
|
|
* @param mixed $helper The tag value. |
166
|
|
|
* @return MustacheEngine Chainable |
167
|
|
|
*/ |
168
|
|
|
public function addHelper($name, $helper) |
169
|
|
|
{ |
170
|
|
|
$this->helpers[$name] = $helper; |
171
|
|
|
|
172
|
|
|
return $this; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Retrieve the engine's helpers. |
177
|
|
|
* |
178
|
|
|
* @return array |
179
|
|
|
*/ |
180
|
|
|
public function helpers() |
181
|
|
|
{ |
182
|
|
|
return $this->helpers; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* @param string $templateIdent The template identifier to load and render. |
187
|
|
|
* @param mixed $context The rendering context. |
188
|
|
|
* @return string The rendered template string. |
189
|
|
|
*/ |
190
|
|
|
public function render($templateIdent, $context) |
191
|
|
|
{ |
192
|
|
|
return $this->mustache()->render($templateIdent, $context); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @param string $templateString The template string to render. |
197
|
|
|
* @param mixed $context The rendering context. |
198
|
|
|
* @return string The rendered template string. |
199
|
|
|
*/ |
200
|
|
|
public function renderTemplate($templateString, $context) |
201
|
|
|
{ |
202
|
|
|
return $this->mustache()->render($templateString, $context); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.