Completed
Branch ci (2c70be)
by Florian
02:33
created

File::create()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4.0629

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 18
c 2
b 0
f 0
nc 5
nop 10
dl 0
loc 36
ccs 16
cts 19
cp 0.8421
crap 4.0629
rs 9.6666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * Copyright (c) Florian Krämer (https://florian-kraemer.net)
5
 * Licensed under The MIT License
6
 * For full copyright and license information, please see the LICENSE.txt
7
 * Redistributions of files must retain the above copyright notice.
8
 *
9
 * @copyright Copyright (c) Florian Krämer (https://florian-kraemer.net)
10
 * @author    Florian Krämer
11
 * @link      https://github.com/Phauthentic
12
 * @license   https://opensource.org/licenses/MIT MIT License
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phauthentic\Infrastructure\Storage;
18
19
use Phauthentic\Infrastructure\Storage\Exception\InvalidStreamResourceException;
20
use Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface;
21
use RuntimeException;
22
use InvalidArgumentException;
23
24
/**
25
 * File
26
 */
27
class File implements FileInterface
28
{
29
    /**
30
     * @var int
31
     */
32
    protected int $id;
33
34
    /**
35
     * @var string
36
     */
37
    protected string $uuid;
38
39
    /**
40
     * @var string
41
     */
42
    protected string $filename;
43
44
    /**
45
     * @var int
46
     */
47
    protected int $filesize;
48
49
    /**
50
     * @var string
51
     */
52
    protected string $mimeType = '';
53
54
    /**
55
     * @var string|null
56
     */
57
    protected ?string $extension = null;
58
59
    /**
60
     * @var string
61
     */
62
    protected ?string $path = null;
63
64
    /**
65
     * @var string|null
66
     */
67
    protected ?string $collection = null;
68
69
    /**
70
     * @var string
71
     */
72
    protected string $storage = 'local';
73
74
    /**
75
     * @var array
76
     */
77
    protected array $metadata = [];
78
79
    /**
80
     * @var string|null
81
     */
82
    protected ?string $model = null;
83
84
    /**
85
     * @var string|null
86
     */
87
    protected ?string $modelId = null;
88
89
    /**
90
     * Source file to be stored in our system
91
     *
92
     * @var mixed
93
     */
94
    protected $sourceFile;
95
96
    /**
97
     * @var resource
98
     */
99
    protected $resource;
100
101
    /**
102
     * @var array
103
     */
104
    protected array $variants = [];
105
106
    /**
107
     * Creates a new instance
108
     *
109
     * @param string $filename Filename
110
     * @param int $filesize Filesize
111
     * @param string $mimeType Mime Type
112
     * @param string $storage Storage config name
113
     * @param string|null $collection Collection name
114
     * @param string|null $model Model name
115
     * @param string|null $modelId Model id
116
     * @param array $variants Variants
117
     * @param array $metadata Meta data
118
     * @param resource|null $resource
119
     * @return self
120
     */
121 7
    public static function create(
122
        string $filename,
123
        int $filesize,
124
        string $mimeType,
125
        string $storage,
126
        ?string $collection = null,
127
        ?string $model = null,
128
        ?string $modelId = null,
129
        array $metadata = [],
130
        array $variants = [],
131
        $resource = null
132
    ): self {
133 7
        $that = new self();
134
135 7
        $that->filename = $filename;
136 7
        $that->filesize = $filesize;
137 7
        $that->mimeType = $mimeType;
138 7
        $that->storage = $storage;
139 7
        $that->model = $model;
140 7
        $that->modelId = $modelId;
141 7
        $that->collection = $collection;
142 7
        $that->variants = $variants;
143 7
        $that->metadata = $metadata;
144
145 7
        if (is_resource($resource)) {
146
            $that = $that->withResource($resource);
147 7
        } elseif ($resource !== null) {
0 ignored issues
show
introduced by
The condition $resource !== null is always false.
Loading history...
148
            throw new InvalidArgumentException(sprintf(
149
               'The $resource argument is not a valid resource'
150
            ));
151
        }
152
153 7
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
154 7
        $that->extension = empty($extension) ? null : (string)$extension;
155
156 7
        return $that;
157
    }
158
159
    /**
160
     * Storage name
161
     *
162
     * @return string
163
     */
164 1
    public function storage(): string
165
    {
166 1
        return $this->storage;
167
    }
168
169
    /**
170
     * UUID of the file
171
     *
172
     * @param string $uuid UUID string
173
     * @return self
174
     */
175 5
    public function withUuid(string $uuid): self
176
    {
177 5
        $that = clone $this;
178 5
        $that->uuid = $uuid;
179
180 5
        return $that;
181
    }
182
183
    /**
184
     * Stream resource that should be stored
185
     *
186
     * @return resource|null
187
     */
188 1
    public function resource()
189
    {
190 1
        return $this->resource;
191
    }
192
193
    /**
194
     * Same as withResource() but takes a file path
195
     *
196
     * @param string $file File
197
     * @return self
198
     */
199
    public function withFile(string $file): self
200
    {
201
        $resource = fopen($file, 'rb');
202
203
        return $this->withResource($resource);
204
    }
205
206
    /**
207
     * @param mixed $resource
208
     */
209 6
    protected function assertStreamResource($resource): void
210
    {
211
        if (
212 6
            !is_resource($resource)
213 6
            || get_resource_type($resource) !== 'stream'
214
        ) {
215
            throw InvalidStreamResourceException::create();
216
        }
217 6
    }
218
219
    /**
220
     * Stream resource of the file to be stored
221
     *
222
     * @param resource  $resource
223
     * @return self
224
     */
225 6
    public function withResource($resource): self
226
    {
227 6
        $this->assertStreamResource($resource);
228
229 6
        $that = clone $this;
230 6
        $that->resource = $resource;
231
232 6
        return $that;
233
    }
234
235
    /**
236
     * Assign a model and model id to a file
237
     *
238
     * @param string $model Model
239
     * @param string|int $modelId Model ID, UUID string or integer
240
     * @return $this
241
     */
242 5
    public function belongsToModel(string $model, $modelId): self
243
    {
244 5
        $this->model = $model;
245 5
        $this->modelId = $modelId;
246
247 5
        return $this;
248
    }
249
250
    /**
251
     * Adds the file to a collection
252
     *
253
     * @param string $collection Collection
254
     * @return $this
255
     */
256 3
    public function addToCollection(string $collection): self
257
    {
258 3
        $this->collection = $collection;
259
260 3
        return $this;
261
    }
262
263
    /**
264
     * Sets the path, immutable
265
     *
266
     * @param string $path Path to the file
267
     * @return $this
268
     */
269
    public function withPath(string $path): self
270
    {
271
        $that = clone $this;
272
        $that->path = $path;
273
274
        return $that;
275
    }
276
277
    /**
278
     * Filename
279
     *
280
     * @param string $filename Filename
281
     * @return self
282
     */
283 2
    public function withFilename(string $filename): self
284
    {
285 2
        $that = clone $this;
286 2
        $that->filename = $filename;
287
288 2
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
289 2
        $that->extension = empty($extension) ? null : (string)$extension;
290
291 2
        return $that;
292
    }
293
294
    /**
295
     * The collections name this file belongs into
296
     *
297
     * @return string|null
298
     */
299 4
    public function collection(): ?string
300
    {
301 4
        return $this->collection;
302
    }
303
304
    /**
305
     * Model name
306
     *
307
     * @return string|null
308
     */
309 5
    public function model(): ?string
310
    {
311 5
        return $this->model;
312
    }
313
314
    /**
315
     * Model ID
316
     *
317
     * @return string|null
318
     */
319 4
    public function modelId(): ?string
320
    {
321 4
        return $this->modelId;
322
    }
323
324
    /**
325
     * Size of the file in bytes
326
     *
327
     * @return int
328
     */
329
    public function filesize(): int
330
    {
331
        return $this->filesize;
332
    }
333
334
    /**
335
     * Returns a human readable file size
336
     *
337
     * @return string
338
     */
339
    public function readableSize(): string
340
    {
341
        $i = floor(log($this->filesize, 1024));
342
        $round = (string)round($this->filesize / (1024 ** $i), [0, 0, 2, 2, 3][$i]);
343
344
        return $round . ['B','kB','MB','GB','TB'][$i];
345
    }
346
347
    /**
348
     * @return string|null
349
     */
350 4
    public function extension(): ?string
351
    {
352 4
        return $this->extension;
353
    }
354
355
    /**
356
     * @return string
357
     */
358 4
    public function mimeType(): string
359
    {
360 4
        return $this->mimeType;
361
    }
362
363
    /**
364
     * @return string
365
     */
366 4
    public function filename(): string
367
    {
368 4
        return $this->filename;
369
    }
370
371
    /**
372
     * @return string
373
     */
374 4
    public function uuid(): string
375
    {
376 4
        return $this->uuid;
377
    }
378
379
    /**
380
     * @return string
381
     */
382 3
    public function path(): string
383
    {
384 3
        if ($this->path === null) {
385 1
            throw new RuntimeException(
386 1
                'Path has not been set'
387
            );
388
        }
389
390 2
        return $this->path;
391
    }
392
393
    /**
394
     * Builds the path for this file
395
     *
396
     * @param \Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface $pathBuilder Path Builder
397
     * @return $this
398
     */
399 2
    public function buildPath(PathBuilderInterface $pathBuilder): self
400
    {
401 2
        $that = clone $this;
402 2
        $that->path = $pathBuilder->path($this);
403
404 2
        return $that;
405
    }
406
407
    /**
408
     * @param array $metadata Meta data
409
     * @return $this
410
     */
411 1
    public function withMetadata(array $metadata): self
412
    {
413 1
        $that = clone $this;
414 1
        $that->metadata = $metadata;
415
416 1
        return $that;
417
    }
418
419
    /**
420
     * @param string $name Name
421
     * @param mixed $data Data
422
     * @return $this
423
     */
424 2
    public function withMetadataKey(string $name, $data): self
425
    {
426 2
        $that = clone $this;
427 2
        $that->metadata[$name] = $data;
428
429 2
        return $that;
430
    }
431
432
    /**
433
     * @param string $name Name
434
     * @return $this
435
     */
436
    public function withoutMetadataKey(string $name): self
437
    {
438
        $that = clone $this;
439
        unset($that->metadata[$name]);
440
441
        return $that;
442
    }
443
444
    /**
445
     * @return $this
446
     */
447
    public function withoutMetadata(): self
448
    {
449
        $that = clone $this;
450
        $that->metadata = [];
451
452
        return $that;
453
    }
454
455
    /**
456
     * @return array
457
     */
458
    public function metadata(): array
459
    {
460
        return $this->metadata;
461
    }
462
463
    /**
464
     * @return bool
465
     */
466
    public function hasVariants(): bool
467
    {
468
        return !empty($this->variants);
469
    }
470
471
    /**
472
     * @param string $name Name
473
     * @return bool
474
     */
475
    public function hasVariant(string $name): bool
476
    {
477
        return isset($this->variants[$name]);
478
    }
479
480
    /**
481
     * @return array
482
     */
483 2
    public function variants(): array
484
    {
485 2
        return $this->variants;
486
    }
487
488
    /**
489
     * Returns a variant by name
490
     *
491
     * @param string $name Name
492
     * @return array
493
     */
494
    public function variant(string $name): array
495
    {
496
        if (!isset($this->variants[$name])) {
497
            throw new RuntimeException(
498
                'Variant %s does not exist',
499
                $name
0 ignored issues
show
Bug introduced by
$name of type string is incompatible with the type integer expected by parameter $code of RuntimeException::__construct(). ( Ignorable by Annotation )

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

499
                /** @scrutinizer ignore-type */ $name
Loading history...
500
            );
501
        }
502
503
        return $this->variants[$name];
504
    }
505
506
    /**
507
     * Adds a variant
508
     *
509
     * @param string $name Name
510
     * @param array $data Data
511
     * @return $this
512
     */
513
    public function withVariant(string $name, array $data): self
514
    {
515
        $that = clone $this;
516
        $that->variants[$name] = $data;
517
518
        return $that;
519
    }
520
521
    /**
522
     * Gets the paths for all variants
523
     *
524
     * @return array
525
     */
526
    public function variantPaths(): array
527
    {
528
        $paths = [];
529
        foreach ($this->variants as $variant => $data) {
530
            if (isset($data['path'])) {
531
                $paths[$variant] = $data['path'];
532
            }
533
        }
534
535
        return $paths;
536
    }
537
538
    /**
539
     * Sets many variants at once
540
     *
541
     * @param array $variants Variants
542
     * @param bool $merge Merge Variants, default is true
543
     * @return $this
544
     */
545 2
    public function withVariants(array $variants, bool $merge = true): self
546
    {
547 2
        $that = clone $this;
548 2
        $that->variants = array_merge_recursive(
549 2
            $merge ? $that->variants : [],
550
            $variants
551
        );
552
553 2
        return $that;
554
    }
555
556
    /**
557
     * @return array
558
     */
559
    public function toArray(): array
560
    {
561
        return [
562
            'uuid' => $this->uuid,
563
            'filename' => $this->filename,
564
            'filesize' => $this->filesize,
565
            'mimeType' => $this->mimeType,
566
            'extension' => $this->extension,
567
            'path' => $this->path,
568
            'model' => $this->model,
569
            'modelId' => $this->modelId,
570
            'collection' => $this->collection,
571
            'readableSize' => $this->readableSize(),
572
            'variants' => $this->variants,
573
            'metaData' => $this->metadata,
574
        ];
575
    }
576
577
    /**
578
     * @inheritDoc
579
     */
580
    public function jsonSerialize()
581
    {
582
        return $this->toArray();
583
    }
584
}
585