Completed
Pull Request — master (#83)
by
unknown
11:18
created

View::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
crap 1
1
<?php
2
namespace Zewa;
3
4
use Zewa\Interfaces\ContainerInterface;
5
6
/**
7
 * View management
8
 *
9
 * @author Zechariah Walden<zech @ zewadesign.com>
10
 */
11
class View
12
{
13
    /**
14
     * Active layout for view
15
     *
16
     * @var string|bool
17
     */
18
    protected $layout;
19
20
    /**
21
     * Active module for view
22
     *
23
     * @var string|bool
24
     */
25
    protected $module = false;
26
27
    /**
28
     * Rendered view content
29
     *
30
     * @var string
31
     */
32
    protected $view = false;
33
34
    /**
35
     * Data object for view
36
     *
37
     * @var object
38
     */
39
    protected $properties;
40
41
    /**
42
     * \Zewa\Config reference
43
     *
44
     * @var Config
45
     */
46
    protected $configuration;
47
48
    /**
49
     * \Zewa\Router reference
50
     *
51
     * @var Router
52
     */
53
    protected $router;
54
55
    /**
56
     * \Zewa\Router reference
57
     *
58
     * @var Router
59
     */
60
    protected $request;
61
62
    /**
63
     * @var array
64
     */
65
    private $queuedJS = [];
66
67
    /**
68
     * @var array
69
     */
70
    private $queuedCSS = [];
71
72
    /**
73
     * Load up some basic configuration settings.
74
     */
75 18
    public function __construct(Config $config, Router $router, Request $request)
76
    {
77 18
        $this->configuration = $config;
78 18
        $this->router = $router;
79 18
        $this->request = $request;
0 ignored issues
show
Documentation Bug introduced by
It seems like $request of type object<Zewa\Request> is incompatible with the declared type object<Zewa\Router> of property $request.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
80 18
    }
81
82
    /**
83
     * Returns base URL for app
84
     * @return string
85
     */
86
    private function baseURL($path = '')
87
    {
88
        return $this->router->baseURL($path);
89
    }
90
91
    /**
92
     * Returns the current request URL
93
     * @return string
94
     */
95
    private function currentURL($params = false)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
96
    {
97
        return $this->router->currentURL($params);
98
    }
99
100
    /**
101
     * Returns uri string
102
     * @return string
103
     */
104
    private function currentURI()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
105
    {
106
        return $this->router->uri;
107
    }
108
109
    /*
110
     * @todo create method for returning
111
     * a valid json string with header..
112
     * view shouldn't set header logic,
113
     * and the framework doesn't care what returns the string
114
     * ..but view should handle the json_encode...
115
     * seems overkill to call header() with returning a $view->json;
116
     * thoughts?*/
117
118
    /**
119
     * Loads a view
120
     *
121
     * @access public
122
     * @param string|bool $view view to load
123
     * @param string|bool $layout
124
     * @return string
125
     */
126
    public function render($view = false, $layout = false)
127
    {
128
        if ($layout !== false) {
129
            $this->setLayout($layout);
130
        }
131
132
        if ($view !== false) {
133
            $view = $this->prepareView($view);
134
135
            $this->view = $return = $this->process($view);
136
137
            if (! is_null($this->layout)) {
138
                $return = $this->process($this->layout);
139
            }
140
141
            return $return;
142
        } else {
143
            if ($this->view !== false) {
144
                $this->view = $this->process($this->view);
145
            }
146
147
            if (! is_null($this->layout)) {
148
                return $this->process($this->layout);
149
            } else {
150
                return $this->view;
151
            }
152
        }
153
    }
154
155
    /**
156
     * formats and prepares view for inclusion
157
     * @param $viewName
158
     * @return string
159
     * @throws Exception\LookupException
160
     */
161
    private function prepareView($viewName)
162
    {
163
        if ($this->module === false) {
164
            $this->setModule();
165
        }
166
167
        $view = APP_PATH
168
            . DIRECTORY_SEPARATOR
169
            . 'Modules'
170
            . DIRECTORY_SEPARATOR
171
            . $this->module
172
            . DIRECTORY_SEPARATOR
173
            . 'Views'
174
            . DIRECTORY_SEPARATOR
175
            . strtolower($viewName)
176
            . '.php';
177
178
        if (!file_exists($view)) {
179
            throw new Exception\LookupException('View: "' . $view . '" could not be found.');
180
        }
181
182
        return $view;
183
    }
184
185
    public function setView($viewName, $layout = false)
186
    {
187
        if ($layout !== false) {
188
            $this->setLayout($layout);
189
        }
190
        $this->view = $this->prepareView($viewName);
191
    }
192
193
    public function setProperty($property, $value = false)
194
    {
195
        if ($value !== false) {
196
            $this->properties[$property] = $value;
197
        } elseif (!empty($property)) {
198
            $this->properties = $property;
199
        }
200
        return false;
201
    }
202
203
    public function setLayout($layout)
204
    {
205
        if ($layout === false) {
206
            $this->layout = null;
207
        } else {
208
            $layout = APP_PATH . DIRECTORY_SEPARATOR . 'Layouts' . DIRECTORY_SEPARATOR . strtolower($layout) . '.php';
209
210
            if (!file_exists($layout)) {
211
                throw new Exception\LookupException('Layout: "' . $layout . '" could not be found.');
212
            }
213
214
            $this->layout = $layout;
215
216
            return true;
217
        }
218
    }
219
220
    /**
221
     * Set the module for view look
222
     *
223
     * @access public
224
     * @param string|bool $module module to override
225
     */
226
    public function setModule($module = false)
227
    {
228
        if ($module === false) {
229
            $routerConfig = $this->router->getConfig()->get('Routing');
230
            $this->module = $routerConfig->module;
231
        } else {
232
            $this->module = ucfirst($module);
233
        }
234
    }
235
236
    /**
237
     * Processes view/layouts and exposes variables to the view/layout
238
     *
239
     * @access private
240
     * @param string $file file being rendered
241
     * @return string processed content
242
     */
243
    //@TODO: come back and clean up this and the way the view receives stuff
244
    private function process($file)
245
    {
246
        ob_start();
247
248
        if (is_array($this->properties)) {
249
            extract($this->properties); // yuck. could produce undeclared errors. hmm..
250
        }
251
        //should i set $this->data in abstract controller, and provide all access vars ? seems bad practice..
252
253
        include $file;
254
255
        $return = ob_get_contents();
256
257
        ob_end_clean();
258
259
        return $return;
260
    }
261
262
    /**
263
     * Helper method for grabbing aggregated css files
264
     *
265
     * @access protected
266
     * @return string css includes
267
     */
268
    protected function fetchCSS()
269
    {
270
        $string = "";
271
272
        if (empty($this->queuedCSS)) {
273
            return $string;
274
        }
275
276
        foreach ($this->queuedCSS as $sheet) {
277
            $string .= '<link rel="stylesheet" href="' . $sheet .'">' . "\r\n";
278
        }
279
280
        return $string;
281
    }
282
283
    /**
284
     * Helper method for grabbing aggregated JS files
285
     *
286
     * @access protected
287
     * @return string JS includes
288
     */
289
    protected function fetchJS()
290
    {
291
        $string = "<script>baseURL = '" . $this->baseURL() . "/'</script>\r\n";
292
293
        if (empty($this->queuedJS)) {
294
            return $string;
295
        }
296
297
        foreach ($this->queuedJS as $script) {
298
            $string .= '<script src="' . $script . '"></script>' . "\r\n";
299
        }
300
301
        return $string;
302
    }
303
304
    /**
305
     * Helper method for adding css files for aggregation/render
306
     *
307
     * @access public
308
     * @param $files array
309
     * @param $place string
310
     * @return string css includes
311
     * @throws Exception\LookupException
312
     */
313 View Code Duplication
    public function addCSS($files = [], $place = 'append')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
314
    {
315
        if ($place === 'append') {
316
            $this->queuedCSS = array_merge($files, $this->queuedCSS);
317
        } else {
318
            $this->queuedCSS = array_merge($this->queuedCSS, $files);
319
        }
320
    }
321
322 View Code Duplication
    public function addJS($files = [], $place = 'append')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
323
    {
324
        if ($place === 'append') {
325
            $this->queuedJS = array_merge($files, $this->queuedJS);
326
        } else {
327
            $this->queuedJS = array_merge($this->queuedJS, $files);
328
        }
329
    }
330
331
    /**
332
     * Set 404 header, and return 404 view contents
333
     *
334
     * @access public
335
     * @param  $data array
336
     * @return string
337
     */
338
    public function render404($data = [])
339
    {
340
        header('HTTP/1.1 404 Not Found');
341
        $this->setProperty($data);
342
        $this->setLayout('404');
343
        return $this->render();
344
    }
345
}
346