Renderer   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 5
dl 0
loc 126
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A render() 0 8 1
A normalizeArguments() 0 16 4
A buildJavaScriptSyntax() 0 10 1
A buildNamespaceDeclaration() 0 8 2
A buildVariableInitialization() 0 6 2
A optimizeValueForJavaScript() 0 4 1
A getAllTransformers() 0 6 1
A getTransformer() 0 10 3
1
<?php
2
3
namespace Spatie\BladeJavaScript;
4
5
use Illuminate\Config\Repository;
6
use Illuminate\Contracts\Support\Arrayable;
7
use Illuminate\Support\Collection;
8
use Spatie\BladeJavaScript\Exceptions\Untransformable;
9
use Spatie\BladeJavaScript\Transformers\ArrayTransformer;
10
use Spatie\BladeJavaScript\Transformers\BooleanTransformer;
11
use Spatie\BladeJavaScript\Transformers\NullTransformer;
12
use Spatie\BladeJavaScript\Transformers\NumericTransformer;
13
use Spatie\BladeJavaScript\Transformers\ObjectTransformer;
14
use Spatie\BladeJavaScript\Transformers\StringTransformer;
15
use Spatie\BladeJavaScript\Transformers\Transformer;
16
17
class Renderer
18
{
19
    protected $namespace = 'window';
20
21
    protected $transformers = [
22
        ArrayTransformer::class,
23
        BooleanTransformer::class,
24
        NullTransformer::class,
25
        NumericTransformer::class,
26
        ObjectTransformer::class,
27
        StringTransformer::class,
28
    ];
29
30
    public function __construct(Repository $config)
31
    {
32
        $this->namespace = $config->get('blade-javascript.namespace', 'window');
33
    }
34
35
    /**
36
     * @param array ...$arguments
37
     *
38
     * @return string
39
     *
40
     * @throws \Throwable
41
     */
42
    public function render(...$arguments): string
43
    {
44
        $variables = $this->normalizeArguments($arguments);
45
46
        return view('bladeJavaScript::index', [
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...
47
            'javaScript' => $this->buildJavaScriptSyntax($variables),
48
        ])->render();
49
    }
50
51
    /**
52
     * @param $arguments
53
     *
54
     * @return mixed
55
     */
56
    protected function normalizeArguments(array $arguments)
57
    {
58
        if (count($arguments) === 2) {
59
            return [$arguments[0] => $arguments[1]];
60
        }
61
62
        if ($arguments[0] instanceof Arrayable) {
63
            return $arguments[0]->toArray();
64
        }
65
66
        if (! is_array($arguments[0])) {
67
            $arguments[0] = [$arguments[0]];
68
        }
69
70
        return $arguments[0];
71
    }
72
73
    public function buildJavaScriptSyntax(array $variables): string
74
    {
75
        return collect($variables)
76
            ->map(function ($value, $key) {
77
                return $this->buildVariableInitialization($key, $value);
78
            })
79
            ->reduce(function ($javaScriptSyntax, $variableInitialization) {
80
                return $javaScriptSyntax.$variableInitialization;
81
            }, $this->buildNamespaceDeclaration());
82
    }
83
84
    protected function buildNamespaceDeclaration(): string
85
    {
86
        if (empty($this->namespace)) {
87
            return '';
88
        }
89
90
        return "window['{$this->namespace}'] = window['{$this->namespace}'] || {};";
91
    }
92
93
    /**
94
     * @param string $key
95
     * @param mixed  $value
96
     *
97
     * @return string
98
     */
99
    protected function buildVariableInitialization(string $key, $value)
100
    {
101
        $variableName = $this->namespace ? "window['{$this->namespace}']['{$key}']" : "window['{$key}']";
102
103
        return "{$variableName} = {$this->optimizeValueForJavaScript($value)};";
104
    }
105
106
    /**
107
     * @param mixed $value
108
     *
109
     * @return string
110
     *
111
     * @throws \Spatie\BladeJavaScript\Exceptions\Untransformable
112
     */
113
    protected function optimizeValueForJavaScript($value): string
114
    {
115
        return $this->getTransformer($value)->transform($value);
116
    }
117
118
    public function getAllTransformers(): Collection
119
    {
120
        return collect($this->transformers)->map(function (string $className): Transformer {
121
            return new $className();
122
        });
123
    }
124
125
    /**
126
     * @param mixed $value
127
     *
128
     * @return \Spatie\BladeJavaScript\Transformers\Transformer
129
     *
130
     * @throws \Spatie\BladeJavaScript\Exceptions\Untransformable
131
     */
132
    public function getTransformer($value): Transformer
133
    {
134
        foreach ($this->getAllTransformers() as $transformer) {
135
            if ($transformer->canTransform($value)) {
136
                return $transformer;
137
            }
138
        }
139
140
        throw Untransformable::noTransformerFound($value);
141
    }
142
}
143