Completed
Push — master ( 3f0c83...8770ea )
by Iman
02:28
created

WidgetRenderer::_makeWidgetObj()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
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
    private $_viewData;
11
    private $_policies;
12
13
    /**
14
     * BaseWidget constructor.
15
     */
16
    public function __construct()
17
    {
18
        $this->_policies = app(Policies::class);
19
    }
20
21
    /**
22
     * @param Widget Object $widget
23
     * @param array $args
24
     * @return string
25
     */
26
    public function renderWidget($widget, ...$args)
27
    {
28
        if(is_string($widget))
29
        {
30
            $widget = $this->_makeWidgetObj($widget);
31
        }
32
33
        app(Normalizer::class)->normalizeWidgetConfig($widget);
34
35
        try {
36
            $html = $this->_generateHtml($widget, ...$args);
37
        } catch (\Exception $e) {
38
            return app()->make(ExceptionHandler::class)->render(app('request'), $e)->send();
39
        }
40
41
        return $html;
42
    }
43
44
    /**
45
     * It tries to get the html from cache if possible, otherwise generates it.
46
     *
47
     * @param $widget
48
     * @param array ...$args
49
     *
50
     * @return string
51
     */
52
    private function _generateHtml($widget, ...$args)
53
    {
54
        // Everything inside this function is executed only when the cache is not available.
55
        $expensivePhpCode = function () use ($widget, $args) {
56
            $this->_makeDataForView($widget, $args);
57
            // render the template with the resulting data.
58
            return $this->renderTemplate($widget);
59
        };
60
61
        // We first try to get the output from the cache before trying to run the expensive $expensivePhpCode...
62
        if ($this->_policies->widgetShouldUseCache($widget->cacheLifeTime)) {
63
            return app(Cache::class)->cacheResult($args, $expensivePhpCode, $widget);
64
        }
65
66
        return $expensivePhpCode();
67
    }
68
69
    /**
70
     * @param Widget Object $widget
71
     * @param $args
72
     *
73
     * @return null
74
     */
75
    private function _makeDataForView($widget, $args)
76
    {
77
        // Here we call the data method on the widget class.
78
        $viewData = \App::call($widget->controller, ...$args);
79
80
        if (($widget->presenter)) {
81
            // We make an object and call the `present` method on it.
82
            // Piping the data through the presenter before sending it to view.
83
            $viewData = \App::call($widget->presenter, [$viewData]);
84
        }
85
86
        $this->_viewData = $viewData;
87
    }
88
89
    private function renderTemplate($widget)
90
    {
91
        // Here we render the view file to raw html.
92
        $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...
93
94
        // We try to minify the html before storing it in cache to save space.
95
        if ($this->_policies->widgetShouldBeMinified()) {
96
            $this->html = app(HtmlMinifier::class)->minify($this->html);
97
        }
98
99
        // We add some HTML comments before and after the widget output
100
        // So then, we will be able to easily identify the widget in browser's developer tool.
101
        if ($this->_policies->widgetShouldHaveDebugInfo()) {
102
            $this->html = app(DebugInfo::class)->addIdentifierToHtml($widget, $this->html);
103
        }
104
105
        return $this->html;
106
    }
107
108
    /**
109
     * @param $widget
110
     * @return \Illuminate\Foundation\Application|mixed
111
     */
112
    private function _makeWidgetObj($widget)
113
    {
114
        $widget = app()->getNamespace().'Widgets\\'.$widget;
115
        return $widgetObj = app($widget);
0 ignored issues
show
Unused Code introduced by
$widgetObj is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
116
    }
117
}
118