Passed
Push — master ( 293623...648522 )
by Aleksei
01:53
created

FileBucket::fileContentType()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4.25

Importance

Changes 0
Metric Value
cc 4
eloc 3
nc 3
nop 1
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 4.25
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace roxblnfk\SmartStream\Data;
4
5
use InvalidArgumentException;
6
use SplFileInfo;
7
use Yiisoft\Http\Header;
8
9
class FileBucket extends DataBucket
10
{
11
    public const TYPE_OCTET_STREAM = 'application/octet-stream';
12
13
    protected const DISPOSITION_INLINE = 'inline';
14
    protected const DISPOSITION_ATTACHMENT = 'attachment';
15
16
    protected const IS_CONVERTABLE = false;
17
    protected ?string $contentType = null;
18
    protected ?string $contentDisposition = null;
19
    protected ?string $fileName = null;
20
21
    /**
22
     * FileBucket constructor.
23
     * @param string|resource|SplFileInfo $data
24
     * @param null|string $contentType
25
     * @param null|string $fileName
26
     * @throws \Exception
27
     */
28 41
    public function __construct($data, string $contentType = null, string $fileName = null)
29
    {
30
        switch (true) {
31 41
            case $data instanceof SplFileInfo:
32 5
                if (!$data->isFile()) {
33 2
                    throw new InvalidArgumentException('File does not exist or is not a file.');
34
                }
35 3
                $fileName = $fileName ?? $data->getFilename();
36
                // $contentType = $contentType ?? $this->fileContentType($data->getPathname());
37 3
                parent::__construct($data);
38 3
                break;
39 36
            case is_string($data):
40 2
            case is_resource($data):
41 35
                parent::__construct($data);
42 35
                break;
43
            default:
44 1
                throw new InvalidArgumentException(
45 1
                    'The $data parameter must be a resource, a string or an instance of SplFileInfo.'
46
                );
47
        }
48
49 38
        if ($contentType !== null) {
50 2
            $this->setContentType($contentType);
51
        }
52 38
        if ($fileName !== null) {
53 4
            $this->setAttachment($fileName);
54
        }
55 38
    }
56
57 4
    public static function createFromPath(string $filePath, string $contentType = null, string $fileName = null): self
58
    {
59 4
        return new static(new SplFileInfo($filePath), $contentType, $fileName);
60
    }
61
62 12
    public function getContentType(): ?string
63
    {
64 12
        return $this->contentType;
65
    }
66 9
    public function getFileName(): ?string
67
    {
68 9
        return $this->fileName;
69
    }
70 4
    public function hasDisposition(): bool
71
    {
72 4
        return $this->contentDisposition !== null;
73
    }
74 6
    public function isAttachment(): bool
75
    {
76 6
        return $this->contentDisposition === self::DISPOSITION_ATTACHMENT;
77
    }
78 4
    public function isInline(): bool
79
    {
80 4
        return $this->contentDisposition === self::DISPOSITION_INLINE;
81
    }
82
83 14
    public function withAttachment(string $filename = null): self
84
    {
85 14
        $clone = clone $this;
86 14
        $clone->setAttachment($filename);
87 14
        return $clone;
88
    }
89 4
    public function withContentType(?string $contentType): self
90
    {
91 4
        $clone = clone $this;
92 4
        $clone->setContentType($contentType);
93 4
        return $clone;
94
    }
95 5
    public function withInline(): self
96
    {
97 5
        $clone = clone $this;
98 5
        $clone->setInline();
99 5
        return $clone;
100
    }
101 1
    public function withoutDisposition(): self
102
    {
103 1
        $clone = clone $this;
104 1
        $clone->contentDisposition = null;
105 1
        $clone->setDispositionHeader();
106 1
        return $clone;
107
    }
108 3
    public function withAutoContentType(): self
109
    {
110 3
        $clone = clone $this;
111 3
        $type = null;
112 3
        if ($clone->data instanceof SplFileInfo) {
113 1
            $type = $clone->fileContentType($clone->data->getPathname());
114 2
        } elseif (is_string($clone->data)) {
115 2
            $type = $clone->bufferContentType($clone->data);
116
        }
117 3
        $clone->setContentType($type);
118 3
        return $clone;
119
    }
120
121 8
    protected function setContentType(?string $contentType): void
122
    {
123 8
        $this->contentType = $contentType;
124 8
        $this->setHeader(Header::CONTENT_TYPE, $contentType);
125 8
    }
126 5
    protected function setInline(): void
127
    {
128 5
        $this->contentDisposition = self::DISPOSITION_INLINE;
129 5
        $this->setDispositionHeader();
130 5
    }
131 18
    final protected function setAttachment(?string $fileName): void
132
    {
133 18
        $this->contentDisposition = self::DISPOSITION_ATTACHMENT;
134 18
        $this->fileName = $fileName;
135 18
        $this->setDispositionHeader();
136 18
    }
137 21
    final protected function setDispositionHeader(): void
138
    {
139 21
        $headerBody = ($this->contentDisposition === self::DISPOSITION_ATTACHMENT && $this->fileName !== null)
140 14
            ? sprintf(
141 14
                '%s; filename="%s"; filename*=UTF-8\'\'%s',
142 14
                $this->contentDisposition,
143 14
                preg_replace('/[\x00-\x1F\x7F\"]/', ' ', $this->fileName),
144 14
                rawurlencode($this->fileName)
145
            )
146 21
            : $this->contentDisposition;
147 21
        $this->setHeader(Header::CONTENT_DISPOSITION, $headerBody);
148 21
    }
149 1
    private function fileContentType(string $filePath): ?string
150
    {
151 1
        if (!is_file($filePath) || !is_readable($filePath)) {
152
            return null;
153
        }
154 1
        return function_exists('mime_content_type') ? mime_content_type($filePath) : null;
155
    }
156 2
    private function bufferContentType(string $buffer): ?string
157
    {
158 2
        if (function_exists('finfo_open')) {
159 2
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
160 2
            $result = finfo_buffer($finfo, $buffer);
161 2
            if (is_string($result)) {
0 ignored issues
show
introduced by
The condition is_string($result) is always true.
Loading history...
162 2
                return $result;
163
            }
164
        }
165
        return null;
166
    }
167
}
168