1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace Charcoal\View; |
4
|
|
|
|
5
|
|
|
// Dependencies from `PHP` |
6
|
|
|
use \Exception; |
7
|
|
|
use \InvalidArgumentException; |
8
|
|
|
|
9
|
|
|
// PSR-3 (logger) dependencies |
10
|
|
|
use \Psr\Log\LoggerAwareInterface; |
11
|
|
|
use \Psr\Log\LoggerAwareTrait; |
12
|
|
|
|
13
|
|
|
// Module `charcoal-config` dependencies |
14
|
|
|
use \Charcoal\Config\ConfigurableInterface; |
15
|
|
|
use \Charcoal\Config\ConfigurableTrait; |
16
|
|
|
|
17
|
|
|
// Local namespace dependencies |
18
|
|
|
use \Charcoal\View\Mustache\MustacheEngine; |
19
|
|
|
use \Charcoal\View\Php\PhpEngine; |
20
|
|
|
use \Charcoal\View\PhpMustache\PhpMustacheEngine; |
21
|
|
|
use \Charcoal\View\Twig\TwigEngine; |
22
|
|
|
use \Charcoal\View\ViewInterface; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Base abstract class for _View_ interfaces, implements `ViewInterface`. |
26
|
|
|
* |
27
|
|
|
* Also implements the `ConfigurableInterface` |
28
|
|
|
*/ |
29
|
|
|
abstract class AbstractView implements |
|
|
|
|
30
|
|
|
ConfigurableInterface, |
31
|
|
|
LoggerAwareInterface, |
32
|
|
|
ViewInterface |
33
|
|
|
{ |
34
|
|
|
use LoggerAwareTrait; |
35
|
|
|
use ConfigurableTrait; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var string $templateIdent |
39
|
|
|
*/ |
40
|
|
|
private $templateIdent; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var string $template |
44
|
|
|
*/ |
45
|
|
|
private $template; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var EngineInterface $engine |
49
|
|
|
*/ |
50
|
|
|
private $engine; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var mixed $context |
54
|
|
|
*/ |
55
|
|
|
private $context; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* A view object can simply be echoed to be rendered. |
59
|
|
|
* |
60
|
|
|
* @return string |
61
|
|
|
*/ |
62
|
|
|
public function __toString() |
63
|
|
|
{ |
64
|
|
|
return $this->renderTemplate(); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* > ConfigurableTrait . createConfig() |
69
|
|
|
* |
70
|
|
|
* @param array $data |
71
|
|
|
* @return ViewConfig |
72
|
|
|
*/ |
73
|
|
|
public function createConfig(array $data = null) |
74
|
|
|
{ |
75
|
|
|
$config = new ViewConfig(); |
76
|
|
|
if ($data !== null) { |
77
|
|
|
$config->merge($data); |
|
|
|
|
78
|
|
|
} |
79
|
|
|
return $config; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Set the engine (`EngineInterface`) dependency. |
84
|
|
|
* |
85
|
|
|
* @param EngineInterface $engine The |
86
|
|
|
* @return ViewInterface Chainable |
87
|
|
|
*/ |
88
|
|
|
public function setEngine(EngineInterface $engine) |
89
|
|
|
{ |
90
|
|
|
$this->engine = $engine; |
91
|
|
|
return $this; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Get the view's rendering engine instance. |
96
|
|
|
* |
97
|
|
|
* @throws Exception If the engine is accessed before it was properly set. |
98
|
|
|
* @return EngineInterface |
99
|
|
|
*/ |
100
|
|
|
public function engine() |
101
|
|
|
{ |
102
|
|
|
if (!isset($this->engine)) { |
103
|
|
|
throw new Exception( |
104
|
|
|
'Engine must first be set on view, with `setEngine()`' |
105
|
|
|
); |
106
|
|
|
} |
107
|
|
|
return $this->engine; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* @param string $templateIdent |
112
|
|
|
* @throws InvalidArgumentException if the provided argument is not a string |
113
|
|
|
* @return AbstractView Chainable |
114
|
|
|
*/ |
115
|
|
|
public function setTemplateIdent($templateIdent) |
116
|
|
|
{ |
117
|
|
|
if (!is_string($templateIdent)) { |
118
|
|
|
throw new InvalidArgumentException( |
119
|
|
|
'Template ident must be a string.' |
120
|
|
|
); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
$this->templateIdent = $templateIdent; |
124
|
|
|
return $this; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* @return string |
129
|
|
|
*/ |
130
|
|
|
public function templateIdent() |
131
|
|
|
{ |
132
|
|
|
return $this->templateIdent; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* @param string $template |
137
|
|
|
* @throws InvalidArgumentException if the provided argument is not a string |
138
|
|
|
* @return AbstractView Chainable |
139
|
|
|
*/ |
140
|
|
|
public function setTemplate($template) |
141
|
|
|
{ |
142
|
|
|
if (!is_string($template)) { |
143
|
|
|
throw new InvalidArgumentException( |
144
|
|
|
'Template must be a string.' |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$this->template = $template; |
149
|
|
|
return $this; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* @return string |
154
|
|
|
*/ |
155
|
|
|
public function template() |
156
|
|
|
{ |
157
|
|
|
if ($this->template === null) { |
158
|
|
|
return $this->loadTemplate(); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
return $this->template; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* @param string $templateIdent |
166
|
|
|
* @throws InvalidArgumentException |
167
|
|
|
* @return string |
168
|
|
|
*/ |
169
|
|
|
public function loadTemplate($templateIdent = null) |
170
|
|
|
{ |
171
|
|
|
if ($templateIdent === null) { |
172
|
|
|
$templateIdent = $this->templateIdent(); |
173
|
|
|
} |
174
|
|
|
if (!is_string($templateIdent)) { |
175
|
|
|
throw new InvalidArgumentException( |
176
|
|
|
'Template ident must be a string' |
177
|
|
|
); |
178
|
|
|
} |
179
|
|
|
if (!$templateIdent) { |
180
|
|
|
return ''; |
181
|
|
|
} |
182
|
|
|
$template = $this->engine()->loadTemplate($templateIdent); |
183
|
|
|
return $template; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Set the rendering context ("view controller"). |
188
|
|
|
* |
189
|
|
|
* @param mixed $context The context / view controller to render the template with. |
190
|
|
|
* @return AbstractView Chainable |
191
|
|
|
*/ |
192
|
|
|
public function setContext($context) |
193
|
|
|
{ |
194
|
|
|
$this->context = $context; |
195
|
|
|
return $this; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Get the rendering context ("view controller"). |
200
|
|
|
* @return mixed |
201
|
|
|
*/ |
202
|
|
|
public function context() |
203
|
|
|
{ |
204
|
|
|
return $this->context; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* @param string $templateIdent Optional. The template identifier to load. If none then use instance's. |
209
|
|
|
* @param mixed $context The rendering context. |
210
|
|
|
* @return string The rendered template string. |
211
|
|
|
*/ |
212
|
|
View Code Duplication |
public function render($templateIdent = null, $context = null) |
|
|
|
|
213
|
|
|
{ |
214
|
|
|
if ($templateIdent === null) { |
215
|
|
|
$templateIdent = $this->templateIdent(); |
216
|
|
|
} |
217
|
|
|
if ($context === null) { |
218
|
|
|
$context = $this->context(); |
219
|
|
|
} |
220
|
|
|
return $this->engine()->render($templateIdent, $context); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* @param string $templateString Optional. The template string to render. If none then load instance's. |
225
|
|
|
* @param mixed $context The rendering context. |
226
|
|
|
* @return string The rendered template string. |
227
|
|
|
*/ |
228
|
|
View Code Duplication |
public function renderTemplate($templateString = null, $context = null) |
|
|
|
|
229
|
|
|
{ |
230
|
|
|
if ($templateString === null) { |
231
|
|
|
$templateString = $this->template(); |
232
|
|
|
} |
233
|
|
|
if ($context === null) { |
234
|
|
|
$context = $this->context(); |
235
|
|
|
} |
236
|
|
|
return $this->engine()->render($templateString, $context); |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.