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 (#5715)
by Cristian
11:33
created

UploadersRepository   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 61
c 0
b 0
f 0
dl 0
loc 218
rs 9.52
wmc 36

17 Methods

Rating   Name   Duplication   Size   Complexity  
A markAsHandled() 0 4 2
A isUploadHandled() 0 3 1
A hasUploadFor() 0 3 1
A __construct() 0 3 1
A getUploadFor() 0 7 2
A getRegisteredUploadNames() 0 5 1
A getRepeatableUploadersFor() 0 3 1
A registerRepeatableUploader() 0 4 3
A addUploaderClasses() 0 9 3
A isUploadRegistered() 0 3 2
B getFieldUploaderInstance() 0 36 7
A getUploadersGroupsNames() 0 3 1
A hasRepeatableUploadersFor() 0 3 1
A getGroupUploadersClasses() 0 3 1
A isValidUploadField() 0 12 3
A getUploadCrudObjectMacroType() 0 11 3
A getAjaxUploadTypes() 0 10 3
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Uploaders\Support;
4
5
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
6
use Backpack\CRUD\app\Library\Uploaders\Support\Interfaces\UploaderInterface;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
10
final class UploadersRepository
11
{
12
    /**
13
     * The array of uploaders classes for field types.
14
     */
15
    private array $uploaderClasses;
16
17
    /**
18
     * Uploaders registered in a repeatable group.
19
     */
20
    private array $repeatableUploaders = [];
21
22
    /**
23
     * Uploaders that have already been handled (events registered) for each field/column instance.
24
     */
25
    private array $handledUploaders = [];
26
27
    public function __construct()
28
    {
29
        $this->uploaderClasses = config('backpack.crud.uploaders', []);
30
    }
31
32
    /**
33
     * Mark the given uploader as handled.
34
     */
35
    public function markAsHandled(string $objectName): void
36
    {
37
        if (! in_array($objectName, $this->handledUploaders)) {
38
            $this->handledUploaders[] = $objectName;
39
        }
40
    }
41
42
    /**
43
     * Check if the given uploader for field/column have been handled.
44
     */
45
    public function isUploadHandled(string $objectName): bool
46
    {
47
        return in_array($objectName, $this->handledUploaders);
48
    }
49
50
    /**
51
     * Check if there are uploads for the give object(field/column) type.
52
     */
53
    public function hasUploadFor(string $objectType, string $group): bool
54
    {
55
        return array_key_exists($objectType, $this->uploaderClasses[$group] ?? []);
56
    }
57
58
    /**
59
     * Return the uploader for the given object type.
60
     */
61
    public function getUploadFor(string $objectType, string $group): string
62
    {
63
        if (! $this->hasUploadFor($objectType, $group)) {
64
            throw new \Exception('There is no uploader defined for the given field type.');
65
        }
66
67
        return $this->uploaderClasses[$group][$objectType];
68
    }
69
70
    /**
71
     * return the registered groups names AKA macros. eg: withFiles, withMedia.
72
     */
73
    public function getUploadersGroupsNames(): array
74
    {
75
        return array_keys($this->uploaderClasses);
76
    }
77
78
    /**
79
     * Register new uploaders or override existing ones.
80
     */
81
    public function addUploaderClasses(array $uploaders, string $group): void
82
    {
83
        // ensure all uploaders implement the UploaderInterface
84
        foreach ($uploaders as $uploader) {
85
            if (! is_a($uploader, UploaderInterface::class, true)) {
86
                throw new \Exception('The uploader class must implement the UploaderInterface.');
87
            }
88
        }
89
        $this->uploaderClasses[$group] = array_merge($this->getGroupUploadersClasses($group), $uploaders);
90
    }
91
92
    /**
93
     * Return the uploaders classes for the given group.
94
     */
95
    private function getGroupUploadersClasses(string $group): array
96
    {
97
        return $this->uploaderClasses[$group] ?? [];
98
    }
99
100
    /**
101
     * Register the specified uploader for the given upload name.
102
     */
103
    public function registerRepeatableUploader(string $uploadName, UploaderInterface $uploader): void
104
    {
105
        if (! array_key_exists($uploadName, $this->repeatableUploaders) || ! in_array($uploader, $this->repeatableUploaders[$uploadName])) {
106
            $this->repeatableUploaders[$uploadName][] = $uploader;
107
        }
108
    }
109
110
    /**
111
     * Check if there are uploaders registered for the given upload name.
112
     */
113
    public function hasRepeatableUploadersFor(string $uploadName): bool
114
    {
115
        return array_key_exists($uploadName, $this->repeatableUploaders);
116
    }
117
118
    /**
119
     * Get the repeatable uploaders for the given upload name.
120
     */
121
    public function getRepeatableUploadersFor(string $uploadName): array
122
    {
123
        return $this->repeatableUploaders[$uploadName] ?? [];
124
    }
125
126
    /**
127
     * Check if the specified upload is registered for the given repeatable uploads.
128
     */
129
    public function isUploadRegistered(string $uploadName, UploaderInterface $upload): bool
130
    {
131
        return $this->hasRepeatableUploadersFor($uploadName) && in_array($upload->getName(), $this->getRegisteredUploadNames($uploadName));
132
    }
133
134
    /**
135
     * Return the registered uploaders names for the given repeatable upload name.
136
     */
137
    public function getRegisteredUploadNames(string $uploadName): array
138
    {
139
        return array_map(function ($uploader) {
140
            return $uploader->getName();
141
        }, $this->getRepeatableUploadersFor($uploadName));
142
    }
143
144
    /**
145
     * Get the uploaders classes for the given group of uploaders.
146
     */
147
    public function getAjaxUploadTypes(string $uploaderMacro = 'withFiles'): array
148
    {
149
        $ajaxFieldTypes = [];
150
        foreach ($this->uploaderClasses[$uploaderMacro] as $fieldType => $uploader) {
151
            if (is_a($uploader, 'Backpack\Pro\Uploads\BackpackAjaxUploader', true)) {
152
                $ajaxFieldTypes[] = $fieldType;
153
            }
154
        }
155
156
        return $ajaxFieldTypes;
157
    }
158
159
    /**
160
     * Get an ajax uploader instance for a given input name.
161
     */
162
    public function getFieldUploaderInstance(string $requestInputName): UploaderInterface
163
    {
164
        if (strpos($requestInputName, '#') !== false) {
165
            $repeatableContainerName = Str::before($requestInputName, '#');
166
            $requestInputName = Str::after($requestInputName, '#');
167
168
            $uploaders = $this->getRepeatableUploadersFor($repeatableContainerName);
169
170
            $uploader = Arr::first($uploaders, function ($uploader) use ($requestInputName) {
171
                return $uploader->getName() === $requestInputName;
172
            });
173
174
            if (! $uploader) {
175
                abort(500, 'Could not find the field in the repeatable uploaders.');
176
            }
177
178
            return $uploader;
179
        }
180
181
        if (empty($crudObject = CRUD::fields()[$requestInputName] ?? [])) {
0 ignored issues
show
Bug introduced by
The method fields() does not exist on Backpack\CRUD\app\Librar...udPanel\CrudPanelFacade. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

181
        if (empty($crudObject = CRUD::/** @scrutinizer ignore-call */ fields()[$requestInputName] ?? [])) {
Loading history...
182
            abort(500, 'Could not find the field in the CRUD fields.');
183
        }
184
185
        if (! $uploaderMacro = $this->getUploadCrudObjectMacroType($crudObject)) {
186
            abort(500, 'There is no uploader defined for the given field type.');
187
        }
188
189
        if (! $this->isValidUploadField($crudObject, $uploaderMacro)) {
190
            abort(500, 'Invalid field for upload.');
191
        }
192
193
        $uploaderConfiguration = $crudObject[$uploaderMacro] ?? [];
194
        $uploaderConfiguration = ! is_array($uploaderConfiguration) ? [] : $uploaderConfiguration;
195
        $uploaderClass = $this->getUploadFor($crudObject['type'], $uploaderMacro);
0 ignored issues
show
Bug introduced by
It seems like $uploaderMacro can also be of type null; however, parameter $group of Backpack\CRUD\app\Librar...ository::getUploadFor() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

195
        $uploaderClass = $this->getUploadFor($crudObject['type'], /** @scrutinizer ignore-type */ $uploaderMacro);
Loading history...
196
197
        return new $uploaderClass(['name' => $requestInputName], $uploaderConfiguration);
198
    }
199
200
    /**
201
     * Get the upload field macro type for the given object.
202
     */
203
    private function getUploadCrudObjectMacroType(array $crudObject): string|null
204
    {
205
        $uploadersGroups = $this->getUploadersGroupsNames();
206
207
        foreach ($uploadersGroups as $uploaderMacro) {
208
            if (isset($crudObject[$uploaderMacro])) {
209
                return $uploaderMacro;
210
            }
211
        }
212
213
        return null;
214
    }
215
216
    private function isValidUploadField($crudObject, $uploaderMacro)
217
    {
218
        if (Str::contains($crudObject['name'], '#')) {
219
            $container = Str::before($crudObject['name'], '#');
220
            $field = array_filter(CRUD::fields()[$container]['subfields'] ?? [], function ($item) use ($crudObject, $uploaderMacro) {
221
                return $item['name'] === $crudObject['name'] && in_array($item['type'], $this->getAjaxUploadTypes($uploaderMacro));
222
            });
223
224
            return ! empty($field);
225
        }
226
227
        return in_array($crudObject['type'], $this->getAjaxUploadTypes($uploaderMacro));
228
    }
229
}
230