View::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
eloc 1
nc 1
nop 0
1
<?php /** MicroView */
2
3
namespace Micro\Mvc\Views;
4
5
use Micro\Base\Exception;
6
use Micro\Mvc\Module;
7
use Micro\Mvc\Widget;
8
use Micro\Web\Html\Html;
9
10
/**
11
 * Class View
12
 *
13
 * @author Oleg Lunegov <[email protected]>
14
 * @link https://github.com/linpax/microphp-framework
15
 * @copyright Copyright (c) 2013 Oleg Lunegov
16
 * @license https://github.com/linpax/microphp-framework/blob/master/LICENSE
17
 * @package Micro
18
 * @subpackage Mvc/Views
19
 * @version 1.0
20
 * @since 1.0
21
 */
22
abstract class View implements IView
23
{
24
    /** @var array $styleScripts */
25
    public $styleScripts = [];
26
    /** @var bool $asWidget */
27
    public $asWidget = false;
28
    /** @var array $params */
29
    public $params = [];
30
    /** @var array $stack */
31
    public $stack = [];
32
    /** @var Module $module */
33
    public $module;
34
35
36
    /**
37
     * @access public
38
     * @result void
39
     */
40
    public function __construct()
41
    {
42
    }
43
44
    /**
45
     * Add parameter into view
46
     *
47
     * @access public
48
     *
49
     * @param string $name parameter name
50
     * @param mixed $value parameter value
51
     *
52
     * @return void
53
     */
54
    public function addParameter($name, $value)
55
    {
56
        $this->params[$name] = $value;
57
    }
58
59
    /**
60
     * Widget
61
     *
62
     * @access public
63
     *
64
     * @param string $name widget name
65
     * @param array $options options array
66
     * @param bool $capture capture output
67
     *
68
     * @return string
69
     * @throws Exception
70
     */
71
    public function widget($name, array $options = [], $capture = false)
72
    {
73
        if (!class_exists($name)) {
74
            throw new Exception('Widget '.$name.' not found.');
75
        }
76
77
        /** @var \Micro\mvc\Widget $widget widget */
78
        $widget = new $name($options);
79
        $widget->init();
80
81
        if ($capture) {
82
            ob_start();
83
            $widget->run();
84
            $result = ob_get_clean();
85
        } else {
86
            $result = $widget->run();
87
        }
88
89 View Code Duplication
        if ($result instanceof PhpView) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
90
            $result->asWidget = true;
91
            $result->path = get_class($widget);
92
93
            $result = $result->render();
94
        }
95
96
        unset($widget);
97
98
        if ($capture) {
99
            return $result;
100
        }
101
102
        echo $result;
103
104
        return '';
105
    }
106
107
    /**
108
     * Begin widget
109
     *
110
     * @access public
111
     *
112
     * @param string $name widget name
113
     * @param array $options options array
114
     *
115
     * @return mixed
116
     * @throws Exception
117
     */
118
    public function beginWidget($name, array $options = [])
0 ignored issues
show
Coding Style introduced by
beginWidget uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
119
    {
120
        if (!class_exists($name)) {
121
            throw new Exception('Widget `'.$name.'` not found.');
122
        }
123
124 View Code Duplication
        if (!empty($GLOBALS['widgetStack'][$name])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
125
            throw new Exception('This widget `'.$name.'` already started!');
126
        }
127
128
        $GLOBALS['widgetStack'][$name] = new $name($options);
129
130
        /** @noinspection PhpUndefinedMethodInspection */
131
132
        return $GLOBALS['widgetStack'][$name]->init();
133
    }
134
135
    /**
136
     * Ending widget
137
     *
138
     * @access public
139
     *
140
     * @param string $name widget name
141
     *
142
     * @throws Exception
143
     */
144
    public function endWidget($name = '')
0 ignored issues
show
Coding Style introduced by
endWidget uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
145
    {
146
        if (!$name && $GLOBALS['widgetStack']) {
147
            /** @var Widget $widget */
148
            $widget = array_pop($GLOBALS['widgetStack']);
149
            $v = $widget->run();
150
151 View Code Duplication
            if ($v instanceof PhpView) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
152
                $v->asWidget = true;
153
                $v->path = get_class($widget);
154
155
                $v = $v->render();
156
            }
157
158
            unset($widget);
159
            echo $v;
160
        }
161
162
        if (empty($GLOBALS['widgetStack'][$name]) && !class_exists($name)) {
163
            throw new Exception('Widget `'.$name.'` not started.');
164
        }
165
166
        /** @var \Micro\mvc\Widget $widget widget */
167
        $widget = $GLOBALS['widgetStack'][$name];
168
        unset($GLOBALS['widgetStack'][$name]);
169
170
        $v = $widget->run();
171
172 View Code Duplication
        if ($v instanceof PhpView) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
173
            $v->asWidget = true;
174
            $v->path = get_class($widget);
175
176
            $v = $v->render();
177
        }
178
179
        unset($widget);
180
        echo $v;
181
    }
182
183
    /**
184
     * Register JS script
185
     *
186
     * @access public
187
     *
188
     * @param string $source file name
189
     * @param bool $isHead is head block
190
     *
191
     * @return void
192
     */
193
    public function registerScript($source, $isHead = true)
194
    {
195
        $this->styleScripts[] = [
196
            'isHead' => $isHead,
197
            'body' => Html::script($source)
198
        ];
199
    }
200
201
    /**
202
     * Register JS file
203
     *
204
     * @access public
205
     *
206
     * @param string $source file name
207
     * @param bool $isHead is head block
208
     *
209
     * @return void
210
     */
211
    public function registerScriptFile($source, $isHead = true)
212
    {
213
        $this->styleScripts[] = [
214
            'isHead' => $isHead,
215
            'body' => Html::scriptFile($source)
216
        ];
217
    }
218
219
    /**
220
     * Register CSS code
221
     *
222
     * @access public
223
     *
224
     * @param string $source file name
225
     * @param bool $isHead is head block
226
     *
227
     * @return void
228
     */
229
    public function registerCss($source, $isHead = true)
230
    {
231
        $this->styleScripts[] = [
232
            'isHead' => $isHead,
233
            'body' => Html::css($source)
234
        ];
235
    }
236
237
    /**
238
     * Register CSS file
239
     *
240
     * @access public
241
     *
242
     * @param string $source file name
243
     * @param bool $isHead is head block
244
     *
245
     * @return void
246
     */
247
    public function registerCssFile($source, $isHead = true)
248
    {
249
        $this->styleScripts[] = [
250
            'isHead' => $isHead,
251
            'body' => Html::cssFile($source)
252
        ];
253
    }
254
255
    /**
256
     * Insert styles and scripts into cache
257
     *
258
     * @access protected
259
     *
260
     * @param string $cache cache of generated page
261
     *
262
     * @return string
263
     */
264
    protected function insertStyleScripts($cache)
265
    {
266
        $heads = '';
267
        $ends = '';
268
        $result = '';
269
270
        foreach ($this->styleScripts AS $element) {
271
            if ($element['isHead']) {
272
                $heads .= $element['body'];
273
            } else {
274
                $ends .= $element['body'];
275
            }
276
        }
277
278
        $positionHead = strpos($cache, Html::closeTag('head'));
279
        $positionBody = strpos($cache, Html::closeTag('body'), $positionHead);
280
281
        $result .= substr($cache, 0, $positionHead);
282
        $result .= $heads;
283
        $result .= substr($cache, $positionHead, $positionBody);
284
        $result .= $ends;
285
        $result .= substr($cache, $positionHead + $positionBody);
286
287
        return $result;
288
    }
289
}
290