Passed
Push — master ( 32fc02...88ceb8 )
by Aleksei
02:03
created

FileBucket   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Test Coverage

Coverage 77.14%

Importance

Changes 2
Bugs 2 Features 1
Metric Value
eloc 60
dl 0
loc 126
ccs 54
cts 70
cp 0.7714
rs 10
c 2
b 2
f 1
wmc 26

15 Methods

Rating   Name   Duplication   Size   Complexity  
A contentType() 0 7 4
A isInline() 0 3 1
A hasDisposition() 0 3 1
A withInline() 0 5 1
A getContentType() 0 3 1
A isAttachment() 0 3 1
A withContentType() 0 5 1
A getFileName() 0 3 1
A createFromPath() 0 3 1
A setAttachment() 0 5 1
A setContentType() 0 4 1
A withAttachment() 0 5 1
A setInline() 0 4 1
A __construct() 0 21 6
A setDispositionHeader() 0 14 4
1
<?php
2
3
namespace roxblnfk\SmartStream\Data;
4
5
use SplFileInfo;
6
use Yiisoft\Http\Header;
7
8
class FileBucket extends DataBucket
9
{
10
    public const TYPE_OCTET_STREAM = 'application/octet-stream';
11
12
    protected const DISPOSITION_INLINE = 'inline';
13
    protected const DISPOSITION_ATTACHMENT = 'attachment';
14
15
    protected const IS_CONVERTABLE = false;
16
    protected ?string $contentType = null;
17
    protected ?string $contentDisposition = null;
18
    protected ?string $fileName = null;
19
20
    /**
21
     * FileBucket constructor.
22
     * @param string|resource|SplFileInfo $data
23
     * @param null|string $contentType
24
     * @param null|string $filename
25
     * @throws \Exception
26
     */
27 27
    public function __construct($data, string $contentType = null, string $filename = null)
28
    {
29
        switch (true) {
30 27
            case $data instanceof SplFileInfo:
31
                $filename = $filename ?? $data->getFilename();
32
                $contentType = $contentType ?? $this->contentType($filename);
33
                parent::__construct($data);
34
                break;
35 27
            case is_string($data):
36
            case is_resource($data):
37 27
                parent::__construct($data);
38 27
                break;
39
            default:
40
                throw new \Exception('The $data parameter must be a resource, a string or an instance of SplFileInfo');
41
        }
42
43 27
        if ($contentType !== null) {
44
            $this->setContentType($contentType);
45
        }
46 27
        if ($filename !== null) {
47
            $this->setAttachment($filename);
48
        }
49 27
    }
50
51
    public static function createFromPath(string $filePath): self
52
    {
53
        return new static(new SplFileInfo($filePath));
54
    }
55
56 4
    public function getContentType(): ?string
57
    {
58 4
        return $this->contentType;
59
    }
60 3
    public function getFileName(): ?string
61
    {
62 3
        return $this->fileName;
63
    }
64 3
    public function hasDisposition(): bool
65
    {
66 3
        return $this->contentDisposition !== null;
67
    }
68 6
    public function isAttachment(): bool
69
    {
70 6
        return $this->contentDisposition === self::DISPOSITION_ATTACHMENT;
71
    }
72 4
    public function isInline(): bool
73
    {
74 4
        return $this->contentDisposition === self::DISPOSITION_INLINE;
75
    }
76
77 14
    public function withAttachment(string $filename = null): self
78
    {
79 14
        $clone = clone $this;
80 14
        $clone->setAttachment($filename);
81 14
        return $clone;
82
    }
83 3
    public function withContentType(?string $contentType): self
84
    {
85 3
        $clone = clone $this;
86 3
        $clone->setContentType($contentType);
87 3
        return $clone;
88
    }
89 4
    public function withInline(): self
90
    {
91 4
        $clone = clone $this;
92 4
        $clone->setInline();
93 4
        return $clone;
94
    }
95
96 3
    public function setContentType(?string $contentType): void
97
    {
98 3
        $this->contentType = $contentType;
99 3
        $this->setHeader(Header::CONTENT_TYPE, $contentType);
100 3
    }
101 4
    public function setInline(): void
102
    {
103 4
        $this->contentDisposition = self::DISPOSITION_INLINE;
104 4
        $this->setDispositionHeader();
105 4
    }
106 14
    final protected function setAttachment(?string $filename): void
107
    {
108 14
        $this->contentDisposition = self::DISPOSITION_ATTACHMENT;
109 14
        $this->fileName = $filename;
110 14
        $this->setDispositionHeader();
111 14
    }
112 16
    final protected function setDispositionHeader(): void
113
    {
114 16
        if ($this->contentDisposition === null) {
115
            return;
116
        }
117 16
        $headerBody = ($this->contentDisposition === self::DISPOSITION_ATTACHMENT && $this->fileName !== null)
118 10
            ? sprintf(
119 10
                '%s; filename="%s"; filename*=UTF-8\'\'%s',
120 10
                $this->contentDisposition,
121 10
                preg_replace('/[\x00-\x1F\x7F\"]/', ' ', $this->fileName),
122 10
                rawurlencode($this->fileName)
123
            )
124 16
            : $this->contentDisposition;
125 16
        $this->setHeader(Header::CONTENT_DISPOSITION, $headerBody);
126 16
    }
127
    private function contentType(?string $filename): ?string
128
    {
129
        if ($filename === null) {
130
            return null;
131
        }
132
        $result = function_exists('mime_content_type') ? mime_content_type($filename) : null;
133
        return is_string($result) ? $result : null;
134
    }
135
}
136