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 ( f5e93a...469ece )
by Pedro
11:36
created

Uploader   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 316
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 67
dl 0
loc 316
rs 9.76
c 0
b 0
f 0
wmc 33

17 Methods

Rating   Name   Duplication   Size   Complexity  
A retrieveFile() 0 13 4
A performFileDeletion() 0 9 3
A for() 0 3 1
A processFileUpload() 0 9 2
A shouldDeleteFiles() 0 3 1
A getName() 0 3 1
A getExpiration() 0 3 1
A deleteFiles() 0 18 5
A getDisk() 0 3 1
A getTemporary() 0 3 1
A multiple() 0 5 1
A retrieveUploadedFile() 0 7 2
A __construct() 0 13 2
A getPath() 0 3 1
A relationship() 0 5 1
A getIdentifier() 0 7 2
A deleteUploadedFile() 0 11 4
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Uploaders;
4
5
use Backpack\CRUD\app\Library\Uploaders\Support\Interfaces\UploaderInterface;
6
use Backpack\CRUD\app\Library\Uploaders\Support\Traits\HandleFileNaming;
7
use Backpack\CRUD\app\Library\Uploaders\Support\Traits\HandleRepeatableUploads;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Database\Eloquent\SoftDeletes;
10
use Illuminate\Support\Facades\Storage;
11
use Illuminate\Support\Str;
12
13
abstract class Uploader implements UploaderInterface
14
{
15
    use HandleFileNaming;
16
    use HandleRepeatableUploads;
17
18
    /**
19
     * The name of the uploader AKA CrudField/Column name.
20
     *
21
     * @var string
22
     */
23
    private string $name;
24
25
    /**
26
     * Indicates the uploaded file should be deleted when entry is deleted.
27
     *
28
     * @var bool
29
     */
30
    private $deleteWhenEntryIsDeleted = true;
31
32
    /**
33
     * The disk where upload will be stored. By default `public`.
34
     *
35
     * @var string
36
     */
37
    private $disk = 'public';
38
39
    /**
40
     * Indicates if the upload handles multiple files.
41
     *
42
     * @var bool
43
     */
44
    private $isMultiple = false;
45
46
    /**
47
     * The path inside the disk to store the uploads.
48
     *
49
     * @var string
50
     */
51
    private $path = '';
52
53
    /**
54
     * Should the url to the object be a temporary one (eg: s3).
55
     *
56
     * @var bool
57
     */
58
    private $useTemporaryUrl = false;
59
60
    /**
61
     * When using temporary urls, defines the time that the url
62
     * should be available in minutes.
63
     *
64
     * By default 1 minute
65
     *
66
     * @var int
67
     */
68
    private $temporaryUrlExpirationTime = 1;
69
70
    /**
71
     * Indicates if the upload is relative to a relationship field/column.
72
     *
73
     * @var bool
74
     */
75
    private $isRelationship = false;
76
77
    final public function __construct(array $crudObject, array $configuration)
78
    {
79
        $this->name = $crudObject['name'];
80
        $this->disk = $configuration['disk'] ?? $crudObject['disk'] ?? $this->disk;
81
        $this->useTemporaryUrl = $configuration['temporary'] ?? $this->useTemporaryUrl;
82
        $this->temporaryUrlExpirationTime = $configuration['expiration'] ?? $this->temporaryUrlExpirationTime;
83
        $this->deleteWhenEntryIsDeleted = $configuration['whenDelete'] ?? $this->deleteWhenEntryIsDeleted;
84
85
        $this->path = $configuration['path'] ?? $crudObject['prefix'] ?? $this->path;
86
        $this->path = empty($this->path) ? $this->path : Str::of($this->path)->finish('/')->value();
87
88
        $this->setFileNameGenerator($configuration['fileNameGenerator'] ?? null);
89
        $this->fileName = $configuration['fileName'] ?? $this->fileName;
90
    }
91
92
    /**
93
     * An abstract function that all uploaders must implement for a single file save process.
94
     *
95
     * @param  Model  $entry
96
     * @param  mixed  $values
97
     * @return mixed
98
     */
99
    abstract public function uploadFile(Model $entry, $values = null);
100
101
    /**
102
     * The function called in the saving event that starts the upload process.
103
     *
104
     * @param  Model  $entry
105
     * @return Model
106
     */
107
    public function processFileUpload(Model $entry)
108
    {
109
        if ($this->isRepeatable) {
110
            return $this->handleRepeatableFiles($entry);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->handleRepeatableFiles($entry) returns the type Illuminate\Database\Eloquent\Model which is incompatible with the return type mandated by Backpack\CRUD\app\Librar...ce::processFileUpload() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
111
        }
112
113
        $entry->{$this->name} = $this->uploadFile($entry);
114
115
        return $entry;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $entry returns the type Illuminate\Database\Eloquent\Model which is incompatible with the return type mandated by Backpack\CRUD\app\Librar...ce::processFileUpload() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
116
    }
117
118
    /**
119
     * Return the uploader name.
120
     *
121
     * @return string
122
     */
123
    public function getName()
124
    {
125
        return $this->name;
126
    }
127
128
    /**
129
     * Return the uploader disk.
130
     *
131
     * @return string
132
     */
133
    public function getDisk()
134
    {
135
        return $this->disk;
136
    }
137
138
    /**
139
     * Return the uploader path.
140
     *
141
     * @return string
142
     */
143
    public function getPath()
144
    {
145
        return $this->path;
146
    }
147
148
    /**
149
     * Return the uploader temporary option.
150
     *
151
     * @return bool
152
     */
153
    public function getTemporary()
154
    {
155
        return $this->useTemporaryUrl;
156
    }
157
158
    /**
159
     * Return the uploader expiration time in minutes.
160
     *
161
     * @return int
162
     */
163
    public function getExpiration()
164
    {
165
        return $this->temporaryUrlExpirationTime;
166
    }
167
168
    /**
169
     * The function called in the retrieved event that handles the display of uploaded values.
170
     *
171
     * @param  Model  $entry
172
     * @return Model
173
     */
174
    public function retrieveUploadedFile(Model $entry)
175
    {
176
        if ($this->isRepeatable) {
177
            return $this->retrieveRepeatableFiles($entry);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->retrieveRepeatableFiles($entry) targeting Backpack\CRUD\app\Librar...trieveRepeatableFiles() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug Best Practice introduced by
The expression return $this->retrieveRepeatableFiles($entry) returns the type void which is incompatible with the documented return type Illuminate\Database\Eloquent\Model.
Loading history...
178
        }
179
180
        return $this->retrieveFile($entry);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->retrieveFile($entry) returns the type Illuminate\Database\Eloquent\Model which is incompatible with the return type mandated by Backpack\CRUD\app\Librar...:retrieveUploadedFile() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
181
    }
182
183
    /**
184
     * Retrive the regular entry files.
185
     *
186
     * @param  Model  $entry
187
     * @return Model
188
     */
189
    protected function retrieveFile(Model $entry)
190
    {
191
        $value = $entry->{$this->name};
192
193
        if ($this->isMultiple && ! isset($entry->getCasts()[$this->name]) && is_string($value)) {
194
            $entry->{$this->name} = json_decode($value, true);
195
196
            return $entry;
197
        }
198
199
        $entry->{$this->name} = Str::after($value, $this->path);
200
201
        return $entry;
202
    }
203
204
    /**
205
     * The function called in the deleting event. It checks if the uploaded file should be deleted.
206
     *
207
     * @param  Model  $entry
208
     * @return void
209
     */
210
    public function deleteUploadedFile(Model $entry)
211
    {
212
        if ($this->deleteWhenEntryIsDeleted) {
213
            if (! in_array(SoftDeletes::class, class_uses_recursive($entry), true)) {
214
                $this->performFileDeletion($entry);
215
216
                return;
217
            }
218
219
            if ($entry->isForceDeleting() === true) {
220
                $this->performFileDeletion($entry);
221
            }
222
        }
223
    }
224
225
    /**
226
     * The function called in the retrieved event that handles the display of uploaded values.
227
     *
228
     * @param  Model  $entry
229
     * @return void
230
     */
231
    private function deleteFiles($entry)
232
    {
233
        $values = $entry->{$this->name};
234
235
        if ($this->isMultiple) {
236
            // ensure we have an array of values when field is not casted in model.
237
            if (! isset($entry->getCasts()[$this->name]) && is_string($values)) {
238
                $values = json_decode($values, true);
239
            }
240
            foreach ($values as $value) {
241
                Storage::disk($this->disk)->delete($this->path.$value);
242
            }
243
244
            return;
245
        }
246
247
        $values = (array) Str::after($values, $this->path);
248
        Storage::disk($this->disk)->delete($this->path.$values);
0 ignored issues
show
Bug introduced by
Are you sure $values of type array can be used in concatenation? ( Ignorable by Annotation )

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

248
        Storage::disk($this->disk)->delete($this->path./** @scrutinizer ignore-type */ $values);
Loading history...
249
    }
250
251
    /**
252
     * When the file should be deleted, this function is called to delete the file using the
253
     * appropriate delete method depending on some uploader properties.
254
     *
255
     * @param  Model  $entry
256
     * @return void
257
     */
258
    private function performFileDeletion($entry)
259
    {
260
        if ($this->isRelationship || ! $this->isRepeatable) {
261
            $this->deleteFiles($entry);
262
263
            return;
264
        }
265
266
        $this->deleteRepeatableFiles($entry);
267
    }
268
269
    /**
270
     * Build an uploader instance.
271
     *
272
     * @param  array  $crudObject
273
     * @param  array  $definition
274
     * @return self
275
     */
276
    public static function for(array $crudObject, array $definition)
277
    {
278
        return new static($crudObject, $definition);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($crudObject, $definition) returns the type Backpack\CRUD\app\Library\Uploaders\Uploader which is incompatible with the return type mandated by Backpack\CRUD\app\Librar...ploaderInterface::for() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
279
    }
280
281
    /**
282
     * Set multiple attribute to true in the uploader.
283
     *
284
     * @return self
285
     */
286
    protected function multiple()
287
    {
288
        $this->isMultiple = true;
289
290
        return $this;
291
    }
292
293
    /**
294
     * Set relationship attribute in uploader.
295
     * When true, it also removes the repeatable in case the relationship is handled.
296
     *
297
     * @param  bool  $isRelationship
298
     * @return self
299
     */
300
    public function relationship(bool $isRelationship): self
301
    {
302
        $this->isRelationship = $isRelationship;
303
304
        return $this;
305
    }
306
307
    /**
308
     * Should the files be deleted when the entry is deleted.
309
     *
310
     * @return bool
311
     */
312
    public function shouldDeleteFiles()
313
    {
314
        return $this->deleteWhenEntryIsDeleted;
315
    }
316
317
    /**
318
     * Return the uploader identifier. Either the name or the combination of the repeatable container name and the name.
319
     *
320
     * @return void
321
     */
322
    public function getIdentifier()
323
    {
324
        if ($this->isRepeatable) {
325
            return $this->repeatableContainerName.'_'.$this->name;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->repeatable...ame . '_' . $this->name returns the type string which is incompatible with the documented return type void.
Loading history...
326
        }
327
328
        return $this->name;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->name returns the type string which is incompatible with the documented return type void.
Loading history...
329
    }
330
}
331