Completed
Pull Request — master (#1281)
by
unknown
02:32
created

Tree::disableSave()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Encore\Admin;
4
5
use Closure;
6
use Encore\Admin\Tree\Tools;
7
use Illuminate\Contracts\Support\Renderable;
8
use Illuminate\Database\Eloquent\Model;
9
10
class Tree implements Renderable
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $items = [];
16
17
    /**
18
     * @var string
19
     */
20
    protected $elementId = 'tree-';
21
22
    /**
23
     * @var Model
24
     */
25
    protected $model;
26
27
    /**
28
     * @var \Closure
29
     */
30
    protected $queryCallback;
31
32
    /**
33
     * View of tree to render.
34
     *
35
     * @var string
36
     */
37
    protected $view = [
38
        'tree'      => 'admin::tree',
39
        'branch'    => 'admin::tree.branch',
40
    ];
41
42
    /**
43
     * @var \Closure
44
     */
45
    protected $callback;
46
47
    /**
48
     * @var null
49
     */
50
    protected $branchCallback = null;
51
52
    /**
53
     * @var bool
54
     */
55
    public $useCreate = true;
56
57
    /**
58
     * @var bool
59
     */
60
    public $useSave = true;
61
62
    /**
63
     * @var bool
64
     */
65
    public $useRefresh = true;
66
67
    /**
68
     * @var array
69
     */
70
    protected $nestableOptions = [];
71
72
    /**
73
     * Header tools.
74
     *
75
     * @var Tools
76
     */
77
    public $tools;
78
79
    /**
80
     * Menu constructor.
81
     *
82
     * @param Model|null $model
83
     */
84
    public function __construct(Model $model = null, \Closure $callback = null)
85
    {
86
        $this->model = $model;
87
88
        $this->path = app('request')->getPathInfo();
0 ignored issues
show
Bug introduced by
The property path does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
89
        $this->elementId .= uniqid();
90
91
        $this->setupTools();
92
93
        if ($callback instanceof \Closure) {
94
            call_user_func($callback, $this);
95
        }
96
97
        $this->initBranchCallback();
98
    }
99
100
    /**
101
     * Setup tree tools.
102
     */
103
    public function setupTools()
104
    {
105
        $this->tools = new Tools($this);
106
    }
107
108
    /**
109
     * Initialize branch callback.
110
     *
111
     * @return void
112
     */
113
    protected function initBranchCallback()
114
    {
115
        if (is_null($this->branchCallback)) {
116
            $this->branchCallback = function ($branch) {
0 ignored issues
show
Documentation Bug introduced by
It seems like function ($branch) { ... "{$key} - {$title}"; } of type object<Closure> is incompatible with the declared type null of property $branchCallback.

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...
117
                $key = $branch[$this->model->getKeyName()];
118
                $title = $branch[$this->model->getTitleColumn()];
119
120
                return "$key - $title";
121
            };
122
        }
123
    }
124
125
    /**
126
     * Set branch callback.
127
     *
128
     * @param \Closure $branchCallback
129
     *
130
     * @return $this
131
     */
132
    public function branch(\Closure $branchCallback)
133
    {
134
        $this->branchCallback = $branchCallback;
0 ignored issues
show
Documentation Bug introduced by
It seems like $branchCallback of type object<Closure> is incompatible with the declared type null of property $branchCallback.

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...
135
136
        return $this;
137
    }
138
139
    /**
140
     * Set query callback this tree.
141
     *
142
     * @return Model
143
     */
144
    public function query(\Closure $callback)
145
    {
146
        $this->queryCallback = $callback;
147
148
        return $this;
149
    }
150
151
    /**
152
     * Set nestable options.
153
     *
154
     * @param array $options
155
     *
156
     * @return $this
157
     */
158
    public function nestable($options = [])
159
    {
160
        $this->nestableOptions = array_merge($this->nestableOptions, $options);
161
162
        return $this;
163
    }
164
165
    /**
166
     * Disable create.
167
     *
168
     * @return void
169
     */
170
    public function disableCreate()
171
    {
172
        $this->useCreate = false;
173
    }
174
175
    /**
176
     * Disable save.
177
     *
178
     * @return void
179
     */
180
    public function disableSave()
181
    {
182
        $this->useSave = false;
183
    }
184
185
    /**
186
     * Disable refresh.
187
     *
188
     * @return void
189
     */
190
    public function disableRefresh()
191
    {
192
        $this->useRefresh = false;
193
    }
194
195
    /**
196
     * Save tree order from a input.
197
     *
198
     * @param string $serialize
199
     *
200
     * @return bool
201
     */
202
    public function saveOrder($serialize)
203
    {
204
        $tree = json_decode($serialize, true);
205
206
        if (json_last_error() != JSON_ERROR_NONE) {
207
            throw new \InvalidArgumentException(json_last_error_msg());
208
        }
209
210
        $this->model->saveOrder($tree);
211
212
        return true;
213
    }
214
215
    /**
216
     * Build tree grid scripts.
217
     *
218
     * @return string
219
     */
220
    protected function script()
221
    {
222
        $deleteConfirm = trans('admin.delete_confirm');
223
        $saveSucceeded = trans('admin.save_succeeded');
224
        $refreshSucceeded = trans('admin.refresh_succeeded');
225
        $deleteSucceeded = trans('admin.delete_succeeded');
0 ignored issues
show
Unused Code introduced by
$deleteSucceeded 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...
226
        $confirm = trans('admin.confirm');
227
        $cancel = trans('admin.cancel');
228
229
        $nestableOptions = json_encode($this->nestableOptions);
230
231
        return <<<SCRIPT
232
233
        $('#{$this->elementId}').nestable($nestableOptions);
234
235
        $('.tree_branch_delete').click(function() {
236
            var id = $(this).data('id');
237
            swal({
238
              title: "$deleteConfirm",
239
              type: "warning",
240
              showCancelButton: true,
241
              confirmButtonColor: "#DD6B55",
242
              confirmButtonText: "$confirm",
243
              closeOnConfirm: false,
244
              cancelButtonText: "$cancel"
245
            },
246
            function(){
247
                $.ajax({
248
                    method: 'post',
249
                    url: '{$this->path}/' + id,
250
                    data: {
251
                        _method:'delete',
252
                        _token:LA.token,
253
                    },
254
                    success: function (data) {
255
                        $.pjax.reload('#pjax-container');
256
257
                        if (typeof data === 'object') {
258
                            if (data.status) {
259
                                swal(data.message, '', 'success');
260
                            } else {
261
                                swal(data.message, '', 'error');
262
                            }
263
                        }
264
                    }
265
                });
266
            });
267
        });
268
269
        $('.{$this->elementId}-save').click(function () {
270
            var serialize = $('#{$this->elementId}').nestable('serialize');
271
272
            $.post('{$this->path}', {
273
                _token: LA.token,
274
                _order: JSON.stringify(serialize)
275
            },
276
            function(data){
277
                $.pjax.reload('#pjax-container');
278
                toastr.success('{$saveSucceeded}');
279
            });
280
        });
281
282
        $('.{$this->elementId}-refresh').click(function () {
283
            $.pjax.reload('#pjax-container');
284
            toastr.success('{$refreshSucceeded}');
285
        });
286
287
        $('.{$this->elementId}-tree-tools').on('click', function(e){
288
            var target = $(e.target),
289
                action = target.data('action');
290
            if (action === 'expand') {
291
                $('.dd').nestable('expandAll');
292
            }
293
            if (action === 'collapse') {
294
                $('.dd').nestable('collapseAll');
295
            }
296
        });
297
298
299
SCRIPT;
300
    }
301
302
    /**
303
     * Set view of tree.
304
     *
305
     * @param string $view
306
     */
307
    public function setView($view)
308
    {
309
        $this->view = $view;
310
    }
311
312
    /**
313
     * Return all items of the tree.
314
     *
315
     * @param array $items
0 ignored issues
show
Bug introduced by
There is no parameter named $items. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
316
     */
317
    public function getItems()
318
    {
319
        return $this->model->withQuery($this->queryCallback)->toTree();
320
    }
321
322
    /**
323
     * Variables in tree template.
324
     *
325
     * @return array
326
     */
327
    public function variables()
328
    {
329
        return [
330
            'id'        => $this->elementId,
331
            'tools'     => $this->tools->render(),
332
            'items'     => $this->getItems(),
333
            'useCreate' => $this->useCreate,
334
            'useSave'   => $this->useSave,
335
            'useRefresh'=> $this->useRefresh,
336
        ];
337
    }
338
339
    /**
340
     * Setup grid tools.
341
     *
342
     * @param Closure $callback
343
     *
344
     * @return void
345
     */
346
    public function tools(Closure $callback)
347
    {
348
        call_user_func($callback, $this->tools);
349
    }
350
351
    /**
352
     * Render a tree.
353
     *
354
     * @return \Illuminate\Http\JsonResponse|string
355
     */
356
    public function render()
357
    {
358
        Admin::script($this->script());
359
360
        view()->share([
0 ignored issues
show
Bug introduced by
The method share does only exist in Illuminate\Contracts\View\Factory, but not in Illuminate\View\View.

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...
361
            'path'           => $this->path,
362
            'keyName'        => $this->model->getKeyName(),
363
            'branchView'     => $this->view['branch'],
364
            'branchCallback' => $this->branchCallback,
365
        ]);
366
367
        return view($this->view['tree'], $this->variables())->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...
368
    }
369
370
    /**
371
     * Get the string contents of the grid view.
372
     *
373
     * @return string
374
     */
375
    public function __toString()
376
    {
377
        return $this->render();
378
    }
379
}
380