File::create()   A
last analyzed

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|null
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 10
    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 10
        $that = new self();
140
141 10
        $that->filename = $filename;
142 10
        $that->filesize = $filesize;
143 10
        $that->mimeType = $mimeType;
144 10
        $that->storage = $storage;
145 10
        $that->model = $model;
146 10
        $that->modelId = $modelId;
147 10
        $that->collection = $collection;
148 10
        $that->variants = $variants;
149 10
        $that->metadata = $metadata;
150
151 10
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
152 10
        $that->extension = empty($extension) ? null : (string)$extension;
153
154 10
        if ($resource !== null) {
155
            $that = $that->withResource($resource);
156
        }
157
158 10
        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 9
    protected function assertStreamResource($resource): void
213
    {
214
        if (
215 9
            !is_resource($resource)
216 9
            || get_resource_type($resource) !== 'stream'
217
        ) {
218
            throw InvalidStreamResourceException::create();
219
        }
220 9
    }
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 9
    public function withResource($resource): FileInterface
229
    {
230 9
        $this->assertStreamResource($resource);
231
232 9
        $that = clone $this;
233 9
        $that->resource = $resource;
234
235 9
        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 = (string)$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 1
     */
415
    public function withMetadata(array $metadata, bool $overwrite = false): FileInterface
416 1
    {
417 1
        $that = clone $this;
418
        if ($overwrite) {
419 1
            $that->metadata = $metadata;
420
        } else {
421
            $that->metadata = $metadata + $that->metadata;
422
        }
423
424
        return $that;
425
    }
426
427 2
    /**
428
     * @inheritDoc
429 2
     */
430 2
    public function withMetadataByKey(string $name, $data): FileInterface
431
    {
432 2
        $that = clone $this;
433
        $that->metadata[$name] = $data;
434
435
        return $that;
436
    }
437
438
    /**
439 1
     * @inheritDoc
440
     */
441 1
    public function withoutMetadataByKey(string $name): FileInterface
442 1
    {
443
        $that = clone $this;
444 1
        unset($that->metadata[$name]);
445
446
        return $that;
447
    }
448
449
    /**
450 1
     * @inheritDoc
451
     */
452 1
    public function withoutMetadata(): self
453 1
    {
454
        $that = clone $this;
455 1
        $that->metadata = [];
456
457
        return $that;
458
    }
459
460
    /**
461 1
     * @inheritDoc
462
     */
463 1
    public function metadata(): array
464
    {
465
        return $this->metadata;
466
    }
467
468
    /**
469 1
     * @return bool
470
     */
471 1
    public function hasVariants(): bool
472
    {
473
        return !empty($this->variants);
474
    }
475
476
    /**
477
     * @param string $name Name
478 1
     * @return bool
479
     */
480 1
    public function hasVariant(string $name): bool
481
    {
482
        return isset($this->variants[$name]);
483
    }
484
485
    /**
486 3
     * @return array
487
     */
488 3
    public function variants(): array
489
    {
490
        return $this->variants;
491
    }
492
493
    /**
494
     * Returns a variant by name
495
     *
496
     * @param string $name Name
497
     * @return array
498
     */
499
    public function variant(string $name): array
500
    {
501
        if (!isset($this->variants[$name])) {
502
            throw VariantDoesNotExistException::withName($name);
503
        }
504
505
        return $this->variants[$name];
506
    }
507
508
    /**
509
     * Adds a variant
510
     *
511
     * @param string $name Name
512
     * @param array $data Data
513 1
     * @return \Phauthentic\Infrastructure\Storage\FileInterface
514
     */
515 1
    public function withVariant(string $name, array $data): FileInterface
516 1
    {
517
        $that = clone $this;
518 1
        $that->variants[$name] = $data;
519
520
        return $that;
521
    }
522
523
    /**
524
     * Gets the paths for all variants
525
     *
526
     * @return array
527
     */
528
    public function variantPaths(): array
529
    {
530
        $paths = [];
531
        foreach ($this->variants as $variant => $data) {
532
            if (isset($data['path'])) {
533
                $paths[$variant] = $data['path'];
534
            }
535
        }
536
537
        return $paths;
538
    }
539
540
    /**
541
     * @param string $key
542
     * @param mixed $data;
543
     */
544
    public function withMetadataKey(string $key, $data): FileInterface
545 2
    {
546
        $that = clone $this;
547 2
        $that->metadata[$key] = $data;
548 2
549 2
        return $that;
550
    }
551
552
    /**
553 2
     * @inheritDoc
554
     */
555
    public function withoutMetadataKey(string $key): FileInterface
556
    {
557
        $that = clone $this;
558
        unset($that->metadata[$key]);
559
560
        return $that;
561
    }
562
563
    /**
564
     * Sets many variants at once
565
     *
566
     * @param array $variants Variants
567
     * @param bool $merge Merge Variants, default is true
568
     * @return \Phauthentic\Infrastructure\Storage\FileInterface
569
     */
570
    public function withVariants(array $variants, bool $merge = true): FileInterface
571
    {
572
        $that = clone $this;
573
        $that->variants = array_merge_recursive(
574
            $merge ? $that->variants : [],
575
            $variants
576
        );
577
578
        return $that;
579
    }
580
581
    /**
582
     * @inheritDoc
583
     */
584
    public function buildUrl(UrlBuilderInterface $urlBuilder): FileInterface
585
    {
586
        $this->url = $urlBuilder->url($this);
587
588 1
        return $this;
589
    }
590
591 1
    /**
592 1
     * @inheritDoc
593 1
     */
594 1
    public function url(): string
595 1
    {
596 1
        return $this->url;
597 1
    }
598 1
599 1
    /**
600 1
     * @inheritDoc
601 1
     */
602 1
    public function withUrl(string $url): FileInterface
603 1
    {
604
        $that = clone $this;
605
        $that->url = $url;
606
607
        return $that;
608
    }
609
610 1
    /**
611
     * @return array
612 1
     */
613
    public function toArray(): array
614
    {
615
        return [
616
            'uuid' => $this->uuid,
617
            'filename' => $this->filename,
618
            'filesize' => $this->filesize,
619
            'mimeType' => $this->mimeType,
620
            'extension' => $this->extension,
621
            'path' => $this->path,
622
            'model' => $this->model,
623
            'modelId' => $this->modelId,
624
            'collection' => $this->collection,
625
            'readableSize' => $this->readableSize(),
626
            'variants' => $this->variants,
627
            'metadata' => $this->metadata,
628
            'url' => $this->url
629
        ];
630
    }
631
632
    /**
633
     * @inheritDoc
634
     */
635
    public function jsonSerialize(): array
636
    {
637
        return $this->toArray();
638
    }
639
}
640