1<?php
2
3declare(strict_types=1);
4
5/**
6 * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
7 *
8 * @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
9 *
10 * @license GNU AGPL version 3 or any later version
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License as
14 * published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26namespace OCA\Mail\IMAP;
27
28use Horde_Imap_Client_Exception;
29use OCA\Mail\Account;
30use OCA\Mail\Db\Mailbox;
31use OCA\Mail\Db\Message;
32use OCA\Mail\Db\MessageMapper as DbMapper;
33use OCA\Mail\IMAP\MessageMapper as ImapMapper;
34use Psr\Log\LoggerInterface;
35use function array_key_exists;
36use function array_map;
37use function array_merge;
38use function array_reduce;
39
40class PreviewEnhancer {
41
42	/** @var IMAPClientFactory */
43	private $clientFactory;
44
45	/** @var ImapMapper */
46	private $imapMapper;
47
48	/** @var DbMapper */
49	private $mapper;
50
51	/** @var LoggerInterface */
52	private $logger;
53
54	public function __construct(IMAPClientFactory $clientFactory,
55								ImapMapper $imapMapper,
56								DbMapper $dbMapper,
57								LoggerInterface $logger) {
58		$this->clientFactory = $clientFactory;
59		$this->imapMapper = $imapMapper;
60		$this->mapper = $dbMapper;
61		$this->logger = $logger;
62	}
63
64	/**
65	 * @param Message[] $messages
66	 *
67	 * @return Message[]
68	 */
69	public function process(Account $account, Mailbox $mailbox, array $messages): array {
70		$needAnalyze = array_reduce($messages, function (array $carry, Message $message) {
71			if ($message->getStructureAnalyzed()) {
72				// Nothing to do
73				return $carry;
74			}
75
76			return array_merge($carry, [$message->getUid()]);
77		}, []);
78
79		if (empty($needAnalyze)) {
80			// Nothing to enhance
81			return $messages;
82		}
83
84		try {
85			$data = $this->imapMapper->getBodyStructureData(
86				$this->clientFactory->getClient($account),
87				$mailbox->getName(),
88				$needAnalyze
89			);
90		} catch (Horde_Imap_Client_Exception $e) {
91			// Ignore for now, but log
92			$this->logger->warning('Could not fetch structure detail data to enhance message previews: ' . $e->getMessage(), [
93				'exception' => $e,
94			]);
95
96			return $messages;
97		}
98
99		return $this->mapper->updatePreviewDataBulk(...array_map(function (Message $message) use ($data) {
100			if (!array_key_exists($message->getUid(), $data)) {
101				// Nothing to do
102				return $message;
103			}
104
105			/** @var MessageStructureData $structureData */
106			$structureData = $data[$message->getUid()];
107			$message->setFlagAttachments($structureData->hasAttachments());
108			$message->setPreviewText($structureData->getPreviewText());
109			$message->setStructureAnalyzed(true);
110
111			return $message;
112		}, $messages));
113	}
114}
115