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

Test Failed
Pull Request — main (#5478)
by Pedro
27:49 queued 12:44
created

Uploader::getAttributeName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Librar...HandleRepeatableUploads requires some properties which are not provided by Backpack\CRUD\app\Library\Uploaders\Uploader: $pivot, $exists, $pivotParent
Loading history...
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
    /**
46
     * When previous files are updated, we need to keep track of them so that we don't add deleted files to the new list.
47
     */
48
    private $updatedPreviousFiles = null;
49
50
    public function __construct(array $crudObject, array $configuration)
51
    {
52
        $this->name = $crudObject['name'];
53
        $this->disk = $configuration['disk'] ?? $crudObject['disk'] ?? $this->disk;
54
        $this->path = $this->getPathFromConfiguration($crudObject, $configuration);
55
        $this->attachedToFakeField = isset($crudObject['fake']) && $crudObject['fake'] ? ($crudObject['store_in'] ?? 'extras') : ($crudObject['store_in'] ?? false);
56
        $this->useTemporaryUrl = $configuration['temporaryUrl'] ?? $this->useTemporaryUrl;
57
        $this->temporaryUrlExpirationTimeInMinutes = $configuration['temporaryUrlExpirationTime'] ?? $this->temporaryUrlExpirationTimeInMinutes;
58
        $this->deleteWhenEntryIsDeleted = $configuration['deleteWhenEntryIsDeleted'] ?? $this->deleteWhenEntryIsDeleted;
59
        $this->fileNamer = is_callable($configuration['fileNamer'] ?? null) ? $configuration['fileNamer'] : $this->getFileNameGeneratorInstance($configuration['fileNamer'] ?? null);
60
    }
61
62
    /*******************************
63
     * Static methods
64
     *******************************/
65
    public static function for(array $crudObject, array $definition): UploaderInterface
66
    {
67
        return new static($crudObject, $definition);
68
    }
69
70
    /*******************************
71
     * public methods - event handler methods
72
     *******************************/
73
    public function storeUploadedFiles(Model $entry): Model
74
    {
75
        if ($this->handleRepeatableFiles) {
76
            return $this->handleRepeatableFiles($entry);
77
        }
78
79
        if ($this->attachedToFakeField) {
80
            $fakeFieldValue = $entry->{$this->attachedToFakeField};
81
            $fakeFieldValue = is_string($fakeFieldValue) ? json_decode($fakeFieldValue, true) : (array) $fakeFieldValue;
82
            $fakeFieldValue[$this->getAttributeName()] = $this->uploadFiles($entry);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fakeFieldValue[$this->getAttributeName()] 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...
83
84
            $entry->{$this->attachedToFakeField} = isset($entry->getCasts()[$this->attachedToFakeField]) ? $fakeFieldValue : json_encode($fakeFieldValue);
85
86
            return $entry;
87
        }
88
89
        $entry->{$this->getAttributeName()} = $this->uploadFiles($entry);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $entry->$this->getAttributeName() 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...
90
91
        return $entry;
92
    }
93
94
    public function retrieveUploadedFiles(Model $entry): Model
95
    {
96
        if ($this->handleRepeatableFiles) {
97
            return $this->retrieveRepeatableFiles($entry);
98
        }
99
100
        return $this->retrieveFiles($entry);
101
    }
102
103
    public function deleteUploadedFiles(Model $entry): void
104
    {
105
        if ($this->deleteWhenEntryIsDeleted) {
106
            if (! in_array(SoftDeletes::class, class_uses_recursive($entry), true)) {
107
                $this->performFileDeletion($entry);
108
109
                return;
110
            }
111
112
            if ($entry->isForceDeleting() === true) {
113
                $this->performFileDeletion($entry);
114
            }
115
        }
116
    }
117
118
    /*******************************
119
     * Getters
120
     *******************************/
121
    public function getName(): string
122
    {
123
        return $this->name;
124
    }
125
126
    public function getAttributeName(): string
127
    {
128
        return Str::afterLast($this->name, '.');
129
    }
130
131
    public function getDisk(): string
132
    {
133
        return $this->disk;
134
    }
135
136
    public function getPath(): string
137
    {
138
        return $this->path;
139
    }
140
141
    public function useTemporaryUrl(): bool
142
    {
143
        return $this->useTemporaryUrl;
144
    }
145
146
    public function getExpirationTimeInMinutes(): int
147
    {
148
        return $this->temporaryUrlExpirationTimeInMinutes;
149
    }
150
151
    public function shouldDeleteFiles(): bool
152
    {
153
        return $this->deleteWhenEntryIsDeleted;
154
    }
155
156
    public function getIdentifier(): string
157
    {
158
        if ($this->handleRepeatableFiles) {
159
            return $this->repeatableContainerName.'_'.$this->name;
160
        }
161
162
        return $this->name;
163
    }
164
165
    public function getNameForRequest(): string
166
    {
167
        return $this->repeatableContainerName ?? $this->name;
168
    }
169
170
    public function canHandleMultipleFiles(): bool
171
    {
172
        return $this->handleMultipleFiles;
173
    }
174
175
    public function isRelationship(): bool
176
    {
177
        return $this->isRelationship;
178
    }
179
180
    public function getPreviousFiles(Model $entry): mixed
181
    {
182
        if (! $this->attachedToFakeField) {
183
            return $this->getOriginalValue($entry);
184
        }
185
186
        $value = $this->getOriginalValue($entry, $this->attachedToFakeField);
187
        $value = is_string($value) ? json_decode($value, true) : (array) $value;
188
189
        return $value[$this->getAttributeName()] ?? null;
190
    }
191
192
    public function getValueWithoutPath(?string $value = null): ?string
193
    {
194
        return $value ? Str::after($value, $this->path) : null;
195
    }
196
197
    /*******************************
198
     * Setters - fluently configure the uploader
199
     *******************************/
200
    public function multiple(): self
201
    {
202
        $this->handleMultipleFiles = true;
203
204
        return $this;
205
    }
206
207
    public function relationship(bool $isRelationship): self
208
    {
209
        $this->isRelationship = $isRelationship;
210
211
        return $this;
212
    }
213
214
    /*******************************
215
     * Default implementation functions
216
     *******************************/
217
    public function uploadFiles(Model $entry, $values = null)
218
    {
219
    }
220
221
    private function retrieveFiles(Model $entry): Model
222
    {
223
        $value = $entry->{$this->getAttributeName()};
224
225
        if ($this->handleMultipleFiles) {
226
            if (! isset($entry->getCasts()[$this->getName()]) && is_string($value)) {
227
                $entry->{$this->getAttributeName()} = json_decode($value, true);
228
            }
229
230
            return $entry;
231
        }
232
233
        if ($this->attachedToFakeField) {
234
            $values = $entry->{$this->attachedToFakeField};
235
            $values = is_string($values) ? json_decode($values, true) : (array) $values;
236
237
            $values[$this->getAttributeName()] = isset($values[$this->getAttributeName()]) ? $this->getValueWithoutPath($values[$this->getAttributeName()]) : null;
238
            $entry->{$this->attachedToFakeField} = json_encode($values);
239
240
            return $entry;
241
        }
242
243
        $entry->{$this->getAttributeName()} = $this->getValueWithoutPath($value);
244
245
        return $entry;
246
    }
247
248
    private function deleteFiles(Model $entry)
249
    {
250
        $values = $entry->{$this->getAttributeName()};
251
252
        if ($values === null) {
253
            return;
254
        }
255
256
        if ($this->handleMultipleFiles) {
257
            // ensure we have an array of values when field is not casted in model.
258
            if (! isset($entry->getCasts()[$this->name]) && is_string($values)) {
259
                $values = json_decode($values, true);
260
            }
261
            foreach ($values ?? [] as $value) {
262
                $value = Str::start($value, $this->path);
263
                Storage::disk($this->disk)->delete($value);
264
            }
265
266
            return;
267
        }
268
269
        $values = Str::start($values, $this->path);
270
        Storage::disk($this->disk)->delete($values);
271
    }
272
273
    private function performFileDeletion(Model $entry)
274
    {
275
        if (! $this->handleRepeatableFiles) {
276
            $this->deleteFiles($entry);
277
278
            return;
279
        }
280
281
        $this->deleteRepeatableFiles($entry);
282
    }
283
284
    /*******************************
285
     * helper methods
286
     *******************************/
287
    private function getPathFromConfiguration(array $crudObject, array $configuration): string
288
    {
289
        $this->path = $configuration['path'] ?? $crudObject['prefix'] ?? $this->path;
290
291
        return empty($this->path) ? $this->path : Str::of($this->path)->finish('/')->value();
292
    }
293
294
    private function getOriginalValue(Model $entry, $field = null)
295
    {
296
        $field ??= $this->getAttributeName();
297
298
        if ($this->updatedPreviousFiles !== null) {
299
            return $this->updatedPreviousFiles;
300
        }
301
302
        $previousValue = $entry->getOriginal($field);
303
304
        if (! $previousValue) {
305
            return $previousValue;
306
        }
307
308
        if (
309
            method_exists($entry, 'translationEnabled') &&
310
            $entry->translationEnabled() &&
311
            $entry->isTranslatableAttribute($field)
312
        ) {
313
            return $previousValue[$entry->getLocale()] ?? null;
314
        }
315
316
        return $previousValue;
317
    }
318
}
319