Passed
Pull Request — master (#201)
by
unknown
04:44
created

Query::getMessagesGreaterThanUid()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 10
c 1
b 0
f 1
dl 0
loc 17
rs 9.9332
cc 3
nc 3
nop 1
1
<?php
2
/*
3
* File:     Query.php
4
* Category: -
5
* Author:   M. Goldenbaum
6
* Created:  21.07.18 18:54
7
* Updated:  -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\PHPIMAP\Query;
14
15
use Carbon\Carbon;
16
use Exception;
17
use Illuminate\Pagination\LengthAwarePaginator;
18
use Illuminate\Support\Collection;
19
use ReflectionException;
20
use Webklex\PHPIMAP\Client;
21
use Webklex\PHPIMAP\ClientManager;
22
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
23
use Webklex\PHPIMAP\Exceptions\EventNotFoundException;
24
use Webklex\PHPIMAP\Exceptions\GetMessagesFailedException;
25
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
26
use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException;
27
use Webklex\PHPIMAP\Exceptions\MessageFlagException;
28
use Webklex\PHPIMAP\Exceptions\MessageHeaderFetchingException;
29
use Webklex\PHPIMAP\Exceptions\MessageNotFoundException;
30
use Webklex\PHPIMAP\Exceptions\MessageSearchValidationException;
31
use Webklex\PHPIMAP\Exceptions\RuntimeException;
32
use Webklex\PHPIMAP\IMAP;
33
use Webklex\PHPIMAP\Message;
34
use Webklex\PHPIMAP\Support\MessageCollection;
35
36
/**
37
 * Class Query
38
 *
39
 * @package Webklex\PHPIMAP\Query
40
 */
41
class Query {
42
43
    /** @var Collection $query */
44
    protected $query;
45
46
    /** @var string $raw_query */
47
    protected $raw_query;
48
49
    /** @var string[] $extensions */
50
    protected $extensions;
51
52
    /** @var Client $client */
53
    protected $client;
54
55
    /** @var int $limit */
56
    protected $limit = null;
57
58
    /** @var int $page */
59
    protected $page = 1;
60
61
    /** @var int $fetch_options */
62
    protected $fetch_options = null;
63
64
    /** @var int $fetch_body */
65
    protected $fetch_body = true;
66
67
    /** @var int $fetch_flags */
68
    protected $fetch_flags = true;
69
70
    /** @var int|string $sequence */
71
    protected $sequence = IMAP::NIL;
72
73
    /** @var string $fetch_order */
74
    protected $fetch_order;
75
76
    /** @var string $date_format */
77
    protected $date_format;
78
79
    /** @var bool $soft_fail */
80
    protected $soft_fail = false;
81
82
    /** @var array $errors */
83
    protected $errors = [];
84
85
    /**
86
     * Query constructor.
87
     * @param Client $client
88
     * @param string[] $extensions
89
     */
90
    public function __construct(Client $client, $extensions = []) {
91
        $this->setClient($client);
92
93
        $this->sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN);
94
        if (ClientManager::get('options.fetch') === IMAP::FT_PEEK) $this->leaveUnread();
95
96
        if (ClientManager::get('options.fetch_order') === 'desc') {
97
            $this->fetch_order = 'desc';
98
        } else {
99
            $this->fetch_order = 'asc';
100
        }
101
102
        $this->date_format = ClientManager::get('date_format', 'd M y');
103
        $this->soft_fail = ClientManager::get('options.soft_fail', false);
104
105
        $this->setExtensions($extensions);
106
        $this->query = new Collection();
107
        $this->boot();
108
    }
109
110
    /**
111
     * Instance boot method for additional functionality
112
     */
113
    protected function boot() {
114
    }
115
116
    /**
117
     * Parse a given value
118
     * @param mixed $value
119
     *
120
     * @return string
121
     */
122
    protected function parse_value($value) {
123
        switch (true) {
124
            case $value instanceof Carbon:
125
                $value = $value->format($this->date_format);
126
                break;
127
        }
128
129
        return (string)$value;
130
    }
131
132
    /**
133
     * Check if a given date is a valid carbon object and if not try to convert it
134
     * @param string|Carbon $date
135
     *
136
     * @return Carbon
137
     * @throws MessageSearchValidationException
138
     */
139
    protected function parse_date($date) {
140
        if ($date instanceof Carbon) return $date;
141
142
        try {
143
            $date = Carbon::parse($date);
144
        } catch (Exception $e) {
145
            throw new MessageSearchValidationException();
146
        }
147
148
        return $date;
149
    }
150
151
    /**
152
     * Get the raw IMAP search query
153
     *
154
     * @return string
155
     */
156
    public function generate_query() {
157
        $query = '';
158
        $this->query->each(function($statement) use (&$query) {
159
            if (count($statement) == 1) {
160
                $query .= $statement[0];
161
            } else {
162
                if ($statement[1] === null) {
163
                    $query .= $statement[0];
164
                } else {
165
                    if (is_numeric($statement[1])) {
166
                        $query .= $statement[0] . ' ' . $statement[1];
167
                    } else {
168
                        $query .= $statement[0] . ' "' . $statement[1] . '"';
169
                    }
170
                }
171
            }
172
            $query .= ' ';
173
174
        });
175
176
        $this->raw_query = trim($query);
177
178
        return $this->raw_query;
179
    }
180
181
    /**
182
     * Perform an imap search request
183
     *
184
     * @return Collection
185
     * @throws GetMessagesFailedException
186
     */
187
    protected function search() {
188
        $this->generate_query();
189
190
        try {
191
            $available_messages = $this->client->getConnection()->search([$this->getRawQuery()], $this->sequence);
192
            return $available_messages !== false ? new Collection($available_messages) : new Collection();
0 ignored issues
show
introduced by
The condition $available_messages !== false is always true.
Loading history...
193
        } catch (RuntimeException $e) {
194
            throw new GetMessagesFailedException("failed to fetch messages", 0, $e);
195
        } catch (ConnectionFailedException $e) {
196
            throw new GetMessagesFailedException("failed to fetch messages", 0, $e);
197
        }
198
    }
199
200
    /**
201
     * Count all available messages matching the current search criteria
202
     *
203
     * @return int
204
     * @throws GetMessagesFailedException
205
     */
206
    public function count() {
207
        return $this->search()->count();
208
    }
209
210
    /**
211
     * Fetch a given id collection
212
     * @param Collection $available_messages
213
     *
214
     * @return array
215
     * @throws ConnectionFailedException
216
     * @throws RuntimeException
217
     */
218
    protected function fetch($available_messages) {
219
        if ($this->fetch_order === 'desc') {
220
            $available_messages = $available_messages->reverse();
221
        }
222
223
        $uids = $available_messages->forPage($this->page, $this->limit)->toArray();
224
        $extensions = [];
225
        if (empty($this->getExtensions()) === false) {
226
            $extensions = $this->client->getConnection()->fetch($this->getExtensions(), $uids, null, $this->sequence);
0 ignored issues
show
Bug introduced by
The method fetch() does not exist on Webklex\PHPIMAP\Connecti...ocols\ProtocolInterface. It seems like you code against a sub-type of Webklex\PHPIMAP\Connecti...ocols\ProtocolInterface such as Webklex\PHPIMAP\Connection\Protocols\ImapProtocol. ( Ignorable by Annotation )

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

226
            $extensions = $this->client->getConnection()->/** @scrutinizer ignore-call */ fetch($this->getExtensions(), $uids, null, $this->sequence);
Loading history...
Bug introduced by
The method fetch() does not exist on Webklex\PHPIMAP\Connection\Protocols\Protocol. It seems like you code against a sub-type of Webklex\PHPIMAP\Connection\Protocols\Protocol such as Webklex\PHPIMAP\Connection\Protocols\ImapProtocol. ( Ignorable by Annotation )

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

226
            $extensions = $this->client->getConnection()->/** @scrutinizer ignore-call */ fetch($this->getExtensions(), $uids, null, $this->sequence);
Loading history...
227
        }
228
        $flags = $this->client->getConnection()->flags($uids, $this->sequence);
229
        $headers = $this->client->getConnection()->headers($uids, "RFC822", $this->sequence);
230
231
        $contents = [];
232
        if ($this->getFetchBody()) {
233
            $contents = $this->client->getConnection()->content($uids, "RFC822", $this->sequence);
234
        }
235
236
        return [
237
            "uids"       => $uids,
238
            "flags"      => $flags,
239
            "headers"    => $headers,
240
            "contents"   => $contents,
241
            "extensions" => $extensions,
242
        ];
243
    }
244
245
    /**
246
     * Make a new message from given raw components
247
     * @param integer $uid
248
     * @param integer $msglist
249
     * @param string $header
250
     * @param string $content
251
     * @param array $flags
252
     *
253
     * @return Message|null
254
     * @throws ConnectionFailedException
255
     * @throws EventNotFoundException
256
     * @throws GetMessagesFailedException
257
     * @throws ReflectionException
258
     */
259
    protected function make($uid, $msglist, $header, $content, $flags) {
260
        try {
261
            return Message::make($uid, $msglist, $this->getClient(), $header, $content, $flags, $this->getFetchOptions(), $this->sequence);
262
        } catch (MessageNotFoundException $e) {
263
            $this->setError($uid, $e);
264
        } catch (RuntimeException $e) {
265
            $this->setError($uid, $e);
266
        } catch (MessageFlagException $e) {
267
            $this->setError($uid, $e);
268
        } catch (InvalidMessageDateException $e) {
269
            $this->setError($uid, $e);
270
        } catch (MessageContentFetchingException $e) {
271
            $this->setError($uid, $e);
272
        }
273
274
        $this->handleException($uid);
275
276
        return null;
277
    }
278
279
    /**
280
     * Get the message key for a given message
281
     * @param string $message_key
282
     * @param integer $msglist
283
     * @param Message $message
284
     *
285
     * @return string
286
     */
287
    protected function getMessageKey($message_key, $msglist, $message) {
288
        switch ($message_key) {
289
            case 'number':
290
                $key = $message->getMessageNo();
291
                break;
292
            case 'list':
293
                $key = $msglist;
294
                break;
295
            case 'uid':
296
                $key = $message->getUid();
297
                break;
298
            default:
299
                $key = $message->getMessageId();
300
                break;
301
        }
302
        return (string)$key;
303
    }
304
305
    /**
306
     * Populate a given id collection and receive a fully fetched message collection
307
     * @param Collection $available_messages
308
     *
309
     * @return MessageCollection
310
     * @throws ConnectionFailedException
311
     * @throws EventNotFoundException
312
     * @throws GetMessagesFailedException
313
     * @throws ReflectionException
314
     * @throws RuntimeException
315
     */
316
    protected function populate($available_messages) {
317
        $messages = MessageCollection::make([]);
318
319
        $messages->total($available_messages->count());
320
321
        $message_key = ClientManager::get('options.message_key');
322
323
        $raw_messages = $this->fetch($available_messages);
324
325
        $msglist = 0;
326
        foreach ($raw_messages["headers"] as $uid => $header) {
327
            $content = isset($raw_messages["contents"][$uid]) ? $raw_messages["contents"][$uid] : "";
328
            $flag = isset($raw_messages["flags"][$uid]) ? $raw_messages["flags"][$uid] : [];
329
            $extensions = isset($raw_messages["extensions"][$uid]) ? $raw_messages["extensions"][$uid] : [];
330
331
            $message = $this->make($uid, $msglist, $header, $content, $flag);
332
            foreach($extensions as $key => $extension) {
333
                $message->getHeader()->set($key, $extension);
334
            }
335
            if ($message !== null) {
336
                $key = $this->getMessageKey($message_key, $msglist, $message);
337
                $messages->put("$key", $message);
338
            }
339
            $msglist++;
340
        }
341
342
        return $messages;
343
    }
344
345
    /**
346
     * Fetch the current query and return all found messages
347
     *
348
     * @return MessageCollection
349
     * @throws GetMessagesFailedException
350
     */
351
    public function get() {
352
        $available_messages = $this->search();
353
354
        try {
355
            if ($available_messages->count() > 0) {
356
                return $this->populate($available_messages);
357
            }
358
            return MessageCollection::make([]);
359
        } catch (Exception $e) {
360
            throw new GetMessagesFailedException($e->getMessage(), 0, $e);
361
        }
362
    }
363
364
    /**
365
     * Fetch the current query as chunked requests
366
     * @param callable $callback
367
     * @param int $chunk_size
368
     * @param int $start_chunk
369
     *
370
     * @throws ConnectionFailedException
371
     * @throws EventNotFoundException
372
     * @throws GetMessagesFailedException
373
     * @throws ReflectionException
374
     * @throws RuntimeException
375
     */
376
    public function chunked($callback, $chunk_size = 10, $start_chunk = 1) {
377
        $available_messages = $this->search();
378
        if (($available_messages_count = $available_messages->count()) > 0) {
379
            $old_limit = $this->limit;
380
            $old_page = $this->page;
381
382
            $this->limit = $chunk_size;
383
            $this->page = $start_chunk;
384
            $handled_messages_count = 0;
385
            do {
386
                $messages = $this->populate($available_messages);
387
                $handled_messages_count += $messages->count();
388
                $callback($messages, $this->page);
389
                $this->page++;
390
            } while ($handled_messages_count < $available_messages_count);
391
            $this->limit = $old_limit;
392
            $this->page = $old_page;
393
        }
394
    }
395
396
    /**
397
     * Paginate the current query
398
     * @param int $per_page Results you which to receive per page
399
     * @param int|null $page The current page you are on (e.g. 0, 1, 2, ...) use `null` to enable auto mode
400
     * @param string $page_name The page name / uri parameter used for the generated links and the auto mode
401
     *
402
     * @return LengthAwarePaginator
403
     * @throws GetMessagesFailedException
404
     */
405
    public function paginate($per_page = 5, $page = null, $page_name = 'imap_page') {
406
        if (
407
            $page === null
408
            && isset($_GET[$page_name])
409
            && $_GET[$page_name] > 0
410
        ) {
411
            $this->page = intval($_GET[$page_name]);
412
        } elseif ($page > 0) {
413
            $this->page = $page;
414
        }
415
416
        $this->limit = $per_page;
417
418
        return $this->get()->paginate($per_page, $this->page, $page_name, true);
419
    }
420
421
    /**
422
     * Get a new Message instance
423
     * @param int $uid
424
     * @param int|null $msglist
425
     * @param int|string|null $sequence
426
     *
427
     * @return Message
428
     * @throws ConnectionFailedException
429
     * @throws RuntimeException
430
     * @throws InvalidMessageDateException
431
     * @throws MessageContentFetchingException
432
     * @throws MessageHeaderFetchingException
433
     * @throws EventNotFoundException
434
     * @throws MessageFlagException
435
     * @throws MessageNotFoundException
436
     */
437
    public function getMessage($uid, $msglist = null, $sequence = null) {
438
        return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), $this->getFetchFlags(), $sequence ? $sequence : $this->sequence);
0 ignored issues
show
Bug introduced by
It seems like $sequence ? $sequence : $this->sequence can also be of type string; however, parameter $sequence of Webklex\PHPIMAP\Message::__construct() 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

438
        return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), $this->getFetchFlags(), /** @scrutinizer ignore-type */ $sequence ? $sequence : $this->sequence);
Loading history...
Bug introduced by
$this->getFetchFlags() of type integer is incompatible with the type boolean expected by parameter $fetch_flags of Webklex\PHPIMAP\Message::__construct(). ( Ignorable by Annotation )

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

438
        return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), /** @scrutinizer ignore-type */ $this->getFetchFlags(), $sequence ? $sequence : $this->sequence);
Loading history...
439
    }
440
441
    /**
442
     * Get a message by its message number
443
     * @param $msgn
444
     * @param int|null $msglist
445
     *
446
     * @return Message
447
     * @throws ConnectionFailedException
448
     * @throws InvalidMessageDateException
449
     * @throws MessageContentFetchingException
450
     * @throws MessageHeaderFetchingException
451
     * @throws RuntimeException
452
     * @throws EventNotFoundException
453
     * @throws MessageFlagException
454
     * @throws MessageNotFoundException
455
     */
456
    public function getMessageByMsgn($msgn, $msglist = null) {
457
        return $this->getMessage($msgn, $msglist, IMAP::ST_MSGN);
458
    }
459
460
    /**
461
     * Get a message by its uid
462
     * @param $uid
463
     *
464
     * @return Message
465
     * @throws ConnectionFailedException
466
     * @throws InvalidMessageDateException
467
     * @throws MessageContentFetchingException
468
     * @throws MessageHeaderFetchingException
469
     * @throws RuntimeException
470
     * @throws EventNotFoundException
471
     * @throws MessageFlagException
472
     * @throws MessageNotFoundException
473
     */
474
    public function getMessageByUid($uid) {
475
        return $this->getMessage($uid, null, IMAP::ST_UID);
476
    }
477
478
    /**
479
     * Get messages with UID greater than given UID.
480
     *
481
     * @param int|string $uid
482
     *
483
     * @return MessageCollection
484
     * @throws ConnectionFailedException
485
     * @throws EventNotFoundException
486
     * @throws InvalidMessageDateException
487
     * @throws MessageContentFetchingException
488
     * @throws MessageFlagException
489
     * @throws MessageHeaderFetchingException
490
     * @throws MessageNotFoundException
491
     * @throws RuntimeException
492
     */
493
    public function getMessagesGreaterThanUid($uid) {
494
        $connection = $this->getClient()->getConnection();
495
496
        $uids = $connection->getUid();
497
        $ids = [];
498
        $messages = MessageCollection::make([]);
499
        foreach ($uids as $id) {
500
            if ($id >= $uid) {
501
                $ids[] = $id;
502
503
                $messages->put("$id", $this->getMessageByUid($id));
504
            }
505
        }
506
507
        $messages->total(count($ids));
508
509
        return $messages;
510
    }
511
512
    /**
513
     * Don't mark messages as read when fetching
514
     *
515
     * @return $this
516
     */
517
    public function leaveUnread() {
518
        $this->setFetchOptions(IMAP::FT_PEEK);
0 ignored issues
show
Bug introduced by
Webklex\PHPIMAP\IMAP::FT_PEEK of type integer is incompatible with the type boolean expected by parameter $fetch_options of Webklex\PHPIMAP\Query\Query::setFetchOptions(). ( Ignorable by Annotation )

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

518
        $this->setFetchOptions(/** @scrutinizer ignore-type */ IMAP::FT_PEEK);
Loading history...
519
520
        return $this;
521
    }
522
523
    /**
524
     * Mark all messages as read when fetching
525
     *
526
     * @return $this
527
     */
528
    public function markAsRead() {
529
        $this->setFetchOptions(IMAP::FT_UID);
0 ignored issues
show
Bug introduced by
Webklex\PHPIMAP\IMAP::FT_UID of type integer is incompatible with the type boolean expected by parameter $fetch_options of Webklex\PHPIMAP\Query\Query::setFetchOptions(). ( Ignorable by Annotation )

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

529
        $this->setFetchOptions(/** @scrutinizer ignore-type */ IMAP::FT_UID);
Loading history...
530
531
        return $this;
532
    }
533
534
    /**
535
     * Set the sequence type
536
     * @param int $sequence
537
     *
538
     * @return $this
539
     */
540
    public function setSequence($sequence) {
541
        $this->sequence = $sequence;
542
543
        return $this;
544
    }
545
546
    /**
547
     * Get the sequence type
548
     *
549
     * @return int|string
550
     */
551
    public function getSequence() {
552
        return $this->sequence;
553
    }
554
555
    /**
556
     * @return Client
557
     * @throws ConnectionFailedException
558
     */
559
    public function getClient() {
560
        $this->client->checkConnection();
561
        return $this->client;
562
    }
563
564
    /**
565
     * Set the limit and page for the current query
566
     * @param int $limit
567
     * @param int $page
568
     *
569
     * @return $this
570
     */
571
    public function limit($limit, $page = 1) {
572
        if ($page >= 1) $this->page = $page;
573
        $this->limit = $limit;
574
575
        return $this;
576
    }
577
578
    /**
579
     * @return Collection
580
     */
581
    public function getQuery() {
582
        return $this->query;
583
    }
584
585
    /**
586
     * @param array $query
587
     * @return Query
588
     */
589
    public function setQuery($query) {
590
        $this->query = new Collection($query);
591
        return $this;
592
    }
593
594
    /**
595
     * @return string
596
     */
597
    public function getRawQuery() {
598
        return $this->raw_query;
599
    }
600
601
    /**
602
     * @param string $raw_query
603
     * @return Query
604
     */
605
    public function setRawQuery($raw_query) {
606
        $this->raw_query = $raw_query;
607
        return $this;
608
    }
609
610
    /**
611
     * @return string[]
612
     */
613
    public function getExtensions() {
614
        return $this->extensions;
615
    }
616
617
    /**
618
     * @param string[] $extensions
619
     * @return Query
620
     */
621
    public function setExtensions($extensions) {
622
        $this->extensions = $extensions;
623
        if (count($this->extensions) > 0) {
624
            if (in_array("UID", $this->extensions) === false) {
625
                $this->extensions[] = "UID";
626
            }
627
        }
628
        return $this;
629
    }
630
631
    /**
632
     * @param Client $client
633
     * @return Query
634
     */
635
    public function setClient(Client $client) {
636
        $this->client = $client;
637
        return $this;
638
    }
639
640
    /**
641
     * @return int
642
     */
643
    public function getLimit() {
644
        return $this->limit;
645
    }
646
647
    /**
648
     * @param int $limit
649
     * @return Query
650
     */
651
    public function setLimit($limit) {
652
        $this->limit = $limit <= 0 ? null : $limit;
653
        return $this;
654
    }
655
656
    /**
657
     * @return int
658
     */
659
    public function getPage() {
660
        return $this->page;
661
    }
662
663
    /**
664
     * @param int $page
665
     * @return Query
666
     */
667
    public function setPage($page) {
668
        $this->page = $page;
669
        return $this;
670
    }
671
672
    /**
673
     * @param boolean $fetch_options
674
     * @return Query
675
     */
676
    public function setFetchOptions($fetch_options) {
677
        $this->fetch_options = $fetch_options;
0 ignored issues
show
Documentation Bug introduced by
The property $fetch_options was declared of type integer, but $fetch_options is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
678
        return $this;
679
    }
680
681
    /**
682
     * @param boolean $fetch_options
683
     * @return Query
684
     */
685
    public function fetchOptions($fetch_options) {
686
        return $this->setFetchOptions($fetch_options);
687
    }
688
689
    /**
690
     * @return int
691
     */
692
    public function getFetchOptions() {
693
        return $this->fetch_options;
694
    }
695
696
    /**
697
     * @return boolean
698
     */
699
    public function getFetchBody() {
700
        return $this->fetch_body;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->fetch_body returns the type integer which is incompatible with the documented return type boolean.
Loading history...
701
    }
702
703
    /**
704
     * @param boolean $fetch_body
705
     * @return Query
706
     */
707
    public function setFetchBody($fetch_body) {
708
        $this->fetch_body = $fetch_body;
0 ignored issues
show
Documentation Bug introduced by
The property $fetch_body was declared of type integer, but $fetch_body is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
709
        return $this;
710
    }
711
712
    /**
713
     * @param boolean $fetch_body
714
     * @return Query
715
     */
716
    public function fetchBody($fetch_body) {
717
        return $this->setFetchBody($fetch_body);
718
    }
719
720
    /**
721
     * @return int
722
     */
723
    public function getFetchFlags() {
724
        return $this->fetch_flags;
725
    }
726
727
    /**
728
     * @param int $fetch_flags
729
     * @return Query
730
     */
731
    public function setFetchFlags($fetch_flags) {
732
        $this->fetch_flags = $fetch_flags;
733
        return $this;
734
    }
735
736
    /**
737
     * @param string $fetch_order
738
     * @return Query
739
     */
740
    public function setFetchOrder($fetch_order) {
741
        $fetch_order = strtolower($fetch_order);
742
743
        if (in_array($fetch_order, ['asc', 'desc'])) {
744
            $this->fetch_order = $fetch_order;
745
        }
746
747
        return $this;
748
    }
749
750
    /**
751
     * @param string $fetch_order
752
     * @return Query
753
     */
754
    public function fetchOrder($fetch_order) {
755
        return $this->setFetchOrder($fetch_order);
756
    }
757
758
    /**
759
     * @return string
760
     */
761
    public function getFetchOrder() {
762
        return $this->fetch_order;
763
    }
764
765
    /**
766
     * @return Query
767
     */
768
    public function setFetchOrderAsc() {
769
        return $this->setFetchOrder('asc');
770
    }
771
772
    /**
773
     * @return Query
774
     */
775
    public function fetchOrderAsc() {
776
        return $this->setFetchOrderAsc();
777
    }
778
779
    /**
780
     * @return Query
781
     */
782
    public function setFetchOrderDesc() {
783
        return $this->setFetchOrder('desc');
784
    }
785
786
    /**
787
     * @return Query
788
     */
789
    public function fetchOrderDesc() {
790
        return $this->setFetchOrderDesc();
791
    }
792
793
    /**
794
     * @return Query
795
     * @var boolean $state
796
     *
797
     */
798
    public function softFail($state = true) {
799
        return $this->setSoftFail($state);
800
    }
801
802
    /**
803
     * @return Query
804
     * @var boolean $state
805
     *
806
     */
807
    public function setSoftFail($state = true) {
808
        $this->soft_fail = $state;
809
810
        return $this;
811
    }
812
813
    /**
814
     * @return boolean
815
     */
816
    public function getSoftFail() {
817
        return $this->soft_fail;
818
    }
819
820
    /**
821
     * Handle the exception for a given uid
822
     * @param integer $uid
823
     *
824
     * @throws GetMessagesFailedException
825
     */
826
    protected function handleException($uid) {
827
        if ($this->soft_fail === false && $this->hasError($uid)) {
828
            $error = $this->getError($uid);
829
            throw new GetMessagesFailedException($error->getMessage(), 0, $error);
830
        }
831
    }
832
833
    /**
834
     * Add a new error to the error holder
835
     * @param integer $uid
836
     * @param Exception $error
837
     */
838
    protected function setError($uid, $error) {
839
        $this->errors[$uid] = $error;
840
    }
841
842
    /**
843
     * Check if there are any errors / exceptions present
844
     * @return boolean
845
     * @var integer|null $uid
846
     *
847
     */
848
    public function hasErrors($uid = null) {
849
        if ($uid !== null) {
850
            return $this->hasError($uid);
851
        }
852
        return count($this->errors) > 0;
853
    }
854
855
    /**
856
     * Check if there is an error / exception present
857
     * @return boolean
858
     * @var integer $uid
859
     *
860
     */
861
    public function hasError($uid) {
862
        return isset($this->errors[$uid]);
863
    }
864
865
    /**
866
     * Get all available errors / exceptions
867
     *
868
     * @return array
869
     */
870
    public function errors() {
871
        return $this->getErrors();
872
    }
873
874
    /**
875
     * Get all available errors / exceptions
876
     *
877
     * @return array
878
     */
879
    public function getErrors() {
880
        return $this->errors;
881
    }
882
883
    /**
884
     * Get a specific error / exception
885
     * @return Exception|null
886
     * @var integer $uid
887
     *
888
     */
889
    public function error($uid) {
890
        return $this->getError($uid);
891
    }
892
893
    /**
894
     * Get a specific error / exception
895
     * @return Exception|null
896
     * @var integer $uid
897
     *
898
     */
899
    public function getError($uid) {
900
        if ($this->hasError($uid)) {
901
            return $this->errors[$uid];
902
        }
903
        return null;
904
    }
905
}
906