blob: 60d348a9efd708891065c06a85f9f1ad9f5b3e94 [file] [log] [blame]
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +01001<?php
2
3declare(strict_types=1);
4
5namespace Ddeboer\Imap;
6
7use Ddeboer\Imap\Exception\InvalidResourceException;
8use Ddeboer\Imap\Exception\ReopenMailboxException;
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +01009use IMAP\Connection;
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010010
11/**
12 * An imap resource stream.
13 */
14final class ImapResource implements ImapResourceInterface
15{
16 /**
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020017 * @var resource
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010018 */
19 private $resource;
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020020 private ?MailboxInterface $mailbox = null;
21 private static ?string $lastMailboxUsedCache = null;
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010022
23 /**
24 * Constructor.
25 *
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010026 * @param Connection|resource $resource
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010027 */
28 public function __construct($resource, MailboxInterface $mailbox = null)
29 {
30 $this->resource = $resource;
31 $this->mailbox = $mailbox;
32 }
33
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010034 public function getStream()
35 {
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010036 if (
37 !$this->resource instanceof Connection
38 && (false === \is_resource($this->resource) || 'imap' !== \get_resource_type($this->resource))
39 ) {
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010040 throw new InvalidResourceException('Supplied resource is not a valid imap resource');
41 }
42
43 $this->initMailbox();
44
45 return $this->resource;
46 }
47
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010048 public function clearLastMailboxUsedCache(): void
49 {
50 self::$lastMailboxUsedCache = null;
51 }
52
53 /**
54 * If connection is not currently in this mailbox, switch it to this mailbox.
55 */
56 private function initMailbox(): void
57 {
58 if (null === $this->mailbox || self::isMailboxOpen($this->mailbox, $this->resource)) {
59 return;
60 }
61
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010062 \set_error_handler(static function (): bool {
63 return true;
64 });
65
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010066 \imap_reopen($this->resource, $this->mailbox->getFullEncodedName());
67
Matthias Andreas Benkard1ba53812022-12-27 17:32:58 +010068 \restore_error_handler();
69
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010070 if (self::isMailboxOpen($this->mailbox, $this->resource)) {
71 return;
72 }
73
74 throw new ReopenMailboxException(\sprintf('Cannot reopen mailbox "%s"', $this->mailbox->getName()));
75 }
76
77 /**
78 * Check whether the current mailbox is open.
79 *
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +020080 * @param resource $resource
Matthias Andreas Benkardb382b102021-01-02 15:32:21 +010081 */
82 private static function isMailboxOpen(MailboxInterface $mailbox, $resource): bool
83 {
84 $currentMailboxName = $mailbox->getFullEncodedName();
85 if ($currentMailboxName === self::$lastMailboxUsedCache) {
86 return true;
87 }
88
89 self::$lastMailboxUsedCache = null;
90 $check = \imap_check($resource);
91 $return = false !== $check && $check->Mailbox === $currentMailboxName;
92
93 if (true === $return) {
94 self::$lastMailboxUsedCache = $currentMailboxName;
95 }
96
97 return $return;
98 }
99}