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