Passed
Push — master ( b0bac1...41e857 )
by Malte
03:36
created

Folder::getUnseenMessages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 8
dl 0
loc 2
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/*
3
* File:     Folder.php
4
* Category: -
5
* Author:   M. Goldenbaum
6
* Created:  19.01.17 22:21
7
* Updated:  -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\IMAP;
14
15
use Carbon\Carbon;
16
use Webklex\IMAP\Exceptions\GetMessagesFailedException;
17
use Webklex\IMAP\Exceptions\MessageSearchValidationException;
18
use Webklex\IMAP\Query\WhereQuery;
19
use Webklex\IMAP\Support\FolderCollection;
20
use Webklex\IMAP\Support\MessageCollection;
21
22
/**
23
 * Class Folder
24
 *
25
 * @package Webklex\IMAP
26
 */
27
class Folder {
28
29
    /**
30
     * Client instance
31
     *
32
     * @var \Webklex\IMAP\Client
33
     */
34
    protected $client;
35
36
    /**
37
     * Folder full path
38
     *
39
     * @var string
40
     */
41
    public $path;
42
43
    /**
44
     * Folder name
45
     *
46
     * @var string
47
     */
48
    public $name;
49
50
    /**
51
     * Folder fullname
52
     *
53
     * @var string
54
     */
55
    public $full_name;
56
57
    /**
58
     * Children folders
59
     *
60
     * @var FolderCollection|array
61
     */
62
    public $children = [];
63
64
    /**
65
     * Delimiter for folder
66
     *
67
     * @var string
68
     */
69
    public $delimiter;
70
71
    /**
72
     * Indicates if folder can't containg any "children".
73
     * CreateFolder won't work on this folder.
74
     *
75
     * @var boolean
76
     */
77
    public $no_inferiors;
78
79
    /**
80
     * Indicates if folder is only container, not a mailbox - you can't open it.
81
     *
82
     * @var boolean
83
     */
84
    public $no_select;
85
86
    /**
87
     * Indicates if folder is marked. This means that it may contain new messages since the last time it was checked.
88
     * Not provided by all IMAP servers.
89
     *
90
     * @var boolean
91
     */
92
    public $marked;
93
94
    /**
95
     * Indicates if folder containg any "children".
96
     * Not provided by all IMAP servers.
97
     *
98
     * @var boolean
99
     */
100
    public $has_children;
101
102
    /**
103
     * Indicates if folder refers to other.
104
     * Not provided by all IMAP servers.
105
     *
106
     * @var boolean
107
     */
108
    public $referal;
109
110
    /**
111
     * Folder constructor.
112
     *
113
     * @param \Webklex\IMAP\Client $client
114
     *
115
     * @param object $structure
116
     */
117
    public function __construct(Client $client, $structure) {
118
        $this->client = $client;
119
120
        $this->setDelimiter($structure->delimiter);
121
        $this->path      = $structure->name;
122
        $this->full_name  = $this->decodeName($structure->name);
123
        $this->name      = $this->getSimpleName($this->delimiter, $this->full_name);
124
125
        $this->parseAttributes($structure->attributes);
126
    }
127
128
    /**
129
     * Get a new search query instance
130
     * @param string $charset
131
     *
132
     * @return WhereQuery
133
     * @throws Exceptions\ConnectionFailedException
134
     */
135
    public function query($charset = 'UTF-8'){
136
        $this->getClient()->checkConnection();
137
        $this->getClient()->openFolder($this->path);
138
139
        return new WhereQuery($this->getClient(), $charset);
140
    }
141
142
    /**
143
     * @inheritdoc self::query($charset = 'UTF-8')
144
     * @throws Exceptions\ConnectionFailedException
145
     */
146
    public function search($charset = 'UTF-8'){
147
        return $this->query($charset);
148
    }
149
150
    /**
151
     * @inheritdoc self::query($charset = 'UTF-8')
152
     * @throws Exceptions\ConnectionFailedException
153
     */
154
    public function messages($charset = 'UTF-8'){
155
        return $this->query($charset);
156
    }
157
158
    /**
159
     * Determine if folder has children.
160
     *
161
     * @return bool
162
     */
163
    public function hasChildren() {
164
        return $this->has_children;
165
    }
166
167
    /**
168
     * Set children.
169
     *
170
     * @param FolderCollection|array $children
171
     *
172
     * @return self
173
     */
174
    public function setChildren($children = []) {
175
        $this->children = $children;
176
177
        return $this;
178
    }
179
180
    /**
181
     * Get a specific message by UID
182
     *
183
     * @param integer      $uid     Please note that the uid is not unique and can change
184
     * @param integer|null $msglist
185
     * @param integer|null $fetch_options
186
     * @param boolean      $fetch_body
187
     * @param boolean      $fetch_attachment
188
     * @param boolean      $fetch_flags
189
     *
190
     * @return Message|null
191
     * @throws Exceptions\ConnectionFailedException
192
     * @throws Exceptions\InvalidMessageDateException
193
     */
194
    public function getMessage($uid, $msglist = null, $fetch_options = null, $fetch_body = null, $fetch_attachment = null, $fetch_flags = null) {
195
        $this->client->openFolder($this->path);
196
        if (\imap_msgno($this->getClient()->getConnection(), $uid) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $this->getClient()->getConnection() can also be of type true; however, parameter $imap_stream of imap_msgno() 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

196
        if (\imap_msgno(/** @scrutinizer ignore-type */ $this->getClient()->getConnection(), $uid) > 0) {
Loading history...
197
            return new Message($uid, $msglist, $this->getClient(), $fetch_options, $fetch_body, $fetch_attachment, $fetch_flags);
198
        }
199
200
        return null;
201
    }
202
203
    /**
204
     * Get all messages
205
     *
206
     * @param string    $criteria
207
     * @param int|null  $fetch_options
208
     * @param boolean   $fetch_body
209
     * @param boolean   $fetch_attachment
210
     * @param boolean   $fetch_flags
211
     * @param int|null  $limit
212
     * @param int       $page
213
     * @param string    $charset
214
     *
215
     * @return MessageCollection
216
     * @throws Exceptions\ConnectionFailedException
217
     * @throws Exceptions\InvalidWhereQueryCriteriaException
218
     * @throws GetMessagesFailedException
219
     */
220
    public function getMessages($criteria = 'ALL', $fetch_options = null, $fetch_body = null, $fetch_attachment = null, $fetch_flags = null, $limit = null, $page = 1, $charset = "UTF-8") {
221
222
        return $this->query($charset)->where($criteria)->setFetchOptions($fetch_options)->setFetchBody($fetch_body)
0 ignored issues
show
Bug introduced by
It seems like $fetch_options can also be of type integer; however, parameter $fetch_options of Webklex\IMAP\Query\Query::setFetchOptions() does only seem to accept boolean, 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

222
        return $this->query($charset)->where($criteria)->setFetchOptions(/** @scrutinizer ignore-type */ $fetch_options)->setFetchBody($fetch_body)
Loading history...
223
            ->setFetchAttachment($fetch_attachment)->setFetchFlags($fetch_flags)
0 ignored issues
show
Bug introduced by
It seems like $fetch_flags can also be of type boolean; however, parameter $fetch_flags of Webklex\IMAP\Query\Query::setFetchFlags() does only seem to accept integer, 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

223
            ->setFetchAttachment($fetch_attachment)->setFetchFlags(/** @scrutinizer ignore-type */ $fetch_flags)
Loading history...
224
            ->limit($limit, $page)->get();
225
    }
226
227
    /**
228
     * Get all unseen messages
229
     *
230
     * @param string    $criteria
231
     * @param int|null  $fetch_options
232
     * @param boolean   $fetch_body
233
     * @param boolean   $fetch_attachment
234
     * @param boolean   $fetch_flags
235
     * @param int|null  $limit
236
     * @param int       $page
237
     * @param string    $charset
238
     *
239
     * @return MessageCollection
240
     * @throws Exceptions\ConnectionFailedException
241
     * @throws Exceptions\InvalidWhereQueryCriteriaException
242
     * @throws GetMessagesFailedException
243
     * @throws MessageSearchValidationException
244
     *
245
     * @deprecated 1.0.5:2.0.0 No longer needed. Use Folder::getMessages('UNSEEN') instead
246
     * @see Folder::getMessages()
247
     */
248
    public function getUnseenMessages($criteria = 'UNSEEN', $fetch_options = null, $fetch_body = true, $fetch_attachment = true, $fetch_flags = true, $limit = null, $page = 1, $charset = "UTF-8") {
249
        return $this->getMessages($criteria, $fetch_options, $fetch_body, $fetch_attachment, $fetch_flags, $limit, $page, $charset);
250
    }
251
252
    /**
253
     * Search messages by a given search criteria
254
     *
255
     * @param array   $where  Is a two dimensional array where each array represents a criteria set:
256
     *                        ---------------------------------------------------------------------------------------
257
     *                        The following sample would search for all messages received from [email protected] or
258
     *                        contain the text "Hello world!":
259
     *                        [['FROM' => '[email protected]'],[' TEXT' => 'Hello world!']]
260
     *                        ---------------------------------------------------------------------------------------
261
     *                        The following sample would search for all messages received since march 15 2018:
262
     *                        [['SINCE' => Carbon::parse('15.03.2018')]]
263
     *                        ---------------------------------------------------------------------------------------
264
     *                        The following sample would search for all flagged messages:
265
     *                        [['FLAGGED']]
266
     *                        ---------------------------------------------------------------------------------------
267
     * @param int|null  $fetch_options
268
     * @param boolean   $fetch_body
269
     * @param boolean   $fetch_attachment
270
     * @param boolean   $fetch_flags
271
     * @param int|null  $limit
272
     * @param int       $page
273
     * @param string    $charset
274
     *
275
     * @return MessageCollection
276
     *
277
     * @throws Exceptions\ConnectionFailedException
278
     * @throws Exceptions\InvalidWhereQueryCriteriaException
279
     * @throws GetMessagesFailedException
280
     *
281
     * @doc http://php.net/manual/en/function.imap-search.php
282
     *      \imap_search() only supports IMAP2 search criterias, because the function mail_criteria() (from c-client lib)
283
     *      is used in ext/imap/php_imap.c for parsing the search string.
284
     *      IMAP2 search criteria is defined in RFC 1176, section "tag SEARCH search_criteria".
285
     *
286
     *      https://tools.ietf.org/html/rfc1176 - INTERACTIVE MAIL ACCESS PROTOCOL - VERSION 2
287
     *      https://tools.ietf.org/html/rfc1064 - INTERACTIVE MAIL ACCESS PROTOCOL - VERSION 2
288
     *      https://tools.ietf.org/html/rfc822  - STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES
289
     *      Date and time example from RFC822:
290
     *      date-time   =  [ day "," ] date time        ; dd mm yy
291
     *                                                  ;  hh:mm:ss zzz
292
     *
293
     *      day         =  "Mon"  / "Tue" /  "Wed"  / "Thu" /  "Fri"  / "Sat" /  "Sun"
294
     *
295
     *      date        =  1*2DIGIT month 2DIGIT        ; day month year
296
     *                                                  ;  e.g. 20 Jun 82
297
     *
298
     *      month       =  "Jan"  /  "Feb" /  "Mar"  /  "Apr" /  "May"  /  "Jun" /  "Jul"  /  "Aug" /  "Sep"  /  "Oct" /  "Nov"  /  "Dec"
299
     *
300
     *      time        =  hour zone                    ; ANSI and Military
301
     *
302
     *      hour        =  2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
303
     *
304
     *      zone        =  "UT"  / "GMT"         ; Universal Time
305
     *                                           ; North American : UT
306
     *                  =  "EST" / "EDT"         ;  Eastern:  - 5/ - 4
307
     *                  =  "CST" / "CDT"         ;  Central:  - 6/ - 5
308
     *                  =  "MST" / "MDT"         ;  Mountain: - 7/ - 6
309
     *                  =  "PST" / "PDT"         ;  Pacific:  - 8/ - 7
310
     *                  =  1ALPHA                ; Military: Z = UT;
311
     *                                           ;  A:-1; (J not used)
312
     *                                           ;  M:-12; N:+1; Y:+12
313
     *                  / ( ("+" / "-") 4DIGIT ) ; Local differential
314
     *                                           ;  hours+min. (HHMM)
315
     *
316
     * @deprecated 1.2.1:2.0.0 No longer needed. Use Folder::query() instead
317
     * @see Folder::query()
318
     */
319
    public function searchMessages(array $where, $fetch_options = null, $fetch_body = true,  $fetch_attachment = true, $fetch_flags = true, $limit = null, $page = 1, $charset = "UTF-8") {
320
        $this->getClient()->checkConnection();
321
322
        return $this->query($charset)->where($where)->setFetchOptions($fetch_options)->setFetchBody($fetch_body)
0 ignored issues
show
Bug introduced by
It seems like $fetch_options can also be of type integer; however, parameter $fetch_options of Webklex\IMAP\Query\Query::setFetchOptions() does only seem to accept boolean, 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

322
        return $this->query($charset)->where($where)->setFetchOptions(/** @scrutinizer ignore-type */ $fetch_options)->setFetchBody($fetch_body)
Loading history...
323
            ->setFetchAttachment($fetch_attachment)->setFetchFlags($fetch_flags)
0 ignored issues
show
Bug introduced by
$fetch_flags of type boolean is incompatible with the type integer expected by parameter $fetch_flags of Webklex\IMAP\Query\Query::setFetchFlags(). ( Ignorable by Annotation )

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

323
            ->setFetchAttachment($fetch_attachment)->setFetchFlags(/** @scrutinizer ignore-type */ $fetch_flags)
Loading history...
324
            ->limit($limit, $page)->get();
325
326
    }
327
328
    /**
329
     * Decode name.
330
     * It converts UTF7-IMAP encoding to UTF-8.
331
     *
332
     * @param $name
333
     *
334
     * @return mixed|string
335
     */
336
    protected function decodeName($name) {
337
        preg_match('#\{(.*)\}(.*)#', $name, $preg);
338
        return mb_convert_encoding($preg[2], "UTF-8", "UTF7-IMAP");
339
    }
340
341
    /**
342
     * Get the encoded name.
343
     * It converts the UTF-8 encoded name into an UTF7-IMAP encoded string.
344
     *
345
     * @return mixed|string
346
     */
347
    public function getEncodedName() {
348
        return mb_convert_encoding($this->full_name, "UTF7-IMAP", "UTF-8");
349
    }
350
351
    /**
352
     * Get simple name (without parent folders).
353
     *
354
     * @param $delimiter
355
     * @param $full_name
356
     *
357
     * @return mixed
358
     */
359
    protected function getSimpleName($delimiter, $full_name) {
360
        $arr = explode($delimiter, $full_name);
361
362
        return end($arr);
363
    }
364
365
    /**
366
     * Parse attributes and set it to object properties.
367
     *
368
     * @param $attributes
369
     */
370
    protected function parseAttributes($attributes) {
371
        $this->no_inferiors = ($attributes & LATT_NOINFERIORS) ? true : false;
372
        $this->no_select    = ($attributes & LATT_NOSELECT) ? true : false;
373
        $this->marked       = ($attributes & LATT_MARKED) ? true : false;
374
        $this->referal      = ($attributes & LATT_REFERRAL) ? true : false;
375
        $this->has_children = ($attributes & LATT_HASCHILDREN) ? true : false;
376
    }
377
378
    /**
379
     * Delete the current Mailbox
380
     * @param boolean $expunge
381
     *
382
     * @return bool
383
     *
384
     * @throws Exceptions\ConnectionFailedException
385
     */
386
    public function delete($expunge = true) {
387
        $status = \imap_deletemailbox($this->client->getConnection(), $this->path);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_deletemailbox() 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

387
        $status = \imap_deletemailbox(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path);
Loading history...
388
        if($expunge) $this->client->expunge();
389
390
        return $status;
391
    }
392
393
    /**
394
     * Move or Rename the current Mailbox
395
     *
396
     * @param string $target_mailbox
397
     * @param boolean $expunge
398
     *
399
     * @return bool
400
     *
401
     * @throws Exceptions\ConnectionFailedException
402
     */
403
    public function move($target_mailbox, $expunge = true) {
404
        $status = \imap_renamemailbox($this->client->getConnection(), $this->path, $target_mailbox);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_renamemailbox() 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

404
        $status = \imap_renamemailbox(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $target_mailbox);
Loading history...
405
        if($expunge) $this->client->expunge();
406
407
        return $status;
408
    }
409
410
    /**
411
     * Returns status information on a mailbox
412
     *
413
     * @param integer   $options
414
     *                  SA_MESSAGES     - set $status->messages to the number of messages in the mailbox
415
     *                  SA_RECENT       - set $status->recent to the number of recent messages in the mailbox
416
     *                  SA_UNSEEN       - set $status->unseen to the number of unseen (new) messages in the mailbox
417
     *                  SA_UIDNEXT      - set $status->uidnext to the next uid to be used in the mailbox
418
     *                  SA_UIDVALIDITY  - set $status->uidvalidity to a constant that changes when uids for the mailbox may no longer be valid
419
     *                  SA_ALL          - set all of the above
420
     *
421
     * @return object
422
     * @throws Exceptions\ConnectionFailedException
423
     */
424
    public function getStatus($options) {
425
        return \imap_status($this->client->getConnection(), $this->path, $options);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_status() 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

425
        return \imap_status(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $options);
Loading history...
426
    }
427
428
    /**
429
     * Append a string message to the current mailbox
430
     *
431
     * @param string $message
432
     * @param string $options
433
     * @param string $internal_date
434
     *
435
     * @return bool
436
     * @throws Exceptions\ConnectionFailedException
437
     */
438
    public function appendMessage($message, $options = null, $internal_date = null) {
439
        /**
440
         * Check if $internal_date is parsed. If it is null it should not be set. Otherwise the message can't be stored.
441
         * If this parameter is set, it will set the INTERNALDATE on the appended message. The parameter should be a
442
         * date string that conforms to the rfc2060 specifications for a date_time value or be a Carbon object.
443
         */
444
445
        if ($internal_date != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $internal_date of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
446
            if ($internal_date instanceof \Carbon\Carbon){
0 ignored issues
show
introduced by
$internal_date is never a sub-type of Carbon\Carbon.
Loading history...
447
                $internal_date = $internal_date->format('d-M-Y H:i:s O');
448
            }
449
            return \imap_append($this->client->getConnection(), $this->path, $message, $options, $internal_date);
0 ignored issues
show
Bug introduced by
It seems like $this->client->getConnection() can also be of type true; however, parameter $imap_stream of imap_append() 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

449
            return \imap_append(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $message, $options, $internal_date);
Loading history...
450
        }
451
452
        return \imap_append($this->client->getConnection(), $this->path, $message, $options);
453
    }
454
455
    /**
456
     * Get the current Client instance
457
     *
458
     * @return Client
459
     */
460
    public function getClient() {
461
        return $this->client;
462
    }
463
464
    /**
465
     * @param $delimiter
466
     */
467
    public function setDelimiter($delimiter){
468
        if(in_array($delimiter, [null, '', ' ', false]) === true) {
469
            $delimiter = config('imap.options.delimiter', '/');
470
        }
471
472
        $this->delimiter = $delimiter;
473
    }
474
}
475