Passed
Push — develop ( 86ea71...c4fa00 )
by Florian
03:58
created

File::create()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3.0021

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