Completed
Push — master ( 82a9db...e2864c )
by Song
02:18
created

File   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 247
Duplicated Lines 12.96 %

Coupling/Cohesion

Components 3
Dependencies 3

Importance

Changes 0
Metric Value
dl 32
loc 247
rs 10
c 0
b 0
f 0
wmc 21
lcom 3
cbo 3

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A defaultDirectory() 0 4 1
B getValidator() 0 36 7
A uploadAndDeleteOriginal() 0 16 2
A preview() 0 4 1
A prepare() 0 10 2
A hidePreview() 0 6 1
A initialCaption() 0 4 1
A initialPreviewConfig() 0 8 1
A setupScripts() 32 39 2
A render() 0 24 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Encore\Admin\Form\Field;
4
5
use Encore\Admin\Form\Field;
6
use Illuminate\Support\Arr;
7
use Symfony\Component\HttpFoundation\File\UploadedFile;
8
9
class File extends Field
10
{
11
    use UploadField;
12
13
    /**
14
     * Css.
15
     *
16
     * @var array
17
     */
18
    protected static $css = [
19
        '/vendor/laravel-admin/bootstrap-fileinput/css/fileinput.min.css?v=4.5.2',
20
    ];
21
22
    /**
23
     * Js.
24
     *
25
     * @var array
26
     */
27
    protected static $js = [
28
        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/canvas-to-blob.min.js',
29
        '/vendor/laravel-admin/bootstrap-fileinput/js/fileinput.min.js?v=4.5.2',
30
    ];
31
32
    /**
33
     * Create a new File instance.
34
     *
35
     * @param string $column
36
     * @param array  $arguments
37
     */
38
    public function __construct($column, $arguments = [])
39
    {
40
        $this->initStorage();
41
42
        parent::__construct($column, $arguments);
43
    }
44
45
    /**
46
     * Default directory for file to upload.
47
     *
48
     * @return mixed
49
     */
50
    public function defaultDirectory()
51
    {
52
        return config('admin.upload.directory.file');
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function getValidator(array $input)
59
    {
60
        if (request()->has(static::FILE_DELETE_FLAG)) {
61
            return false;
62
        }
63
64
        if ($this->validator) {
65
            return $this->validator->call($this, $input);
66
        }
67
68
        /*
69
         * If has original value, means the form is in edit mode,
70
         * then remove required rule from rules.
71
         */
72
        if ($this->original()) {
73
            $this->removeRule('required');
74
        }
75
76
        /*
77
         * Make input data validatable if the column data is `null`.
78
         */
79
        if (Arr::has($input, $this->column) && is_null(Arr::get($input, $this->column))) {
0 ignored issues
show
Bug introduced by
It seems like $this->column can also be of type array; however, Illuminate\Support\Arr::get() does only seem to accept string|integer|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
80
            $input[$this->column] = '';
81
        }
82
83
        $rules = $attributes = [];
84
85
        if (!$fieldRules = $this->getRules()) {
86
            return false;
87
        }
88
89
        $rules[$this->column] = $fieldRules;
90
        $attributes[$this->column] = $this->label;
91
92
        return \validator($input, $rules, $this->getValidationMessages(), $attributes);
93
    }
94
95
    /**
96
     * Prepare for saving.
97
     *
98
     * @param UploadedFile|array $file
99
     *
100
     * @return mixed|string
101
     */
102
    public function prepare($file)
103
    {
104
        if (request()->has(static::FILE_DELETE_FLAG)) {
105
            return $this->destroy();
106
        }
107
108
        $this->name = $this->getStoreName($file);
0 ignored issues
show
Bug introduced by
It seems like $file defined by parameter $file on line 102 can also be of type array; however, Encore\Admin\Form\Field\...adField::getStoreName() does only seem to accept object<Symfony\Component...tion\File\UploadedFile>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
Documentation Bug introduced by
It seems like $this->getStoreName($file) of type string is incompatible with the declared type null of property $name.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
109
110
        return $this->uploadAndDeleteOriginal($file);
0 ignored issues
show
Bug introduced by
It seems like $file defined by parameter $file on line 102 can also be of type array; however, Encore\Admin\Form\Field\...loadAndDeleteOriginal() does only seem to accept object<Symfony\Component...tion\File\UploadedFile>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
111
    }
112
113
    /**
114
     * Upload file and delete original file.
115
     *
116
     * @param UploadedFile $file
117
     *
118
     * @return mixed
119
     */
120
    protected function uploadAndDeleteOriginal(UploadedFile $file)
121
    {
122
        $this->renameIfExists($file);
123
124
        $path = null;
0 ignored issues
show
Unused Code introduced by
$path is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
125
126
        if (!is_null($this->storagePermission)) {
127
            $path = $this->storage->putFileAs($this->getDirectory(), $file, $this->name, $this->storagePermission);
128
        } else {
129
            $path = $this->storage->putFileAs($this->getDirectory(), $file, $this->name);
130
        }
131
132
        $this->destroy();
133
134
        return $path;
135
    }
136
137
    /**
138
     * Preview html for file-upload plugin.
139
     *
140
     * @return string
141
     */
142
    protected function preview()
143
    {
144
        return $this->objectUrl($this->value);
145
    }
146
147
    /**
148
     * Hides the file preview.
149
     *
150
     * @return $this
151
     */
152
    public function hidePreview()
153
    {
154
        return $this->options([
155
            'showPreview' => false
156
        ]);
157
    }
158
159
    /**
160
     * Initialize the caption.
161
     *
162
     * @param string $caption
163
     *
164
     * @return string
165
     */
166
    protected function initialCaption($caption)
167
    {
168
        return basename($caption);
169
    }
170
171
    /**
172
     * @return array
173
     */
174
    protected function initialPreviewConfig()
175
    {
176
        $config = ['caption' => basename($this->value), 'key' => 0];
177
178
        $config = array_merge($config, $this->guessPreviewType($this->value));
179
180
        return [$config];
181
    }
182
183
    /**
184
     * @param string $options
185
     */
186
    protected function setupScripts($options)
187
    {
188
        $this->script = <<<EOT
189
$("input{$this->getElementClassSelector()}").fileinput({$options});
190
EOT;
191
192 View Code Duplication
        if ($this->fileActionSettings['showRemove']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
            $text = [
194
                'title'   => trans('admin.delete_confirm'),
195
                'confirm' => trans('admin.confirm'),
196
                'cancel'  => trans('admin.cancel'),
197
            ];
198
199
            $this->script .= <<<EOT
200
$("input{$this->getElementClassSelector()}").on('filebeforedelete', function() {
201
    
202
    return new Promise(function(resolve, reject) {
203
    
204
        var remove = resolve;
205
    
206
        swal({
207
            title: "{$text['title']}",
208
            type: "warning",
209
            showCancelButton: true,
210
            confirmButtonColor: "#DD6B55",
211
            confirmButtonText: "{$text['confirm']}",
212
            showLoaderOnConfirm: true,
213
            cancelButtonText: "{$text['cancel']}",
214
            preConfirm: function() {
215
                return new Promise(function(resolve) {
216
                    resolve(remove());
217
                });
218
            }
219
        });
220
    });
221
});
222
EOT;
223
        }
224
    }
225
226
    /**
227
     * Render file upload field.
228
     *
229
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
230
     */
231
    public function render()
232
    {
233
        $this->options(['overwriteInitial' => true, 'msgPlaceholder' => trans('admin.choose_file')]);
234
235
        $this->setupDefaultOptions();
236
237
        if (!empty($this->value)) {
238
            $this->attribute('data-initial-preview', $this->preview());
239
            $this->attribute('data-initial-caption', $this->initialCaption($this->value));
240
241
            $this->setupPreviewOptions();
242
            /*
243
             * If has original value, means the form is in edit mode,
244
             * then remove required rule from rules.
245
             */
246
            unset($this->attributes['required']);
247
        }
248
249
        $options = json_encode_options($this->options);
250
251
        $this->setupScripts($options);
252
253
        return parent::render();
0 ignored issues
show
Bug Compatibility introduced by
The expression parent::render(); of type string|Illuminate\View\V...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 253 which is incompatible with the return type declared by the interface Illuminate\Contracts\Support\Renderable::render of type string.
Loading history...
254
    }
255
}
256