1
|
|
|
<?php |
2
|
|
|
namespace Zewa; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* Abstract class for model extension |
6
|
|
|
* |
7
|
|
|
* @author Zechariah Walden<zech @ zewadesign.com> |
8
|
|
|
*/ |
9
|
|
|
class View |
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* System configuration |
13
|
|
|
* |
14
|
|
|
* @var object |
15
|
|
|
*/ |
16
|
|
|
protected $configuration; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Instantiated request class pointer |
20
|
|
|
* |
21
|
|
|
* @var object |
22
|
|
|
*/ |
23
|
|
|
protected $request; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Active layout for view |
27
|
|
|
* |
28
|
|
|
* @var string|bool |
29
|
|
|
*/ |
30
|
|
|
protected $layout; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Active module for view |
34
|
|
|
* |
35
|
|
|
* @var string|bool |
36
|
|
|
*/ |
37
|
|
|
protected $module = false; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Rendered view content |
41
|
|
|
* |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
protected $view = false; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Data object for view |
48
|
|
|
* |
49
|
|
|
* @var object |
50
|
|
|
*/ |
51
|
|
|
protected $properties; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Router object for view injection |
55
|
|
|
* |
56
|
|
|
* @var object |
57
|
|
|
*/ |
58
|
|
|
protected $router; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Load up some basic configuration settings. |
62
|
|
|
*/ |
63
|
|
View Code Duplication |
public function __construct() |
|
|
|
|
64
|
|
|
{ |
65
|
|
|
$app = App::getInstance(); |
66
|
|
|
$this->configuration = $app->getConfiguration(); |
67
|
|
|
$this->request = $app->getService('request'); |
68
|
|
|
$this->router = $app->getService('router'); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Returns base URL for app |
73
|
|
|
* @return string |
74
|
|
|
*/ |
75
|
|
|
private function baseURL($path = '') |
76
|
|
|
{ |
77
|
|
|
return $this->router->baseURL($path); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Returns the current request URL |
82
|
|
|
* @return string |
83
|
|
|
*/ |
84
|
|
|
private function currentURL($params = false) |
|
|
|
|
85
|
|
|
{ |
86
|
|
|
return $this->router->currentURL($params); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Returns uri string |
91
|
|
|
* @return string |
92
|
|
|
*/ |
93
|
|
|
private function currentURI() |
|
|
|
|
94
|
|
|
{ |
95
|
|
|
return $this->router->uri; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Loads a view |
100
|
|
|
* |
101
|
|
|
* @access public |
102
|
|
|
* |
103
|
|
|
* @param string|bool $view view to load |
104
|
|
|
* |
105
|
|
|
* @return string |
106
|
|
|
*/ |
107
|
|
|
public function render($view = false) |
108
|
|
|
{ |
109
|
|
|
if ($view !== false) { |
110
|
|
|
$view = $this->prepareView($view); |
111
|
|
|
return $this->process($view); |
112
|
|
|
} else { |
113
|
|
|
if ($this->view !== false) { |
114
|
|
|
$this->view = $this->process($this->view); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
if (! is_null($this->layout)) { |
118
|
|
|
return $this->process($this->layout); |
119
|
|
|
} else { |
120
|
|
|
return $this->view; |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* formats and prepares view for inclusion |
127
|
|
|
* @param $viewName |
128
|
|
|
* @return string |
129
|
|
|
* @throws Exception\LookupException |
130
|
|
|
*/ |
131
|
|
|
private function prepareView($viewName) |
132
|
|
|
{ |
133
|
|
|
if ($this->module === false) { |
134
|
|
|
$this->setModule(); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
$view = APP_PATH |
138
|
|
|
. DIRECTORY_SEPARATOR |
139
|
|
|
. 'Modules' |
140
|
|
|
. DIRECTORY_SEPARATOR |
141
|
|
|
. $this->module |
142
|
|
|
. DIRECTORY_SEPARATOR |
143
|
|
|
. 'Views' |
144
|
|
|
. DIRECTORY_SEPARATOR |
145
|
|
|
. strtolower($viewName) |
146
|
|
|
. '.php'; |
147
|
|
|
|
148
|
|
|
if (!file_exists($view)) { |
149
|
|
|
throw new Exception\LookupException('View: "' . $view . '" could not be found.'); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
return $view; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
public function setView($viewName, $layout = false) |
156
|
|
|
{ |
157
|
|
|
if ($layout !== false) { |
158
|
|
|
$this->setLayout($layout); |
159
|
|
|
} |
160
|
|
|
$this->view = $this->prepareView($viewName); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
public function setProperty($property, $value = false) |
164
|
|
|
{ |
165
|
|
|
if ($value !== false) { |
166
|
|
|
$this->properties[$property] = $value; |
167
|
|
|
} elseif (!empty($property)) { |
168
|
|
|
$this->properties = $property; |
169
|
|
|
} |
170
|
|
|
return false; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
public function setLayout($layout) |
174
|
|
|
{ |
175
|
|
|
|
176
|
|
|
if ($layout === false) { |
177
|
|
|
$this->layout = null; |
178
|
|
|
} else { |
179
|
|
|
$layout = APP_PATH . DIRECTORY_SEPARATOR . 'Layouts' . DIRECTORY_SEPARATOR . strtolower($layout) . '.php'; |
180
|
|
|
|
181
|
|
|
if (!file_exists($layout)) { |
182
|
|
|
throw new Exception\LookupException('Layout: "' . $layout . '" could not be found.'); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
$this->layout = $layout; |
186
|
|
|
|
187
|
|
|
return true; |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Set the module for view look |
193
|
|
|
* |
194
|
|
|
* @access public |
195
|
|
|
* @param string|bool $module module to override |
196
|
|
|
*/ |
197
|
|
|
public function setModule($module = false) |
198
|
|
|
{ |
199
|
|
|
if ($module === false) { |
200
|
|
|
$this->module = $this->configuration->router->module; |
201
|
|
|
} else { |
202
|
|
|
$this->module = ucfirst($module); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Processes view/layouts and exposes variables to the view/layout |
208
|
|
|
* |
209
|
|
|
* @access private |
210
|
|
|
* @param string $file file being rendered |
211
|
|
|
* @return string processed content |
212
|
|
|
*/ |
213
|
|
|
//@TODO: come back and clean up this and the way the view receives stuff |
214
|
|
|
private function process($file) |
215
|
|
|
{ |
216
|
|
|
ob_start(); |
217
|
|
|
|
218
|
|
|
if (is_array($this->properties)) { |
219
|
|
|
extract($this->properties); // yuck. could produce undeclared errors. hmm.. |
220
|
|
|
} |
221
|
|
|
//should i set $this->data in abstract controller, and provide all access vars ? seems bad practice.. |
222
|
|
|
|
223
|
|
|
include $file; |
224
|
|
|
|
225
|
|
|
$return = ob_get_contents(); |
226
|
|
|
|
227
|
|
|
ob_end_clean(); |
228
|
|
|
|
229
|
|
|
return $return; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Helper method for grabbing aggregated css files |
234
|
|
|
* |
235
|
|
|
* @access protected |
236
|
|
|
* @return string css includes |
237
|
|
|
*/ |
238
|
|
View Code Duplication |
protected function fetchCSS() |
|
|
|
|
239
|
|
|
{ |
240
|
|
|
$app = App::getInstance(); |
241
|
|
|
$sheets = $app->getConfiguration('view::css'); |
242
|
|
|
|
243
|
|
|
$string = ""; |
244
|
|
|
|
245
|
|
|
if (empty($sheets)) { |
246
|
|
|
return $string; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
foreach ($sheets as $sheet) { |
250
|
|
|
$string .= '<link rel="stylesheet" href="' . $sheet .'">' . "\r\n"; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
return $string; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Helper method for grabbing aggregated JS files |
258
|
|
|
* |
259
|
|
|
* @access protected |
260
|
|
|
* @return string JS includes |
261
|
|
|
*/ |
262
|
|
View Code Duplication |
protected function fetchJS() |
|
|
|
|
263
|
|
|
{ |
264
|
|
|
|
265
|
|
|
$app = App::getInstance(); |
266
|
|
|
$scripts = $app->getConfiguration('view::js'); |
267
|
|
|
$string = "<script>baseURL = '" . $this->baseURL() . "/'</script>"; |
268
|
|
|
|
269
|
|
|
if (empty($scripts)) { |
270
|
|
|
return $string; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
foreach ($scripts as $script) { |
274
|
|
|
$string .= '<script src="' . $script . '"></script>' . "\r\n"; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
return $string; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Helper method for adding css files for aggregation/render |
282
|
|
|
* |
283
|
|
|
* @access public |
284
|
|
|
* @param $sheets array |
285
|
|
|
* @param $place string |
286
|
|
|
* @return string css includes |
287
|
|
|
* @throws Exception\LookupException |
288
|
|
|
*/ |
289
|
|
View Code Duplication |
public function addCSS($sheets = [], $place = 'append') |
|
|
|
|
290
|
|
|
{ |
291
|
|
|
$app = App::getInstance(); |
292
|
|
|
$existingCSS = $app->getConfiguration('view::css'); |
293
|
|
|
|
294
|
|
|
if ($existingCSS === false) { |
295
|
|
|
$existingCSS = []; |
296
|
|
|
} else { |
297
|
|
|
$existingCSS = (array)$existingCSS; |
298
|
|
|
} |
299
|
|
|
if (empty($sheets)) { |
300
|
|
|
throw new Exception\LookupException('You must provide a valid CSS Resource.'); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
$files = []; |
304
|
|
|
|
305
|
|
|
foreach ($sheets as $file) { |
306
|
|
|
$files[] = $file; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
if ($place === 'prepend') { |
310
|
|
|
$existingCSS = array_merge($files, $existingCSS); |
311
|
|
|
} else { |
312
|
|
|
$existingCSS = array_merge($existingCSS, $files); |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
$app = App::getInstance(); |
316
|
|
|
$app->setConfiguration('view::css', (object)$existingCSS); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
View Code Duplication |
public function addJS($scripts = [], $place = 'append') |
|
|
|
|
320
|
|
|
{ |
321
|
|
|
|
322
|
|
|
$app = App::getInstance(); |
323
|
|
|
$existingJS = $app->getConfiguration('view::js'); |
324
|
|
|
|
325
|
|
|
if ($existingJS === false) { |
326
|
|
|
$existingJS = []; |
327
|
|
|
} else { |
328
|
|
|
$existingJS = (array)$existingJS; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
if (!empty($scripts)) { |
332
|
|
|
$files = []; |
333
|
|
|
|
334
|
|
|
foreach ($scripts as $file) { |
335
|
|
|
$files[] = $file; |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
if ($place === 'prepend') { |
339
|
|
|
$existingJS = array_merge($files, $existingJS); |
340
|
|
|
} else { |
341
|
|
|
$existingJS = array_merge($existingJS, $files); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
$app = App::getInstance(); |
345
|
|
|
$app->setConfiguration('view::js', (object)$existingJS); |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* Set 404 header, and return 404 view contents |
351
|
|
|
* |
352
|
|
|
* @access public |
353
|
|
|
* @param $data array |
354
|
|
|
* @return string |
355
|
|
|
*/ |
356
|
|
|
public function render404($data = []) |
357
|
|
|
{ |
358
|
|
|
header('HTTP/1.1 404 Not Found'); |
359
|
|
|
$this->setProperty($data); |
360
|
|
|
$this->setLayout('404'); |
361
|
|
|
return $this->render(); |
362
|
|
|
} |
363
|
|
|
} |
364
|
|
|
|
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.