Passed
Push — master ( f2b4ae...a14f49 )
by Iman
55s queued 11s
created

WidgetRenderer::callController()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.3731

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 4
eloc 7
c 1
b 1
f 0
nc 3
nop 2
dl 0
loc 12
ccs 5
cts 7
cp 0.7143
crap 4.3731
rs 10
1
<?php
2
3
namespace Imanghafoori\Widgets\Utils;
4
5
use Illuminate\Support\Str;
6
7
class WidgetRenderer
8
{
9
    use SlotRenderer;
10
    
11
    public $html;
12
13
    private $_viewData;
14
15
    private $_policies;
16
17
    /**
18
     * BaseWidget constructor.
19
     */
20 25
    public function __construct()
21
    {
22 25
        $this->_policies = resolve(Policies::class);
23 25
    }
24
25
    /**
26
     * @param $widget object|string
27
     * @param array $args
28
     * @return string
29
     */
30 22
    public function renderWidget($widget, ...$args)
31
    {
32 22
        if (is_string($widget)) {
33 1
            $widget = $this->makeWidgetObj($widget);
34
        }
35
36 22
        if (is_array($widget)) {
37
            $widget = (object) $widget;
38
        }
39
40 22
        event('widgetize.rendering_widget', [$widget]);
41
42 22
        resolve(Normalizer::class)->normalizeWidgetConfig($widget);
43
44 22
        if (app()->offsetExists('debugbar')) {
45
            app('widgetize.debugger')->addMessage(['widget class:' => $widget, 'args:' => $args]);
46
        }
47
48 22
        return $this->generateHtml($widget, ...$args);
49
    }
50
51
    /**
52
     * @param $widget object
53
     * @return \Illuminate\Foundation\Application|mixed
54
     */
55 1
    private function makeWidgetObj($widget)
56
    {
57 1
        if (Str::startsWith($widget, ['\\'])) {
58
            return resolve($widget);
59
        }
60
61 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

61
        $widget = app()->/** @scrutinizer ignore-call */ getNamespace().'Widgets\\'.$widget;
Loading history...
62
63 1
        return resolve($widget);
64
    }
65
66
    /**
67
     * It tries to get the html from cache if possible, otherwise generates it.
68
     *
69
     * @param $widget object
70
     * @param array ...$args
71
     *
72
     * @return string
73
     */
74
    private function generateHtml($widget, ...$args)
75
    {
76
        // Everything inside this function is executed only when the cache is not available.
77 22
        $expensivePhpCode = function () use ($widget, $args) {
78 20
            $this->makeDataForView($widget, $args);
79
80 20
            return $this->renderTemplate($widget, ...$args);
0 ignored issues
show
Bug introduced by
$args is expanded, but the parameter $args of Imanghafoori\Widgets\Uti...derer::renderTemplate() 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

80
            return $this->renderTemplate($widget, /** @scrutinizer ignore-type */ ...$args);
Loading history...
81 22
        };
82
83 22
        if (! $widget->cacheView) {
84 2
            return $expensivePhpCode();
85
        }
86
87
        // We first try to get the output from the cache before trying to run the expensive $expensivePhpCode...
88 21
        return resolve(Cache::class)->cacheResult($args, $expensivePhpCode, $widget);
0 ignored issues
show
Bug introduced by
Are you sure the usage of resolve(Imanghafoori\Wid...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...
89
    }
90
91
    /**
92
     * @param $widget object
93
     * @param $args array
94
     *
95
     * @return null
96
     */
97
    private function makeDataForView($widget, array $args)
98
    {
99 20
        $expensiveCode = function () use ($widget, $args) {
100 20
            $viewData = $this->callController($widget, $args);
101
102 20
            if ($widget->presenter) {
103
                // Pipe the data through the presenter before sending it to view.
104 1
                $viewData = \App::call($widget->presenter, [$viewData]);
105
            }
106
107 20
            return $viewData;
108 20
        };
109
110 20
        if ($widget->cacheView) {
111 19
            $this->_viewData = $expensiveCode();
112
        } else {
113 2
            $this->_viewData = resolve(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 resolve(Imanghafoori\Wid...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...
114
        }
115 20
    }
116
117
    /**
118
     * @param      $widget object
119
     * @param null $args
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $args is correct as it would always require null to be passed?
Loading history...
120
     *
121
     * @throws \Throwable
122
     * @return string HTML output
123
     */
124 20
    private function renderTemplate($widget, $args = null)
125
    {
126
        // Here we render the view file to raw html.
127 20
        $data = [$widget->contextAs => $this->_viewData, 'params' => $args];
128
129
        // add slots if exists
130 20
        $this->hasSlots() && $data['slots'] = $this->getSlots();
131
132
        try {
133 20
            $this->html = view($widget->template, $data)->render();
134
        } catch (\Throwable $t) {
135
            throw new \ErrorException('There was some error rendering '.get_class($widget).', template file: \''.$widget->template.'\' Error: '.$t->getMessage());
136
        }
137
138
        // We try to minify the html before storing it in cache to save space.
139 20
        if ($this->_policies->widgetShouldBeMinified($widget)) {
140 9
            $this->html = resolve(HtmlMinifier::class)->minify($this->html);
141
        }
142
143
        // We add some HTML comments before and after the widget output
144
        // So then, we will be able to easily identify the widget in browser's developer tool.
145 20
        if ($this->_policies->widgetShouldHaveDebugInfo()) {
146 10
            $this->html = resolve(DebugInfo::class)->addIdentifierToHtml($widget, $this->html);
147
        }
148
149 20
        return $this->html;
150
    }
151
152 20
    private function callController($widget, array $args)
153
    {
154 20
        if (! isset($widget->controller)) {
155
            $viewData = [];
156 20
        } elseif (is_array($widget->controller) && is_string($widget->controller[0])) {
157
            $viewData = call_user_func_array($widget->controller, $args);
158
        } else {
159
            // Here we call the data method on the widget class.
160 20
            $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

160
            $viewData = \App::call($widget->controller, /** @scrutinizer ignore-type */ ...$args);
Loading history...
161
        }
162
163 20
        return $viewData;
164
    }
165
}
166