Completed
Push — master ( a0b6f6...c4f43b )
by Arman
21s queued 17s
created

QtView::getParams()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.7
13
 */
14
15
namespace Quantum\View;
16
17
use Quantum\Libraries\Database\Exceptions\DatabaseException;
18
use Quantum\Libraries\Session\Exceptions\SessionException;
19
use Quantum\Libraries\Config\Exceptions\ConfigException;
20
use Quantum\Libraries\Asset\Exceptions\AssetException;
21
use Quantum\Libraries\ResourceCache\ViewCache;
22
use Quantum\View\Exceptions\ViewException;
23
use Quantum\Libraries\Asset\AssetManager;
24
use Quantum\Di\Exceptions\DiException;
25
use Quantum\Exceptions\BaseException;
26
use Quantum\Renderer\Renderer;
27
use Quantum\Debugger\Debugger;
28
use ReflectionException;
29
use Psr\Log\LogLevel;
30
31
/**
32
 * Class QtView
33
 * @package Quantum\View
34
 */
35
class QtView
36
{
37
38
    /**
39
     * @var Renderer
40
     */
41
    private $renderer;
42
43
    /**
44
     * @var AssetManager
45
     */
46
    private $assetManager;
47
48
    /**
49
     * @var Debugger
50
     */
51
    private $debugger;
52
53
    /**
54
     * @var ViewCache
55
     */
56
    private $viewCache;
57
58
    /**
59
     * Layout file
60
     * @var string
61
     */
62
    private $layoutFile = null;
63
64
    /**
65
     * Rendered view
66
     * @var string
67
     */
68
    private $viewContent;
69
70
    /**
71
     * Assets to be included
72
     * @var array
73
     */
74
    private $assets = [];
75
76
    /**
77
     * View params
78
     * @var array
79
     */
80
    private $params = [];
81
82
    /**
83
     * @param Renderer $renderer
84
     * @param AssetManager $assetManager
85
     * @param Debugger $debugger
86
     * @param ViewCache $viewCache
87
     */
88
    public function __construct(
89
        Renderer $renderer,
90
        AssetManager $assetManager,
91
        Debugger $debugger,
92
        ViewCache $viewCache
93
    )
94
    {
95
        $this->renderer = $renderer;
96
        $this->assetManager = $assetManager;
97
        $this->debugger = $debugger;
98
        $this->viewCache = $viewCache;
99
    }
100
101
    /**
102
     * Sets a layout
103
     * @param string|null $layoutFile
104
     * @param array $assets
105
     */
106
    public function setLayout(?string $layoutFile, array $assets = [])
107
    {
108
        $this->layoutFile = $layoutFile;
109
        $this->assets = $assets;
110
    }
111
112
    /**
113
     * Gets the layout
114
     * @return string|null
115
     */
116
    public function getLayout(): ?string
117
    {
118
        return $this->layoutFile;
119
    }
120
121
    /**
122
     * Sets view parameter
123
     * @param string $key
124
     * @param mixed $value
125
     */
126
    public function setParam(string $key, $value)
127
    {
128
        $this->params[$key] = $value;
129
    }
130
131
    /**
132
     * Gets the view parameter
133
     * @param string $key
134
     * @return mixed|null
135
     */
136
    public function getParam(string $key)
137
    {
138
        return $this->params[$key] ?? null;
139
    }
140
141
    /**
142
     * Sets multiple view parameters
143
     * @param array $params
144
     */
145
    public function setParams(array $params)
146
    {
147
        foreach ($params as $key => $value) {
148
            $this->setParam($key, $value);
149
        }
150
    }
151
152
    /**
153
     * Gets all view parameters
154
     * @return array
155
     */
156
    public function getParams(): array
157
    {
158
        return $this->params;
159
    }
160
161
    /**
162
     * Flushes the view params
163
     */
164
    public function flushParams()
165
    {
166
        $this->params = [];
167
    }
168
169
    /**
170
     * Renders the view.
171
     * @param string $viewFile
172
     * @param array $params
173
     * @return string|null
174
     * @throws AssetException
175
     * @throws BaseException
176
     * @throws ConfigException
177
     * @throws DatabaseException
178
     * @throws DiException
179
     * @throws ReflectionException
180
     * @throws SessionException
181
     * @throws ViewException
182
     */
183
    public function render(string $viewFile, array $params = []): ?string
184
    {
185
        if (!$this->layoutFile) {
186
            throw ViewException::noLayoutSet();
187
        }
188
189
        if (!empty($params)) {
190
            $this->params = array_merge($this->params, $params);
191
        }
192
193
        $this->viewContent = $this->renderFile($viewFile);
194
195
        if (!empty($this->assets)) {
196
            $this->assetManager->register($this->assets);
197
        }
198
199
        if ($this->debugger->isEnabled()) {
200
            $this->updateDebugger($viewFile);
201
        }
202
203
        $layoutContent = $this->renderFile($this->layoutFile);
204
205
        if ($this->viewCache->isEnabled()) {
206
            $layoutContent = $this->viewCache
207
                ->set(route_uri(), $layoutContent)
208
                ->get(route_uri());
209
        }
210
211
        return $layoutContent;
212
    }
213
214
    /**
215
     * Renders partial view.
216
     * @param string $viewFile
217
     * @param array $params
218
     * @return string
219
     */
220
    public function renderPartial(string $viewFile, array $params = []): string
221
    {
222
        if (!empty($params)) {
223
            $this->params = array_merge($this->params, $params);
224
        }
225
226
        return $this->renderFile($viewFile);
227
    }
228
229
    /**
230
     * Gets the rendered view.
231
     * @return string|null
232
     * @throws ViewException
233
     */
234
    public function getView(): ?string
235
    {
236
        if ($this->viewContent === null) {
237
            throw ViewException::viewNotRendered();
238
        }
239
240
        return $this->viewContent;
241
    }
242
243
    /**
244
     * Renders the view
245
     * @param string $viewFile
246
     * @return string
247
     */
248
    private function renderFile(string $viewFile): string
249
    {
250
        $params = $this->xssFilter($this->params);
251
252
        return $this->renderer->render($viewFile, $params);
253
    }
254
255
    /**
256
     * XSS Filter
257
     * @param mixed $params
258
     * @return mixed
259
     */
260
    private function xssFilter($params)
261
    {
262
        if (is_string($params)) {
263
            $this->cleaner($params);
264
            $params = [$params];
265
        } else {
266
            array_walk_recursive($params, [$this, 'cleaner']);
267
        }
268
269
        return $params;
270
    }
271
272
    /**
273
     * Cleaner
274
     * @param mixed $value
275
     */
276
    private function cleaner(&$value)
277
    {
278
        if (is_object($value)) {
279
            $this->xssFilter($value);
280
        } else {
281
            $value = htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8');
282
        }
283
    }
284
285
    /**
286
     * @param Debugger $debugger
287
     * @param string $viewFile
288
     * @return void
289
     */
290
    private function updateDebugger(string $viewFile)
291
    {
292
        $routesCell = $this->debugger->getStoreCell(Debugger::ROUTES);
293
        $currentData = current($routesCell)[LogLevel::INFO] ?? [];
294
        $additionalData = ['View' => current_module() . '/Views/' . $viewFile];
295
        $mergedData = array_merge($currentData, $additionalData);
296
        $this->debugger->clearStoreCell(Debugger::ROUTES);
297
        $this->debugger->addToStoreCell(Debugger::ROUTES, LogLevel::INFO, $mergedData);
298
    }
299
}