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
Pull Request — main (#5243)
by Cristian
27:04 queued 12:27
created

Uploader::shouldDeleteFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
    private string $name;
19
20
    private string $disk = 'public';
21
22
    private string $path = '';
23
24
    private bool $handleMultipleFiles = false;
25
26
    private bool $deleteWhenEntryIsDeleted = true;
27
28
    private bool|string $attachedToFakeField = false;
29
30
    /**
31
     * Cloud disks have the ability to generate temporary URLs to files, should we do it?
32
     */
33
    private bool $useTemporaryUrl = false;
34
35
    /**
36
     * When using temporary urls, define the time that the url will be valid.
37
     */
38
    private int $temporaryUrlExpirationTimeInMinutes = 1;
39
40
    /**
41
     * Indicates if the upload is relative to a relationship field/column.
42
     */
43
    private bool $isRelationship = false;
44
45
    public function __construct(array $crudObject, array $configuration)
46
    {
47
        $this->name = $crudObject['name'];
48
        $this->disk = $configuration['disk'] ?? $crudObject['disk'] ?? $this->disk;
49
        $this->path = $this->getPathFromConfiguration($crudObject, $configuration);
50
        $this->attachedToFakeField = isset($crudObject['fake']) && $crudObject['fake'] ? ($crudObject['store_in'] ?? 'extras') : ($crudObject['store_in'] ?? false);
51
        $this->useTemporaryUrl = $configuration['temporaryUrl'] ?? $this->useTemporaryUrl;
52
        $this->temporaryUrlExpirationTimeInMinutes = $configuration['temporaryUrlExpirationTime'] ?? $this->temporaryUrlExpirationTimeInMinutes;
53
        $this->deleteWhenEntryIsDeleted = $configuration['deleteWhenEntryIsDeleted'] ?? $this->deleteWhenEntryIsDeleted;
54
        $this->fileNamer = is_callable($configuration['fileNamer'] ?? null) ? $configuration['fileNamer'] : $this->getFileNameGeneratorInstance($configuration['fileNamer'] ?? null);
55
    }
56
57
    /*******************************
58
     * Static methods
59
     *******************************/
60
    public static function for(array $crudObject, array $definition): UploaderInterface
61
    {
62
        return new static($crudObject, $definition);
63
    }
64
65
    /*******************************
66
     * public methods - event handler methods
67
     *******************************/
68
    public function storeUploadedFiles(Model $entry): Model
69
    {
70
        if ($this->handleRepeatableFiles) {
71
            return $this->handleRepeatableFiles($entry);
72
        }
73
74
        if ($this->attachedToFakeField) {
75
            $fakeFieldValue = $entry->{$this->attachedToFakeField};
76
            $fakeFieldValue = is_string($fakeFieldValue) ? json_decode($fakeFieldValue, true) : (array) $fakeFieldValue;
77
            $fakeFieldValue[$this->getName()] = $this->uploadFiles($entry);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fakeFieldValue[$this->getName()] is correct as $this->uploadFiles($entry) targeting Backpack\CRUD\app\Librar...Uploader::uploadFiles() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
78
79
            $entry->{$this->attachedToFakeField} = isset($entry->getCasts()[$this->attachedToFakeField]) ? $fakeFieldValue : json_encode($fakeFieldValue);
80
81
            return $entry;
82
        }
83
84
        $entry->{$this->getName()} = $this->uploadFiles($entry);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $entry->$this->getName() is correct as $this->uploadFiles($entry) targeting Backpack\CRUD\app\Librar...Uploader::uploadFiles() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
85
86
        return $entry;
87
    }
88
89
    public function retrieveUploadedFiles(Model $entry): Model
90
    {
91
        if ($this->handleRepeatableFiles) {
92
            return $this->retrieveRepeatableFiles($entry);
93
        }
94
95
        return $this->retrieveFiles($entry);
96
    }
97
98
    public function deleteUploadedFiles(Model $entry): void
99
    {
100
        if ($this->deleteWhenEntryIsDeleted) {
101
            if (! in_array(SoftDeletes::class, class_uses_recursive($entry), true)) {
102
                $this->performFileDeletion($entry);
103
104
                return;
105
            }
106
107
            if ($entry->isForceDeleting() === true) {
108
                $this->performFileDeletion($entry);
109
            }
110
        }
111
    }
112
113
    /*******************************
114
     * Getters
115
     *******************************/
116
    public function getName(): string
117
    {
118
        return $this->name;
119
    }
120
121
    public function getDisk(): string
122
    {
123
        return $this->disk;
124
    }
125
126
    public function getPath(): string
127
    {
128
        return $this->path;
129
    }
130
131
    public function useTemporaryUrl(): bool
132
    {
133
        return $this->useTemporaryUrl;
134
    }
135
136
    public function getExpirationTimeInMinutes(): int
137
    {
138
        return $this->temporaryUrlExpirationTimeInMinutes;
139
    }
140
141
    public function shouldDeleteFiles(): bool
142
    {
143
        return $this->deleteWhenEntryIsDeleted;
144
    }
145
146
    public function getIdentifier(): string
147
    {
148
        if ($this->handleRepeatableFiles) {
149
            return $this->repeatableContainerName.'_'.$this->name;
150
        }
151
152
        return $this->name;
153
    }
154
155
    public function canHandleMultipleFiles(): bool
156
    {
157
        return $this->handleMultipleFiles;
158
    }
159
160
    public function isRelationship(): bool
161
    {
162
        return $this->isRelationship;
163
    }
164
165
    public function getPreviousFiles(Model $entry): mixed
166
    {
167
        if (! $this->attachedToFakeField) {
168
            return $this->getOriginalValue($entry);
169
        }
170
171
        $value = $this->getOriginalValue($entry, $this->attachedToFakeField);
172
        $value = is_string($value) ? json_decode($value, true) : (array) $value;
173
174
        return $value[$this->getName()] ?? null;
175
    }
176
177
    /*******************************
178
     * Setters - fluently configure the uploader
179
     *******************************/
180
    public function multiple(): self
181
    {
182
        $this->handleMultipleFiles = true;
183
184
        return $this;
185
    }
186
187
    public function relationship(bool $isRelationship): self
188
    {
189
        $this->isRelationship = $isRelationship;
190
191
        return $this;
192
    }
193
194
    /*******************************
195
     * Default implementation functions
196
     *******************************/
197
    public function uploadFiles(Model $entry, $values = null)
0 ignored issues
show
Unused Code introduced by
The parameter $values is not used and could be removed. ( Ignorable by Annotation )

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

197
    public function uploadFiles(Model $entry, /** @scrutinizer ignore-unused */ $values = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
198
    {
199
    }
200
201
    private function retrieveFiles(Model $entry): Model
202
    {
203
        $value = $entry->{$this->name};
204
205
        if ($this->handleMultipleFiles) {
206
            if (! isset($entry->getCasts()[$this->name]) && is_string($value)) {
207
                $entry->{$this->name} = json_decode($value, true);
208
            }
209
210
            return $entry;
211
        }
212
213
        if ($this->attachedToFakeField) {
214
            $values = $entry->{$this->attachedToFakeField};
215
            $values = is_string($values) ? json_decode($values, true) : (array) $values;
216
217
            $values[$this->name] = isset($values[$this->name]) ? Str::after($values[$this->name], $this->path) : null;
218
            $entry->{$this->attachedToFakeField} = json_encode($values);
219
220
            return $entry;
221
        }
222
223
        $entry->{$this->name} = Str::after($value, $this->path);
224
225
        return $entry;
226
    }
227
228
    private function deleteFiles(Model $entry)
229
    {
230
        $values = $entry->{$this->name};
231
232
        if ($this->handleMultipleFiles) {
233
            // ensure we have an array of values when field is not casted in model.
234
            if (! isset($entry->getCasts()[$this->name]) && is_string($values)) {
235
                $values = json_decode($values, true);
236
            }
237
            foreach ($values as $value) {
238
                Storage::disk($this->disk)->delete($this->path.$value);
239
            }
240
241
            return;
242
        }
243
244
        $values = Str::after($values, $this->path);
245
        Storage::disk($this->disk)->delete($this->path.$values);
246
    }
247
248
    private function performFileDeletion(Model $entry)
249
    {
250
        if (! $this->handleRepeatableFiles) {
251
            $this->deleteFiles($entry);
252
253
            return;
254
        }
255
256
        $this->deleteRepeatableFiles($entry);
257
    }
258
259
    /*******************************
260
     * Private helper methods
261
     *******************************/
262
    private function getPathFromConfiguration(array $crudObject, array $configuration): string
263
    {
264
        $this->path = $configuration['path'] ?? $crudObject['prefix'] ?? $this->path;
265
266
        return empty($this->path) ? $this->path : Str::of($this->path)->finish('/')->value();
267
    }
268
269
    private function getOriginalValue(Model $entry, $field = null)
270
    {
271
        $previousValue = $entry->getOriginal($field ?? $this->getName());
272
273
        if (! $previousValue) {
274
            return $previousValue;
275
        }
276
277
        if (method_exists($entry, 'translationEnabled') && $entry->translationEnabled()) {
278
            return $previousValue[$entry->getLocale()] ?? null;
279
        }
280
281
        return $previousValue;
282
    }
283
}
284