Completed
Pull Request — master (#2988)
by
unknown
03:10 queued 45s
created

Form::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 1
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin\Widgets;
4
5
use Encore\Admin\Form\Field;
6
use Illuminate\Contracts\Support\Arrayable;
7
use Illuminate\Contracts\Support\Renderable;
8
9
/**
10
 * Class Form.
11
 *
12
 * @method Field\Text           text($name, $label = '')
13
 * @method Field\Password       password($name, $label = '')
14
 * @method Field\Checkbox       checkbox($name, $label = '')
15
 * @method Field\Radio          radio($name, $label = '')
16
 * @method Field\Select         select($name, $label = '')
17
 * @method Field\MultipleSelect multipleSelect($name, $label = '')
18
 * @method Field\Textarea       textarea($name, $label = '')
19
 * @method Field\Hidden         hidden($name, $label = '')
20
 * @method Field\Id             id($name, $label = '')
21
 * @method Field\Ip             ip($name, $label = '')
22
 * @method Field\Url            url($name, $label = '')
23
 * @method Field\Color          color($name, $label = '')
24
 * @method Field\Email          email($name, $label = '')
25
 * @method Field\Mobile         mobile($name, $label = '')
26
 * @method Field\Slider         slider($name, $label = '')
27
 * @method Field\Map            map($latitude, $longitude, $label = '')
28
 * @method Field\Editor         editor($name, $label = '')
29
 * @method Field\File           file($name, $label = '')
30
 * @method Field\Image          image($name, $label = '')
31
 * @method Field\Date           date($name, $label = '')
32
 * @method Field\Datetime       datetime($name, $label = '')
33
 * @method Field\Time           time($name, $label = '')
34
 * @method Field\DateRange      dateRange($start, $end, $label = '')
35
 * @method Field\DateTimeRange  dateTimeRange($start, $end, $label = '')
36
 * @method Field\TimeRange      timeRange($start, $end, $label = '')
37
 * @method Field\Number         number($name, $label = '')
38
 * @method Field\Currency       currency($name, $label = '')
39
 * @method Field\Json           json($name, $label = '')
40
 * @method Field\SwitchField    switch($name, $label = '')
41
 * @method Field\Display        display($name, $label = '')
42
 * @method Field\Rate           rate($name, $label = '')
43
 * @method Field\Divide         divide()
44
 * @method Field\Decimal        decimal($column, $label = '')
45
 * @method Field\Html           html($html)
46
 * @method Field\Tags           tags($column, $label = '')
47
 * @method Field\Icon           icon($column, $label = '')
48
 */
49
class Form implements Renderable
50
{
51
    /**
52
     * @var Field[]
53
     */
54
    protected $fields = [];
55
56
    /**
57
     * @var array
58
     */
59
    protected $data = [];
60
61
    /**
62
     * @var array
63
     */
64
    protected $attributes = [];
65
66
    /**
67
     * Available buttons.
68
     *
69
     * @var array
70
     */
71
    protected $buttons = ['reset', 'submit'];
72
73
    /**
74
     * Form constructor.
75
     *
76
     * @param array $data
77
     */
78
    public function __construct($data = [])
79
    {
80
        if ($data instanceof Arrayable) {
81
            $data = $data->toArray();
82
        }
83
84
        if (!empty($data)) {
85
            $this->data = $data;
86
        }
87
88
        $this->initFormAttributes();
89
    }
90
91
    /**
92
     * Initialize the form attributes.
93
     */
94
    protected function initFormAttributes()
95
    {
96
        $this->attributes = [
97
            'method'         => 'POST',
98
            'action'         => '',
99
            'class'          => 'form-horizontal',
100
            'accept-charset' => 'UTF-8',
101
            'pjax-container' => true,
102
        ];
103
    }
104
105
    /**
106
     * Action uri of the form.
107
     *
108
     * @param string $action
109
     *
110
     * @return $this
111
     */
112
    public function action($action)
113
    {
114
        return $this->attribute('action', $action);
115
    }
116
117
    /**
118
     * Method of the form.
119
     *
120
     * @param string $method
121
     *
122
     * @return $this
123
     */
124
    public function method($method = 'POST')
125
    {
126
        return $this->attribute('method', strtoupper($method));
127
    }
128
129
    /**
130
     * Add form attributes.
131
     *
132
     * @param string|array $attr
133
     * @param string       $value
134
     *
135
     * @return $this
136
     */
137
    public function attribute($attr, $value = '')
138
    {
139
        if (is_array($attr)) {
140
            foreach ($attr as $key => $value) {
141
                $this->attribute($key, $value);
142
            }
143
        } else {
144
            $this->attributes[$attr] = $value;
145
        }
146
147
        return $this;
148
    }
149
150
    /**
151
     * Disable Pjax.
152
     *
153
     * @return $this
154
     */
155
    public function disablePjax()
156
    {
157
        array_forget($this->attributes, 'pjax-container');
158
159
        return $this;
160
    }
161
162
    /**
163
     * Disable reset button.
164
     *
165
     * @return $this
166
     */
167
    public function disableReset()
168
    {
169
        array_delete($this->buttons, 'reset');
170
171
        return $this;
172
    }
173
174
    /**
175
     * Disable submit button.
176
     *
177
     * @return $this
178
     */
179
    public function disableSubmit()
180
    {
181
        array_delete($this->buttons, 'submit');
182
183
        return $this;
184
    }
185
186
    /**
187
     * Set field and label width in current form.
188
     *
189
     * @param int $fieldWidth
190
     * @param int $labelWidth
191
     *
192
     * @return $this
193
     */
194
    public function setWidth($fieldWidth = 8, $labelWidth = 2)
195
    {
196
        collect($this->fields)->each(function ($field) use ($fieldWidth, $labelWidth) {
197
            /* @var Field $field  */
198
            $field->setWidth($fieldWidth, $labelWidth);
199
        });
200
201
        return $this;
202
    }
203
204
    /**
205
     * Find field class with given name.
206
     *
207
     * @param string $method
208
     *
209
     * @return bool|string
210
     */
211
    public static function findFieldClass($method)
212
    {
213
        $class = array_get(\Encore\Admin\Form::$availableFields, $method);
214
215
        if (class_exists($class)) {
216
            return $class;
217
        }
218
219
        return false;
220
    }
221
222
    /**
223
     * Add a form field to form.
224
     *
225
     * @param Field $field
226
     *
227
     * @return $this
228
     */
229
    public function pushField(Field &$field)
230
    {
231
        array_push($this->fields, $field);
232
233
        return $this;
234
    }
235
236
    /**
237
     * Get variables for render form.
238
     *
239
     * @return array
240
     */
241
    protected function getVariables()
242
    {
243
        foreach ($this->fields as $field) {
244
            $field->fill($this->data);
245
        }
246
247
        return [
248
            'fields'     => $this->fields,
249
            'attributes' => $this->formatAttribute(),
250
            'method'     => $this->attributes['method'],
251
            'buttons'    => $this->buttons,
252
        ];
253
    }
254
255
    /**
256
     * Format form attributes form array to html.
257
     *
258
     * @param array $attributes
259
     *
260
     * @return string
261
     */
262
    public function formatAttribute($attributes = [])
263
    {
264
        $attributes = $attributes ?: $this->attributes;
265
266
        if ($this->hasFile()) {
267
            $attributes['enctype'] = 'multipart/form-data';
268
        }
269
270
        $html = [];
271
        foreach ($attributes as $key => $val) {
272
            // set action as absolute url
273
            if ($key == 'action') {
274
                $val = url($val);
275
            }
276
277
            $html[] = "$key=\"$val\"";
278
        }
279
280
        return implode(' ', $html) ?: '';
281
    }
282
283
    /**
284
     * Determine if form fields has files.
285
     *
286
     * @return bool
287
     */
288
    public function hasFile()
289
    {
290
        foreach ($this->fields as $field) {
291
            if ($field instanceof Field\File) {
292
                return true;
293
            }
294
        }
295
296
        return false;
297
    }
298
299
    /**
300
     * Generate a Field object and add to form builder if Field exists.
301
     *
302
     * @param string $method
303
     * @param array  $arguments
304
     *
305
     * @return Field|null
306
     */
307
    public function __call($method, $arguments)
308
    {
309
        if ($className = static::findFieldClass($method)) {
310
            $name = array_get($arguments, 0, '');
311
312
            $element = new $className($name, array_slice($arguments, 1));
313
314
            $this->pushField($element);
315
316
            return $element;
317
        }
318
    }
319
320
    /**
321
     * Render the form.
322
     *
323
     * @return string
324
     */
325
    public function render()
326
    {
327
        return view('admin::widgets.form', $this->getVariables())->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...
328
    }
329
330
    /**
331
     * Output as string.
332
     *
333
     * @return string
334
     */
335
    public function __toString()
336
    {
337
        return $this->render();
338
    }
339
}
340