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 — main ( 9a5531...79449a )
by Pedro
12:50 queued 11:45
created

processRepeatableUploads()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
nc 2
nop 2
dl 0
loc 13
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Library\Uploaders\Support\Traits;
4
5
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
6
use Backpack\CRUD\app\Library\Uploaders\Support\Interfaces\UploaderInterface;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Facades\Storage;
10
11
trait HandleRepeatableUploads
12
{
13
    public bool $handleRepeatableFiles = false;
14
15
    public ?string $repeatableContainerName = null;
16
17
    /*******************************
18
     * Setters - fluently configure the uploader
19
     *******************************/
20
    public function repeats(string $repeatableContainerName): self
21
    {
22
        $this->handleRepeatableFiles = true;
23
24
        $this->repeatableContainerName = $repeatableContainerName;
25
26
        return $this;
27
    }
28
29
    /*******************************
30
     * Getters
31
     *******************************/
32
    public function getRepeatableContainerName(): ?string
33
    {
34
        return $this->repeatableContainerName;
35
    }
36
37
    /*******************************
38
     * Default implementation methods
39
     *******************************/
40
    protected function uploadRepeatableFiles($values, $previousValues, $entry = 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

40
    protected function uploadRepeatableFiles(/** @scrutinizer ignore-unused */ $values, $previousValues, $entry = 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...
Unused Code introduced by
The parameter $previousValues 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

40
    protected function uploadRepeatableFiles($values, /** @scrutinizer ignore-unused */ $previousValues, $entry = 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...
Unused Code introduced by
The parameter $entry 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

40
    protected function uploadRepeatableFiles($values, $previousValues, /** @scrutinizer ignore-unused */ $entry = 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...
41
    {
42
    }
43
44
    protected function handleRepeatableFiles(Model $entry): Model
45
    {
46
        $values = collect(CRUD::getRequest()->get($this->getRepeatableContainerName()));
0 ignored issues
show
Bug introduced by
The method getRequest() 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

46
        $values = collect(CRUD::/** @scrutinizer ignore-call */ getRequest()->get($this->getRepeatableContainerName()));
Loading history...
47
        $files = collect(CRUD::getRequest()->file($this->getRepeatableContainerName()));
48
        $value = $this->mergeValuesRecursive($values, $files);
49
50
        if ($this->isRelationship) {
51
            return $this->uploadRelationshipFiles($entry, $value);
52
        }
53
54
        $entry->{$this->getRepeatableContainerName()} = json_encode($this->processRepeatableUploads($entry, $value));
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type array; however, parameter $values of Backpack\CRUD\app\Librar...cessRepeatableUploads() does only seem to accept Illuminate\Support\Collection, 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

54
        $entry->{$this->getRepeatableContainerName()} = json_encode($this->processRepeatableUploads($entry, /** @scrutinizer ignore-type */ $value));
Loading history...
55
56
        return $entry;
57
    }
58
59
    private function uploadRelationshipFiles(Model $entry, mixed $value): Model
60
    {
61
        $modelCount = CRUD::get('uploaded_'.$this->getRepeatableContainerName().'_count');
0 ignored issues
show
Bug introduced by
The method get() 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

61
        /** @scrutinizer ignore-call */ 
62
        $modelCount = CRUD::get('uploaded_'.$this->getRepeatableContainerName().'_count');
Loading history...
62
        $value = $value->slice($modelCount, 1)->toArray();
63
64
        foreach (app('UploadersRepository')->getRepeatableUploadersFor($this->getRepeatableContainerName()) as $uploader) {
65
            if (array_key_exists($modelCount, $value) && isset($value[$modelCount][$uploader->getName()])) {
66
                $entry->{$uploader->getName()} = $uploader->uploadFiles($entry, $value[$modelCount][$uploader->getName()]);
67
            }
68
        }
69
70
        return $entry;
71
    }
72
73
    protected function processRepeatableUploads(Model $entry, Collection $values): Collection
74
    {
75
        foreach (app('UploadersRepository')->getRepeatableUploadersFor($this->getRepeatableContainerName()) as $uploader) {
76
            $uploadedValues = $uploader->uploadRepeatableFiles($values->pluck($uploader->getName())->toArray(), $this->getPreviousRepeatableValues($entry, $uploader));
77
78
            $values = $values->map(function ($item, $key) use ($uploadedValues, $uploader) {
79
                $item[$uploader->getName()] = $uploadedValues[$key] ?? null;
80
81
                return $item;
82
            });
83
        }
84
85
        return $values;
86
    }
87
88
    private function retrieveRepeatableFiles(Model $entry): Model
89
    {
90
        if ($this->isRelationship) {
91
            return $this->retrieveFiles($entry);
0 ignored issues
show
Bug introduced by
It seems like retrieveFiles() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

91
            return $this->/** @scrutinizer ignore-call */ retrieveFiles($entry);
Loading history...
92
        }
93
94
        return $entry;
95
    }
96
97
    private function deleteRepeatableFiles(Model $entry): void
98
    {
99
        if ($this->isRelationship) {
100
            $this->deleteFiles($entry);
0 ignored issues
show
Bug introduced by
It seems like deleteFiles() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

100
            $this->/** @scrutinizer ignore-call */ 
101
                   deleteFiles($entry);
Loading history...
101
102
            return;
103
        }
104
105
        $repeatableValues = collect($entry->{$this->getName()});
0 ignored issues
show
Bug introduced by
It seems like getName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

105
        $repeatableValues = collect($entry->{$this->/** @scrutinizer ignore-call */ getName()});
Loading history...
106
        foreach (app('UploadersRepository')->getRepeatableUploadersFor($this->getRepeatableContainerName()) as $upload) {
107
            if (! $upload->shouldDeleteFiles()) {
108
                continue;
109
            }
110
            $values = $repeatableValues->pluck($upload->getName())->toArray();
111
            foreach ($values as $value) {
112
                if (! $value) {
113
                    continue;
114
                }
115
116
                if (is_array($value)) {
117
                    foreach ($value as $subvalue) {
118
                        Storage::disk($upload->getDisk())->delete($upload->getPath().$subvalue);
119
                    }
120
121
                    continue;
122
                }
123
124
                Storage::disk($upload->getDisk())->delete($upload->getPath().$value);
125
            }
126
        }
127
    }
128
    /*******************************
129
     * Helper methods
130
     *******************************/
131
132
    /**
133
     * Given two multidimensional arrays/collections, merge them recursively.
134
     */
135
    protected function mergeValuesRecursive(array|Collection $array1, array|Collection $array2): array|Collection
136
    {
137
        $merged = $array1;
138
        foreach ($array2 as $key => &$value) {
139
            if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
140
                $merged[$key] = $this->mergeValuesRecursive($merged[$key], $value);
141
            } else {
142
                $merged[$key] = $value;
143
            }
144
        }
145
146
        return $merged;
147
    }
148
149
    /**
150
     * Repeatable items send `_order_` parameter in the request.
151
     * This holds the order of the items in the repeatable container.
152
     */
153
    protected function getFileOrderFromRequest(): array
154
    {
155
        $items = CRUD::getRequest()->input('_order_'.$this->getRepeatableContainerName()) ?? [];
156
157
        array_walk($items, function (&$key, $value) {
0 ignored issues
show
Unused Code introduced by
The parameter $value 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

157
        array_walk($items, function (&$key, /** @scrutinizer ignore-unused */ $value) {

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...
158
            $requestValue = $key[$this->getName()] ?? null;
159
            $key = $this->handleMultipleFiles ? (is_string($requestValue) ? explode(',', $requestValue) : $requestValue) : $requestValue;
160
        });
161
162
        return $items;
163
    }
164
165
    private function getPreviousRepeatableValues(Model $entry, UploaderInterface $uploader): array
166
    {
167
        $previousValues = json_decode($entry->getOriginal($uploader->getRepeatableContainerName()), true);
0 ignored issues
show
Bug introduced by
It seems like $entry->getOriginal($upl...eatableContainerName()) can also be of type array; however, parameter $json of json_decode() 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

167
        $previousValues = json_decode(/** @scrutinizer ignore-type */ $entry->getOriginal($uploader->getRepeatableContainerName()), true);
Loading history...
168
169
        if (! empty($previousValues)) {
170
            $previousValues = array_column($previousValues, $uploader->getName());
171
        }
172
173
        return $previousValues ?? [];
174
    }
175
}
176