Passed
Push — master ( 598f6d...882e76 )
by Thierry
02:48
created

ViewRenderer::setDefaultRenderer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 3
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace Jaxon\App\View;
4
5
use Jaxon\Di\Container;
6
use Jaxon\Utils\Config\Config;
7
8
use Closure;
9
10
use function array_filter;
11
use function array_merge;
12
use function is_array;
13
use function rtrim;
14
use function strrpos;
15
use function substr;
16
17
class ViewRenderer
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class ViewRenderer
Loading history...
18
{
19
    /**
20
     * @var Container
21
     */
22
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
23
24
    /**
25
     * The view namespaces
26
     *
27
     * @var array
28
     */
29
    protected $aNamespaces = [];
30
31
    /**
32
     * The view data store
33
     *
34
     * @var Store
35
     */
36
    protected $xStore = null;
37
38
    /**
39
     * The default namespace
40
     *
41
     * @var string
42
     */
43
    protected $sDefaultNamespace = 'jaxon';
44
45
    /**
46
     * The view global data
47
     *
48
     * @var array
49
     */
50
    protected $aViewData = [];
51
52
    /**
53
     * The class constructor
54
     *
55
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
56
     */
57
    public function __construct(Container $di)
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
58
    {
59
        $this->di = $di;
60
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
61
62
    /**
63
     * Add a view namespace, and set the corresponding renderer.
64
     *
65
     * @param string $sNamespace    The namespace name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
66
     * @param string $sDirectory    The namespace directory
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
67
     * @param string $sExtension    The extension to append to template names
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
68
     * @param string $sRenderer    The corresponding renderer name
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
69
     *
70
     * @return void
71
     */
72
    public function addNamespace(string $sNamespace, string $sDirectory, string $sExtension, string $sRenderer)
73
    {
74
        $aNamespace = [
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 21 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
75
            'directory' => $sDirectory,
76
            'extension' => $sExtension,
77
            'renderer' => $sRenderer,
78
        ];
79
        $this->aNamespaces[$sNamespace] = $aNamespace;
80
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
81
82
    /**
83
     * Set the view namespaces.
84
     *
85
     * @param Config $xAppConfig    The config options provided in the library
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
86
     * @param Config|null $xUserConfig    The config options provided in the app section of the global config file.
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
87
     *
88
     * @return void
89
     */
90
    public function addNamespaces(Config $xAppConfig, ?Config $xUserConfig = null)
91
    {
92
        if(empty($aNamespaces = $xAppConfig->getOptionNames('views')))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
93
        {
94
            return;
95
        }
96
        $sPackage = $xAppConfig->getOption('package', '');
97
        foreach($aNamespaces as $sNamespace => $sOption)
98
        {
99
            // Save the namespace
100
            $aNamespace = $xAppConfig->getOption($sOption);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 12 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
101
            $aNamespace['package'] = $sPackage;
102
            if(!isset($aNamespace['renderer']))
103
            {
104
                $aNamespace['renderer'] = 'jaxon'; // 'jaxon' is the default renderer.
105
            }
106
107
            // If the lib config has defined a template option, then its value must be
108
            // read from the app config.
109
            if($xUserConfig !== null && isset($aNamespace['template']) && is_array($aNamespace['template']))
110
            {
111
                $sTemplateOption = $xAppConfig->getOption($sOption . '.template.option');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
112
                $sTemplateDefault = $xAppConfig->getOption($sOption . '.template.default');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
113
                $sTemplate = $xUserConfig->getOption($sTemplateOption, $sTemplateDefault);
0 ignored issues
show
Bug introduced by
It seems like $sTemplateOption can also be of type null; however, parameter $sName of Jaxon\Utils\Config\Config::getOption() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
                $sTemplate = $xUserConfig->getOption(/** @scrutinizer ignore-type */ $sTemplateOption, $sTemplateDefault);
Loading history...
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 15 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
114
                $aNamespace['directory'] = rtrim($aNamespace['directory'], '/') . '/' . $sTemplate;
115
            }
116
117
            $this->aNamespaces[$sNamespace] = $aNamespace;
118
        }
119
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
120
121
    /**
122
     * Get the view renderer
123
     *
124
     * @param string $sId    The unique identifier of the view renderer
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
125
     *
126
     * @return ViewInterface
127
     */
128
    public function getRenderer(string $sId): ViewInterface
129
    {
130
        // Return the view renderer with the given id
131
        return $this->di->g('jaxon.app.view.' . $sId);
132
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
133
134
    /**
135
     * Add a view renderer with an id
136
     *
137
     * @param string $sId    The unique identifier of the view renderer
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter name; 4 found
Loading history...
138
     * @param Closure $xClosure    A closure to create the view instance
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
139
     *
140
     * @return void
141
     */
142
    public function addRenderer(string $sId, Closure $xClosure)
143
    {
144
        // Return the initialized view renderer
145
        $this->di->set('jaxon.app.view.' . $sId, function($di) use ($sId, $xClosure) {
146
            // Get the defined renderer
147
            $xRenderer = $xClosure($di);
148
            // Init the renderer with the template namespaces
149
            $aNamespaces = array_filter($this->aNamespaces, function($aNamespace) use($sId) {
150
                return $aNamespace['renderer'] === $sId;
151
            });
152
            foreach($aNamespaces as $sNamespace => $aNamespace)
153
            {
154
                $xRenderer->addNamespace($sNamespace, $aNamespace['directory'], $aNamespace['extension']);
155
            }
156
            return $xRenderer;
157
        });
158
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
159
160
    /**
161
     * Add a view renderer with an id
162
     *
163
     * @param string $sId    The unique identifier of the view renderer
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter name; 4 found
Loading history...
164
     * @param string $sExtension    The extension to append to template names
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
165
     * @param Closure $xClosure    A closure to create the view instance
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 4 found
Loading history...
166
     *
167
     * @return void
168
     */
169
    public function setDefaultRenderer(string $sId, string $sExtension, Closure $xClosure)
170
    {
171
        $this->setDefaultNamespace($sId);
172
        $this->addNamespace($sId, '', $sExtension, $sId);
173
        $this->addRenderer($sId, $xClosure);
174
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
175
176
    /**
177
     * Get the view renderer for a given namespace
178
     *
179
     * @param string $sNamespace    The namespace name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
180
     *
181
     * @return ViewInterface|null
182
     */
183
    public function getNamespaceRenderer(string $sNamespace): ?ViewInterface
184
    {
185
        if(!isset($this->aNamespaces[$sNamespace]))
186
        {
187
            return null;
188
        }
189
        // Return the view renderer with the configured id
190
        return $this->getRenderer($this->aNamespaces[$sNamespace]['renderer']);
191
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
192
193
    /**
194
     * Set the default namespace
195
     *
196
     * @param string $sDefaultNamespace
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
197
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
198
    public function setDefaultNamespace(string $sDefaultNamespace): void
199
    {
200
        $this->sDefaultNamespace = $sDefaultNamespace;
201
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
202
203
    /**
204
     * Get the current store or create a new store
205
     *
206
     * @return Store
207
     */
208
    protected function store(): Store
209
    {
210
        if(!$this->xStore)
211
        {
212
            $this->xStore = new Store();
213
        }
214
        return $this->xStore;
215
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
216
217
    /**
218
     * Make a piece of data available for the rendered view
219
     *
220
     * @param string $sName    The data name
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
221
     * @param mixed $xValue    The data value
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
222
     *
223
     * @return ViewRenderer
224
     */
225
    public function set(string $sName, $xValue): ViewRenderer
226
    {
227
        $this->store()->with($sName, $xValue);
228
        return $this;
229
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
230
231
    /**
232
     * Make a piece of data available for all views
233
     *
234
     * @param string $sName    The data name
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
235
     * @param mixed $xValue    The data value
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
236
     *
237
     * @return ViewRenderer
238
     */
239
    public function share(string $sName, $xValue): ViewRenderer
240
    {
241
        $this->aViewData[$sName] = $xValue;
242
        return $this;
243
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
244
245
    /**
246
     * Make an array of data available for all views
247
     *
248
     * @param array $aValues    The data values
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
249
     *
250
     * @return ViewRenderer
251
     */
252
    public function shareValues(array $aValues): ViewRenderer
253
    {
254
        foreach($aValues as $sName => $xValue)
255
        {
256
            $this->share($sName, $xValue);
257
        }
258
        return $this;
259
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
260
261
    /**
262
     * Render a view using a store
263
     *
264
     * The store returned by this function will later be used with the make() method to render the view.
265
     *
266
     * @param string $sViewName    The view name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
267
     * @param array $aViewData    The view data
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
268
     *
269
     * @return null|Store   A store populated with the view data
270
     */
271
    public function render(string $sViewName, array $aViewData = []): ?Store
272
    {
273
        $xStore = $this->store();
274
        // Get the default view namespace
275
        $sNamespace = $this->sDefaultNamespace;
276
        // Get the namespace from the view name
277
        $nSeparatorPosition = strrpos($sViewName, '::');
278
        if($nSeparatorPosition !== false)
279
        {
280
            $sNamespace = substr($sViewName, 0, $nSeparatorPosition);
281
        }
282
        $xRenderer = $this->getNamespaceRenderer($sNamespace);
283
        if(!$xRenderer)
284
        {
285
            // Cannot render a view if there's no renderer corresponding to the namespace.
286
            return null;
287
        }
288
        $xStore->setData(array_merge($this->aViewData, $aViewData))->setView($xRenderer, $sNamespace, $sViewName);
289
        // Set the store to null so a new store will be created for the next view.
290
        $this->xStore = null;
291
        // Return the store
292
        return $xStore;
293
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
294
}
295