Completed
Push — master ( 50def4...4d092b )
by Sang
21:49 queued 01:43
created

Assets::getJavascript()   D

Complexity

Conditions 17
Paths 134

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 58
rs 4.9333
c 0
b 0
f 0
cc 17
nc 134
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Botble\Assets;
4
5
use Collective\Html\HtmlBuilder;
6
use Illuminate\Config\Repository;
7
8
/**
9
 * Class Assets
10
 * @package Botble\Assets
11
 * @author Sang Nguyen
12
 * @since 22/07/2015 11:23 PM
13
 */
14
class Assets
15
{
16
    /**
17
     * @var Repository
18
     */
19
    protected $config;
20
21
    /**
22
     * @var HtmlBuilder
23
     */
24
    protected $htmlBuilder;
25
26
    /**
27
     * @var array
28
     */
29
    protected $javascript = [];
30
31
    /**
32
     * @var array
33
     */
34
    protected $stylesheets = [];
35
36
    /**
37
     * @var string
38
     */
39
    protected $build = '';
40
41
    /**
42
     * @var array
43
     */
44
    protected $appendedJs = [
45
        'top'    => [],
46
        'bottom' => [],
47
    ];
48
49
    /**
50
     * @var array
51
     */
52
    protected $appendedCss = [];
53
54
    /**
55
     * Assets constructor.
56
     * @author Sang Nguyen
57
     * @param Repository $config
58
     * @param HtmlBuilder $htmlBuilder
59
     */
60
    public function __construct(Repository $config, HtmlBuilder $htmlBuilder)
61
    {
62
        $this->config = $config;
63
        $this->htmlBuilder = $htmlBuilder;
64
65
        $this->javascript = $this->config->get('assets.javascript');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->config->get('assets.javascript') of type * is incompatible with the declared type array of property $javascript.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
66
        $this->stylesheets = $this->config->get('assets.stylesheets');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->config->get('assets.stylesheets') of type * is incompatible with the declared type array of property $stylesheets.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
67
68
        $this->build = $this->config->get('assets.enable_version') ? '?v=' . $this->config->get('assets.version') : '';
69
    }
70
71
    /**
72
     * Add Javascript to current module
73
     *
74
     * @param array $assets
75
     * @return $this
76
     * @author Sang Nguyen
77
     */
78
    public function addJavascript($assets)
79
    {
80
        if (!is_array($assets)) {
81
            $assets = [$assets];
82
        }
83
        $this->javascript = array_merge($this->javascript, $assets);
84
        return $this;
85
    }
86
87
    /**
88
     * Add Css to current module
89
     *
90
     * @param array $assets
91
     * @return $this
92
     * @author Sang Nguyen
93
     */
94
    public function addStylesheets($assets)
95
    {
96
        if (!is_array($assets)) {
97
            $assets = [$assets];
98
        }
99
        $this->stylesheets = array_merge($this->stylesheets, $assets);
100
        return $this;
101
    }
102
103
    /**
104
     * @param $assets
105
     * @return $this
106
     * @author Sang Nguyen
107
     */
108 View Code Duplication
    public function addStylesheetsDirectly($assets)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
109
    {
110
        if (!is_array($assets)) {
111
            $assets = func_get_args();
112
        }
113
        foreach ($assets as &$item) {
114
            $item = $item . $this->build;
115
            if (!in_array($item, $this->appendedCss)) {
116
                $this->appendedCss[] = ['src' => $item, 'attributes' => []];
117
            }
118
        }
119
        return $this;
120
    }
121
122
    /**
123
     * @param $assets
124
     * @param string $location
125
     * @return $this
126
     * @author Sang Nguyen
127
     */
128 View Code Duplication
    public function addJavascriptDirectly($assets, $location = 'bottom')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
    {
130
        if (!is_array($assets)) {
131
            $assets = func_get_args();
132
        }
133
134
        foreach ($assets as &$item) {
135
            $item = $item . $this->build;
136
            if (!in_array($item, $this->appendedJs[$location])) {
137
                $this->appendedJs[$location][] = ['src' => $item, 'attributes' => []];
138
            }
139
        }
140
        return $this;
141
    }
142
143
    /**
144
     * Remove Css to current module
145
     *
146
     * @param array $assets
147
     * @return $this
148
     * @author Sang Nguyen
149
     */
150 View Code Duplication
    public function removeStylesheets($assets)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
    {
152
        if (!is_array($assets)) {
153
            $assets = [$assets];
154
        }
155
        foreach ($assets as $rem) {
156
            unset($this->stylesheets[array_search($rem, $this->stylesheets)]);
157
        }
158
        return $this;
159
    }
160
161
    /**
162
     * Add Javascript to current module
163
     *
164
     * @param array $assets
165
     * @return $this
166
     * @author Sang Nguyen
167
     */
168 View Code Duplication
    public function removeJavascript($assets)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
    {
170
        if (!is_array($assets)) {
171
            $assets = [$assets];
172
        }
173
        foreach ($assets as $rem) {
174
            unset($this->javascript[array_search($rem, $this->javascript)]);
175
        }
176
        return $this;
177
    }
178
179
    /**
180
     * Get All Javascript in current module
181
     *
182
     * @param string $location : top or bottom
183
     * @param boolean $version : show version?
184
     * @return array
185
     * @author Sang Nguyen
186
     */
187
    public function getJavascript($location = null, $version = true)
188
    {
189
        $scripts = [];
190
        // get the final scripts need for page
191
        $this->javascript = array_unique($this->javascript);
192
        foreach ($this->javascript as $js) {
193
            $jsConfig = 'assets.resources.javascript.' . $js;
194
195
            if ($this->config->has($jsConfig)) {
196
                if (!empty($location) && $location != $this->config->get($jsConfig . '.location')) {
197
                    // Skip assets that don't match this location
198
                    continue;
199
                }
200
201
                $src = $this->config->get($jsConfig . '.src.local');
202
                $cdn = false;
203
                if ($this->config->get($jsConfig . '.use_cdn') && !$this->config->get('assets.offline')) {
204
                    $src = $this->config->get($jsConfig . '.src.cdn');
205
                    $cdn = true;
206
                }
207
208
                if ($this->config->get($jsConfig . '.include_style')) {
209
                    $this->addStylesheets([$js]);
210
                }
211
212
                $attributes = $this->config->get($jsConfig . '.attributes', []);
213
                if ($cdn === false) {
214
                    array_forget($attributes, 'integrity');
215
                    array_forget($attributes, 'crossorigin');
216
                }
217
218
                $version = $version ? $this->build : '';
219
                if (!is_array($src)) {
220
                    $scripts[] = ['src' => $src . $version, 'attributes' => $attributes];
221
                } else {
222
                    foreach ($src as $s) {
223
                        $scripts[] = ['src' => $s . $version, 'attributes' => $attributes];
224
                    }
225
                }
226
227
                if (empty($src) && $cdn && $location === 'top' && $this->config->has($jsConfig . '.fallback')) {
228
                    // Fallback to local script if CDN fails
229
                    $fallback = $this->config->get($jsConfig . '.fallback');
230
                    $scripts[] = [
231
                        'src'         => $src,
232
                        'fallback'    => $fallback,
233
                        'fallbackURL' => $this->config->get($jsConfig . '.src.local'),
234
                    ];
235
                }
236
            }
237
        }
238
239
        if (isset($this->appendedJs[$location])) {
240
            $scripts = array_merge($scripts, $this->appendedJs[$location]);
241
        }
242
243
        return $scripts;
244
    }
245
246
    /**
247
     * Get All CSS in current module
248
     *
249
     * @param array $lastModules : append last CSS to current module
250
     * @param boolean $version : show version?
251
     * @return array
252
     * @author Sang Nguyen
253
     */
254
    public function getStylesheets($lastModules = [], $version = true)
255
    {
256
        $stylesheets = [];
257
        if (!empty($lastModules)) {
258
            $this->stylesheets = array_merge($this->stylesheets, $lastModules);
259
        }
260
        // get the final scripts need for page
261
        $this->stylesheets = array_unique($this->stylesheets);
262
        foreach ($this->stylesheets as $style) {
263
            if ($this->config->has('assets.resources.stylesheets.' . $style)) {
264
                $src = $this->config->get('assets.resources.stylesheets.' . $style . '.src.local');
265
                $cdn = false;
266
                if ($this->config->get('assets.resources.stylesheets.' . $style . '.use_cdn') && !$this->config->get('assets.offline')) {
267
                    $src = $this->config->get('assets.resources.stylesheets.' . $style . '.src.cdn');
268
                    $cdn = true;
269
                }
270
271
                $attributes = $this->config->get('assets.resources.stylesheets.' . $style . '.attributes', []);
272
                if ($cdn === false) {
273
                    array_forget($attributes, 'integrity');
274
                    array_forget($attributes, 'crossorigin');
275
                }
276
277
                if (!is_array($src)) {
278
                    $src = [$src];
279
                }
280
                foreach ($src as $s) {
281
                    $stylesheets[] = [
282
                        'src'        => $s . ($version ? $this->build : ''),
283
                        'attributes' => $attributes,
284
                    ];
285
                }
286
            }
287
        }
288
289
        $stylesheets = array_merge($stylesheets, $this->appendedCss);
290
291
        return $stylesheets;
292
    }
293
294
    /**
295
     * @param $name
296
     * @param bool $version
297
     * @author Sang Nguyen
298
     */
299
    public function javascriptToHtml($name, $version = true)
300
    {
301
        return $this->itemToHtml($name, $version, 'script');
302
    }
303
304
    /**
305
     * @param $name
306
     * @param bool $version
307
     * @author Sang Nguyen
308
     */
309
    public function stylesheetToHtml($name, $version = true)
310
    {
311
        return $this->itemToHtml($name, $version, 'style');
312
    }
313
314
    /**
315
     * @param $name
316
     * @param bool $version
317
     * @param string $type
318
     * @return null|string
319
     */
320
    protected function itemToHtml($name, $version = true, $type = 'style')
321
    {
322
        if (!in_array($type, ['style', 'script'])) {
323
            return null;
324
        }
325
326
        $config = 'assets.resources.stylesheets.' . $name;
327
        if ($type === 'script') {
328
            $config = 'assets.resources.javascript.' . $name;
329
        }
330
331
        if ($this->config->has($config)) {
332
333
            $src = $this->config->get($config . '.src.local');
334
            if ($this->config->get($config . '.use_cdn') && !$this->config->get('assets.offline')) {
335
                $src = $this->config->get($config . '.src.cdn');
336
            }
337
338
            if (!is_array($src)) {
339
                $src = [$src];
340
            }
341
342
            $html = '';
343
            foreach ($src as $item) {
344
                $html .= $this->htmlBuilder->{$type}($item . ($version ? $this->build : ''), ['class' => 'hidden'])->toHtml();
345
            }
346
347
            return $html;
348
        }
349
350
        return null;
351
    }
352
353
    /**
354
     * @return string
355
     * @throws \Throwable
356
     * @author Sang Nguyen
357
     */
358
    public function renderHeader()
359
    {
360
        $stylesheets = $this->getStylesheets(['core']);
361
        $headScripts = $this->getJavascript('top');
362
        return view('assets::header', compact('stylesheets', 'headScripts'))->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...
363
    }
364
365
    /**
366
     * @return string
367
     * @throws \Throwable
368
     * @author Sang Nguyen
369
     */
370
    public function renderFooter()
371
    {
372
        $bodyScripts = $this->getJavascript('bottom');
373
        return view('assets::footer', compact('bodyScripts'))->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...
374
    }
375
}
376