Passed
Push — master ( 58d69a...b9c060 )
by Iman
02:45
created

WidgetRenderer::renderWidget()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 7
Bugs 4 Features 0
Metric Value
cc 3
eloc 7
c 7
b 4
f 0
nc 4
nop 2
dl 0
loc 14
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 10
1
<?php
2
3
namespace Imanghafoori\Widgets\Utils;
4
5
class WidgetRenderer
6
{
7
    public $html;
8
9
    private $_viewData;
10
11
    private $_policies;
12
13
    /**
14
     * BaseWidget constructor.
15
     */
16 20
    public function __construct()
17
    {
18 20
        $this->_policies = app(Policies::class);
19 20
    }
20
21
    /**
22
     * @param $widget object|string
23
     * @param array $args
24
     * @return string
25
     */
26 20
    public function renderWidget($widget, ...$args)
27
    {
28 20
        if (is_string($widget)) {
29 1
            $widget = $this->makeWidgetObj($widget);
30
        }
31 20
        event('widgetize.rendering_widget', [$widget]);
32
33 20
        app(Normalizer::class)->normalizeWidgetConfig($widget);
34
35 20
        if (app()->offsetExists('debugbar')) {
36
            app('widgetize.debugger')->addMessage(['widget class:' => $widget, 'args:' => $args]);
37
        }
38
39 20
        return $this->generateHtml($widget, ...$args);
40
    }
41
42
    /**
43
     * @param $widget object
44
     * @return \Illuminate\Foundation\Application|mixed
45
     */
46 1
    private function makeWidgetObj($widget)
47
    {
48 1
        if (starts_with($widget, ['\\'])) {
49
            return app($widget);
50
        }
51
52 1
        $widget = app()->getNamespace().'Widgets\\'.$widget;
0 ignored issues
show
introduced by
The method getNamespace() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

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

52
        $widget = app()->/** @scrutinizer ignore-call */ getNamespace().'Widgets\\'.$widget;
Loading history...
53
54 1
        return app($widget);
55
    }
56
57
    /**
58
     * It tries to get the html from cache if possible, otherwise generates it.
59
     *
60
     * @param $widget object
61
     * @param array ...$args
62
     *
63
     * @return string
64
     */
65
    private function generateHtml($widget, ...$args)
66
    {
67
        // Everything inside this function is executed only when the cache is not available.
68 20
        $expensivePhpCode = function () use ($widget, $args) {
69 18
            $this->makeDataForView($widget, $args);
70
71 18
            return $this->renderTemplate($widget);
72 20
        };
73
74 20
        if (! $widget->cacheView) {
75 2
            return $expensivePhpCode();
76
        }
77
78
        // We first try to get the output from the cache before trying to run the expensive $expensivePhpCode...
79 19
        return app(Cache::class)->cacheResult($args, $expensivePhpCode, $widget);
0 ignored issues
show
Bug introduced by
Are you sure the usage of app(Imanghafoori\Widgets...ensivePhpCode, $widget) targeting Imanghafoori\Widgets\Utils\Cache::cacheResult() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
80
    }
81
82
    /**
83
     * @param $widget object
84
     * @param $args array
85
     *
86
     * @return null
87
     */
88
    private function makeDataForView($widget, array $args)
89
    {
90 18
        $expensiveCode = function () use ($widget, $args) {
91
92
            // Here we call the data method on the widget class.
93 18
            $viewData = \App::call($widget->controller, ...$args);
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $parameters of Illuminate\Foundation\Application::call() does not expect variable arguments. ( Ignorable by Annotation )

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

93
            $viewData = \App::call($widget->controller, /** @scrutinizer ignore-type */ ...$args);
Loading history...
94
95 18
            if (($widget->presenter)) {
96
                // We make an object and call the `present` method on it.
97
                // Piping the data through the presenter before sending it to view.
98 1
                $viewData = \App::call($widget->presenter, [$viewData]);
99
            }
100
101 18
            return $viewData;
102 18
        };
103
104 18
        if ($widget->cacheView) {
105 17
            $this->_viewData = $expensiveCode();
106
        } else {
107 2
            $this->_viewData = app(Cache::class)->cacheResult($args, $expensiveCode, $widget, 'dataProvider');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $this->_viewData is correct as app(Imanghafoori\Widgets...widget, 'dataProvider') targeting Imanghafoori\Widgets\Utils\Cache::cacheResult() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
108
        }
109 18
    }
110
111
    /**
112
     * @param $widget object
113
     * @return string HTML output
114
     * @throws \Throwable
115
     */
116 18
    private function renderTemplate($widget)
117
    {
118
        // Here we render the view file to raw html.
119 18
        $this->html = view($widget->template, [$widget->contextAs => $this->_viewData])->render();
120
121
        // We try to minify the html before storing it in cache to save space.
122 18
        if ($this->_policies->widgetShouldBeMinified($widget)) {
123 9
            $this->html = app(HtmlMinifier::class)->minify($this->html);
124
        }
125
126
        // We add some HTML comments before and after the widget output
127
        // So then, we will be able to easily identify the widget in browser's developer tool.
128 18
        if ($this->_policies->widgetShouldHaveDebugInfo()) {
129 8
            $this->html = app(DebugInfo::class)->addIdentifierToHtml($widget, $this->html);
130
        }
131
132 18
        return $this->html;
133
    }
134
}
135