Passed
Push — master ( b7736e...36606a )
by Iman
02:00
created

WidgetRenderer::makeDataForView()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 13
ccs 6
cts 6
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Imanghafoori\Widgets\Utils;
4
5
use Illuminate\Contracts\Debug\ExceptionHandler;
6
7
class WidgetRenderer
8
{
9
    public $html;
10
11
    private $_viewData;
12
13
    private $_policies;
14
15
    /**
16
     * BaseWidget constructor.
17
     */
18 13
    public function __construct()
19
    {
20 13
        $this->_policies = app(Policies::class);
21 13
    }
22
23
    /**
24
     * @param $widget object|string
25
     * @param array $args
26
     * @return string
27
     */
28 13
    public function renderWidget($widget, ...$args)
29
    {
30 13
        if (is_string($widget)) {
31 1
            $widget = $this->makeWidgetObj($widget);
32
        }
33
34 13
        app(Normalizer::class)->normalizeWidgetConfig($widget);
35
36 13
        if (app()->offsetExists('debugbar')) {
37
            app('widgetize.debugger')->addMessage(['widget class:' => $widget, 'args:' => $args]);
38
        }
39
40
        try {
41 13
            $html = $this->generateHtml($widget, ...$args);
42
        } catch (\Exception $e) {
43
            return app()->make(ExceptionHandler::class)->render(app('request'), $e)->send();
44
        }
45
46 13
        return $html;
47
    }
48
49
    /**
50
     * @param $widget object
51
     * @return \Illuminate\Foundation\Application|mixed
52
     */
53 1
    private function makeWidgetObj($widget)
54
    {
55 1
        if (starts_with($widget, ['\\'])) {
56
            return app($widget);
57
        }
58
59 1
        $widget = app()->getNamespace().'Widgets\\'.$widget;
60
61 1
        return app($widget);
62
    }
63
64
    /**
65
     * It tries to get the html from cache if possible, otherwise generates it.
66
     *
67
     * @param $widget object
68
     * @param array ...$args
69
     *
70
     * @return string
71
     */
72
    private function generateHtml($widget, ...$args)
73
    {
74
        // Everything inside this function is executed only when the cache is not available.
75 13
        $expensivePhpCode = function () use ($widget, $args) {
76 11
            $this->makeDataForView($widget, $args);
77
78
            // render the template with the resulting data.
79 11
            return $this->renderTemplate($widget);
80 13
        };
81
82
        // We first try to get the output from the cache before trying to run the expensive $expensivePhpCode...
83 13
        if ($this->_policies->widgetShouldUseCache($widget->cacheLifeTime)) {
84 5
            return app(Cache::class)->cacheResult($args, $expensivePhpCode, $widget);
85
        }
86
87 8
        return $expensivePhpCode();
88
    }
89
90
    /**
91
     * @param $widget object
92
     * @param $args array
93
     *
94
     * @return null
95
     */
96 11
    private function makeDataForView($widget, array $args)
97
    {
98
        // Here we call the data method on the widget class.
99 11
        $viewData = \App::call($widget->controller, ...$args);
100
101 11
        if (($widget->presenter)) {
102
            // We make an object and call the `present` method on it.
103
            // Piping the data through the presenter before sending it to view.
104 1
            $viewData = \App::call($widget->presenter, [$viewData]);
105
        }
106
107 11
        $this->_viewData = $viewData;
108 11
    }
109
110
    /**
111
     * @param $widget object
112
     * @return string HTML output
113
     */
114 11
    private function renderTemplate($widget)
115
    {
116
        // Here we render the view file to raw html.
117 11
        $this->html = view($widget->template, [$widget->contextAs => $this->_viewData])->render();
0 ignored issues
show
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
118
119
        // We try to minify the html before storing it in cache to save space.
120 11
        if ($this->_policies->widgetShouldBeMinified()) {
121 5
            $this->html = app(HtmlMinifier::class)->minify($this->html);
122
        }
123
124
        // We add some HTML comments before and after the widget output
125
        // So then, we will be able to easily identify the widget in browser's developer tool.
126 11
        if ($this->_policies->widgetShouldHaveDebugInfo()) {
127 6
            $this->html = app(DebugInfo::class)->addIdentifierToHtml($widget, $this->html);
128
        }
129
130 11
        return $this->html;
131
    }
132
}
133