Completed
Push — master ( 2c7ea9...284ef7 )
by Iman
01:59
created

BaseWidget::minifyHtml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 0
1
<?php
2
3
4
namespace Imanghafoori\Widgets;
5
6
use Illuminate\Contracts\Debug\ExceptionHandler;
7
8
abstract class BaseWidget
9
{
10
    public $template = null;
11
    public $minifyOutput = true;
12
    public $cacheLifeTime = 'env_default';
13
    public $contextAs = '$data';
14
    public $presenter = 'default';
15
    public $controller = null;
16
    public $cacheTags = null;
17
    public $html;
18
    private $viewData;
19
    private $policies;
20
21
    /**
22
     * BaseWidget constructor.
23
     */
24
    public function __construct()
25
    {
26
        $this->policies = app('imanghafoori.widget.policies');
27
        app('imanghafoori.widget.normalizer')->normalizeWidgetConfig($this);
28
    }
29
30
    /**
31
     * This method is called when you try to invoke the object like a function in blade files.
32
     * like this : {!! $myWidgetObj('param1') !!}
33
     * @param array $args
34
     * @return string
35
     */
36
    public function __invoke(...$args)
37
    {
38
        return $this->renderWidget(...$args);
39
    }
40
41
    /**
42
     * @param array $args
43
     * @return string
44
     */
45
    private function renderWidget(...$args)
46
    {
47
        try {
48
            $html = $this->generateHtml(...$args);
49
        } catch (\Exception $e) {
50
            return app()->make(ExceptionHandler::class)->render(app('request'), $e)->send();
51
        }
52
        return $html;
53
    }
54
55
    /**
56
     * It tries to get the html from cache if possible, otherwise generates it.
57
     * @param array ...$args
58
     * @return string
59
     */
60
    private function generateHtml(...$args)
61
    {
62
        // Everything inside this function is executed only when the cache is not available.
63
        $expensivePhpCode = function () use ($args) {
64
            $this->prepareDataForView($args);
65
            // render the template with the resulting data.
66
            return $this->renderTemplate();
67
        };
68
69
        // We first try to get the output from the cache before trying to run the expensive $expensivePhpCode...
70
        if ($this->policies->widgetShouldUseCache($this->cacheLifeTime)) {
71
            $key = $this->makeCacheKey($args);
72
            return app('imanghafoori.widget.cache')->cacheResult($key, $expensivePhpCode, $this->cacheLifeTime,$this->cacheTags);
73
        }
74
75
        return $expensivePhpCode();
76
    }
77
78
    /**
79
     * @param $args
80
     * @return null
81
     */
82
    private function prepareDataForView($args)
83
    {
84
        // Here we call the data method on the widget class.
85
        $viewData = \App::call($this->controller, $args);
86
87
        if (($this->presenter)) {
88
            // We make an object and call the `present` method on it.
89
            // Piping the data through the presenter before sending it to view.
90
            $viewData = \App::call($this->presenter, [$viewData]);
91
        }
92
93
        $this->viewData = $viewData;
94
    }
95
96
    private function renderTemplate()
97
    {
98
        // Here we render the view file to raw html.
99
        $this->html = view($this->template, [$this->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...
100
        // We try to minify the html before storing it in cache to save space.
101
        if ($this->policies->widgetShouldBeMinified()) {
102
            $this->html = app('imanghafoori.widget.minifier')->minify($this->html);
103
        }
104
        // We add some HTML comments before and after the widget output
105
        // So then, we will be able to easily identify the widget in browser's developer tool.
106
        if ($this->policies->widgetShouldHaveDebugInfo()) {
107
            app('imanghafoori.widget.debugInfo')->addIdentifierToHtml($this);
108
        }
109
110
        return $this->html;
111
    }
112
113
    /**
114
     * @param $arg
115
     * @return string
116
     */
117
    private function makeCacheKey($arg)
118
    {
119
        return md5(json_encode($arg, JSON_FORCE_OBJECT) . $this->template . get_called_class());
120
    }
121
122
    /**
123
     * This method is called when you try to print the object like an string in blade files.
124
     * like this : {!! $myWidgetObj !!}
125
     */
126
    public function __toString()
127
    {
128
        return $this->renderWidget();
129
    }
130
}