Passed
Push — dependabot/npm_and_yarn/docs/i... ( c833a7...57c7e0 )
by
unknown
15:22 queued 08:01
created

MediaLibraryController::shouldReplaceMedia()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace A17\Twill\Http\Controllers\Admin;
4
5
use A17\Twill\Http\Requests\Admin\MediaRequest;
6
use A17\Twill\Models\Media;
7
use A17\Twill\Services\Uploader\SignAzureUpload;
8
use A17\Twill\Services\Uploader\SignS3Upload;
9
use A17\Twill\Services\Uploader\SignUploadListener;
10
use Illuminate\Config\Repository as Config;
11
use Illuminate\Contracts\Foundation\Application;
12
use Illuminate\Http\JsonResponse;
13
use Illuminate\Http\Request;
14
use Illuminate\Routing\ResponseFactory;
15
use Illuminate\Support\Arr;
16
use Illuminate\Support\Collection;
17
use Illuminate\Support\Facades\Storage;
18
19
class MediaLibraryController extends ModuleController implements SignUploadListener
20
{
21
    /**
22
     * @var string
23
     */
24
    protected $moduleName = 'medias';
25
26
    /**
27
     * @var string
28
     */
29
    protected $namespace = 'A17\Twill';
30
31
    /**
32
     * @var array
33
     */
34
    protected $defaultOrders = [
35
        'id' => 'desc',
36
    ];
37
38
    /**
39
     * @var array
40
     */
41
    protected $defaultFilters = [
42
        'search' => 'search',
43
        'tag' => 'tag_id',
44
        'unused' => 'unused',
45
    ];
46
47
    /**
48
     * @var int
49
     */
50
    protected $perPage = 40;
51
52
    /**
53
     * @var string
54
     */
55
    protected $endpointType;
56
57
    /**
58
     * @var array
59
     */
60
    protected $customFields;
61
62
    /**
63
     * @var Illuminate\Routing\ResponseFactory
0 ignored issues
show
Bug introduced by
The type A17\Twill\Http\Controlle...Routing\ResponseFactory was not found. Did you mean Illuminate\Routing\ResponseFactory? If so, make sure to prefix the type with \.
Loading history...
64
     */
65
    protected $responseFactory;
66
67
    /**
68
     * @var Illuminate\Config\Repository
0 ignored issues
show
Bug introduced by
The type A17\Twill\Http\Controlle...inate\Config\Repository was not found. Did you mean Illuminate\Config\Repository? If so, make sure to prefix the type with \.
Loading history...
69
     */
70
    protected $config;
71
72 4
    public function __construct(
73
        Application $app,
74
        Config $config,
75
        Request $request,
76
        ResponseFactory $responseFactory
77
    ) {
78 4
        parent::__construct($app, $request);
79 4
        $this->responseFactory = $responseFactory;
0 ignored issues
show
Documentation Bug introduced by
It seems like $responseFactory of type Illuminate\Routing\ResponseFactory is incompatible with the declared type A17\Twill\Http\Controlle...Routing\ResponseFactory of property $responseFactory.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
80 4
        $this->config = $config;
0 ignored issues
show
Documentation Bug introduced by
It seems like $config of type Illuminate\Config\Repository is incompatible with the declared type A17\Twill\Http\Controlle...inate\Config\Repository of property $config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
81
82 4
        $this->removeMiddleware('can:edit');
83 4
        $this->middleware('can:edit', ['only' => ['signS3Upload', 'signAzureUpload', 'tags', 'store', 'singleUpdate', 'bulkUpdate']]);
84 4
        $this->endpointType = $this->config->get('twill.media_library.endpoint_type');
85 4
        $this->customFields = $this->config->get('twill.media_library.extra_metadatas_fields');
86 4
    }
87
88
    /**
89
     * @param int|null $parentModuleId
90
     * @return array
91
     */
92 1
    public function index($parentModuleId = null)
93
    {
94 1
        if ($this->request->has('except')) {
95 1
            $prependScope['exceptIds'] = $this->request->get('except');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$prependScope was never initialized. Although not strictly required by PHP, it is generally a good practice to add $prependScope = array(); before regardless.
Loading history...
96
        }
97
98 1
        return $this->getIndexData($prependScope ?? []);
99
    }
100
101
    /**
102
     * @param array $prependScope
103
     * @return array
104
     */
105 1
    public function getIndexData($prependScope = [])
106
    {
107 1
        $scopes = $this->filterScope($prependScope);
108 1
        $items = $this->getIndexItems($scopes);
109
110
        return [
111 1
            'items' => $items->map(function ($item) {
112
                return $item->toCmsArray();
113 1
            })->toArray(),
114 1
            'maxPage' => $items->lastPage(),
115 1
            'total' => $items->total(),
116 1
            'tags' => $this->repository->getTagsList(),
0 ignored issues
show
Bug introduced by
The method getTagsList() does not exist on A17\Twill\Repositories\ModuleRepository. Since you implemented __call, 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

116
            'tags' => $this->repository->/** @scrutinizer ignore-call */ getTagsList(),
Loading history...
117
        ];
118
    }
119
120
    /**
121
     * @return array
122
     */
123 2
    protected function getRequestFilters()
124
    {
125 2
        if ($this->request->has('search')) {
126 1
            $requestFilters['search'] = $this->request->get('search');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$requestFilters was never initialized. Although not strictly required by PHP, it is generally a good practice to add $requestFilters = array(); before regardless.
Loading history...
127
        }
128
129 2
        if ($this->request->has('tag')) {
130 1
            $requestFilters['tag'] = $this->request->get('tag');
131
        }
132
133 2
        if ($this->request->has('unused') && (int) $this->request->unused === 1) {
134
            $requestFilters['unused'] = $this->request->get('unused');
135
        }
136
137 2
        return $requestFilters ?? [];
138
    }
139
140
    /**
141
     * @param int|null $parentModuleId
142
     * @return
143
     */
144 3
    public function store($parentModuleId = null)
145
    {
146 3
        $request = $this->app->make(MediaRequest::class);
147 3
        if ($this->endpointType === 'local') {
148 3
            $media = $this->storeFile($request);
149
        } else {
150
            $media = $this->storeReference($request);
151
        }
152
153 3
        return $this->responseFactory->json(['media' => $media->toCmsArray(), 'success' => true], 200);
154
    }
155
156
    /**
157
     * @param Request $request
158
     * @return Media
159
     */
160 3
    public function storeFile($request)
161
    {
162 3
        $originalFilename = $request->input('qqfilename');
163
164 3
        $filename = sanitizeFilename($originalFilename);
165
166 3
        $fileDirectory = $request->input('unique_folder_name');
167
168 3
        $uuid = $request->input('unique_folder_name') . '/' . $filename;
169
170 3
        if ($this->config->get('twill.media_library.prefix_uuid_with_local_path', false)) {
171
            $prefix = trim($this->config->get('twill.media_library.local_path'), '/ ') . '/';
172
            $fileDirectory = $prefix . $fileDirectory;
173
            $uuid = $prefix . $uuid;
174
        }
175
176 3
        $disk = $this->config->get('twill.media_library.disk');
177
178 3
        $request->file('qqfile')->storeAs($fileDirectory, $filename, $disk);
179
180 3
        $filePath = Storage::disk($disk)->path($fileDirectory . '/' . $filename);
181
182 3
        list($w, $h) = getimagesize($filePath);
183
184
        $fields = [
185 3
            'uuid' => $uuid,
186 3
            'filename' => $originalFilename,
187 3
            'width' => $w,
188 3
            'height' => $h,
189
        ];
190
191 3
        if ($this->shouldReplaceMedia($id = $request->input('media_to_replace_id'))) {
192
            $media = $this->repository->whereId($id)->first();
0 ignored issues
show
Bug introduced by
The method whereId() does not exist on A17\Twill\Repositories\ModuleRepository. Since you implemented __call, 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

192
            $media = $this->repository->/** @scrutinizer ignore-call */ whereId($id)->first();
Loading history...
193
            $this->repository->afterDelete($media);
194
            $media->replace($fields);
195
            return $media->fresh();
196
        } else {
197
            return $this->repository->create($fields);
198
        }
199
    }
200
201
    /**
202
     * @param Request $request
203
     * @return Media
204
     */
205
    public function storeReference($request)
206
    {
207
        $fields = [
208
            'uuid' => $request->input('key') ?? $request->input('blob'),
209
            'filename' => $request->input('name'),
210
            'width' => $request->input('width'),
211
            'height' => $request->input('height'),
212
        ];
213 1
214
        if ($this->shouldReplaceMedia($id = $request->input('media_to_replace_id'))) {
215 1
            $media = $this->repository->whereId($id)->first();
216 1
            $this->repository->afterDelete($media);
217
            $media->update($fields);
218 1
            return $media->fresh();
219 1
        } else {
220 1
            return $this->repository->create($fields);
221 1
        }
222
    }
223
224 1
    /**
225 1
     * @return JsonResponse
226 1
     */
227
    public function singleUpdate()
228
    {
229
        $this->repository->update(
230
            $this->request->input('id'),
231
            array_merge([
232 1
                'alt_text' => $this->request->get('alt_text', null),
233
                'caption' => $this->request->get('caption', null),
234 1
                'tags' => $this->request->get('tags', null),
235
            ], $this->getExtraMetadatas()->toArray())
236 1
        );
237
238 1
        return $this->responseFactory->json([
239
            'tags' => $this->repository->getTagsList(),
240 1
        ], 200);
241
    }
242 1
243
    /**
244
     * @return JsonResponse
245 1
     */
246 1
    public function bulkUpdate()
247
    {
248
        $ids = explode(',', $this->request->input('ids'));
249 1
250 1
        $metadatasFromRequest = $this->getExtraMetadatas()->reject(function ($meta) {
251 1
            return is_null($meta);
252 1
        })->toArray();
253 1
254
        $extraMetadatas = array_diff_key($metadatasFromRequest, array_flip((array) $this->request->get('fieldsRemovedFromBulkEditing', [])));
255
256 1
        if (in_array('tags', $this->request->get('fieldsRemovedFromBulkEditing', []))) {
257 1
            $this->repository->addIgnoreFieldsBeforeSave('bulk_tags');
0 ignored issues
show
Bug introduced by
'bulk_tags' of type string is incompatible with the type array expected by parameter $ignore of A17\Twill\Repositories\M...gnoreFieldsBeforeSave(). ( Ignorable by Annotation )

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

257
            $this->repository->addIgnoreFieldsBeforeSave(/** @scrutinizer ignore-type */ 'bulk_tags');
Loading history...
258
        } else {
259 1
            $previousCommonTags = $this->repository->getTags(null, $ids);
0 ignored issues
show
Bug introduced by
The method getTags() does not exist on A17\Twill\Repositories\ModuleRepository. Since you implemented __call, 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

259
            /** @scrutinizer ignore-call */ 
260
            $previousCommonTags = $this->repository->getTags(null, $ids);
Loading history...
260 1
            $newTags = array_filter(explode(',', $this->request->input('tags')));
261 1
        }
262 1
263 1
        foreach ($ids as $id) {
264 1
            $this->repository->update($id, [
265
                'bulk_tags' => $newTags ?? [],
266
                'previous_common_tags' => $previousCommonTags ?? [],
267
            ] + $extraMetadatas);
268
        }
269
270
        $scopes = $this->filterScope(['id' => $ids]);
271
        $items = $this->getIndexItems($scopes);
272
273
        return $this->responseFactory->json([
274
            'items' => $items->map(function ($item) {
275
                return $item->toCmsArray();
276
            })->toArray(),
277
            'tags' => $this->repository->getTagsList(),
278
        ], 200);
279
    }
280
281
    /**
282
     * @param Request $request
283
     * @param SignS3Upload $signS3Upload
284
     * @return mixed
285
     */
286
    public function signS3Upload(Request $request, SignS3Upload $signS3Upload)
287
    {
288
        return $signS3Upload->fromPolicy($request->getContent(), $this, $this->config->get('twill.media_library.disk'));
289
    }
290
291
    /**
292
     * @param Request $request
293
     * @param SignAzureUpload $signAzureUpload
294
     * @return mixed
295
     */
296
    public function signAzureUpload(Request $request, SignAzureUpload $signAzureUpload)
297
    {
298
        return $signAzureUpload->getSasUrl($request, $this, $this->config->get('twill.media_library.disk'));
299
    }
300
301
    /**
302
     * @param $signature
303
     * @param bool $isJsonResponse
304
     * @return mixed
305
     */
306
    public function uploadIsSigned($signature, $isJsonResponse = true)
307
    {
308
        return $isJsonResponse
309
        ? $this->responseFactory->json($signature, 200)
310 2
        : $this->responseFactory->make($signature, 200, ['Content-Type' => 'text/plain']);
311
    }
312 2
313
    /**
314
     * @return JsonResponse
315
     */
316
    public function uploadIsNotValid()
317
    {
318
        return $this->responseFactory->json(["invalid" => true], 500);
319
    }
320 2
321
    /**
322
     * @return Collection
323
     */
324
    private function getExtraMetadatas()
325
    {
326
        return Collection::make($this->customFields)->mapWithKeys(function ($field) {
327
            $fieldInRequest = $this->request->get($field['name']);
328
329
            if (isset($field['type']) && $field['type'] === 'checkbox') {
330
                return [$field['name'] => $fieldInRequest ? Arr::first($fieldInRequest) : false];
331
            }
332
333
            return [$field['name'] => $fieldInRequest];
334
        });
335
    }
336
337
    /**
338
     * @return bool
339
     */
340
    private function shouldReplaceMedia($id)
341
    {
342
        return $this->repository->whereId($id)->exists();
343
    }
344
}
345