Passed
Push — master ( e9f09a...b5f4ee )
by Malte
04:35
created

Attachment::fetch()   D

Complexity

Conditions 14
Paths 300

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
cc 14
eloc 24
c 3
b 0
f 2
nc 300
nop 0
dl 0
loc 39
rs 4.1833

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
* File:     Attachment.php
4
* Category: -
5
* Author:   M. Goldenbaum
6
* Created:  16.03.18 19:37
7
* Updated:  -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\IMAP;
14
15
use Illuminate\Support\Facades\File;
16
use Illuminate\Support\Str;
17
use Webklex\IMAP\Exceptions\MaskNotFoundException;
18
use Webklex\IMAP\Exceptions\MethodNotFoundException;
19
use Webklex\IMAP\Support\Masks\AttachmentMask;
20
21
/**
22
 * Class Attachment
23
 *
24
 * @package Webklex\IMAP
25
 * 
26
 * @property integer part_number
27
 * @property integer size
28
 * @property string content
29
 * @property string type
30
 * @property string content_type
31
 * @property string id
32
 * @property string name
33
 * @property string disposition
34
 * @property string img_src
35
 *
36
 * @method integer getPartNumber()
37
 * @method integer setPartNumber(integer $part_number)
38
 * @method string  getContent()
39
 * @method string  setContent(string $content)
40
 * @method string  getType()
41
 * @method string  setType(string $type)
42
 * @method string  getContentType()
43
 * @method string  setContentType(string $content_type)
44
 * @method string  getId()
45
 * @method string  setId(string $id)
46
 * @method string  getSize()
47
 * @method string  setSize(integer $size)
48
 * @method string  getName()
49
 * @method string  getDisposition()
50
 * @method string  setDisposition(string $disposition)
51
 * @method string  setImgSrc(string $img_src)
52
 */
53
class Attachment {
54
55
    /** @var Message $oMessage */
56
    protected $oMessage;
57
58
    /** @var array $config */
59
    protected $config = [];
60
61
    /** @var object $structure */
62
    protected $structure;
63
    
64
    /** @var array $attributes */
65
    protected $attributes = [
66
        'part_number' => 1,
67
        'content' => null,
68
        'type' => null,
69
        'content_type' => null,
70
        'id' => null,
71
        'name' => null,
72
        'disposition' => null,
73
        'img_src' => null,
74
        'size' => null,
75
    ];
76
77
    /**
78
     * Default mask
79
     * @var string $mask
80
     */
81
    protected $mask = AttachmentMask::class;
82
83
    /**
84
     * Attachment constructor.
85
     *
86
     * @param Message   $oMessage
87
     * @param object    $structure
88
     * @param integer   $part_number
89
     *
90
     * @throws Exceptions\ConnectionFailedException
91
     */
92
    public function __construct(Message $oMessage, $structure, $part_number = 1) {
93
        $this->config = config('imap.options');
94
95
        $this->oMessage = $oMessage;
96
        $this->structure = $structure;
97
        $this->part_number = ($part_number) ? $part_number : $this->part_number;
98
99
        $default_mask = $this->oMessage->getClient()->getDefaultAttachmentMask();
100
        if($default_mask != null) {
101
            $this->mask = $default_mask;
102
        }
103
104
        $this->findType();
105
        $this->fetch();
106
    }
107
108
    /**
109
     * Call dynamic attribute setter and getter methods
110
     * @param string $method
111
     * @param array $arguments
112
     *
113
     * @return mixed
114
     * @throws MethodNotFoundException
115
     */
116
    public function __call($method, $arguments) {
117
        if(strtolower(substr($method, 0, 3)) === 'get') {
118
            $name = Str::snake(substr($method, 3));
119
120
            if(isset($this->attributes[$name])) {
121
                return $this->attributes[$name];
122
            }
123
124
            return null;
125
        }elseif (strtolower(substr($method, 0, 3)) === 'set') {
126
            $name = Str::snake(substr($method, 3));
127
128
            $this->attributes[$name] = array_pop($arguments);
129
130
            return $this->attributes[$name];
131
        }
132
133
        throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
134
    }
135
136
    /**
137
     * @param $name
138
     * @param $value
139
     *
140
     * @return mixed
141
     */
142
    public function __set($name, $value) {
143
        $this->attributes[$name] = $value;
144
145
        return $this->attributes[$name];
146
    }
147
148
    /**
149
     * @param $name
150
     *
151
     * @return mixed|null
152
     */
153
    public function __get($name) {
154
        if(isset($this->attributes[$name])) {
155
            return $this->attributes[$name];
156
        }
157
158
        return null;
159
    }
160
161
    /**
162
     * Determine the structure type
163
     */
164
    protected function findType() {
165
        switch ($this->structure->type) {
166
            case IMAP::ATTACHMENT_TYPE_MESSAGE:
167
                $this->type = 'message';
168
                break;
169
            case IMAP::ATTACHMENT_TYPE_APPLICATION:
170
                $this->type = 'application';
171
                break;
172
            case IMAP::ATTACHMENT_TYPE_AUDIO:
173
                $this->type = 'audio';
174
                break;
175
            case IMAP::ATTACHMENT_TYPE_IMAGE:
176
                $this->type = 'image';
177
                break;
178
            case IMAP::ATTACHMENT_TYPE_VIDEO:
179
                $this->type = 'video';
180
                break;
181
            case IMAP::ATTACHMENT_TYPE_MODEL:
182
                $this->type = 'model';
183
                break;
184
            case IMAP::ATTACHMENT_TYPE_TEXT:
185
                $this->type = 'text';
186
                break;
187
            case IMAP::ATTACHMENT_TYPE_MULTIPART:
188
                $this->type = 'multipart';
189
                break;
190
            default:
191
                $this->type = 'other';
192
                break;
193
        }
194
    }
195
196
    /**
197
     * Fetch the given attachment
198
     *
199
     * @throws Exceptions\ConnectionFailedException
200
     */
201
    protected function fetch() {
202
203
        $content = \imap_fetchbody($this->oMessage->getClient()->getConnection(), $this->oMessage->getUid(), $this->part_number, $this->oMessage->getFetchOptions() | FT_UID);
0 ignored issues
show
Bug introduced by
It seems like $this->oMessage->getClient()->getConnection() can also be of type true; however, parameter $imap_stream of imap_fetchbody() does only seem to accept resource, 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

203
        $content = \imap_fetchbody(/** @scrutinizer ignore-type */ $this->oMessage->getClient()->getConnection(), $this->oMessage->getUid(), $this->part_number, $this->oMessage->getFetchOptions() | FT_UID);
Loading history...
204
205
        $this->content_type = $this->type.'/'.strtolower($this->structure->subtype);
206
        $this->content = $this->oMessage->decodeString($content, $this->structure->encoding);
207
208
        if (property_exists($this->structure, 'id')) {
209
            $this->id = str_replace(['<', '>'], '', $this->structure->id);
210
        }
211
212
        if (property_exists($this->structure, 'bytes')) {
213
            $this->size = $this->structure->bytes;
214
        }
215
216
        if (property_exists($this->structure, 'dparameters')) {
217
            foreach ($this->structure->dparameters as $parameter) {
218
                if (strtolower($parameter->attribute) == "filename") {
219
                    $this->setName($parameter->value);
220
                    $this->disposition = property_exists($this->structure, 'disposition') ? $this->structure->disposition : null;
221
                    break;
222
                }
223
            }
224
        }
225
226
        if (IMAP::ATTACHMENT_TYPE_MESSAGE == $this->structure->type) {
227
            if ($this->structure->ifdescription) {
228
                $this->setName($this->structure->description);
229
            } else {
230
                $this->setName($this->structure->subtype);
231
            }
232
        }
233
234
        if (!$this->name && property_exists($this->structure, 'parameters')) {
235
            foreach ($this->structure->parameters as $parameter) {
236
                if (strtolower($parameter->attribute) == "name") {
237
                    $this->setName($parameter->value);
238
                    $this->disposition = property_exists($this->structure, 'disposition') ? $this->structure->disposition : null;
239
                    break;
240
                }
241
            }
242
        }
243
    }
244
245
    /**
246
     * Save the attachment content to your filesystem
247
     *
248
     * @param string|null $path
249
     * @param string|null $filename
250
     *
251
     * @return boolean
252
     */
253
    public function save($path = null, $filename = null) {
254
        $path = $path ?: storage_path();
255
        $filename = $filename ?: $this->getName();
256
257
        $path = substr($path, -1) == DIRECTORY_SEPARATOR ? $path : $path.DIRECTORY_SEPARATOR;
258
259
        return File::put($path.$filename, $this->getContent()) !== false;
260
    }
261
262
    /**
263
     * @param $name
264
     */
265
    public function setName($name) {
266
        if($this->config['decoder']['message']['subject'] === 'utf-8') {
267
            $this->name = \imap_utf8($name);
268
        }else{
269
            $this->name = mb_decode_mimeheader($name);
270
        }
271
    }
272
273
    /**
274
     * @return null|string
275
     *
276
     * @deprecated 1.4.0:2.0.0 No longer needed. Use AttachmentMask::getImageSrc() instead
277
     */
278
    public function getImgSrc() {
279
        if ($this->type == 'image' && $this->img_src == null) {
280
            $this->img_src = 'data:'.$this->content_type.';base64,'.base64_encode($this->content);
281
        }
282
        return $this->img_src;
283
    }
284
285
    /**
286
     * @return string|null
287
     */
288
    public function getMimeType(){
289
        return (new \finfo())->buffer($this->getContent(), FILEINFO_MIME_TYPE);
290
    }
291
292
    /**
293
     * @return string|null
294
     */
295
    public function getExtension(){
296
        $deprecated_guesser = "\Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser";
297
        if (class_exists($deprecated_guesser) !== false){
298
            return $deprecated_guesser::getInstance()->guess($this->getMimeType());
299
        }
300
        $guesser = "\Symfony\Component\Mime\MimeTypes";
301
        $extensions = $guesser::getDefault()->getExtensions($this->getMimeType());
302
        return isset($extensions[0]) ? $extensions[0] : null;
303
    }
304
305
    /**
306
     * @return array
307
     */
308
    public function getAttributes(){
309
        return $this->attributes;
310
    }
311
312
    /**
313
     * @return Message
314
     */
315
    public function getMessage(){
316
        return $this->oMessage;
317
    }
318
319
    /**
320
     * @param $mask
321
     * @return $this
322
     */
323
    public function setMask($mask){
324
        if(class_exists($mask)){
325
            $this->mask = $mask;
326
        }
327
328
        return $this;
329
    }
330
331
    /**
332
     * @return string
333
     */
334
    public function getMask(){
335
        return $this->mask;
336
    }
337
338
    /**
339
     * Get a masked instance by providing a mask name
340
     * @param string|null $mask
341
     *
342
     * @return mixed
343
     * @throws MaskNotFoundException
344
     */
345
    public function mask($mask = null){
346
        $mask = $mask !== null ? $mask : $this->mask;
347
        if(class_exists($mask)){
348
            return new $mask($this);
349
        }
350
351
        throw new MaskNotFoundException("Unknown mask provided: ".$mask);
352
    }
353
}
354