Passed
Push — master ( a61a57...835875 )
by Malte
03:03
created

Folder   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 401
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 55
dl 0
loc 401
rs 10
c 0
b 0
f 0
wmc 24

18 Methods

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

189
        if (imap_msgno(/** @scrutinizer ignore-type */ $this->getClient()->getConnection(), $uid) > 0) {
Loading history...
190
            return new Message($uid, $msglist, $this->getClient(), $fetch_options, $fetch_body, $fetch_attachment, $fetch_flags);
191
        }
192
193
        return null;
194
    }
195
196
    /**
197
     * Get all messages
198
     *
199
     * @param string    $criteria
200
     * @param int|null  $fetch_options
201
     * @param boolean   $fetch_body
202
     * @param boolean   $fetch_attachment
203
     * @param boolean   $fetch_flags
204
     * @param int|null  $limit
205
     * @param int       $page
206
     * @param string    $charset
207
     *
208
     * @return MessageCollection
209
     * @throws Exceptions\ConnectionFailedException
210
     * @throws GetMessagesFailedException
211
     * @throws MessageSearchValidationException
212
     */
213
    public function getMessages($criteria = 'ALL', $fetch_options = null, $fetch_body = true, $fetch_attachment = true, $fetch_flags = true, $limit = null, $page = 1, $charset = "UTF-8") {
214
215
        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

215
        return $this->query($charset)->where($criteria)->setFetchOptions(/** @scrutinizer ignore-type */ $fetch_options)->setFetchBody($fetch_body)
Loading history...
216
            ->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

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

314
        return $this->query($charset)->where($where)->setFetchOptions(/** @scrutinizer ignore-type */ $fetch_options)->setFetchBody($fetch_body)
Loading history...
315
            ->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

315
            ->setFetchAttachment($fetch_attachment)->setFetchFlags(/** @scrutinizer ignore-type */ $fetch_flags)
Loading history...
316
            ->limit($limit, $page)->get();
317
318
    }
319
320
    /**
321
     * Decode name.
322
     * It converts UTF7-IMAP encoding to UTF-8.
323
     *
324
     * @param $name
325
     *
326
     * @return mixed|string
327
     */
328
    protected function decodeName($name) {
329
        preg_match('#\{(.*)\}(.*)#', $name, $preg);
330
        return mb_convert_encoding($preg[2], "UTF-8", "UTF7-IMAP");
331
    }
332
333
    /**
334
     * Get simple name (without parent folders).
335
     *
336
     * @param $delimiter
337
     * @param $fullName
338
     *
339
     * @return mixed
340
     */
341
    protected function getSimpleName($delimiter, $fullName) {
342
        $arr = explode($delimiter, $fullName);
343
344
        return end($arr);
345
    }
346
347
    /**
348
     * Parse attributes and set it to object properties.
349
     *
350
     * @param $attributes
351
     */
352
    protected function parseAttributes($attributes) {
353
        $this->no_inferiors = ($attributes & LATT_NOINFERIORS) ? true : false;
354
        $this->no_select    = ($attributes & LATT_NOSELECT) ? true : false;
355
        $this->marked       = ($attributes & LATT_MARKED) ? true : false;
356
        $this->referal      = ($attributes & LATT_REFERRAL) ? true : false;
357
        $this->has_children = ($attributes & LATT_HASCHILDREN) ? true : false;
358
    }
359
360
    /**
361
     * Delete the current Mailbox
362
     *
363
     * @return bool
364
     *
365
     * @throws Exceptions\ConnectionFailedException
366
     */
367
    public function delete() {
368
        $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

368
        $status = imap_deletemailbox(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path);
Loading history...
369
        $this->client->expunge();
370
371
        return $status;
372
    }
373
374
    /**
375
     * Move or Rename the current Mailbox
376
     *
377
     * @param string $target_mailbox
378
     *
379
     * @return bool
380
     *
381
     * @throws Exceptions\ConnectionFailedException
382
     */
383
    public function move($target_mailbox) {
384
        $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

384
        $status = imap_renamemailbox(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $target_mailbox);
Loading history...
385
        $this->client->expunge();
386
387
        return $status;
388
    }
389
390
    /**
391
     * Returns status information on a mailbox
392
     *
393
     * @param integer   $options
394
     *                  SA_MESSAGES     - set $status->messages to the number of messages in the mailbox
395
     *                  SA_RECENT       - set $status->recent to the number of recent messages in the mailbox
396
     *                  SA_UNSEEN       - set $status->unseen to the number of unseen (new) messages in the mailbox
397
     *                  SA_UIDNEXT      - set $status->uidnext to the next uid to be used in the mailbox
398
     *                  SA_UIDVALIDITY  - set $status->uidvalidity to a constant that changes when uids for the mailbox may no longer be valid
399
     *                  SA_ALL          - set all of the above
400
     *
401
     * @return object
402
     */
403
    public function getStatus($options) {
404
        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

404
        return imap_status(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $options);
Loading history...
405
    }
406
407
    /**
408
     * Append a string message to the current mailbox
409
     *
410
     * @param string $message
411
     * @param string $options
412
     * @param string $internal_date
413
     *
414
     * @return bool
415
     */
416
    public function appendMessage($message, $options = null, $internal_date = null) {
417
        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

417
        return imap_append(/** @scrutinizer ignore-type */ $this->client->getConnection(), $this->path, $message, $options, $internal_date);
Loading history...
418
    }
419
420
    /**
421
     * Get the current Client instance
422
     *
423
     * @return Client
424
     */
425
    public function getClient() {
426
        return $this->client;
427
    }
428
}
429