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 — crud-uploads ( c657db...bf972d )
by Pedro
13:12
created

CrudField::upload()   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\app\Library\CrudPanel\Traits\Support\HasMacros;
6
use Illuminate\Support\Traits\Macroable;
7
8
/**
9
 * Adds fluent syntax to Backpack CRUD Fields.
10
 *
11
 * In addition to the existing:
12
 * - CRUD::addField(['name' => 'price', 'type' => 'number']);
13
 *
14
 * Developers can also do:
15
 * - CRUD::field('price')->type('number');
16
 *
17
 * And if the developer uses CrudField as Field in their CrudController:
18
 * - Field::name('price')->type('number');
19
 *
20
 * @method self type(string $value)
21
 * @method self label(string $value)
22
 * @method self tab(string $value)
23
 * @method self prefix(string $value)
24
 * @method self suffix(string $value)
25
 * @method self default(mixed $value)
26
 * @method self hint(string $value)
27
 * @method self attributes(array $value)
28
 * @method self wrapper(array $value)
29
 * @method self fake(bool $value)
30
 * @method self store_in(string $value)
31
 * @method self validationRules(string $value)
32
 * @method self validationMessages(array $value)
33
 * @method self entity(string $value)
34
 * @method self addMorphOption(string $key, string $label, array $options)
35
 * @method self morphTypeField(array $value)
36
 * @method self morphIdField(array $value)
37
 * @method self upload(bool $value)
38
 */
39
class CrudField
40
{
41
    use Macroable { __call as macroCall; }
0 ignored issues
show
Bug introduced by
The trait Illuminate\Support\Traits\Macroable requires the property $name which is not provided by Backpack\CRUD\app\Library\CrudPanel\CrudField.
Loading history...
42
    use HasMacros;
43
44
    protected $attributes;
45
46
    public function __construct($name)
47
    {
48
        if (empty($name)) {
49
            abort(500, 'Field name can\'t be empty.');
50
        }
51
52
        $field = $this->crud()->firstFieldWhere('name', $name);
53
54
        // if field exists
55
        if ((bool) $field) {
56
            // use all existing attributes
57
            $this->setAllAttributeValues($field);
0 ignored issues
show
Bug introduced by
$field of type boolean is incompatible with the type array expected by parameter $array of Backpack\CRUD\app\Librar...setAllAttributeValues(). ( Ignorable by Annotation )

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

57
            $this->setAllAttributeValues(/** @scrutinizer ignore-type */ $field);
Loading history...
58
        } else {
59
            // it means we're creating the field now,
60
            // so at the very least set the name attribute
61
            $this->setAttributeValue('name', $name);
62
        }
63
64
        $this->save();
65
    }
66
67
    public function crud()
68
    {
69
        return app()->make('crud');
70
    }
71
72
    /**
73
     * Create a CrudField object with the parameter as its name.
74
     *
75
     * @param  string  $name  Name of the column in the db, or model attribute.
76
     * @return CrudField
77
     */
78
    public static function name($name)
79
    {
80
        return new static($name);
81
    }
82
83
    /**
84
     * When defining the entity, make sure Backpack guesses the relationship attributes if needed.
85
     *
86
     * @param  string|bool  $entity
87
     * @return self
88
     */
89
    public function entity($entity)
90
    {
91
        $this->attributes['entity'] = $entity;
92
93
        if ($entity !== false) {
94
            $this->attributes = $this->crud()->makeSureFieldHasRelationshipAttributes($this->attributes);
95
        }
96
97
        return $this->save();
98
    }
99
100
    /**
101
     * Remove the current field from the current operation.
102
     *
103
     * @return void
104
     */
105
    public function remove()
106
    {
107
        $this->crud()->removeField($this->attributes['name']);
108
    }
109
110
    /**
111
     * Remove an attribute from the current field definition array.
112
     *
113
     * @param  string  $attribute  Name of the attribute being removed.
114
     * @return CrudField
115
     */
116
    public function forget($attribute)
117
    {
118
        $this->crud()->removeFieldAttribute($this->attributes['name'], $attribute);
119
120
        return $this;
121
    }
122
123
    /**
124
     * Move the current field after another field.
125
     *
126
     * @param  string  $destinationField  Name of the destination field.
127
     * @return CrudField
128
     */
129
    public function after($destinationField)
130
    {
131
        $this->crud()->removeField($this->attributes['name']);
132
        $this->crud()->addField($this->attributes)->afterField($destinationField);
133
134
        return $this;
135
    }
136
137
    /**
138
     * Move the current field before another field.
139
     *
140
     * @param  string  $destinationField  Name of the destination field.
141
     * @return CrudField
142
     */
143
    public function before($destinationField)
144
    {
145
        $this->crud()->removeField($this->attributes['name']);
146
        $this->crud()->addField($this->attributes)->beforeField($destinationField);
147
148
        return $this;
149
    }
150
151
    /**
152
     * Make the current field the first one in the fields list.
153
     *
154
     * @return CrudField
155
     */
156
    public function makeFirst()
157
    {
158
        $this->crud()->removeField($this->attributes['name']);
159
        $this->crud()->addField($this->attributes)->makeFirstField();
160
161
        return $this;
162
    }
163
164
    /**
165
     * Make the current field the last one in the fields list.
166
     *
167
     * @return CrudField
168
     */
169
    public function makeLast()
170
    {
171
        $this->crud()->removeField($this->attributes['name']);
172
        $this->crud()->addField($this->attributes);
173
174
        return $this;
175
    }
176
177
    // -------------------
178
    // CONVENIENCE METHODS
179
    // -------------------
180
    // These methods don't do exactly what advertised by their name.
181
    // They exist because the original syntax was too long.
182
183
    /**
184
     * Set the wrapper width at this many number of columns.
185
     * For example, to set a field wrapper to span across 6 columns, you can do both:
186
     * ->wrapper(['class' => 'form-group col-md-6'])
187
     * ->size(6).
188
     *
189
     * @param  int  $numberOfColumns  How many columns should this field span across (1-12)?
190
     * @return CrudField
191
     */
192
    public function size($numberOfColumns)
193
    {
194
        $this->attributes['wrapper']['class'] = 'form-group col-md-'.$numberOfColumns;
195
196
        return $this->save();
197
    }
198
199
    /**
200
     * Set an event to a certain closure. Will overwrite if existing.
201
     *
202
     * @param  string  $event  Name of Eloquent Model event
203
     * @param  \Closure  $closure  The function aka callback aka closure to run.
204
     * @return CrudField
205
     */
206
    public function on(string $event, \Closure $closure)
207
    {
208
        $this->attributes['events'][$event] = $closure;
209
210
        return $this->save();
211
    }
212
213
    /**
214
     * When subfields are defined, pass them through the guessing function
215
     * so that they have label, relationship attributes, etc.
216
     *
217
     * @param  array  $subfields  Subfield definition array
218
     * @return self
219
     */
220
    public function subfields($subfields)
221
    {
222
        $this->attributes['subfields'] = $subfields;
223
        $this->attributes = $this->crud()->makeSureFieldHasNecessaryAttributes($this->attributes);
224
        $this->crud()->callRegisteredAttributeMacros($this);
0 ignored issues
show
Bug introduced by
$this of type Backpack\CRUD\app\Library\CrudPanel\CrudField is incompatible with the type Backpack\CRUD\app\Library\CrudPanel\CrudColumn expected by parameter $macroable of Backpack\CRUD\app\Librar...steredAttributeMacros(). ( Ignorable by Annotation )

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

224
        $this->crud()->callRegisteredAttributeMacros(/** @scrutinizer ignore-type */ $this);
Loading history...
225
226
        return $this->save();
227
    }
228
229
    /**
230
     * Mark the field has having upload functionality, so that the form would become multipart.
231
     *
232
     * @param boolean $upload
233
     * @return self
234
     */
235
    public function upload($upload = true)
236
    {
237
        $this->attributes['upload'] = $upload;
238
239
        return $this->save();
240
    }
241
242
    /**
243
     * Save the validation rules on the CrudPanel per field basis.
244
     *
245
     * @param  string  $rules  the field rules: required|min:1|max:5
246
     * @return self
247
     */
248
    public function validationRules(string $rules)
249
    {
250
        $this->attributes['validationRules'] = $rules;
251
        $this->crud()->setValidationFromArray([$this->attributes['name'] => $rules]);
252
253
        return $this;
254
    }
255
256
    /**
257
     * Save the validation messages on the CrudPanel per field basis.
258
     *
259
     * @param  array  $messages  the messages for field rules: [required => please input something, min => the minimum allowed is 1]
260
     * @return self
261
     */
262
    public function validationMessages(array $messages)
263
    {
264
        $this->attributes['validationMessages'] = $messages;
265
266
        // append the field name to the rule name of validationMessages array.
267
        // eg: ['required => 'This field is required']
268
        // will be transformed into: ['field_name.required' => 'This field is required]
269
        $this->crud()->setValidationFromArray([], array_merge(...array_map(function ($rule, $message) {
270
            return [$this->attributes['name'].'.'.$rule => $message];
271
        }, array_keys($messages), $messages)));
272
273
        return $this;
274
    }
275
276
    /**
277
     * This function is responsible for setting up the morph fields structure.
278
     * Developer can define the morph structure as follows:
279
     *  'morphOptions => [
280
     *       ['nameOnAMorphMap', 'label', [options]],
281
     *       ['App\Models\Model'], // display the name of the model
282
     *       ['App\Models\Model', 'label', ['data_source' => backpack_url('smt')]
283
     *  ]
284
     * OR
285
     * ->addMorphOption('App\Models\Model', 'label', ['data_source' => backpack_url('smt')]).
286
     *
287
     * @param  string  $key  - the morph option key, usually a \Model\Class or a string for the morphMap
288
     * @param  string|null  $label  - the displayed text for this option
289
     * @param  array  $options  - options for the corresponding morphable_id field (usually ajax options)
290
     * @return self
291
     *
292
     * @throws \Exception
293
     */
294
    public function addMorphOption(string $key, $label = null, array $options = [])
295
    {
296
        $this->crud()->addMorphOption($this->attributes['name'], $key, $label, $options);
297
298
        return $this;
299
    }
300
301
    /**
302
     * Allow developer to configure the morph type field.
303
     *
304
     * @param  array  $configs
305
     * @return self
306
     *
307
     * @throws \Exception
308
     */
309
    public function morphTypeField(array $configs)
310
    {
311
        $morphField = $this->crud()->fields()[$this->attributes['name']];
312
313
        if (empty($morphField) || ($morphField['relation_type'] ?? '') !== 'MorphTo') {
314
            throw new \Exception('Trying to configure the morphType on a non-morphTo field. Check if field and relation name matches.');
315
        }
316
        [$morphTypeField, $morphIdField] = $morphField['subfields'];
317
318
        $morphTypeField = array_merge($morphTypeField, $configs);
319
320
        $morphField['subfields'] = [$morphTypeField, $morphIdField];
321
322
        $this->crud()->modifyField($this->attributes['name'], $morphField);
323
324
        return $this;
325
    }
326
327
    /**
328
     * Allow developer to configure the morph type id selector.
329
     *
330
     * @param  array  $configs
331
     * @return self
332
     *
333
     * @throws \Exception
334
     */
335
    public function morphIdField(array $configs)
336
    {
337
        $morphField = $this->crud()->fields()[$this->attributes['name']];
338
339
        if (empty($morphField) || ($morphField['relation_type'] ?? '') !== 'MorphTo') {
340
            throw new \Exception('Trying to configure the morphType on a non-morphTo field. Check if field and relation name matches.');
341
        }
342
343
        [$morphTypeField, $morphIdField] = $morphField['subfields'];
344
345
        $morphIdField = array_merge($morphIdField, $configs);
346
347
        $morphField['subfields'] = [$morphTypeField, $morphIdField];
348
349
        $this->crud()->modifyField($this->attributes['name'], $morphField);
350
351
        return $this;
352
    }
353
354
    public function getAttributes()
355
    {
356
        return $this->attributes;
357
    }
358
    // ---------------
359
    // PRIVATE METHODS
360
    // ---------------
361
362
    /**
363
     * Set the value for a certain attribute on the CrudField object.
364
     *
365
     * @param  string  $attribute  Name of the attribute.
366
     * @param  mixed  $value  Value of that attribute.
367
     */
368
    private function setAttributeValue($attribute, $value)
369
    {
370
        $this->attributes[$attribute] = $value;
371
    }
372
373
    /**
374
     * Replace all field attributes on the CrudField object
375
     * with the given array of attribute-value pairs.
376
     *
377
     * @param  array  $array  Array of attributes and their values.
378
     */
379
    private function setAllAttributeValues($array)
380
    {
381
        $this->attributes = $array;
382
    }
383
384
    /**
385
     * Update the global CrudPanel object with the current field attributes.
386
     *
387
     * @return CrudField
388
     */
389
    private function save()
390
    {
391
        $key = $this->attributes['name'];
392
393
        if ($this->crud()->hasFieldWhere('name', $key)) {
394
            $this->crud()->modifyField($key, $this->attributes);
395
        } else {
396
            $this->crud()->addField($this->attributes);
397
        }
398
399
        return $this;
400
    }
401
402
    // -----------------
403
    // DEBUGGING METHODS
404
    // -----------------
405
406
    /**
407
     * Dump the current object to the screen,
408
     * so that the developer can see its contents.
409
     *
410
     * @codeCoverageIgnore
411
     *
412
     * @return CrudField
413
     */
414
    public function dump()
415
    {
416
        dump($this);
417
418
        return $this;
419
    }
420
421
    /**
422
     * Dump and die. Duumps the current object to the screen,
423
     * so that the developer can see its contents, then stops
424
     * the execution.
425
     *
426
     * @codeCoverageIgnore
427
     *
428
     * @return CrudField
429
     */
430
    public function dd()
431
    {
432
        dd($this);
433
434
        return $this;
435
    }
436
437
    // -------------
438
    // MAGIC METHODS
439
    // -------------
440
441
    /**
442
     * If a developer calls a method that doesn't exist, assume they want:
443
     * - the CrudField object to have an attribute with that value;
444
     * - that field be updated inside the global CrudPanel object;.
445
     *
446
     * Eg: type('number') will set the "type" attribute to "number"
447
     *
448
     * @param  string  $method  The method being called that doesn't exist.
449
     * @param  array  $parameters  The arguments when that method was called.
450
     * @return CrudField
451
     */
452
    public function __call($method, $parameters)
453
    {
454
        if (static::hasMacro($method)) {
455
            return $this->macroCall($method, $parameters);
0 ignored issues
show
Bug introduced by
The method macroCall() does not exist on Backpack\CRUD\app\Library\CrudPanel\CrudField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

455
            return $this->/** @scrutinizer ignore-call */ macroCall($method, $parameters);
Loading history...
456
        }
457
458
        $this->setAttributeValue($method, $parameters[0]);
459
460
        return $this->save();
461
    }
462
}
463