Completed
Push — master ( 82be35...1537c0 )
by Song
02:28
created

src/Form/Field/Tags.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Encore\Admin\Form\Field;
4
5
use Encore\Admin\Facades\Admin;
6
use Encore\Admin\Form\Field;
7
use Illuminate\Contracts\Support\Arrayable;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Collection;
10
11
class Tags extends Field
12
{
13
    /**
14
     * @var array
15
     */
16
    protected $value = [];
17
18
    /**
19
     * @var bool
20
     */
21
    protected $keyAsValue = false;
22
23
    /**
24
     * @var string
25
     */
26
    protected $visibleColumn = null;
27
28
    /**
29
     * @var string
30
     */
31
    protected $key = null;
32
33
    /**
34
     * @var \Closure
35
     */
36
    protected $saveAction = null;
37
38
    /**
39
     * @var array
40
     */
41
    protected $separators = [',', ';', ',', ';', ' '];
42
43
    /**
44
     * @var array
45
     */
46
    protected static $css = [
47
        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.min.css',
48
    ];
49
50
    /**
51
     * @var array
52
     */
53
    protected static $js = [
54
        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.full.min.js',
55
    ];
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function fill($data)
61
    {
62
        $this->value = Arr::get($data, $this->column);
63
64
        if (is_array($this->value) && $this->keyAsValue) {
65
            $this->value = array_column($this->value, $this->visibleColumn, $this->key);
66
        }
67
68
        if (is_string($this->value)) {
69
            $this->value = explode(',', $this->value);
70
        }
71
72
        $this->value = array_filter((array) $this->value, 'strlen');
73
    }
74
75
    /**
76
     * Set visible column and key of data.
77
     *
78
     * @param $visibleColumn
79
     * @param $key
80
     *
81
     * @return $this
82
     */
83
    public function pluck($visibleColumn, $key)
84
    {
85
        if (!empty($visibleColumn) && !empty($key)) {
86
            $this->keyAsValue = true;
87
        }
88
89
        $this->visibleColumn = $visibleColumn;
90
        $this->key = $key;
91
92
        return $this;
93
    }
94
95
    /**
96
     * Set the field options.
97
     *
98
     * @param array|Collection|Arrayable $options
99
     *
100
     * @return $this|Field
101
     */
102
    public function options($options = [])
103
    {
104
        if (!$this->keyAsValue) {
105
            return parent::options($options);
106
        }
107
108
        if ($options instanceof Collection) {
109
            $options = $options->pluck($this->visibleColumn, $this->key)->toArray();
110
        }
111
112
        if ($options instanceof Arrayable) {
113
            $options = $options->toArray();
114
        }
115
116
        $this->options = $options + $this->options;
117
118
        return $this;
119
    }
120
121
    /**
122
     * Set Tag Separators.
123
     *
124
     * @param array $separators
125
     *
126
     * @return $this
127
     */
128
    public function separators($separators = [])
129
    {
130
        if ($separators instanceof Collection or $separators instanceof Arrayable) {
131
            $separators = $separators->toArray();
132
        }
133
        if (!empty($separators)) {
134
            $this->separators = $separators;
135
        }
136
137
        return $this;
138
    }
139
140
    /**
141
     * Set save Action.
142
     *
143
     * @param \Closure $saveAction
144
     *
145
     * @return $this
146
     */
147
    public function saving(\Closure $saveAction)
148
    {
149
        $this->saveAction = $saveAction;
150
151
        return $this;
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function prepare($value)
158
    {
159
        $value = array_filter($value, 'strlen');
160
161
        if ($this->keyAsValue) {
162
            return is_null($this->saveAction) ? $value : ($this->saveAction)($value);
163
        }
164
165
        if (is_array($value) && !Arr::isAssoc($value)) {
166
            $value = implode(',', $value);
167
        }
168
169
        return $value;
170
    }
171
172
    /**
173
     * Get or set value for this field.
174
     *
175
     * @param mixed $value
176
     *
177
     * @return $this|array|mixed
178
     */
179
    public function value($value = null)
180
    {
181
        if (is_null($value)) {
182
            return empty($this->value) ? ($this->getDefault() ?? []) : $this->value;
183
        }
184
185
        $this->value = (array) $value;
186
187
        return $this;
188
    }
189
190
    /**
191
     * {@inheritdoc}
192
     */
193
    public function render()
194
    {
195
        if (!$this->shouldRender()) {
196
            return '';
197
        }
198
199
        $this->setupScript();
200
201
        if ($this->keyAsValue) {
202
            $options = $this->value + $this->options;
203
        } else {
204
            $options = array_unique(array_merge($this->value, $this->options));
205
        }
206
207
        return parent::render()->with([
0 ignored issues
show
The method with 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...
208
            'options'    => $options,
209
            'keyAsValue' => $this->keyAsValue,
210
        ]);
211
    }
212
213
    protected function setupScript()
214
    {
215
        $separators = json_encode($this->separators);
216
        $separatorsStr = implode('', $this->separators);
217
        $this->script = <<<JS
218
$("{$this->getElementClassSelector()}").select2({
219
    tags: true,
220
    tokenSeparators: $separators,
221
    createTag: function(params) {
222
        if (/[$separatorsStr]/.test(params.term)) {
223
            var str = params.term.trim().replace(/[$separatorsStr]*$/, '');
224
            return { id: str, text: str }
225
        } else {
226
            return null;
227
        }
228
    }
229
});
230
JS;
231
232
        Admin::script(
233
            <<<'JS'
234
$(document).off('keyup', '.select2-selection--multiple .select2-search__field').on('keyup', '.select2-selection--multiple .select2-search__field', function (event) {
235
    try {
236
        if (event.keyCode == 13) {
237
            var $this = $(this), optionText = $this.val();
238
            if (optionText != "" && $this.find("option[value='" + optionText + "']").length === 0) {
239
                var $select = $this.parents('.select2-container').prev("select");
240
                var newOption = new Option(optionText, optionText, true, true);
241
                $select.append(newOption).trigger('change');
242
                $this.val('');
243
                $select.select2('close');
244
            }
245
        }
246
    } catch (e) {
247
        console.error(e);
248
    }
249
});
250
JS
251
        );
252
    }
253
}
254