Passed
Push — master ( 2fbd23...3c6f7d )
by Aleksei
01:50
created

FileBucket::withInline()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
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
    public function __construct($data, string $contentType = null, string $filename = null)
28
    {
29
        switch (true) {
30
            case $data instanceof SplFileInfo:
31
                $filename = $filename ?? $data->getFilename();
32
                $contentType = $contentType ?? $this->contentType($filename);
33
                parent::__construct($data);
34
                break;
35
            case is_string($data):
36
            case is_resource($data):
37
                parent::__construct($data);
38
                break;
39
            default:
40
                throw new \Exception('The $data parameter must be a resource, a string or an instance of SplFileInfo');
41
        }
42
43
        if ($contentType !== null) {
44
            $this->setContentType($contentType);
45
        }
46
        if ($filename !== null) {
47
            $this->setAttachment($filename);
48
        }
49
    }
50
51
    public static function createFromPath(string $filePath): self
52
    {
53
        return new static(new SplFileInfo($filePath));
54
    }
55
56
    public function getContentType(): ?string
57
    {
58
        return $this->contentType;
59
    }
60
    public function getFileName(): ?string
61
    {
62
        return $this->fileName;
63
    }
64
    public function hasDisposition(): bool
65
    {
66
        return $this->contentDisposition !== null;
67
    }
68
    public function isAttachment(): bool
69
    {
70
        return $this->contentDisposition === self::DISPOSITION_ATTACHMENT;
71
    }
72
    public function isInline(): bool
73
    {
74
        return $this->contentDisposition === self::DISPOSITION_INLINE;
75
    }
76
77
    public function withAttachment(?string $filename): self
78
    {
79
        $clone = clone $this;
80
        $clone->setAttachment($filename);
81
        return $clone;
82
    }
83
    public function withContentType(?string $contentType): self
84
    {
85
        $clone = clone $this;
86
        $clone->setContentType($contentType);
87
        return $clone;
88
    }
89
    public function withInline(): self
90
    {
91
        $clone = clone $this;
92
        $clone->setInline();
93
        return $clone;
94
    }
95
96
    public function setContentType(?string $contentType): void
97
    {
98
        $this->contentType = $contentType;
99
        $this->setHeader(Header::CONTENT_TYPE, $contentType);
0 ignored issues
show
Bug introduced by
It seems like $contentType can also be of type null; however, parameter $value of roxblnfk\SmartStream\Data\DataBucket::setHeader() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

99
        $this->setHeader(Header::CONTENT_TYPE, /** @scrutinizer ignore-type */ $contentType);
Loading history...
100
    }
101
    public function setInline(): void
102
    {
103
        $this->contentDisposition = self::DISPOSITION_INLINE;
104
        $this->setDispositionHeader();
105
    }
106
    final protected function setAttachment(?string $filename): void
107
    {
108
        $this->contentDisposition = self::DISPOSITION_ATTACHMENT;
109
        $this->fileName = $filename;
110
        $this->setDispositionHeader();
111
    }
112
    final protected function setDispositionHeader(): void
113
    {
114
        if ($this->contentDisposition === null) {
115
            return;
116
        }
117
        $headerBody = ($this->contentDisposition === self::DISPOSITION_ATTACHMENT && $this->fileName !== null)
118
            ? sprintf(
119
                '%s; filename="%s"; filename*=UTF-8\'\'%s',
120
                $this->contentDisposition,
121
                preg_replace('/[\x00-\x1F\x7F\"]/', ' ', $this->fileName),
122
                rawurlencode($this->fileName)
123
            )
124
            : $this->contentDisposition;
125
        $this->setHeader(Header::CONTENT_DISPOSITION, $headerBody);
126
    }
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