Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — columns-link-to ( bd8a41...d52cfc )
by Pedro
22:21 queued 11:43
created

CrudButton::meta()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel;
4
5
use Backpack\CRUD\ViewNamespaces;
6
use Illuminate\Contracts\Support\Arrayable;
7
use Illuminate\Support\Traits\Conditionable;
8
9
/**
10
 * Adds fluent syntax to Backpack CRUD Buttons.
11
 *
12
 * In addition to the existing:
13
 * - CRUD::addButton('top', 'create', 'view', 'crud::buttons.create');
14
 *
15
 * Developers can also do:
16
 * - CRUD::button('create')->stack('top')->view('crud::buttons.create');
17
 *
18
 * And if the developer uses CrudButton as Button in their CrudController:
19
 * - Button::name('create')->stack('top')->view('crud::butons.create');
20
 */
21
class CrudButton implements Arrayable
22
{
23
    use Conditionable;
24
25
    public $stack;
26
27
    public $name;
28
29
    public $type;
30
31
    public $content;
32
33
    public $position;
34
35
    public $meta = [];
36
37
    public function __construct($nameOrAttributes, $stack = null, $type = null, $content = null, $position = null, $meta = [])
38
    {
39
        // in case an array was passed as name
40
        // assume it's an array that includes [$name, $stack, $type, $content]
41
        if (is_array($nameOrAttributes)) {
42
            extract($nameOrAttributes);
43
        }
44
45
        $this->name = $nameOrAttributes ?? 'button_'.rand(1, 999999999);
46
        $this->stack = $stack ?? 'top';
47
        $this->type = $type ?? 'view';
48
        $this->content = $content;
49
        $this->meta = $meta;
50
51
        // if no position was passed, the defaults are:
52
        // - 'beginning' for the 'line' stack
53
        // - 'end' for all other stacks
54
        $this->position = $position ?? ($this->stack == 'line' ? 'beginning' : 'end');
55
56
        return $this->save();
57
    }
58
59
    // ------
60
    // MAKERS
61
    // ------
62
63
    /**
64
     * Add a new button to the default stack.
65
     *
66
     * @param  string|array  $nameOrAttributes  Button name or array that contains name, stack, type and content.
67
     */
68
    public static function name($nameOrAttributes)
69
    {
70
        return new static($nameOrAttributes);
71
    }
72
73
    /**
74
     * Add a new button to the default stack.
75
     *
76
     * @param  string|array  $nameOrAttributes  Button name or array that contains name, stack, type and content.
77
     */
78
    public static function add($nameOrAttributes)
79
    {
80
        return new static($nameOrAttributes);
81
    }
82
83
    /**
84
     * This method allows one to create a button without attaching it to any 'real'
85
     * button stack, by moving it to a 'hidden' stack.
86
     *
87
     * It exists for one reason: so that developers can add buttons to a custom array, without
88
     * adding them to one of the button stacks.
89
     *
90
     * Ex: when developers need to pass multiple buttons as contents of the
91
     * div button. But they don't want them added to the before_content of after_content
92
     * stacks. So what they do is basically add them to a 'hidden' stack, that nobody will ever see.
93
     *
94
     * @param  string|array  $nameOrAttributes  Button name or array that contains name, stack, type and content.
95
     * @return CrudButton
96
     */
97
    public static function make($nameOrAttributes)
98
    {
99
        $button = static::add($nameOrAttributes);
100
        $button->stack('hidden');
101
102
        return $button;
103
    }
104
105
    // -------
106
    // SETTERS
107
    // -------
108
109
    /**
110
     * Set the button stack (where the button will be shown).
111
     *
112
     * @param  string  $stack  The name of the stack where the button should be moved.
113
     * @return CrudButton
114
     */
115
    public function stack($stack)
116
    {
117
        $this->stack = $stack;
118
119
        return $this->save();
120
    }
121
122
    /**
123
     * Sets the button type (view or model_function).
124
     *
125
     * @param  string  $type  The type of button - view or model_function.
126
     * @return CrudButton
127
     */
128
    public function type($type)
129
    {
130
        $this->type = $type;
131
132
        return $this->save();
133
    }
134
135
    /**
136
     * Sets the content of the button.
137
     * For the view button type, set it to the view path, including namespace.
138
     * For the model_function button type, set it to the name of the method on the model.
139
     *
140
     * @param  string  $content  Path to view or name of method on Model.
141
     * @return CrudButton
142
     */
143
    public function content($content)
144
    {
145
        $this->content = $content;
146
147
        return $this->save();
148
    }
149
150
    /**
151
     * Sets the namespace and path of the view for this button.
152
     * Sets the button type as 'view'.
153
     *
154
     * @param  string  $value  Path to view file.
155
     * @return CrudButton
156
     */
157
    public function view($value)
158
    {
159
        $this->content = $value;
160
        $this->type = 'view';
161
162
        return $this->save();
163
    }
164
165
    /**
166
     * Sets the meta that will be available in the view.
167
     *
168
     * @param  array  $value  Array of metadata that will be available in the view.
169
     * @return CrudButton
170
     */
171
    public function meta($value)
172
    {
173
        $this->meta = $value;
174
175
        return $this->save();
176
    }
177
178
    /**
179
     * Sets the name of the method on the model that contains the HTML for this button.
180
     * Sets the button type as 'model_function'.
181
     *
182
     * @param  string  $value  Name of the method on the model.
183
     * @return CrudButton
184
     */
185
    public function modelFunction($value)
186
    {
187
        $this->content = $value;
188
        $this->type = 'model_function';
189
        $this->stack = 'line';
190
191
        return $this->save();
192
    }
193
194
    /**
195
     * Sets the name of the method on the model that contains the HTML for this button.
196
     * Sets the button type as 'model_function'.
197
     * Alias of the modelFunction() method.
198
     *
199
     * @param  string  $value  Name of the method on the model.
200
     * @return CrudButton
201
     */
202
    public function model_function($value)
203
    {
204
        return $this->modelFunction($value);
205
    }
206
207
    /**
208
     * Unserts an property that is set on the current button.
209
     * Possible properties: name, stack, type, content.
210
     *
211
     * @param  string  $property  Name of the property that should be cleared.
212
     * @return CrudButton
213
     */
214
    public function forget($property)
215
    {
216
        $this->{$property} = null;
217
218
        return $this->save();
219
    }
220
221
    // --------------
222
    // SETTER ALIASES
223
    // --------------
224
225
    /**
226
     * Moves the button to a certain button stack.
227
     * Alias of stack().
228
     *
229
     * @param  string  $stack  The name of the stack where the button should be moved.
230
     * @return self
231
     */
232
    public function to($stack)
233
    {
234
        return $this->stack($stack);
235
    }
236
237
    /**
238
     * Moves the button to a certain button stack.
239
     * Alias of stack().
240
     *
241
     * @param  string  $stack  The name of the stack where the button should be moved.
242
     * @return self
243
     */
244
    public function group($stack)
245
    {
246
        return $this->stack($stack);
247
    }
248
249
    /**
250
     * Moves the button to a certain button stack.
251
     * Alias of stack().
252
     *
253
     * @param  string  $stack  The name of the stack where the button should be moved.
254
     * @return self
255
     */
256
    public function section($stack)
257
    {
258
        return $this->stack($stack);
259
    }
260
261
    // -------
262
    // GETTERS
263
    // -------
264
265
    /**
266
     * Get the end result that should be displayed to the user.
267
     * The HTML itself of the button.
268
     *
269
     * @param  object|null  $entry  The eloquent Model for the current entry or null if no current entry.
270
     * @return \Illuminate\Contracts\View\View
271
     */
272
    public function getHtml($entry = null)
273
    {
274
        $button = $this;
275
        $crud = $this->crud();
276
277
        if ($this->type == 'model_function') {
278
            if (is_null($entry)) {
279
                return $crud->model->{$button->content}($crud);
280
            }
281
282
            return $entry->{$button->content}($crud);
283
        }
284
285
        if ($this->type == 'view') {
286
            return view($button->getFinalViewPath(), compact('button', 'crud', 'entry'));
287
        }
288
289
        abort(500, 'Unknown button type');
290
    }
291
292
    /**
293
     * Get an array of full paths to the filter view, consisting of:
294
     * - the path given in the button definition
295
     * - fallback view paths as configured in backpack/config/crud.php.
296
     *
297
     * @return array
298
     */
299
    private function getViewPathsWithFallbacks()
300
    {
301
        $type = $this->name;
302
        $paths = array_map(function ($item) use ($type) {
303
            return $item.'.'.$type;
304
        }, ViewNamespaces::getFor('buttons'));
305
306
        return array_merge([$this->content], $paths);
307
    }
308
309
    private function getFinalViewPath()
310
    {
311
        foreach ($this->getViewPathsWithFallbacks() as $path) {
312
            if (view()->exists($path)) {
313
                return $path;
314
            }
315
        }
316
317
        abort(500, 'Button view and fallbacks do not exist for '.$this->name.' button.');
318
    }
319
320
    /**
321
     * Get the key for this button in the global buttons collection.
322
     *
323
     * @return int
324
     */
325
    public function getKey()
326
    {
327
        return $this->crud()->getButtonKey($this->name);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->crud()->getButtonKey($this->name) returns the type string which is incompatible with the documented return type integer.
Loading history...
328
    }
329
330
    // -----
331
    // ORDER
332
    // -----
333
    // Manipulate the button collection (inside the global CrudPanel object).
334
335
    /**
336
     * Move this button to be the first in the buttons list.
337
     *
338
     * @return CrudButton
339
     */
340
    public function makeFirst()
341
    {
342
        return $this->before($this->collection()->first()->name);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->before($th...ction()->first()->name) returns the type Backpack\CRUD\app\Library\CrudPanel\CrudFilter which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudButton.
Loading history...
343
    }
344
345
    /**
346
     * Move this button to be the last one in the buttons list.
347
     *
348
     * @return CrudButton
349
     */
350
    public function makeLast()
351
    {
352
        return $this->after($this->collection()->last()->name);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->after($thi...ection()->last()->name) returns the type Backpack\CRUD\app\Library\CrudPanel\CrudFilter which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudButton.
Loading history...
353
    }
354
355
    /**
356
     * Move the current filter after another filter.
357
     *
358
     * @param  string  $destination  Name of the destination filter.
359
     * @return CrudFilter
360
     */
361
    public function after($destination)
362
    {
363
        $this->crud()->moveButton($this->name, 'after', $destination);
364
365
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Backpack\CRUD\app\Library\CrudPanel\CrudButton which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudFilter.
Loading history...
366
    }
367
368
    /**
369
     * Move the current field before another field.
370
     *
371
     * @param  string  $destination  Name of the destination field.
372
     * @return CrudFilter
373
     */
374
    public function before($destination)
375
    {
376
        $this->crud()->moveButton($this->name, 'before', $destination);
377
378
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Backpack\CRUD\app\Library\CrudPanel\CrudButton which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudFilter.
Loading history...
379
    }
380
381
    /**
382
     * Remove the button from the global button collection.
383
     *
384
     * @return void
385
     */
386
    public function remove()
387
    {
388
        $this->crud()->removeButton($this->getKey());
389
    }
390
391
    // --------------
392
    // GLOBAL OBJECTS
393
    // --------------
394
    // Access to the objects stored in Laravel's service container.
395
396
    /**
397
     * Access the global collection when all buttons are stored.
398
     *
399
     * @return \Illuminate\Support\Collection
400
     */
401
    public function collection()
402
    {
403
        return $this->crud()->buttons();
404
    }
405
406
    /**
407
     * Access the global CrudPanel object.
408
     *
409
     * @return \Backpack\CRUD\app\Library\CrudPanel\CrudPanel
410
     */
411
    public function crud()
412
    {
413
        return app('crud');
414
    }
415
416
    // -----------------
417
    // DEBUGGING METHODS
418
    // -----------------
419
420
    /**
421
     * Dump the current object to the screen,
422
     * so that the developer can see its contents.
423
     *
424
     * @codeCoverageIgnore
425
     *
426
     * @return CrudButton
427
     */
428
    public function dump()
429
    {
430
        dump($this);
431
432
        return $this;
433
    }
434
435
    /**
436
     * Dump and die. Duumps the current object to the screen,
437
     * so that the developer can see its contents, then stops
438
     * the execution.
439
     *
440
     * @codeCoverageIgnore
441
     *
442
     * @return CrudButton
443
     */
444
    public function dd()
445
    {
446
        dd($this);
447
448
        return $this;
449
    }
450
451
    // ---------------
452
    // PRIVATE METHODS
453
    // ---------------
454
455
    /**
456
     * Update the global CrudPanel object with the current button.
457
     *
458
     * @return CrudButton
459
     */
460
    private function save()
461
    {
462
        if ($this->collection()->isEmpty()) {
463
            $this->crud()->addCrudButton($this);
464
465
            return $this;
466
        }
467
468
        $itemExists = $this->collection()->contains('name', $this->name);
469
470
        if (! $itemExists) {
471
            $this->crud()->addCrudButton($this);
472
            if ($this->position == 'beginning') {
473
                $this->before($this->collection()->first()->name);
474
            } else {
475
                $this->after($this->collection()->last()->name);
476
            }
477
478
            // clear the custom position, so that the next daisy chained method
479
            // doesn't move it yet again
480
            $this->position = null;
481
        } else {
482
            $this->crud()->modifyButton($this->name, $this->toArray());
483
        }
484
485
        return $this;
486
    }
487
488
    public function toArray()
489
    {
490
        return (array) $this;
491
    }
492
}
493