Issues (18)

src/JavaScript.php (13 issues)

1
<?php namespace Blok\JavaScript;
2
3
use Illuminate\Support\Arr;
4
5
/**
6
 * Class JavaScript
7
 *
8
 * @package Blok\JavaScript
9
 *
10
 * @see https://github.com/cretueusebiu/laravel-javascript
11
 * @see https://github.com/laracasts/PHP-Vars-To-Js-Transformer
12
 */
13
class JavaScript
14
{
15
    /**
16
     * @var string
17
     */
18
    private static $globalNamespace = 'JavaScript';
19
20
    /**
21
     * Globals namespace
22
     * @var string
23
     */
24
    private $namespace = '__app';
25
26
    private static $_instances = [];
27
28
    /**
29
     * Selected data
30
     * @var null
31
     */
32
    private $activeData = null;
33
34
    /**
35
     * JavaScript constructor.
36
     * @param null $namespace
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $namespace is correct as it would always require null to be passed?
Loading history...
37
     *
38
     * @example
39
     * $js = new JavaScript('__globals');
40
     * $js->set('foo', 'bar');
41
     */
42
    public function __construct($namespace = null)
43
    {
44
        if (!is_string($namespace)) {
0 ignored issues
show
The condition is_string($namespace) is always false.
Loading history...
45
            $namespace = null;
46
        }
47
48
        if ($namespace) {
0 ignored issues
show
$namespace is of type null, thus it always evaluated to false.
Loading history...
49
            $this->namespace = $namespace;
50
        }
51
52
        if (!isset($GLOBALS[static::$globalNamespace])) {
0 ignored issues
show
Since $globalNamespace is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $globalNamespace to at least protected.
Loading history...
53
            $GLOBALS[static::$globalNamespace] = [];
54
        }
55
56
        if (!isset($GLOBALS[static::$globalNamespace][$this->namespace])) {
57
            $GLOBALS[static::$globalNamespace][$this->namespace] = [];
58
        }
59
60
        self::$_instances[$this->namespace] = $this;
61
    }
62
63
    /**
64
     * Calling methods statically
65
     * @param $name
66
     * @param $arguments
67
     * @return mixed
68
     * @throws \Exception
69
     */
70
    public static function __callStatic($name, $arguments)
71
    {
72
        $instance = new self();
73
74
        if (method_exists($instance, $name)) {
75
            return call_user_func_array([$instance, $name], $arguments);
76
        }
77
78
        throw new \Exception('[' . static::class . '::' . $name . '] method is not implemented');
79
    }
80
81
    /**
82
     * Magic getter
83
     * @param $name
84
     * @return mixed
85
     */
86
    public function __get($name)
87
    {
88
        return $this->get($name);
89
    }
90
91
    /**
92
     * Magic setter
93
     * @param $name
94
     * @param $value
95
     * @return JavaScript
96
     */
97
    public function __set($name, $value)
98
    {
99
        return $this->set($name, $value);
100
    }
101
102
    /**
103
     * Remove one or many array items from a given array using "dot" notation.
104
     * @param array|string $keys
105
     * @return $this
106
     */
107
    public function forget($keys)
108
    {
109
        $data = $this->getActiveData();
110
        $this->setActiveData(Arr::forget($data, $keys), false);
0 ignored issues
show
Are you sure the usage of Illuminate\Support\Arr::forget($data, $keys) targeting Illuminate\Support\Arr::forget() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
111
112
        return $this;
113
    }
114
115
    /**
116
     * Check if an item or items exist in an array using "dot" notation.
117
     *
118
     * @param  string|array $keys
119
     * @return bool
120
     */
121
    public function has($keys)
122
    {
123
        return Arr::has($GLOBALS[static::$globalNamespace][$this->namespace], $keys);
0 ignored issues
show
Since $globalNamespace is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $globalNamespace to at least protected.
Loading history...
124
    }
125
126
    /**
127
     * Get an item from an array using "dot" notation.
128
     *
129
     * @param  string $key
130
     * @param  mixed $default
131
     * @return mixed
132
     */
133
    public function get($key = null, $default = null)
134
    {
135
        $data = $this->getActiveData();
136
137
        if (is_null($key)) {
138
            return $data;
139
        }
140
141
        return Arr::get($data, $key, $default);
142
    }
143
144
    /**
145
     * Set an array item to a given value using "dot" notation.
146
     *
147
     * @param  string $key
148
     * @param  mixed $value
149
     * @return $this
150
     */
151
    public function set($key, $value = null)
152
    {
153
        if (is_null($value)) {
154
            $key = Arr::wrap($key);
155
156
            $this->merge($key);
157
158
            return $this;
159
        } elseif (isset($GLOBALS[static::$globalNamespace][$this->namespace][$key]) && is_array($value)) {
0 ignored issues
show
Since $globalNamespace is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $globalNamespace to at least protected.
Loading history...
160
            foreach ($value as $item) {
161
                if (!in_array($item, $GLOBALS[static::$globalNamespace][$this->namespace][$key])) {
162
                    $GLOBALS[static::$globalNamespace][$this->namespace][$key][] = $item;
163
                }
164
            }
165
        } else {
166
            Arr::set($GLOBALS[static::$globalNamespace][$this->namespace], $key, $value);
167
        }
168
169
        return $this;
170
    }
171
172
    /**
173
     * @alias Javascript::set()
174
     * @param $key
175
     * @param $value
176
     * @return JavaScript
177
     */
178
    public function add($key, $value = null){
179
        return $this->set($key, $value);
180
    }
181
182
    /**
183
     * Set the namespace
184
     * @param $namespace
185
     * @return $this
186
     */
187
    public static function namespace($namespace)
188
    {
189
        if (!isset(self::$_instances[$namespace])) {
190
            self::$_instances[$namespace] = new static($namespace);
191
        }
192
193
        return self::$_instances[$namespace];
194
    }
195
196
    /**
197
     * Flatten a multi-dimensional associative array with dots.
198
     *
199
     * @param  string $prepend
200
     * @return $this
201
     */
202
    public function dot($prepend = '')
203
    {
204
        $data = $this->getActiveData();
205
        $this->setActiveData(Arr::dot($data, $prepend));
206
207
        return $this;
208
    }
209
210
    /**
211
     * Get a subset of the items from the given array.
212
     *
213
     * @param  array|string $keys
214
     * @return $this
215
     */
216
    public function only($keys)
217
    {
218
        $data = $this->getActiveData();
219
        $this->setActiveData(Arr::only($data, $keys));
220
221
        return $this;
222
    }
223
224
    /**
225
     * Pluck an array of values from an array.
226
     *
227
     * @param  string|array|null $value
228
     * @param null $key
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $key is correct as it would always require null to be passed?
Loading history...
229
     * @return $this
230
     */
231
    public function pluck($value, $key = null)
232
    {
233
        $data = $this->getActiveData();
234
        $this->setActiveData(Arr::pluck($data, $value, $key));
235
236
        return $this;
237
    }
238
239
    /**
240
     * Filter the array using the given callback.
241
     *
242
     * @param  callable $callback
243
     * @return $this
244
     */
245
    public function where(callable $callback)
246
    {
247
        $data = $this->getActiveData();
248
        $this->setActiveData(Arr::where($data, $callback));
249
250
        return $this;
251
    }
252
253
    /**
254
     * Merge the given arrays
255
     *
256
     * @param  array * $arrays
257
     * @return $this
258
     * @throws \Exception
259
     */
260
    public function merge()
261
    {
262
        $arrays = func_get_args();
263
264
        foreach ($arrays as $array) {
265
            if (!is_array($array)) {
266
                throw new \Exception('[Hook::merge] all arguments must be Array.');
267
            }
268
269
            foreach ($array as $key => $value) {
270
                if ($this->has($key)) {
271
                    $tmp = $this->get($key);
272
273
                    if (is_array($tmp)) {
274
                        $value = Arr::wrap($value);
275
                        $value = array_merge_recursive($tmp, $value);
276
                    }
277
                }
278
279
                $this->set($key, $value);
280
            }
281
        }
282
283
        return $this;
284
    }
285
286
    /**
287
     * JSON encode
288
     * @return string
289
     */
290
    public function toJson()
291
    {
292
        return json_encode($this->get(), true);
0 ignored issues
show
true of type true is incompatible with the type integer expected by parameter $options of json_encode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

292
        return json_encode($this->get(), /** @scrutinizer ignore-type */ true);
Loading history...
293
    }
294
295
    /**
296
     * Render as Script tag
297
     * @param null $varName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $varName is correct as it would always require null to be passed?
Loading history...
298
     * @param array $variables
299
     * @param bool $scriptTag
300
     * @return string
301
     * @internal param null $namespace
302
     */
303
    public function render($varName = null, $variables = [], $scriptTag = true)
304
    {
305
        if (is_null($varName)) {
0 ignored issues
show
The condition is_null($varName) is always true.
Loading history...
306
            $varName = $this->namespace;
307
        }
308
309
        $this->merge($variables);
310
311
        return ($scriptTag?'<script>':'').'window.' . $varName . ' = ' . $this->toJson() . ';'.($scriptTag?'</script>':'');
312
    }
313
314
    public function renderVar($namespace = null, $variables = []){
315
        return $this->render($namespace, $variables, false);
316
    }
317
318
    /**
319
     * Retrieve selected data
320
     * @return mixed|null
321
     */
322
    private function getActiveData()
323
    {
324
        if (!is_null($this->activeData)) {
325
            return $this->activeData;
326
        }
327
328
        return $GLOBALS[static::$globalNamespace][$this->namespace];
0 ignored issues
show
Since $globalNamespace is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $globalNamespace to at least protected.
Loading history...
329
    }
330
331
    /**
332
     * Set selected data
333
     * @param $data
334
     */
335
    private function setActiveData($data, $force = true)
336
    {
337
        if ($force) {
338
            $this->activeData = $data;
339
        } else {
340
            $GLOBALS[static::$globalNamespace][$this->namespace] = $data;
0 ignored issues
show
Since $globalNamespace is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $globalNamespace to at least protected.
Loading history...
341
        }
342
    }
343
}