GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( cf9260...b52382 )
by
unknown
03:19
created

View::getFilePath()   B

Complexity

Conditions 8
Paths 10

Size

Total Lines 51
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 28
nc 10
nop 1
dl 0
loc 51
rs 8.4444
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Framework\Http;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Framework\Containers\Modules\DataStructures\Module\Theme;
19
use O2System\Framework\Http\Presenter\Meta;
20
use O2System\Gear\Toolbar;
21
use O2System\Html;
22
use O2System\Psr\Patterns\Structural\Composite\RenderableInterface;
23
use O2System\Spl\DataStructures\SplArrayObject;
24
use O2System\Spl\Exceptions\ErrorException;
25
use O2System\Spl\Traits\Collectors\FileExtensionCollectorTrait;
26
use O2System\Spl\Traits\Collectors\FilePathCollectorTrait;
27
28
/**
29
 * Class View
30
 *
31
 * @package O2System
32
 */
33
class View implements RenderableInterface
34
{
35
    use FilePathCollectorTrait;
36
    use FileExtensionCollectorTrait;
37
38
    /**
39
     * View Config
40
     *
41
     * @var \O2System\Kernel\DataStructures\Config
42
     */
43
    protected $config;
44
45
    /**
46
     * View HTML Document
47
     *
48
     * @var Html\Document
49
     */
50
    protected $document;
51
52
    // ------------------------------------------------------------------------
53
54
    /**
55
     * View::__construct
56
     *
57
     * @return View
58
     */
59
    public function __construct()
60
    {
61
        $this->setFileDirName('views');
62
        $this->addFilePath(PATH_RESOURCES);
63
64
        output()->addFilePath(PATH_RESOURCES);
65
66
        $this->config = config()->loadFile('view', true);
0 ignored issues
show
Bug introduced by
The method loadFile() does not exist on O2System\Kernel\Datastructures\Config. ( Ignorable by Annotation )

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

66
        $this->config = config()->/** @scrutinizer ignore-call */ loadFile('view', true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Documentation Bug introduced by
It seems like config()->loadFile('view', true) can also be of type false. However, the property $config is declared as type O2System\Kernel\DataStructures\Config. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
67
68
        $this->setFileExtensions(
69
            [
70
                '.php',
71
                '.phtml',
72
            ]
73
        );
74
75
        if ($this->config->offsetExists('extensions')) {
76
            $this->setFileExtensions($this->config[ 'extensions' ]);
77
        }
78
79
        $this->document = new Html\Document();
80
        $this->document->formatOutput = (bool)$this->config->beautify;
81
    }
82
83
    /**
84
     * View::__get
85
     *
86
     * @param string $property
87
     *
88
     * @return bool Returns FALSE when property is not set.
89
     */
90
    public function &__get($property)
91
    {
92
        $get[ $property ] = false;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$get was never initialized. Although not strictly required by PHP, it is generally a good practice to add $get = array(); before regardless.
Loading history...
93
94
        if (property_exists($this, $property)) {
95
            return $this->{$property};
96
        }
97
98
        return $get[ $property ];
99
    }
100
101
    // ------------------------------------------------------------------------
102
103
    /**
104
     * View::parse
105
     *
106
     * @param string $string
107
     * @param array  $vars
108
     *
109
     * @return bool|string Returns FALSE if failed.
110
     */
111
    public function parse($string, array $vars = [])
112
    {
113
        parser()->loadString($string);
114
115
        return parser()->parse($vars);
116
    }
117
118
    // ------------------------------------------------------------------------
119
120
    /**
121
     * View::with
122
     *
123
     * @param mixed $vars
124
     * @param mixed $value
125
     *
126
     * @return static
127
     */
128
    public function with($vars, $value = null)
129
    {
130
        if (is_string($vars)) {
131
            $vars = [$vars => $value];
132
        }
133
134
        presenter()->merge($vars);
135
136
        return $this;
137
    }
138
139
    // ------------------------------------------------------------------------
140
141
    /**
142
     * View::modal
143
     *
144
     * @param string $filename
145
     * @param array  $vars
146
     */
147
    public function modal($filename, array $vars = [])
148
    {
149
        if (presenter()->theme->hasLayout('modal')) {
150
            if (presenter()->theme->hasLayout('modal')) {
151
                presenter()->theme->setLayout('modal');
152
                echo $this->load($filename, $vars, true);
0 ignored issues
show
Bug introduced by
Are you sure $this->load($filename, $vars, true) of type false|string can be used in echo? ( Ignorable by Annotation )

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

152
                echo /** @scrutinizer ignore-type */ $this->load($filename, $vars, true);
Loading history...
153
                exit(EXIT_SUCCESS);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
154
            }
155
        }
156
157
        if ($content = $this->load($filename, $vars, true)) {
158
            echo $content;
159
            exit(EXIT_SUCCESS);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
160
        }
161
    }
162
163
    // ------------------------------------------------------------------------
164
165
    /**
166
     * View::load
167
     *
168
     * @param string $filename
169
     * @param array  $vars
170
     * @param bool   $return
171
     *
172
     * @return false|string
173
     */
174
    public function load($filename, array $vars = [], $return = false)
175
    {
176
        if ($filename instanceof \SplFileInfo) {
0 ignored issues
show
introduced by
$filename is never a sub-type of SplFileInfo.
Loading history...
177
            return $this->page($filename->getRealPath(), array_merge($vars, $filename->getVars()));
178
        }
179
180
        if (strpos($filename, 'Pages') !== false) {
181
            return $this->page($filename, $vars, $return);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->page($filename, $vars, $return) also could return the type boolean which is incompatible with the documented return type false|string.
Loading history...
182
        }
183
184
        presenter()->merge($vars);
185
186
        if (false !== ($filePath = $this->getFilePath($filename))) {
187
            if ($return === false) {
188
                if (presenter()->partials->hasPartial('content') === false) {
189
                    if(is_ajax()) {
190
                        parser()->loadFile($filePath);
191
                        $content = parser()->parse(presenter()->getArrayCopy());
192
193
                        presenter()->partials->addPartial('content', $content);
194
                    } else {
195
                        presenter()->partials->addPartial('content', $filePath);
196
                    }
197
                } else {
198
                    presenter()->partials->addPartial(pathinfo($filePath, PATHINFO_FILENAME), $filePath);
199
                }
200
            } else {
201
                parser()->loadFile($filePath);
202
203
                return parser()->parse(presenter()->getArrayCopy());
204
            }
205
        } else {
206
            $vars = presenter()->getArrayCopy();
207
            extract($vars);
208
209
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
210
211
            $error = new ErrorException(
212
                'E_VIEW_NOT_FOUND',
213
                0,
214
                @$backtrace[ 0 ][ 'file' ],
215
                @$backtrace[ 0 ][ 'line' ],
216
                [trim($filename)]
217
            );
218
219
            unset($backtrace);
220
221
            ob_start();
222
            include output()->getFilePath('error');
0 ignored issues
show
Bug introduced by
The method getFilePath() does not exist on O2System\Kernel\Cli\Output. Did you maybe mean getFilePaths()? ( Ignorable by Annotation )

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

222
            include output()->/** @scrutinizer ignore-call */ getFilePath('error');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
223
            $content = ob_get_contents();
224
            ob_end_clean();
225
226
            if ($return === false) {
227
                if (presenter()->partials->hasPartial('content') === false) {
228
                    presenter()->addPartial('content', $content);
0 ignored issues
show
Bug introduced by
The method addPartial() does not exist on O2System\Framework\Http\Presenter. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

228
                    presenter()->/** @scrutinizer ignore-call */ addPartial('content', $content);
Loading history...
229
                } else {
230
                    presenter()->addPartial(pathinfo($filePath, PATHINFO_FILENAME), $content);
0 ignored issues
show
Bug introduced by
It seems like $filePath can also be of type false; however, parameter $path of pathinfo() 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

230
                    presenter()->addPartial(pathinfo(/** @scrutinizer ignore-type */ $filePath, PATHINFO_FILENAME), $content);
Loading history...
231
                }
232
            } else {
233
                return $content;
234
            }
235
        }
236
    }
237
238
    // ------------------------------------------------------------------------
239
240
    /**
241
     * View::page
242
     *
243
     * @param string $filename
244
     * @param array  $vars
245
     * @param bool   $return
246
     *
247
     * @return bool|string Returns FALSE if failed.
248
     */
249
    public function page($filename, array $vars = [], $return = false)
250
    {
251
        if ( ! is_file($filename)) {
252
            $pageDirectories = modules()->getResourcesDirs('pages');
0 ignored issues
show
Bug introduced by
The method getResourcesDirs() does not exist on O2System\Framework\Conta...s\DataStructures\Module. Did you maybe mean getResourcesDir()? ( Ignorable by Annotation )

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

252
            $pageDirectories = modules()->/** @scrutinizer ignore-call */ getResourcesDirs('pages');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
253
            foreach ($pageDirectories as $pageDirectory) {
254
                if (is_file($pageFilePath = $pageDirectory . $filename . '.phtml')) {
255
                    $filename = $pageFilePath;
256
                    break;
257
                }
258
            }
259
        }
260
261
        if (count($vars)) {
262
            presenter()->merge($vars);
263
        }
264
265
        presenter()->merge(presenter()->page->getVars());
266
267
        if ($return === false) {
268
            if (presenter()->partials->hasPartial('content') === false) {
269
                presenter()->partials->addPartial('content', $filename);
270
            } else {
271
                presenter()->partials->addPartial(pathinfo($filename, PATHINFO_FILENAME), $filename);
272
            }
273
        } elseif (parser()->loadFile($filename)) {
274
            return parser()->parse(presenter()->getArrayCopy());
275
        }
276
    }
277
278
    // ------------------------------------------------------------------------
279
280
    /**
281
     * View::getFilePath
282
     *
283
     * @param string $filename
284
     *
285
     * @return bool|string
286
     */
287
    public function getFilePath($filename)
288
    {
289
        $filename = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $filename);
290
291
        if (is_file($filename)) {
292
            return realpath($filename);
293
        } else {
294
            $viewsDirectories = array_merge([
295
                PATH_KERNEL . 'Views' . DIRECTORY_SEPARATOR,
296
                PATH_FRAMEWORK . 'Views' . DIRECTORY_SEPARATOR,
297
            ], $this->filePaths);
298
299
            $viewsDirectories = array_unique($viewsDirectories);
300
            $viewsDirectories = array_reverse($viewsDirectories);
301
302
            $controllerSubDir = services('controller')->getParameter() . DIRECTORY_SEPARATOR;
0 ignored issues
show
Bug introduced by
The method getParameter() does not exist on O2System\Kernel\Containers\Services. ( Ignorable by Annotation )

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

302
            $controllerSubDir = services('controller')->/** @scrutinizer ignore-call */ getParameter() . DIRECTORY_SEPARATOR;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
303
304
            foreach ($viewsDirectories as $viewsDirectory) {
305
                $filename = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $filename);
306
307
                // Find specific view file for mobile version
308
                if (services('userAgent')->isMobile()) {
0 ignored issues
show
Bug introduced by
The method isMobile() does not exist on O2System\Kernel\Containers\Services. ( Ignorable by Annotation )

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

308
                if (services('userAgent')->/** @scrutinizer ignore-call */ isMobile()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
309
                    // Find without controller parameter as sub directory
310
                    if (is_file($filePath = $viewsDirectory . $filename . '.mobile.phtml')) {
311
                        return realpath($filePath);
312
                        break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
313
                    }
314
315
                    // Find without controller parameter as sub directory
316
                    if (is_file($filePath = $viewsDirectory . $controllerSubDir . $filename . '.mobile.phtml')) {
317
                        return realpath($filePath);
318
                        break;
319
                    }
320
                }
321
322
                // Find without controller parameter as sub directory
323
                if (is_file($filePath = $viewsDirectory . $filename . '.phtml')) {
324
                    return realpath($filePath);
325
                    break;
326
                }
327
328
                // Find without controller parameter as sub directory
329
                if (is_file($filePath = $viewsDirectory . $controllerSubDir . $filename . '.phtml')) {
330
                    print_line('found: ' . $viewsDirectory . $controllerSubDir . $filename . '.phtml');
331
                    return realpath($filePath);
332
                    break;
333
                }
334
            }
335
        }
336
337
        return false;
338
    }
339
340
    // ------------------------------------------------------------------------
341
342
    /**
343
     * View::render
344
     *
345
     * @param array $options
346
     *
347
     * @return string
348
     */
349
    public function render(array $options = [])
350
    {
351
        if (profiler() !== false) {
0 ignored issues
show
introduced by
The condition profiler() !== false is always true.
Loading history...
352
            profiler()->watch('Starting View Rendering');
353
        }
354
355
        parser()->loadVars(presenter()->getArrayCopy());
356
357
        if (presenter()->page->file instanceof \SplFileInfo) {
0 ignored issues
show
introduced by
presenter()->page->file is always a sub-type of SplFileInfo.
Loading history...
358
359
            if (false === ($pagePresets = presenter()->page->getPresets())) {
0 ignored issues
show
introduced by
The condition false === $pagePresets =...r()->page->getPresets() is always false.
Loading history...
360
                if (presenter()->page->file->getFilename() === 'index') {
361
                    $title = presenter()->page->file->getDirectoryInfo()->getDirName();
362
                } else {
363
                    $titles[] = presenter()->page->file->getDirectoryInfo()->getDirName();
364
                    $titles[] = presenter()->page->file->getFilename();
365
366
                    $title = implode(' - ', array_unique($titles));
367
                }
368
369
                $pagePresets = new SplArrayObject([
370
                    'title'  => readable($title, true),
371
                    'access' => 'public',
372
                ]);
373
            }
374
375
            /**
376
             * Sets Page Theme
377
             */
378
            if ($pagePresets->offsetExists('theme')) {
379
                presenter()->setTheme($pagePresets->theme);
380
            } elseif (false !== ($theme = presenter()->getConfig('theme'))) {
381
                if (modules()->top()->hasTheme($theme)) {
0 ignored issues
show
Bug introduced by
The method top() does not exist on O2System\Framework\Conta...s\DataStructures\Module. ( Ignorable by Annotation )

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

381
                if (modules()->/** @scrutinizer ignore-call */ top()->hasTheme($theme)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
382
                    presenter()->setTheme($theme);
0 ignored issues
show
Bug introduced by
It seems like $theme can also be of type array; however, parameter $theme of O2System\Framework\Http\Presenter::setTheme() 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

382
                    presenter()->setTheme(/** @scrutinizer ignore-type */ $theme);
Loading history...
383
                }
384
            }
385
386
            /**
387
             * Sets Page Layout
388
             */
389
            if (presenter()->theme !== false) {
390
                if ($pagePresets->offsetExists('layout')) {
391
                    presenter()->theme->setLayout($pagePresets->layout);
392
                }
393
394
                /**
395
                 * Autoload Theme Assets
396
                 */
397
                presenter()->theme->load();
398
399
                if (false !== ($modulePresets = modules()->top()->getPresets())) {
400
401
                    /**
402
                     * Autoload Module Assets
403
                     */
404
                    if ($modulePresets->offsetExists('assets')) {
405
                        presenter()->assets->autoload($modulePresets->assets);
406
                    }
407
408
                    /**
409
                     * Sets Module Meta
410
                     */
411
                    if ($modulePresets->offsetExists('title')) {
412
                        presenter()->meta->title->append(language()->getLine($modulePresets->title));
413
                    }
414
415
                    if ($modulePresets->offsetExists('pageTitle')) {
416
                        presenter()->meta->title->replace(language()->getLine($modulePresets->pageTitle));
417
                    }
418
419
                    if ($modulePresets->offsetExists('browserTitle')) {
420
                        presenter()->meta->title->replace(language()->getLine($modulePresets->browserTitle));
421
                    }
422
423
                    if ($modulePresets->offsetExists('meta')) {
424
                        foreach ($modulePresets->meta as $name => $content) {
425
                            presenter()->meta->store($name, $content);
426
                        }
427
                    }
428
                }
429
430
                $moduleAssets = [
431
                    'app',
432
                    'module',
433
                    modules()->top()->getParameter(),
434
                ];
435
                
436
                // Autoload Assets
437
                presenter()->assets->loadCss($moduleAssets);
438
                presenter()->assets->loadJs($moduleAssets);
439
440
                /**
441
                 * Autoload Page Assets
442
                 */
443
                if ($pagePresets->offsetExists('assets')) {
444
                    presenter()->assets->autoload($pagePresets->assets);
445
                }
446
447
                if (presenter()->page->file instanceof \SplFileInfo) {
0 ignored issues
show
introduced by
presenter()->page->file is always a sub-type of SplFileInfo.
Loading history...
448
                    $pageDir = presenter()->page->file->getRealPath();
449
                    $pageDir = str_replace('.' . pathinfo($pageDir, PATHINFO_EXTENSION), '', $pageDir);
450
                    $pageDirParts = explode('pages' . DIRECTORY_SEPARATOR,
451
                        str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $pageDir));
452
                    $pageDir = end($pageDirParts);
453
454
                    $pageDir = rtrim($pageDir, DIRECTORY_SEPARATOR);
455
                    $pageDirParts = explode(DIRECTORY_SEPARATOR, $pageDir);
456
457
                    $totalParts = count($pageDirParts);
458
459
                    for ($i = 0; $i < $totalParts; $i++) {
460
                        $pageAssets[] = implode(DIRECTORY_SEPARATOR, array_slice($pageDirParts, 0, ($totalParts - $i)));
461
                    }
462
463
                    $pageAssets[] = implode(DIRECTORY_SEPARATOR, [end($pageAssets), end($pageAssets)]);
464
465
                    // Autoload Assets
466
                    presenter()->assets->loadCss($pageAssets);
467
                    presenter()->assets->loadJs($pageAssets);
468
                }
469
470
                /**
471
                 * Sets Page Meta
472
                 */
473
                if ($pagePresets->offsetExists('title')) {
474
                    presenter()->meta->title->append(language()->getLine($pagePresets->title));
475
                }
476
477
                if ($pagePresets->offsetExists('pageTitle')) {
478
                    presenter()->meta->title->replace(language()->getLine($pagePresets->pageTitle));
479
                }
480
481
                if ($pagePresets->offsetExists('browserTitle')) {
482
                    presenter()->meta->title->replace(language()->getLine($pagePresets->browserTitle));
483
                }
484
485
                if ($pagePresets->offsetExists('meta')) {
486
                    foreach ($pagePresets->meta as $name => $content) {
487
                        presenter()->meta->store($name, $content);
488
                    }
489
                }
490
491
                if (false !== ($layout = presenter()->theme->getLayout())) {
0 ignored issues
show
introduced by
The condition false !== $layout = pres...r()->theme->getLayout() is always true.
Loading history...
492
                    parser()->loadFile($layout->getRealPath());
493
494
                    $htmlOutput = parser()->parse();
495
                    $htmlOutput = presenter()->assets->parseSourceCode($htmlOutput);
496
497
                    $this->document->loadHTML($htmlOutput);
498
                }
499
            } else {
500
                output()->sendError(204, language()->getLine('E_THEME_NOT_FOUND', [$theme]));
501
            }
502
        } elseif (presenter()->theme instanceof Theme) {
503
            /**
504
             * Autoload Theme Assets
505
             */
506
            presenter()->theme->load();
507
508
            if (false !== ($modulePresets = modules()->top()->getPresets())) {
509
510
                /**
511
                 * Autoload Module Assets
512
                 */
513
                if ($modulePresets->offsetExists('assets')) {
514
                    presenter()->assets->autoload($modulePresets->assets);
515
                }
516
517
                /**
518
                 * Sets Module Meta
519
                 */
520
                if ($modulePresets->offsetExists('title')) {
521
                    presenter()->meta->title->append(language()->getLine($modulePresets->title));
522
                }
523
524
                if ($modulePresets->offsetExists('pageTitle')) {
525
                    presenter()->meta->title->replace(language()->getLine($modulePresets->pageTitle));
526
                }
527
528
                if ($modulePresets->offsetExists('browserTitle')) {
529
                    presenter()->meta->title->replace(language()->getLine($modulePresets->browserTitle));
530
                }
531
532
                if ($modulePresets->offsetExists('meta')) {
533
                    foreach ($modulePresets->meta as $name => $content) {
534
                        presenter()->meta->store($name, $content);
535
                    }
536
                }
537
            }
538
539
            $moduleAssets = [
540
                'app',
541
                'module',
542
                modules()->top()->getParameter(),
543
            ];
544
545
            // Autoload Assets
546
            presenter()->assets->loadCss($moduleAssets);
547
            presenter()->assets->loadJs($moduleAssets);
548
549
            /**
550
             * Autoload Controller Assets
551
             */
552
            $controllerFilename = str_replace([modules()->top()->getDir('Controllers'), '.php'], '',
553
                controller()->getFileInfo()->getRealPath());
554
            $controllerFilename = dash($controllerFilename);
555
            $controllerAssets[] = $controllerFilename;
556
            $controllerAssets[] = implode('/', [
557
                $controllerFilename,
558
                controller()->getRequestMethod(),
559
            ]);
560
561
            presenter()->assets->loadCss($controllerAssets);
562
            presenter()->assets->loadJs($controllerAssets);
563
564
            if (false !== ($layout = presenter()->theme->getLayout())) {
565
                parser()->loadFile($layout->getRealPath());
566
567
                $htmlOutput = parser()->parse();
568
                $htmlOutput = presenter()->assets->parseSourceCode($htmlOutput);
569
570
                $this->document->loadHTML($htmlOutput);
571
            }
572
        } elseif (false !== ($theme = presenter()->getConfig('theme'))) {
573
            if (modules()->top()->hasTheme($theme)) {
574
                presenter()->setTheme($theme);
575
576
                /**
577
                 * Autoload Theme Assets
578
                 */
579
                presenter()->theme->load();
580
581
                if (false !== ($modulePresets = modules()->top()->getPresets())) {
582
583
                    /**
584
                     * Autoload Module Assets
585
                     */
586
                    if ($modulePresets->offsetExists('assets')) {
587
                        presenter()->assets->autoload($modulePresets->assets);
588
                    }
589
590
                    /**
591
                     * Sets Module Meta
592
                     */
593
                    if ($modulePresets->offsetExists('title')) {
594
                        presenter()->meta->title->append(language()->getLine($modulePresets->title));
595
                    }
596
597
                    if ($modulePresets->offsetExists('pageTitle')) {
598
                        presenter()->meta->title->replace(language()->getLine($modulePresets->pageTitle));
599
                    }
600
601
                    if ($modulePresets->offsetExists('browserTitle')) {
602
                        presenter()->meta->title->replace(language()->getLine($modulePresets->browserTitle));
603
                    }
604
605
                    if ($modulePresets->offsetExists('meta')) {
606
                        foreach ($modulePresets->meta as $name => $content) {
607
                            presenter()->meta->store($name, $content);
608
                        }
609
                    }
610
                }
611
612
                $moduleAssets = [
613
                    'app',
614
                    'module',
615
                    modules()->top()->getParameter(),
616
                ];
617
618
                // Autoload Assets
619
                presenter()->assets->loadCss($moduleAssets);
620
                presenter()->assets->loadJs($moduleAssets);
621
622
                /**
623
                 * Autoload Controller Assets
624
                 */
625
                $controllerFilename = str_replace([modules()->top()->getDir('Controllers'), '.php'], '',
626
                    controller()->getFileInfo()->getRealPath());
627
                $controllerFilename = dash($controllerFilename);
628
                $controllerAssets[] = $controllerFilename;
629
                $controllerAssets[] = implode('/', [
630
                    $controllerFilename,
631
                    controller()->getRequestMethod(),
632
                ]);
633
634
                if (false !== ($layout = presenter()->theme->getLayout())) {
635
                    parser()->loadFile($layout->getRealPath());
636
637
                    $htmlOutput = parser()->parse();
638
                    $htmlOutput = presenter()->assets->parseSourceCode($htmlOutput);
639
640
                    $this->document->loadHTML($htmlOutput);
641
                }
642
            } else {
643
                output()->sendError(204, language()->getLine('E_THEME_NOT_FOUND', [$theme]));
644
            }
645
        } else {
646
            $this->document->find('body')->append(presenter()->partials->__get('content'));
647
        }
648
649
        /**
650
         * Set Document Meta Title
651
         */
652
        if (presenter()->meta->title instanceof Meta\Title) {
0 ignored issues
show
introduced by
presenter()->meta->title is always a sub-type of O2System\Framework\Http\Presenter\Meta\Title.
Loading history...
653
            $this->document->title->text(presenter()->meta->title->__toString());
654
        }
655
656
        /**
657
         * Injecting Meta Opengraph
658
         */
659
        if (presenter()->meta->opengraph instanceof Meta\Opengraph) {
0 ignored issues
show
introduced by
presenter()->meta->opengraph is always a sub-type of O2System\Framework\Http\Presenter\Meta\Opengraph.
Loading history...
660
            // set opengraph title
661
            if (presenter()->meta->title instanceof Meta\Title) {
0 ignored issues
show
introduced by
presenter()->meta->title is always a sub-type of O2System\Framework\Http\Presenter\Meta\Title.
Loading history...
662
                presenter()->meta->opengraph->setTitle(presenter()->meta->title->__toString());
663
            }
664
665
            // set opengraph site name
666
            if (presenter()->exists('siteName')) {
667
                presenter()->meta->opengraph->setSiteName(presenter()->offsetGet('siteName'));
668
            }
669
670
            if (presenter()->meta->opengraph->count()) {
671
                $htmlElement = $this->document->getElementsByTagName('html')->item(0);
672
                $htmlElement->setAttribute('prefix', 'og: ' . presenter()->meta->opengraph->prefix);
673
674
                if (presenter()->meta->opengraph->exists('og:type') === false) {
675
                    presenter()->meta->opengraph->setType('website');
676
                }
677
678
                $opengraph = presenter()->meta->opengraph->getArrayCopy();
679
680
                foreach ($opengraph as $tag) {
681
                    $this->document->metaNodes->createElement($tag->attributes->getArrayCopy());
682
                }
683
            }
684
        }
685
686
        if (presenter()->meta->count()) {
687
            $meta = presenter()->meta->getArrayCopy();
688
689
            foreach ($meta as $tag) {
690
                $this->document->metaNodes->createElement($tag->attributes->getArrayCopy());
691
            }
692
        }
693
694
        /**
695
         * Inject body attributes
696
         */
697
        $body = $this->document->getElementsByTagName('body');
698
        $body->item(0)->setAttribute('module', modules()->top()->getParameter());
699
700
        /**
701
         * Injecting Single Sign-On (SSO) iFrame
702
         */
703
        if (services()->has('user')) {
704
            $iframe = services()->get('user')->getIframeCode();
705
706
            if ( ! empty($iframe)) {
707
                $this->document->find('body')->append($iframe);
708
            }
709
        }
710
711
        if (input()->env('DEBUG_STAGE') === 'DEVELOPER' and
712
            presenter()->getConfig('debugToolBar') === true and
713
            services()->has('profiler')
714
        ) {
715
            $this->document->find('body')->append((new Toolbar())->__toString());
716
        }
717
718
        /**
719
         * Injecting Progressive Web Application (PWA) Manifest
720
         */
721
        $this->document->linkNodes->createElement([
722
            'rel'  => 'manifest',
723
            'href' => '/manifest.json',
724
        ]);
725
726
        $htmlOutput = $this->document->saveHTML();
727
728
        // Uglify Output
729
        if ($this->config->output[ 'uglify' ] === true) {
730
            $htmlOutput = preg_replace(
731
                [
732
                    '/\>[^\S ]+/s',     // strip whitespaces after tags, except space
733
                    '/[^\S ]+\</s',     // strip whitespaces before tags, except space
734
                    '/(\s)+/s',         // shorten multiple whitespace sequences
735
                    '/<!--(.|\s)*?-->/', // Remove HTML comments
736
                    '/<!--(.*)-->/Uis',
737
                    "/[[:blank:]]+/",
738
                ],
739
                [
740
                    '>',
741
                    '<',
742
                    '\\1',
743
                    '',
744
                    '',
745
                    ' ',
746
                ],
747
                str_replace(["\n", "\r", "\t"], '', $htmlOutput));
748
        }
749
750
        // Beautify Output
751
        if ($this->config->output[ 'beautify' ] === true) {
752
            $beautifier = new Html\Dom\Beautifier();
753
            $htmlOutput = $beautifier->format($htmlOutput);
754
        }
755
756
        if (profiler() !== false) {
0 ignored issues
show
introduced by
The condition profiler() !== false is always true.
Loading history...
757
            profiler()->watch('Ending View Rendering');
758
        }
759
760
        return $htmlOutput;
761
    }
762
}
763