Passed
Pull Request — master (#201)
by
unknown
02:25
created

Query::getByUidGreaterThanEqual()   A

Complexity

Conditions 5
Paths 15

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 13
c 1
b 1
f 0
dl 0
loc 19
rs 9.5222
cc 5
nc 15
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 equal or greater than given UID.
480
     *
481
     * @param int|string $uid
482
     *
483
     * @return MessageCollection
484
     * @throws ConnectionFailedException
485
     * @throws GetMessagesFailedException
486
     * @throws MessageNotFoundException
487
     */
488
    public function getByUidGreaterThanEqual($uid) {
489
        $connection = $this->getClient()->getConnection();
490
491
        $uids = $connection->getUid();
492
        $available_messages = new Collection();
493
        $i = 0;
494
        foreach ($uids as $id) {
495
            if ($id >= $uid) {
496
                $available_messages->put($i++, $id);
497
            }
498
        }
499
500
        try {
501
            if ($available_messages->count() > 0) {
502
                return $this->populate($available_messages);
503
            }
504
            return MessageCollection::make([]);
505
        } catch (Exception $e) {
506
            throw new GetMessagesFailedException($e->getMessage(), 0, $e);
507
        }
508
    }
509
510
    /**
511
     * Don't mark messages as read when fetching
512
     *
513
     * @return $this
514
     */
515
    public function leaveUnread() {
516
        $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

516
        $this->setFetchOptions(/** @scrutinizer ignore-type */ IMAP::FT_PEEK);
Loading history...
517
518
        return $this;
519
    }
520
521
    /**
522
     * Mark all messages as read when fetching
523
     *
524
     * @return $this
525
     */
526
    public function markAsRead() {
527
        $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

527
        $this->setFetchOptions(/** @scrutinizer ignore-type */ IMAP::FT_UID);
Loading history...
528
529
        return $this;
530
    }
531
532
    /**
533
     * Set the sequence type
534
     * @param int $sequence
535
     *
536
     * @return $this
537
     */
538
    public function setSequence($sequence) {
539
        $this->sequence = $sequence;
540
541
        return $this;
542
    }
543
544
    /**
545
     * Get the sequence type
546
     *
547
     * @return int|string
548
     */
549
    public function getSequence() {
550
        return $this->sequence;
551
    }
552
553
    /**
554
     * @return Client
555
     * @throws ConnectionFailedException
556
     */
557
    public function getClient() {
558
        $this->client->checkConnection();
559
        return $this->client;
560
    }
561
562
    /**
563
     * Set the limit and page for the current query
564
     * @param int $limit
565
     * @param int $page
566
     *
567
     * @return $this
568
     */
569
    public function limit($limit, $page = 1) {
570
        if ($page >= 1) $this->page = $page;
571
        $this->limit = $limit;
572
573
        return $this;
574
    }
575
576
    /**
577
     * @return Collection
578
     */
579
    public function getQuery() {
580
        return $this->query;
581
    }
582
583
    /**
584
     * @param array $query
585
     * @return Query
586
     */
587
    public function setQuery($query) {
588
        $this->query = new Collection($query);
589
        return $this;
590
    }
591
592
    /**
593
     * @return string
594
     */
595
    public function getRawQuery() {
596
        return $this->raw_query;
597
    }
598
599
    /**
600
     * @param string $raw_query
601
     * @return Query
602
     */
603
    public function setRawQuery($raw_query) {
604
        $this->raw_query = $raw_query;
605
        return $this;
606
    }
607
608
    /**
609
     * @return string[]
610
     */
611
    public function getExtensions() {
612
        return $this->extensions;
613
    }
614
615
    /**
616
     * @param string[] $extensions
617
     * @return Query
618
     */
619
    public function setExtensions($extensions) {
620
        $this->extensions = $extensions;
621
        if (count($this->extensions) > 0) {
622
            if (in_array("UID", $this->extensions) === false) {
623
                $this->extensions[] = "UID";
624
            }
625
        }
626
        return $this;
627
    }
628
629
    /**
630
     * @param Client $client
631
     * @return Query
632
     */
633
    public function setClient(Client $client) {
634
        $this->client = $client;
635
        return $this;
636
    }
637
638
    /**
639
     * @return int
640
     */
641
    public function getLimit() {
642
        return $this->limit;
643
    }
644
645
    /**
646
     * @param int $limit
647
     * @return Query
648
     */
649
    public function setLimit($limit) {
650
        $this->limit = $limit <= 0 ? null : $limit;
651
        return $this;
652
    }
653
654
    /**
655
     * @return int
656
     */
657
    public function getPage() {
658
        return $this->page;
659
    }
660
661
    /**
662
     * @param int $page
663
     * @return Query
664
     */
665
    public function setPage($page) {
666
        $this->page = $page;
667
        return $this;
668
    }
669
670
    /**
671
     * @param boolean $fetch_options
672
     * @return Query
673
     */
674
    public function setFetchOptions($fetch_options) {
675
        $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...
676
        return $this;
677
    }
678
679
    /**
680
     * @param boolean $fetch_options
681
     * @return Query
682
     */
683
    public function fetchOptions($fetch_options) {
684
        return $this->setFetchOptions($fetch_options);
685
    }
686
687
    /**
688
     * @return int
689
     */
690
    public function getFetchOptions() {
691
        return $this->fetch_options;
692
    }
693
694
    /**
695
     * @return boolean
696
     */
697
    public function getFetchBody() {
698
        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...
699
    }
700
701
    /**
702
     * @param boolean $fetch_body
703
     * @return Query
704
     */
705
    public function setFetchBody($fetch_body) {
706
        $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...
707
        return $this;
708
    }
709
710
    /**
711
     * @param boolean $fetch_body
712
     * @return Query
713
     */
714
    public function fetchBody($fetch_body) {
715
        return $this->setFetchBody($fetch_body);
716
    }
717
718
    /**
719
     * @return int
720
     */
721
    public function getFetchFlags() {
722
        return $this->fetch_flags;
723
    }
724
725
    /**
726
     * @param int $fetch_flags
727
     * @return Query
728
     */
729
    public function setFetchFlags($fetch_flags) {
730
        $this->fetch_flags = $fetch_flags;
731
        return $this;
732
    }
733
734
    /**
735
     * @param string $fetch_order
736
     * @return Query
737
     */
738
    public function setFetchOrder($fetch_order) {
739
        $fetch_order = strtolower($fetch_order);
740
741
        if (in_array($fetch_order, ['asc', 'desc'])) {
742
            $this->fetch_order = $fetch_order;
743
        }
744
745
        return $this;
746
    }
747
748
    /**
749
     * @param string $fetch_order
750
     * @return Query
751
     */
752
    public function fetchOrder($fetch_order) {
753
        return $this->setFetchOrder($fetch_order);
754
    }
755
756
    /**
757
     * @return string
758
     */
759
    public function getFetchOrder() {
760
        return $this->fetch_order;
761
    }
762
763
    /**
764
     * @return Query
765
     */
766
    public function setFetchOrderAsc() {
767
        return $this->setFetchOrder('asc');
768
    }
769
770
    /**
771
     * @return Query
772
     */
773
    public function fetchOrderAsc() {
774
        return $this->setFetchOrderAsc();
775
    }
776
777
    /**
778
     * @return Query
779
     */
780
    public function setFetchOrderDesc() {
781
        return $this->setFetchOrder('desc');
782
    }
783
784
    /**
785
     * @return Query
786
     */
787
    public function fetchOrderDesc() {
788
        return $this->setFetchOrderDesc();
789
    }
790
791
    /**
792
     * @return Query
793
     * @var boolean $state
794
     *
795
     */
796
    public function softFail($state = true) {
797
        return $this->setSoftFail($state);
798
    }
799
800
    /**
801
     * @return Query
802
     * @var boolean $state
803
     *
804
     */
805
    public function setSoftFail($state = true) {
806
        $this->soft_fail = $state;
807
808
        return $this;
809
    }
810
811
    /**
812
     * @return boolean
813
     */
814
    public function getSoftFail() {
815
        return $this->soft_fail;
816
    }
817
818
    /**
819
     * Handle the exception for a given uid
820
     * @param integer $uid
821
     *
822
     * @throws GetMessagesFailedException
823
     */
824
    protected function handleException($uid) {
825
        if ($this->soft_fail === false && $this->hasError($uid)) {
826
            $error = $this->getError($uid);
827
            throw new GetMessagesFailedException($error->getMessage(), 0, $error);
828
        }
829
    }
830
831
    /**
832
     * Add a new error to the error holder
833
     * @param integer $uid
834
     * @param Exception $error
835
     */
836
    protected function setError($uid, $error) {
837
        $this->errors[$uid] = $error;
838
    }
839
840
    /**
841
     * Check if there are any errors / exceptions present
842
     * @return boolean
843
     * @var integer|null $uid
844
     *
845
     */
846
    public function hasErrors($uid = null) {
847
        if ($uid !== null) {
848
            return $this->hasError($uid);
849
        }
850
        return count($this->errors) > 0;
851
    }
852
853
    /**
854
     * Check if there is an error / exception present
855
     * @return boolean
856
     * @var integer $uid
857
     *
858
     */
859
    public function hasError($uid) {
860
        return isset($this->errors[$uid]);
861
    }
862
863
    /**
864
     * Get all available errors / exceptions
865
     *
866
     * @return array
867
     */
868
    public function errors() {
869
        return $this->getErrors();
870
    }
871
872
    /**
873
     * Get all available errors / exceptions
874
     *
875
     * @return array
876
     */
877
    public function getErrors() {
878
        return $this->errors;
879
    }
880
881
    /**
882
     * Get a specific error / exception
883
     * @return Exception|null
884
     * @var integer $uid
885
     *
886
     */
887
    public function error($uid) {
888
        return $this->getError($uid);
889
    }
890
891
    /**
892
     * Get a specific error / exception
893
     * @return Exception|null
894
     * @var integer $uid
895
     *
896
     */
897
    public function getError($uid) {
898
        if ($this->hasError($uid)) {
899
            return $this->errors[$uid];
900
        }
901
        return null;
902
    }
903
}
904