Completed
Push — master ( 25c87f...4df12c )
by Frederik
03:27
created

FileAttachment   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 93.75%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 9
dl 0
loc 134
ccs 45
cts 48
cp 0.9375
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 4
A fromUnknownFileType() 0 24 3
A getHeaders() 0 4 1
A hasHeader() 0 4 1
A getHeader() 0 4 1
A withHeader() 0 10 2
A withoutHeader() 0 10 2
A withBody() 0 4 1
A getBody() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Mime;
5
6
use Genkgo\Mail\Header\ContentDisposition;
7
use Genkgo\Mail\Header\ContentTransferEncoding;
8
use Genkgo\Mail\Header\ContentType;
9
use Genkgo\Mail\Header\HeaderValue;
10
use Genkgo\Mail\HeaderInterface;
11
use Genkgo\Mail\Stream\Base64EncodedStream;
12
use Genkgo\Mail\StreamInterface;
13
14
final class FileAttachment implements PartInterface
15
{
16
    /**
17
     * @var PartInterface
18
     */
19
    private $decoratedPart;
20
21
    /**
22
     * @param string $filename
23
     * @param ContentType $contentType
24
     * @param string $attachmentName
25
     */
26 15
    public function __construct(string $filename, ContentType $contentType, string $attachmentName = '')
27
    {
28 15
        if (!\file_exists($filename) || !\is_file($filename)) {
29 2
            throw new \InvalidArgumentException('Attachment does not exists');
30
        }
31
32 13
        if ($attachmentName === '') {
33 13
            $attachmentName = \basename($filename);
34
        }
35
36 13
        $resource = \fopen($filename, 'r');
37
38 13
        $this->decoratedPart = (new GenericPart())
39 13
            ->withBody(new Base64EncodedStream($resource))
40 13
            ->withHeader($contentType)
41 13
            ->withHeader(new ContentTransferEncoding('base64'))
42 13
            ->withHeader(ContentDisposition::newAttachment($attachmentName));
43 13
    }
44
45
    /**
46
     * @param string $filename
47
     * @param string $attachmentName
48
     * @return FileAttachment
49
     */
50 1
    public static function fromUnknownFileType(string $filename, string $attachmentName = ''): FileAttachment
51
    {
52 1
        $fileInfo = new \finfo(FILEINFO_MIME);
53 1
        $mime = $fileInfo->file($filename);
54
55 1
        $headerValue = HeaderValue::fromString($mime);
56
57
        try {
58 1
            $charset = $headerValue->getParameter('charset')->getValue();
59 1
            if ($charset === 'binary') {
60
                $contentType = new ContentType($headerValue->getRaw());
61
            } else {
62 1
                $contentType = new ContentType($headerValue->getRaw(), $charset);
63
            }
64
        } catch (\UnexpectedValueException $e) {
65
            $contentType = new ContentType($headerValue->getRaw());
66
        }
67
68 1
        return new self(
69 1
            $filename,
70 1
            $contentType,
71 1
            $attachmentName
72
        );
73
    }
74
75
    /**
76
     * @return iterable
77
     */
78 2
    public function getHeaders(): iterable
79
    {
80 2
        return $this->decoratedPart->getHeaders();
81
    }
82
83
    /**
84
     * @param string $name
85
     * @return bool
86
     */
87 2
    public function hasHeader(string $name): bool
88
    {
89 2
        return $this->decoratedPart->hasHeader($name);
90
    }
91
92
    /**
93
     * @param string $name
94
     * @return HeaderInterface
95
     */
96 3
    public function getHeader(string $name): HeaderInterface
97
    {
98 3
        return $this->decoratedPart->getHeader($name);
99
    }
100
101
    /**
102
     * @param HeaderInterface $header
103
     * @return PartInterface
104
     */
105 4
    public function withHeader(HeaderInterface $header): PartInterface
106
    {
107 4
        if (\strtolower((string)$header->getName()) === 'content-disposition') {
108 2
            throw new \InvalidArgumentException('Cannot modify content disposition for file attachment');
109
        }
110
111 2
        $clone = clone $this;
112 2
        $clone->decoratedPart = $this->decoratedPart->withHeader($header);
113 2
        return $clone;
114
    }
115
116
    /**
117
     * @param string $name
118
     * @return PartInterface
119
     */
120 4
    public function withoutHeader(string $name): PartInterface
121
    {
122 4
        if (\strtolower($name) === 'content-disposition') {
123 2
            throw new \InvalidArgumentException('Cannot modify content disposition for file attachment');
124
        }
125
126 2
        $clone = clone $this;
127 2
        $clone->decoratedPart = $this->decoratedPart->withoutHeader($name);
128 2
        return $clone;
129
    }
130
131
    /**
132
     * @param StreamInterface $body
133
     * @return PartInterface
134
     */
135 2
    public function withBody(StreamInterface $body): PartInterface
136
    {
137 2
        throw new \RuntimeException('Cannot modify body of FileAttachment');
138
    }
139
140
    /**
141
     * @return StreamInterface
142
     */
143 2
    public function getBody(): StreamInterface
144
    {
145 2
        return $this->decoratedPart->getBody();
146
    }
147
}
148