Passed
Push — master ( 2e24e3...16e45e )
by Oleg
03:51
created

View::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php /** MicroView */
2
3
namespace Micro\Mvc\Views;
4
5
use Micro\Base\Exception;
6
use Micro\Base\IContainer;
7
use Micro\Mvc\Module;
8
use Micro\Web\Html;
9
10
/**
11
 * Class View
12
 *
13
 * @author Oleg Lunegov <[email protected]>
14
 * @link https://github.com/lugnsk/micro
15
 * @copyright Copyright &copy; 2013 Oleg Lunegov
16
 * @license /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
    /** @var IContainer $container */
35
    public $container;
36
37
    /**
38
     * @param IContainer $container
39
     */
40
    public function __construct(IContainer $container)
41
    {
42
        $this->container = $container;
43
    }
44
45
    /**
46
     * @inheritdoc
47
     */
48
    public function addParameter($name, $value)
49
    {
50
        $this->params[$name] = $value;
51
    }
52
53
    /**
54
     * @inheritdoc
55
     */
56
    public function widget($name, array $options = [], $capture = false)
57
    {
58
        if (!class_exists($name)) {
59
            throw new Exception('Widget ' . $name . ' not found.');
60
        }
61
62
        $options = array_merge($options, ['container' => $this->container]);
63
64
        /** @var \Micro\mvc\Widget $widget widget */
65
        $widget = new $name($options);
66
        $widget->init();
67
68
        if ($capture) {
69
            ob_start();
70
            $widget->run();
71
            $result = ob_get_clean();
72
        } else {
73
            $result = $widget->run();
74
        }
75
76 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...
77
            $result->asWidget = true;
78
            $result->path = get_class($widget);
79
80
            $result = $result->render();
81
        }
82
83
        unset($widget);
84
85
        if ($capture) {
86
            return $result;
87
        }
88
89
        echo $result;
90
91
        return '';
92
    }
93
94
    /**
95
     * @inheritdoc
96
     */
97
    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...
98
    {
99
        if (!class_exists($name)) {
100
            throw new Exception('Widget ' . $name . ' not found.');
101
        }
102
103 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...
104
            throw new Exception('This widget (' . $name . ') already started!');
105
        }
106
107
        $options = array_merge($options, ['container' => $this->container]);
108
109
        $GLOBALS['widgetStack'][$name] = new $name($options, $this->container);
110
111
        /** @noinspection PhpUndefinedMethodInspection */
112
113
        return $GLOBALS['widgetStack'][$name]->init();
114
    }
115
116
    /**
117
     * @inheritdoc
118
     */
119
    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...
120
    {
121
        if (!$name && $GLOBALS['widgetStack']) {
122
            $widget = array_pop($GLOBALS['widgetStack']);
123
            $v = $widget->run();
124
125 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...
126
                $v->asWidget = true;
127
                $v->path = get_class($widget);
128
129
                $v = $v->render();
130
            }
131
132
            unset($widget);
133
            echo $v;
134
        }
135
136 View Code Duplication
        if (!class_exists($name) || 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...
137
            throw new Exception('Widget ' . $name . ' not started.');
138
        }
139
140
        /** @var \Micro\mvc\Widget $widget widget */
141
        $widget = $GLOBALS['widgetStack'][$name];
142
        unset($GLOBALS['widgetStack'][$name]);
143
144
        $v = $widget->run();
145
146 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...
147
            $v->asWidget = true;
148
            $v->path = get_class($widget);
149
150
            $v = $v->render();
151
        }
152
153
        unset($widget);
154
        echo $v;
155
    }
156
157
    /**
158
     * @inheritdoc
159
     */
160
    public function registerScript($source, $isHead = true)
161
    {
162
        $this->styleScripts[] = [
163
            'isHead' => $isHead,
164
            'body' => Html::script($source)
165
        ];
166
    }
167
168
    /**
169
     * @inheritdoc
170
     */
171
    public function registerScriptFile($source, $isHead = true)
172
    {
173
        $this->styleScripts[] = [
174
            'isHead' => $isHead,
175
            'body' => Html::scriptFile($source)
176
        ];
177
    }
178
179
    /**
180
     * @inheritdoc
181
     */
182
    public function registerCss($source, $isHead = true)
183
    {
184
        $this->styleScripts[] = [
185
            'isHead' => $isHead,
186
            'body' => Html::css($source)
187
        ];
188
    }
189
190
    /**
191
     * @inheritdoc
192
     */
193
    public function registerCssFile($source, $isHead = true)
194
    {
195
        $this->styleScripts[] = [
196
            'isHead' => $isHead,
197
            'body' => Html::cssFile($source)
198
        ];
199
    }
200
201
    /**
202
     * Insert styles and scripts into cache
203
     *
204
     * @access protected
205
     *
206
     * @param string $cache cache of generated page
207
     *
208
     * @return string
209
     */
210
    protected function insertStyleScripts($cache)
211
    {
212
        $heads = '';
213
        $ends = '';
214
        $result = '';
215
216
        foreach ($this->styleScripts AS $element) {
217
            if ($element['isHead']) {
218
                $heads .= $element['body'];
219
            } else {
220
                $ends .= $element['body'];
221
            }
222
        }
223
224
        $positionHead = strpos($cache, Html::closeTag('head'));
225
        $positionBody = strpos($cache, Html::closeTag('body'), $positionHead);
226
227
        $result .= substr($cache, 0, $positionHead);
228
        $result .= $heads;
229
        $result .= substr($cache, $positionHead, $positionBody);
230
        $result .= $ends;
231
        $result .= substr($cache, $positionHead + $positionBody);
232
233
        return $result;
234
    }
235
}
236