Completed
Push — master ( e22186...b6a9dc )
by Song
02:47
created

Builder::isCreating()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Form;
4
5
use Encore\Admin\Admin;
6
use Encore\Admin\Form;
7
use Encore\Admin\Form\Field\Hidden;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Facades\URL;
10
use Illuminate\Support\Str;
11
12
/**
13
 * Class Builder.
14
 */
15
class Builder
16
{
17
    /**
18
     *  Previous url key.
19
     */
20
    const PREVIOUS_URL_KEY = '_previous_';
21
22
    /**
23
     * @var mixed
24
     */
25
    protected $id;
26
27
    /**
28
     * @var Form
29
     */
30
    protected $form;
31
32
    /**
33
     * @var
34
     */
35
    protected $action;
36
37
    /**
38
     * @var Collection
39
     */
40
    protected $fields;
41
42
    /**
43
     * @var array
44
     */
45
    protected $options = [];
46
47
    /**
48
     * Modes constants.
49
     */
50
    const MODE_EDIT = 'edit';
51
    const MODE_CREATE = 'create';
52
53
    /**
54
     * Form action mode, could be create|view|edit.
55
     *
56
     * @var string
57
     */
58
    protected $mode = 'create';
59
60
    /**
61
     * @var array
62
     */
63
    protected $hiddenFields = [];
64
65
    /**
66
     * @var Tools
67
     */
68
    protected $tools;
69
70
    /**
71
     * @var Footer
72
     */
73
    protected $footer;
74
75
    /**
76
     * Width for label and field.
77
     *
78
     * @var array
79
     */
80
    protected $width = [
81
        'label' => 2,
82
        'field' => 8,
83
    ];
84
85
    /**
86
     * View for this form.
87
     *
88
     * @var string
89
     */
90
    protected $view = 'admin::form';
91
92
    /**
93
     * Form title.
94
     *
95
     * @var string
96
     */
97
    protected $title;
98
99
    /**
100
     * Builder constructor.
101
     *
102
     * @param Form $form
103
     */
104
    public function __construct(Form $form)
105
    {
106
        $this->form = $form;
107
108
        $this->fields = new Collection();
109
110
        $this->init();
111
    }
112
113
    /**
114
     * Do initialize.
115
     */
116
    public function init()
117
    {
118
        $this->tools = new Tools($this);
119
        $this->footer = new Footer($this);
120
    }
121
122
    /**
123
     * Get form tools instance.
124
     *
125
     * @return Tools
126
     */
127
    public function getTools()
128
    {
129
        return $this->tools;
130
    }
131
132
    /**
133
     * Get form footer instance.
134
     *
135
     * @return Footer
136
     */
137
    public function getFooter()
138
    {
139
        return $this->footer;
140
    }
141
142
    /**
143
     * Set the builder mode.
144
     *
145
     * @param string $mode
146
     *
147
     * @return void
148
     */
149
    public function setMode($mode = 'create')
150
    {
151
        $this->mode = $mode;
152
    }
153
154
    /**
155
     * @return string
156
     */
157
    public function getMode()
158
    {
159
        return $this->mode;
160
    }
161
162
    /**
163
     * Returns builder is $mode.
164
     *
165
     * @param $mode
166
     *
167
     * @return bool
168
     */
169
    public function isMode($mode)
170
    {
171
        return $this->mode == $mode;
172
    }
173
174
    /**
175
     * Check if is creating resource.
176
     *
177
     * @return bool
178
     */
179
    public function isCreating()
180
    {
181
        return $this->isMode(static::MODE_CREATE);
182
    }
183
184
    /**
185
     * Check if is editing resource.
186
     *
187
     * @return bool
188
     */
189
    public function isEditing()
190
    {
191
        return $this->isMode(static::MODE_EDIT);
192
    }
193
194
    /**
195
     * Set resource Id.
196
     *
197
     * @param $id
198
     *
199
     * @return void
200
     */
201
    public function setResourceId($id)
202
    {
203
        $this->id = $id;
204
    }
205
206
    /**
207
     * Get Resource id.
208
     *
209
     * @return mixed
210
     */
211
    public function getResourceId()
212
    {
213
        return $this->id;
214
    }
215
216
    /**
217
     * @return string
218
     */
219
    public function getResource($slice = null)
220
    {
221
        if ($this->mode == self::MODE_CREATE) {
222
            return $this->form->resource(-1);
223
        }
224
        if ($slice !== null) {
225
            return $this->form->resource($slice);
226
        }
227
228
        return $this->form->resource();
229
    }
230
231
    /**
232
     * @param int $field
233
     * @param int $label
234
     *
235
     * @return $this
236
     */
237
    public function setWidth($field = 8, $label = 2)
238
    {
239
        $this->width = [
240
            'label' => $label,
241
            'field' => $field,
242
        ];
243
244
        return $this;
245
    }
246
247
    /**
248
     * Get label and field width.
249
     *
250
     * @return array
251
     */
252
    public function getWidth()
253
    {
254
        return $this->width;
255
    }
256
257
    /**
258
     * Set form action.
259
     *
260
     * @param string $action
261
     */
262
    public function setAction($action)
263
    {
264
        $this->action = $action;
265
    }
266
267
    /**
268
     * Get Form action.
269
     *
270
     * @return string
271
     */
272
    public function getAction()
273
    {
274
        if ($this->action) {
275
            return $this->action;
276
        }
277
278
        if ($this->isMode(static::MODE_EDIT)) {
279
            return $this->form->resource().'/'.$this->id;
280
        }
281
282
        if ($this->isMode(static::MODE_CREATE)) {
283
            return $this->form->resource(-1);
284
        }
285
286
        return '';
287
    }
288
289
    /**
290
     * Set view for this form.
291
     *
292
     * @param string $view
293
     *
294
     * @return $this
295
     */
296
    public function setView($view)
297
    {
298
        $this->view = $view;
299
300
        return $this;
301
    }
302
303
    /**
304
     * Set title for form.
305
     *
306
     * @param string $title
307
     *
308
     * @return $this
309
     */
310
    public function setTitle($title)
311
    {
312
        $this->title = $title;
313
314
        return $this;
315
    }
316
317
    /**
318
     * Get fields of this builder.
319
     *
320
     * @return Collection
321
     */
322
    public function fields()
323
    {
324
        return $this->fields;
325
    }
326
327
    /**
328
     * Get specify field.
329
     *
330
     * @param string $name
331
     *
332
     * @return mixed
333
     */
334
    public function field($name)
335
    {
336
        return $this->fields()->first(function (Field $field) use ($name) {
337
            return $field->column() == $name;
338
        });
339
    }
340
341
    /**
342
     * If the parant form has rows.
343
     *
344
     * @return bool
345
     */
346
    public function hasRows()
347
    {
348
        return !empty($this->form->rows);
349
    }
350
351
    /**
352
     * Get field rows of form.
353
     *
354
     * @return array
355
     */
356
    public function getRows()
357
    {
358
        return $this->form->rows;
359
    }
360
361
    /**
362
     * @return array
363
     */
364
    public function getHiddenFields()
365
    {
366
        return $this->hiddenFields;
367
    }
368
369
    /**
370
     * @param Field $field
371
     *
372
     * @return void
373
     */
374
    public function addHiddenField(Field $field)
375
    {
376
        $this->hiddenFields[] = $field;
377
    }
378
379
    /**
380
     * Add or get options.
381
     *
382
     * @param array $options
383
     *
384
     * @return array|null
385
     */
386
    public function options($options = [])
387
    {
388
        if (empty($options)) {
389
            return $this->options;
390
        }
391
392
        $this->options = array_merge($this->options, $options);
393
    }
394
395
    /**
396
     * Get or set option.
397
     *
398
     * @param string $option
399
     * @param mixed  $value
400
     *
401
     * @return $this
402
     */
403
    public function option($option, $value = null)
404
    {
405
        if (func_num_args() == 1) {
406
            return array_get($this->options, $option);
407
        }
408
409
        $this->options[$option] = $value;
410
411
        return $this;
412
    }
413
414
    /**
415
     * @return string
416
     */
417
    public function title()
418
    {
419
        if ($this->title) {
420
            return $this->title;
421
        }
422
423
        if ($this->mode == static::MODE_CREATE) {
424
            return trans('admin.create');
425
        }
426
427
        if ($this->mode == static::MODE_EDIT) {
428
            return trans('admin.edit');
429
        }
430
431
        return '';
432
    }
433
434
    /**
435
     * Determine if form fields has files.
436
     *
437
     * @return bool
438
     */
439
    public function hasFile()
440
    {
441
        foreach ($this->fields() as $field) {
442
            if ($field instanceof Field\File) {
443
                return true;
444
            }
445
        }
446
447
        return false;
448
    }
449
450
    /**
451
     * Add field for store redirect url after update or store.
452
     *
453
     * @return void
454
     */
455
    protected function addRedirectUrlField()
456
    {
457
        $previous = URL::previous();
458
459
        if (!$previous || $previous == URL::current()) {
460
            return;
461
        }
462
463
        if (Str::contains($previous, url($this->getResource()))) {
0 ignored issues
show
Bug introduced by
It seems like url($this->getResource()) targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Illuminate\Support\Str::contains() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
464
            $this->addHiddenField((new Hidden(static::PREVIOUS_URL_KEY))->value($previous));
465
        }
466
    }
467
468
    /**
469
     * Open up a new HTML form.
470
     *
471
     * @param array $options
472
     *
473
     * @return string
474
     */
475
    public function open($options = [])
476
    {
477
        $attributes = [];
478
479
        if ($this->isMode(self::MODE_EDIT)) {
480
            $this->addHiddenField((new Hidden('_method'))->value('PUT'));
481
        }
482
483
        $this->addRedirectUrlField();
484
485
        $attributes['action'] = $this->getAction();
486
        $attributes['method'] = array_get($options, 'method', 'post');
487
        $attributes['accept-charset'] = 'UTF-8';
488
489
        $attributes['class'] = array_get($options, 'class');
490
491
        if ($this->hasFile()) {
492
            $attributes['enctype'] = 'multipart/form-data';
493
        }
494
495
        $html = [];
496
        foreach ($attributes as $name => $value) {
497
            $html[] = "$name=\"$value\"";
498
        }
499
500
        return '<form '.implode(' ', $html).' pjax-container>';
501
    }
502
503
    /**
504
     * Close the current form.
505
     *
506
     * @return string
507
     */
508
    public function close()
509
    {
510
        $this->form = null;
511
        $this->fields = null;
512
513
        return '</form>';
514
    }
515
516
    /**
517
     * Remove reserved fields like `id` `created_at` `updated_at` in form fields.
518
     *
519
     * @return void
520
     */
521
    protected function removeReservedFields()
522
    {
523
        if (!$this->isMode(static::MODE_CREATE)) {
524
            return;
525
        }
526
527
        $reservedColumns = [
528
            $this->form->model()->getKeyName(),
529
            $this->form->model()->getCreatedAtColumn(),
530
            $this->form->model()->getUpdatedAtColumn(),
531
        ];
532
533
        $this->fields = $this->fields()->reject(function (Field $field) use ($reservedColumns) {
534
            return in_array($field->column(), $reservedColumns);
535
        });
536
    }
537
538
    /**
539
     * Render form header tools.
540
     *
541
     * @return string
542
     */
543
    public function renderTools()
544
    {
545
        return $this->tools->render();
546
    }
547
548
    /**
549
     * Render form footer.
550
     *
551
     * @return string
552
     */
553
    public function renderFooter()
554
    {
555
        return $this->footer->render();
556
    }
557
558
    /**
559
     * Render form.
560
     *
561
     * @return string
562
     */
563
    public function render()
564
    {
565
        $this->removeReservedFields();
566
567
        $tabObj = $this->form->getTab();
568
569
        if (!$tabObj->isEmpty()) {
570
            $script = <<<'SCRIPT'
571
572
var hash = document.location.hash;
573
if (hash) {
574
    $('.nav-tabs a[href="' + hash + '"]').tab('show');
575
}
576
577
// Change hash for page-reload
578
$('.nav-tabs a').on('shown.bs.tab', function (e) {
579
    history.pushState(null,null, e.target.hash);
580
});
581
582
if ($('.has-error').length) {
583
    $('.has-error').each(function () {
584
        var tabId = '#'+$(this).closest('.tab-pane').attr('id');
585
        $('li a[href="'+tabId+'"] i').removeClass('hide');
586
    });
587
588
    var first = $('.has-error:first').closest('.tab-pane').attr('id');
589
    $('li a[href="#'+first+'"]').tab('show');
590
}
591
592
SCRIPT;
593
            Admin::script($script);
594
        }
595
596
        $data = [
597
            'form'   => $this,
598
            'tabObj' => $tabObj,
599
            'width'  => $this->width,
600
        ];
601
602
        return view($this->view, $data)->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...
603
    }
604
}
605