1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Faulancer\View; |
4
|
|
|
|
5
|
|
|
use Faulancer\Event\Observer; |
6
|
|
|
use Faulancer\Event\Type\OnPostRender; |
7
|
|
|
use Faulancer\Event\Type\OnRender; |
8
|
|
|
use Faulancer\Exception\FileNotFoundException; |
9
|
|
|
use Faulancer\Exception\ServiceNotFoundException; |
10
|
|
|
use Faulancer\Exception\ViewHelperException; |
11
|
|
|
use Faulancer\Service\Config; |
12
|
|
|
use Faulancer\ServiceLocator\ServiceLocator; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class ViewController | ViewController.php |
16
|
|
|
* |
17
|
|
|
* @package Faulancer\View |
18
|
|
|
* @author Florian Knapp <[email protected]> |
19
|
|
|
*/ |
20
|
|
|
class ViewController |
21
|
|
|
{ |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @var Config |
25
|
|
|
*/ |
26
|
|
|
private $config; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Holds the view variables |
30
|
|
|
* @var array |
31
|
|
|
*/ |
32
|
|
|
private $variable = []; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Holds the view template |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
private $template = ''; |
39
|
|
|
|
40
|
|
|
/**The template path without filename |
41
|
|
|
* @var string |
42
|
|
|
*/ |
43
|
|
|
private $templatePath = ''; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Holds the registered view helpers |
47
|
|
|
* @var array |
48
|
|
|
*/ |
49
|
|
|
//private $viewHelpers = []; |
|
|
|
|
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Holds the parent template |
53
|
|
|
* @var ViewController |
54
|
|
|
*/ |
55
|
|
|
private $parentTemplate = null; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* ViewController constructor. |
59
|
|
|
* |
60
|
|
|
* @throws ServiceNotFoundException |
61
|
|
|
*/ |
62
|
|
|
public function __construct() |
63
|
|
|
{ |
64
|
|
|
$this->config = ServiceLocator::instance()->get(Config::class); |
|
|
|
|
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Set template for this view |
69
|
|
|
* |
70
|
|
|
* @param string $template |
71
|
|
|
* @return self |
72
|
|
|
* |
73
|
|
|
* @throws FileNotFoundException |
74
|
|
|
*/ |
75
|
|
|
public function setTemplate(string $template = '') |
76
|
|
|
{ |
77
|
|
|
if (empty($this->templatePath) && strpos($template, $this->config->get('viewsRoot')) === false) { |
78
|
|
|
$template = $this->config->get('viewsRoot') . $template; |
79
|
|
|
} else { |
80
|
|
|
$template = $this->templatePath . $template; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
if (empty($template) || !file_exists($template) || is_dir($template)) { |
84
|
|
|
throw new FileNotFoundException('Template "' . $template . '" not found'); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
$this->template = $template; |
88
|
|
|
|
89
|
|
|
return $this; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Set the template path |
94
|
|
|
* |
95
|
|
|
* @param string $path |
96
|
|
|
* @return self |
97
|
|
|
*/ |
98
|
|
|
public function setTemplatePath(string $path = '') |
99
|
|
|
{ |
100
|
|
|
$this->templatePath = $path; |
101
|
|
|
return $this; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Get the template path |
106
|
|
|
* |
107
|
|
|
* @return string |
108
|
|
|
*/ |
109
|
|
|
public function getTemplatePath() |
110
|
|
|
{ |
111
|
|
|
return $this->templatePath; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Add javascript from outside |
116
|
|
|
* |
117
|
|
|
* @param string $file |
118
|
|
|
* @return self |
119
|
|
|
*/ |
120
|
|
|
public function addScript(string $file) |
121
|
|
|
{ |
122
|
|
|
$this->variable['assetsJs'][] = $file; |
123
|
|
|
return $this; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Add stylesheet from outside |
128
|
|
|
* |
129
|
|
|
* @param string $file |
130
|
|
|
* @return self |
131
|
|
|
*/ |
132
|
|
|
public function addStylesheet(string $file) |
133
|
|
|
{ |
134
|
|
|
$this->variable['assetsCss'][] = $file; |
135
|
|
|
return $this; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Return current template |
140
|
|
|
* |
141
|
|
|
* @return string |
142
|
|
|
*/ |
143
|
|
|
public function getTemplate() :string |
144
|
|
|
{ |
145
|
|
|
return (string)$this->template; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Set a single variable |
150
|
|
|
* |
151
|
|
|
* @param string $key |
152
|
|
|
* @param string|array $value |
153
|
|
|
*/ |
154
|
|
|
public function setVariable(string $key = '', $value = '') |
155
|
|
|
{ |
156
|
|
|
$this->variable[$key] = $value; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Get a single variable |
161
|
|
|
* |
162
|
|
|
* @param string $key |
163
|
|
|
* @return string|array |
164
|
|
|
*/ |
165
|
|
|
public function getVariable(string $key) |
166
|
|
|
{ |
167
|
|
|
if(isset($this->variable[$key])) { |
168
|
|
|
return $this->variable[$key]; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
return ''; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* Check if variable exists |
176
|
|
|
* |
177
|
|
|
* @param string $key |
178
|
|
|
* @return bool |
179
|
|
|
*/ |
180
|
|
|
public function hasVariable(string $key) :bool |
181
|
|
|
{ |
182
|
|
|
if(isset($this->variable[$key])) { |
183
|
|
|
return true; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
return false; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Set many variables at once |
191
|
|
|
* |
192
|
|
|
* @param array $variables |
193
|
|
|
* @return self |
194
|
|
|
*/ |
195
|
|
|
public function setVariables(array $variables = []) |
196
|
|
|
{ |
197
|
|
|
foreach($variables AS $key=>$value) { |
198
|
|
|
$this->setVariable($key, $value); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
return $this; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Get all variables |
206
|
|
|
* |
207
|
|
|
* @return array |
208
|
|
|
*/ |
209
|
|
|
public function getVariables() :array |
210
|
|
|
{ |
211
|
|
|
return $this->variable; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Define parent template |
216
|
|
|
* |
217
|
|
|
* @param ViewController $view |
218
|
|
|
*/ |
219
|
|
|
public function setParentTemplate(ViewController $view) |
220
|
|
|
{ |
221
|
|
|
$this->parentTemplate = $view; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Get parent template |
226
|
|
|
* |
227
|
|
|
* @return ViewController |
228
|
|
|
*/ |
229
|
|
|
public function getParentTemplate() |
230
|
|
|
{ |
231
|
|
|
return $this->parentTemplate; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Strip spaces and tabs from output |
236
|
|
|
* |
237
|
|
|
* @param $output |
238
|
|
|
* @return string |
239
|
|
|
*/ |
240
|
|
|
private function _cleanOutput($output) :string |
241
|
|
|
{ |
242
|
|
|
if (defined('APPLICATION_ENV') && APPLICATION_ENV === 'production') { |
243
|
|
|
return preg_replace('/(\s{2,}|\t|\r|\n)/', ' ', trim($output)); |
244
|
|
|
} else { |
245
|
|
|
return str_replace(["\t", "\r", "\n\n\n"], ' ', trim($output)); |
246
|
|
|
} |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Render the current view |
251
|
|
|
* |
252
|
|
|
* @return string |
253
|
|
|
* @throws ServiceNotFoundException |
254
|
|
|
*/ |
255
|
|
|
public function render() |
256
|
|
|
{ |
257
|
|
|
Observer::instance()->trigger(new OnRender($this)); |
258
|
|
|
|
259
|
|
|
extract($this->variable); |
260
|
|
|
|
261
|
|
|
ob_start(); |
262
|
|
|
|
263
|
|
|
include $this->getTemplate(); |
264
|
|
|
|
265
|
|
|
$content = ob_get_contents(); |
266
|
|
|
|
267
|
|
|
if (ob_get_length()) { |
268
|
|
|
ob_end_clean(); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
Observer::instance()->trigger(new OnPostRender($this)); |
272
|
|
|
|
273
|
|
|
if ($this->getParentTemplate() instanceof ViewController) { |
274
|
|
|
return $this->_cleanOutput($this->getParentTemplate()->setVariables($this->getVariables())->render()); |
275
|
|
|
} else { |
276
|
|
|
return $this->_cleanOutput($content); |
277
|
|
|
} |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Magic method for providing a view helpers |
282
|
|
|
* |
283
|
|
|
* @param string $name The class name |
284
|
|
|
* @param array $arguments Arguments if given |
285
|
|
|
* |
286
|
|
|
* @return AbstractViewHelper |
287
|
|
|
* |
288
|
|
|
* @throws ViewHelperException |
289
|
|
|
* @throws ServiceNotFoundException |
290
|
|
|
*/ |
291
|
|
|
public function __call($name, $arguments) |
292
|
|
|
{ |
293
|
|
|
$coreViewHelper = __NAMESPACE__ . '\Helper\\' . ucfirst($name); |
294
|
|
|
|
295
|
|
|
// if (!empty($this->viewHelpers[$coreViewHelper])) { |
|
|
|
|
296
|
|
|
// return $this->_callUserFuncArray($this->viewHelpers[$coreViewHelper], $arguments); |
297
|
|
|
// } |
298
|
|
|
|
299
|
|
|
/** @var Config $config */ |
300
|
|
|
$config = ServiceLocator::instance()->get(Config::class); |
301
|
|
|
$namespace = '\\' . $config->get('namespacePrefix'); |
302
|
|
|
$customViewHelper = $namespace . '\\View\\Helper\\' . ucfirst($name); |
303
|
|
|
|
304
|
|
|
// if (!empty($this->viewHelpers[$customViewHelper])) { |
|
|
|
|
305
|
|
|
// return $this->_callUserFuncArray($this->viewHelpers[$customViewHelper], $arguments); |
306
|
|
|
// } |
307
|
|
|
|
308
|
|
|
// Search in custom view helpers |
309
|
|
|
|
310
|
|
View Code Duplication |
if (class_exists($customViewHelper)) { |
|
|
|
|
311
|
|
|
|
312
|
|
|
/** @var AbstractViewHelper $class */ |
313
|
|
|
$class = new $customViewHelper; |
314
|
|
|
$class->setView($this); |
315
|
|
|
|
316
|
|
|
//$this->viewHelpers[$customViewHelper] = $class; |
|
|
|
|
317
|
|
|
|
318
|
|
|
return $this->_callUserFuncArray($class, $arguments); |
319
|
|
|
|
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
// No custom view helper found, search in core view helpers |
323
|
|
|
|
324
|
|
View Code Duplication |
if (class_exists($coreViewHelper)) { |
|
|
|
|
325
|
|
|
|
326
|
|
|
/** @var AbstractViewHelper $class */ |
327
|
|
|
$class = new $coreViewHelper; |
328
|
|
|
$class->setView($this); |
329
|
|
|
|
330
|
|
|
//$this->viewHelpers[$coreViewHelper] = $class; |
|
|
|
|
331
|
|
|
|
332
|
|
|
return $this->_callUserFuncArray($class, $arguments); |
333
|
|
|
|
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
throw new ViewHelperException('No view helper for "' . $name . '" found.'); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* Abstraction of call_user_func_array |
341
|
|
|
* |
342
|
|
|
* @param $class |
343
|
|
|
* @param $arguments |
344
|
|
|
* |
345
|
|
|
* @return mixed |
346
|
|
|
*/ |
347
|
|
|
private function _callUserFuncArray($class, $arguments) |
348
|
|
|
{ |
349
|
|
|
return call_user_func_array($class, $arguments); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* Destructor |
354
|
|
|
*/ |
355
|
|
|
public function __destruct() |
356
|
|
|
{ |
357
|
|
|
unset( $this->variable ); |
358
|
|
|
unset( $this->template ); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.