Test Failed
Push — develop ( b2458d...8ee119 )
by Florian
07:36
created

File::create()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3.0026

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 15
c 1
b 0
f 0
nc 4
nop 10
dl 0
loc 32
ccs 14
cts 15
cp 0.9333
crap 3.0026
rs 9.7666

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 Phauthentic\Infrastructure\Storage\Processor\Exception\VariantDoesNotExistException;
22
use Phauthentic\Infrastructure\Storage\Processor\Exception\VariantException;
23
use Phauthentic\Infrastructure\Storage\UrlBuilder\UrlBuilderInterface;
24
use RuntimeException;
25
26
/**
27
 * File
28
 */
29
class File implements FileInterface
30
{
31
    /**
32
     * @var int
33
     */
34
    protected int $id;
35
36
    /**
37
     * @var string
38
     */
39
    protected string $uuid;
40
41
    /**
42
     * @var string
43
     */
44
    protected string $filename;
45
46
    /**
47
     * @var int
48
     */
49
    protected int $filesize;
50
51
    /**
52
     * @var string
53
     */
54
    protected string $mimeType = '';
55
56
    /**
57
     * @var string|null
58
     */
59
    protected ?string $extension = null;
60
61
    /**
62
     * @var string
63
     */
64
    protected ?string $path = null;
65
66
    /**
67
     * @var string|null
68
     */
69
    protected ?string $collection = null;
70
71
    /**
72
     * @var string
73
     */
74
    protected string $storage = 'local';
75
76
    /**
77
     * @var array
78
     */
79
    protected array $metadata = [];
80
81
    /**
82
     * @var string|null
83
     */
84
    protected ?string $model = null;
85
86
    /**
87
     * @var string|null
88
     */
89
    protected ?string $modelId = null;
90
91
    /**
92
     * Source file to be stored in our system
93
     *
94
     * @var mixed
95
     */
96
    protected $sourceFile;
97
98
    /**
99
     * @var resource
100
     */
101
    protected $resource;
102
103
    /**
104
     * @var string
105
     */
106
    protected string $url = '';
107
108
    /**
109
     * @var array
110
     */
111
    protected array $variants = [];
112
113
    /**
114
     * Creates a new instance
115
     *
116
     * @param string $filename Filename
117
     * @param int $filesize Filesize
118
     * @param string $mimeType Mime Type
119
     * @param string $storage Storage config name
120
     * @param string|null $collection Collection name
121 8
     * @param string|null $model Model name
122
     * @param string|null $modelId Model id
123
     * @param array $variants Variants
124
     * @param array $metadata Meta data
125
     * @param resource|null $resource
126
     * @return self
127
     */
128
    public static function create(
129
        string $filename,
130
        int $filesize,
131
        string $mimeType,
132
        string $storage,
133 8
        ?string $collection = null,
134
        ?string $model = null,
135 8
        ?string $modelId = null,
136 8
        array $metadata = [],
137 8
        array $variants = [],
138 8
        $resource = null
139 8
    ): self {
140 8
        $that = new self();
141 8
142 8
        $that->filename = $filename;
143 8
        $that->filesize = $filesize;
144
        $that->mimeType = $mimeType;
145 8
        $that->storage = $storage;
146
        $that->model = $model;
147
        $that->modelId = $modelId;
148
        $that->collection = $collection;
149 8
        $that->variants = $variants;
150 8
        $that->metadata = $metadata;
151
152 8
        if ($resource !== null) {
153
            $that = $that->withResource($resource);
154
        }
155
156
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
157
        $that->extension = empty($extension) ? null : (string)$extension;
158
159
        return $that;
160 1
    }
161
162 1
    /**
163
     * Storage name
164
     *
165
     * @return string
166
     */
167
    public function storage(): string
168
    {
169
        return $this->storage;
170
    }
171 6
172
    /**
173 6
     * UUID of the file
174 6
     *
175
     * @param string $uuid UUID string
176 6
     * @return self
177
     */
178
    public function withUuid(string $uuid): self
179
    {
180
        $that = clone $this;
181
        $that->uuid = $uuid;
182
183
        return $that;
184 1
    }
185
186 1
    /**
187
     * Stream resource that should be stored
188
     *
189
     * @return resource|null
190
     */
191
    public function resource()
192
    {
193
        return $this->resource;
194
    }
195
196
    /**
197
     * Same as withResource() but takes a file path
198
     *
199
     * @param string $file File
200
     * @return self
201
     */
202
    public function withFile(string $file): self
203
    {
204
        $resource = fopen($file, 'rb');
205 7
206
        return $this->withResource($resource);
207
    }
208 7
209 7
    /**
210
     * @param mixed $resource
211
     */
212
    protected function assertStreamResource($resource): void
213 7
    {
214
        if (
215
            !is_resource($resource)
216
            || get_resource_type($resource) !== 'stream'
217
        ) {
218
            throw InvalidStreamResourceException::create();
219
        }
220
    }
221 7
222
    /**
223 7
     * Stream resource of the file to be stored
224
     *
225 7
     * @param resource $resource Stream Resource
226 7
     * @return self
227
     */
228 7
    public function withResource($resource): self
229
    {
230
        $this->assertStreamResource($resource);
231
232
        $that = clone $this;
233
        $that->resource = $resource;
234
235
        return $that;
236
    }
237
238 5
    /**
239
     * Assign a model and model id to a file
240 5
     *
241 5
     * @param string $model Model
242
     * @param string|int $modelId Model ID, UUID string or integer
243 5
     * @return $this
244
     */
245
    public function belongsToModel(string $model, $modelId): self
246
    {
247
        $this->model = $model;
248
        $this->modelId = $modelId;
249
250
        return $this;
251
    }
252 3
253
    /**
254 3
     * Adds the file to a collection
255
     *
256 3
     * @param string $collection Collection
257
     * @return $this
258
     */
259
    public function addToCollection(string $collection): self
260
    {
261
        $this->collection = $collection;
262
263
        return $this;
264
    }
265
266
    /**
267
     * Sets the path, immutable
268
     *
269
     * @param string $path Path to the file
270
     * @return $this
271
     */
272
    public function withPath(string $path): self
273
    {
274
        $that = clone $this;
275
        $that->path = $path;
276
277
        return $that;
278
    }
279 2
280
    /**
281 2
     * Filename
282 2
     *
283
     * @param string $filename Filename
284 2
     * @return self
285 2
     */
286
    public function withFilename(string $filename): self
287 2
    {
288
        $that = clone $this;
289
        $that->filename = $filename;
290
291
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
292
        $that->extension = empty($extension) ? null : (string)$extension;
293
294
        return $that;
295 5
    }
296
297 5
    /**
298
     * The collections name this file belongs into
299
     *
300
     * @return string|null
301
     */
302
    public function collection(): ?string
303
    {
304
        return $this->collection;
305 6
    }
306
307 6
    /**
308
     * Model name
309
     *
310
     * @return string|null
311
     */
312
    public function model(): ?string
313
    {
314
        return $this->model;
315 5
    }
316
317 5
    /**
318
     * Model ID
319
     *
320
     * @return string|null
321
     */
322
    public function modelId(): ?string
323
    {
324
        return $this->modelId;
325
    }
326
327
    /**
328
     * Size of the file in bytes
329
     *
330
     * @return int
331
     */
332
    public function filesize(): int
333
    {
334
        return $this->filesize;
335
    }
336
337
    /**
338
     * Returns a human readable file size
339
     *
340
     * @return string
341
     */
342
    public function readableSize(): string
343
    {
344
        $i = floor(log($this->filesize, 1024));
345
        $round = (string)round($this->filesize / (1024 ** $i), [0, 0, 2, 2, 3][$i]);
346 5
347
        return $round . ['B','kB','MB','GB','TB'][$i];
348 5
    }
349
350
    /**
351
     * @return string|null
352
     */
353
    public function extension(): ?string
354 5
    {
355
        return $this->extension;
356 5
    }
357
358
    /**
359
     * @return string
360
     */
361
    public function mimeType(): string
362 5
    {
363
        return $this->mimeType;
364 5
    }
365
366
    /**
367
     * @return string
368
     */
369
    public function filename(): string
370 5
    {
371
        return $this->filename;
372 5
    }
373
374
    /**
375
     * @return string
376
     */
377
    public function uuid(): string
378 3
    {
379
        return $this->uuid;
380 3
    }
381 1
382 1
    /**
383
     * @return string
384
     */
385
    public function path(): string
386 2
    {
387
        if ($this->path === null) {
388
            throw new RuntimeException(
389
                'Path has not been set'
390
            );
391
        }
392
393
        return $this->path;
394
    }
395 2
396
    /**
397 2
     * Builds the path for this file
398 2
     *
399
     * @param \Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface $pathBuilder Path Builder
400 2
     * @return $this
401
     */
402
    public function buildPath(PathBuilderInterface $pathBuilder): self
403
    {
404
        $that = clone $this;
405
        $that->path = $pathBuilder->path($this);
406
407 1
        return $that;
408
    }
409 1
410 1
    /**
411
     * @param array $metadata Meta data
412 1
     * @return $this
413
     */
414
    public function withMetadata(array $metadata): self
415
    {
416
        $that = clone $this;
417
        $that->metadata = $metadata;
418
419
        return $that;
420 2
    }
421
422 2
    /**
423 2
     * @param string $name Name
424
     * @param mixed $data Data
425 2
     * @return $this
426
     */
427
    public function withMetadataKey(string $name, $data): self
428
    {
429
        $that = clone $this;
430
        $that->metadata[$name] = $data;
431
432
        return $that;
433
    }
434
435
    /**
436
     * @param string $name Name
437
     * @return $this
438
     */
439
    public function withoutMetadataKey(string $name): self
440
    {
441
        $that = clone $this;
442
        unset($that->metadata[$name]);
443
444
        return $that;
445
    }
446
447
    /**
448
     * @return $this
449
     */
450
    public function withoutMetadata(): self
451
    {
452
        $that = clone $this;
453
        $that->metadata = [];
454
455
        return $that;
456
    }
457
458
    /**
459
     * @return array
460
     */
461
    public function metadata(): array
462
    {
463
        return $this->metadata;
464
    }
465
466
    /**
467
     * @return bool
468
     */
469
    public function hasVariants(): bool
470
    {
471
        return !empty($this->variants);
472
    }
473
474
    /**
475
     * @param string $name Name
476
     * @return bool
477
     */
478
    public function hasVariant(string $name): bool
479 2
    {
480
        return isset($this->variants[$name]);
481 2
    }
482
483
    /**
484
     * @return array
485
     */
486
    public function variants(): array
487
    {
488
        return $this->variants;
489
    }
490
491
    /**
492
     * Returns a variant by name
493
     *
494
     * @param string $name Name
495
     * @return array
496
     */
497
    public function variant(string $name): array
498
    {
499
        if (!isset($this->variants[$name])) {
500
            throw VariantDoesNotExistException::withName($name);
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 2
     * @param array $variants Variants
542
     * @param bool $merge Merge Variants, default is true
543 2
     * @return $this
544 2
     */
545 2
    public function withVariants(array $variants, bool $merge = true): self
546
    {
547
        $that = clone $this;
548
        $that->variants = array_merge_recursive(
549 2
            $merge ? $that->variants : [],
550
            $variants
551
        );
552
553
        return $that;
554
    }
555
556
    /**
557
     * @inheritDoc
558
     */
559
    public function buildUrl(UrlBuilderInterface $urlBuilder): self
560
    {
561
        $this->url = $urlBuilder->url($this);
562
563
        return $this;
564
    }
565
566
    /**
567
     * @inheritDoc
568
     */
569
    public function url(): string
570
    {
571
        return $this->url;
572
    }
573
574
    /**
575
     * @inheritDoc
576
     */
577
    public function withUrl(string $url): self
578
    {
579
        $that = clone $this;
580
        $that->url = $url;
581
582
        return $that;
583
    }
584
585
    /**
586
     * @return array
587
     */
588
    public function toArray(): array
589
    {
590
        return [
591
            'uuid' => $this->uuid,
592
            'filename' => $this->filename,
593
            'filesize' => $this->filesize,
594
            'mimeType' => $this->mimeType,
595
            'extension' => $this->extension,
596
            'path' => $this->path,
597
            'model' => $this->model,
598
            'modelId' => $this->modelId,
599
            'collection' => $this->collection,
600
            'readableSize' => $this->readableSize(),
601
            'variants' => $this->variants,
602
            'metaData' => $this->metadata,
603
            'url' => $this->url
604
        ];
605
    }
606
607
    /**
608
     * @inheritDoc
609
     */
610
    public function jsonSerialize()
611
    {
612
        return $this->toArray();
613
    }
614
}
615