Passed
Branch ci (cf247c)
by Florian
02:24
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 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 15
c 3
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\VariantException;
22
use RuntimeException;
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 ($resource !== null) {
146
            $that = $that->withResource($resource);
147
        }
148
149 7
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
150 7
        $that->extension = empty($extension) ? null : (string)$extension;
151
152 7
        return $that;
153
    }
154
155
    /**
156
     * Storage name
157
     *
158
     * @return string
159
     */
160 1
    public function storage(): string
161
    {
162 1
        return $this->storage;
163
    }
164
165
    /**
166
     * UUID of the file
167
     *
168
     * @param string $uuid UUID string
169
     * @return self
170
     */
171 5
    public function withUuid(string $uuid): self
172
    {
173 5
        $that = clone $this;
174 5
        $that->uuid = $uuid;
175
176 5
        return $that;
177
    }
178
179
    /**
180
     * Stream resource that should be stored
181
     *
182
     * @return resource|null
183
     */
184 1
    public function resource()
185
    {
186 1
        return $this->resource;
187
    }
188
189
    /**
190
     * Same as withResource() but takes a file path
191
     *
192
     * @param string $file File
193
     * @return self
194
     */
195
    public function withFile(string $file): self
196
    {
197
        $resource = fopen($file, 'rb');
198
199
        return $this->withResource($resource);
200
    }
201
202
    /**
203
     * @param mixed $resource
204
     */
205 6
    protected function assertStreamResource($resource): void
206
    {
207
        if (
208 6
            !is_resource($resource)
209 6
            || get_resource_type($resource) !== 'stream'
210
        ) {
211
            throw InvalidStreamResourceException::create();
212
        }
213 6
    }
214
215
    /**
216
     * Stream resource of the file to be stored
217
     *
218
     * @param resource $resource Stream Resource
219
     * @return self
220
     */
221 6
    public function withResource($resource): self
222
    {
223 6
        $this->assertStreamResource($resource);
224
225 6
        $that = clone $this;
226 6
        $that->resource = $resource;
227
228 6
        return $that;
229
    }
230
231
    /**
232
     * Assign a model and model id to a file
233
     *
234
     * @param string $model Model
235
     * @param string|int $modelId Model ID, UUID string or integer
236
     * @return $this
237
     */
238 5
    public function belongsToModel(string $model, $modelId): self
239
    {
240 5
        $this->model = $model;
241 5
        $this->modelId = $modelId;
242
243 5
        return $this;
244
    }
245
246
    /**
247
     * Adds the file to a collection
248
     *
249
     * @param string $collection Collection
250
     * @return $this
251
     */
252 3
    public function addToCollection(string $collection): self
253
    {
254 3
        $this->collection = $collection;
255
256 3
        return $this;
257
    }
258
259
    /**
260
     * Sets the path, immutable
261
     *
262
     * @param string $path Path to the file
263
     * @return $this
264
     */
265
    public function withPath(string $path): self
266
    {
267
        $that = clone $this;
268
        $that->path = $path;
269
270
        return $that;
271
    }
272
273
    /**
274
     * Filename
275
     *
276
     * @param string $filename Filename
277
     * @return self
278
     */
279 2
    public function withFilename(string $filename): self
280
    {
281 2
        $that = clone $this;
282 2
        $that->filename = $filename;
283
284 2
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
285 2
        $that->extension = empty($extension) ? null : (string)$extension;
286
287 2
        return $that;
288
    }
289
290
    /**
291
     * The collections name this file belongs into
292
     *
293
     * @return string|null
294
     */
295 4
    public function collection(): ?string
296
    {
297 4
        return $this->collection;
298
    }
299
300
    /**
301
     * Model name
302
     *
303
     * @return string|null
304
     */
305 5
    public function model(): ?string
306
    {
307 5
        return $this->model;
308
    }
309
310
    /**
311
     * Model ID
312
     *
313
     * @return string|null
314
     */
315 4
    public function modelId(): ?string
316
    {
317 4
        return $this->modelId;
318
    }
319
320
    /**
321
     * Size of the file in bytes
322
     *
323
     * @return int
324
     */
325
    public function filesize(): int
326
    {
327
        return $this->filesize;
328
    }
329
330
    /**
331
     * Returns a human readable file size
332
     *
333
     * @return string
334
     */
335
    public function readableSize(): string
336
    {
337
        $i = floor(log($this->filesize, 1024));
338
        $round = (string)round($this->filesize / (1024 ** $i), [0, 0, 2, 2, 3][$i]);
339
340
        return $round . ['B','kB','MB','GB','TB'][$i];
341
    }
342
343
    /**
344
     * @return string|null
345
     */
346 4
    public function extension(): ?string
347
    {
348 4
        return $this->extension;
349
    }
350
351
    /**
352
     * @return string
353
     */
354 4
    public function mimeType(): string
355
    {
356 4
        return $this->mimeType;
357
    }
358
359
    /**
360
     * @return string
361
     */
362 4
    public function filename(): string
363
    {
364 4
        return $this->filename;
365
    }
366
367
    /**
368
     * @return string
369
     */
370 4
    public function uuid(): string
371
    {
372 4
        return $this->uuid;
373
    }
374
375
    /**
376
     * @return string
377
     */
378 3
    public function path(): string
379
    {
380 3
        if ($this->path === null) {
381 1
            throw new RuntimeException(
382 1
                'Path has not been set'
383
            );
384
        }
385
386 2
        return $this->path;
387
    }
388
389
    /**
390
     * Builds the path for this file
391
     *
392
     * @param \Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface $pathBuilder Path Builder
393
     * @return $this
394
     */
395 2
    public function buildPath(PathBuilderInterface $pathBuilder): self
396
    {
397 2
        $that = clone $this;
398 2
        $that->path = $pathBuilder->path($this);
399
400 2
        return $that;
401
    }
402
403
    /**
404
     * @param array $metadata Meta data
405
     * @return $this
406
     */
407 1
    public function withMetadata(array $metadata): self
408
    {
409 1
        $that = clone $this;
410 1
        $that->metadata = $metadata;
411
412 1
        return $that;
413
    }
414
415
    /**
416
     * @param string $name Name
417
     * @param mixed $data Data
418
     * @return $this
419
     */
420 2
    public function withMetadataKey(string $name, $data): self
421
    {
422 2
        $that = clone $this;
423 2
        $that->metadata[$name] = $data;
424
425 2
        return $that;
426
    }
427
428
    /**
429
     * @param string $name Name
430
     * @return $this
431
     */
432
    public function withoutMetadataKey(string $name): self
433
    {
434
        $that = clone $this;
435
        unset($that->metadata[$name]);
436
437
        return $that;
438
    }
439
440
    /**
441
     * @return $this
442
     */
443
    public function withoutMetadata(): self
444
    {
445
        $that = clone $this;
446
        $that->metadata = [];
447
448
        return $that;
449
    }
450
451
    /**
452
     * @return array
453
     */
454
    public function metadata(): array
455
    {
456
        return $this->metadata;
457
    }
458
459
    /**
460
     * @return bool
461
     */
462
    public function hasVariants(): bool
463
    {
464
        return !empty($this->variants);
465
    }
466
467
    /**
468
     * @param string $name Name
469
     * @return bool
470
     */
471
    public function hasVariant(string $name): bool
472
    {
473
        return isset($this->variants[$name]);
474
    }
475
476
    /**
477
     * @return array
478
     */
479 2
    public function variants(): array
480
    {
481 2
        return $this->variants;
482
    }
483
484
    /**
485
     * Returns a variant by name
486
     *
487
     * @param string $name Name
488
     * @return array
489
     */
490
    public function variant(string $name): array
491
    {
492
        if (!isset($this->variants[$name])) {
493
            throw new VariantException(sprintf(
494
                'Variant %s does not exist',
495
                $name
496
            ));
497
        }
498
499
        return $this->variants[$name];
500
    }
501
502
    /**
503
     * Adds a variant
504
     *
505
     * @param string $name Name
506
     * @param array $data Data
507
     * @return $this
508
     */
509
    public function withVariant(string $name, array $data): self
510
    {
511
        $that = clone $this;
512
        $that->variants[$name] = $data;
513
514
        return $that;
515
    }
516
517
    /**
518
     * Gets the paths for all variants
519
     *
520
     * @return array
521
     */
522
    public function variantPaths(): array
523
    {
524
        $paths = [];
525
        foreach ($this->variants as $variant => $data) {
526
            if (isset($data['path'])) {
527
                $paths[$variant] = $data['path'];
528
            }
529
        }
530
531
        return $paths;
532
    }
533
534
    /**
535
     * Sets many variants at once
536
     *
537
     * @param array $variants Variants
538
     * @param bool $merge Merge Variants, default is true
539
     * @return $this
540
     */
541 2
    public function withVariants(array $variants, bool $merge = true): self
542
    {
543 2
        $that = clone $this;
544 2
        $that->variants = array_merge_recursive(
545 2
            $merge ? $that->variants : [],
546
            $variants
547
        );
548
549 2
        return $that;
550
    }
551
552
    /**
553
     * @return array
554
     */
555
    public function toArray(): array
556
    {
557
        return [
558
            'uuid' => $this->uuid,
559
            'filename' => $this->filename,
560
            'filesize' => $this->filesize,
561
            'mimeType' => $this->mimeType,
562
            'extension' => $this->extension,
563
            'path' => $this->path,
564
            'model' => $this->model,
565
            'modelId' => $this->modelId,
566
            'collection' => $this->collection,
567
            'readableSize' => $this->readableSize(),
568
            'variants' => $this->variants,
569
            'metaData' => $this->metadata,
570
        ];
571
    }
572
573
    /**
574
     * @inheritDoc
575
     */
576
    public function jsonSerialize()
577
    {
578
        return $this->toArray();
579
    }
580
}
581