Passed
Push — developer ( 4e3135...f5c82a )
by Radosław
30:25 queued 12:59
created

Scanner::setLimit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * Mail scanner file.
4
 *
5
 * @package App
6
 *
7
 * @copyright YetiForce S.A.
8
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
9
 * @author    Radosław Skrzypczak <[email protected]>
10
 */
11
12
namespace App\Mail;
13
14
/**
15
 * Mail scanner class.
16
 */
17
class Scanner extends \App\Base
18
{
19
	/** @var string Base module name */
20
	public const MODULE_NAME = 'MailAccount';
21
	/** @var string Name of the scanned folder table */
22
	public const FOLDER_TABLE = 'u_#__mailscanner_folders';
23
	/** @var string Logs table name */
24
	public const LOG_TABLE = 'vtiger_ossmails_logs';
25
26
	/** @var \App\Mail\Account */
27
	private $account;
28
	/** @var int Limit of scanned e-mails */
29
	private $limit = 100;
30
	/** @var int Number of scanned e-mails */
31
	private $count = 0;
32
	/** @var ScannerLog Scanner log */
33
	private $log;
34
35
	/**
36
	 * Constructor.
37
	 */
38
	public function __construct()
39
	{
40
		$this->log = new ScannerLog();
41
	}
42
43
	/**
44
	 * Set limit.
45
	 *
46
	 * @param int $limit
47
	 *
48
	 * @return $this
49
	 */
50
	public function setLimit(int $limit)
51
	{
52
		$this->limit = $limit;
53
		return $this;
54
	}
55
56
	/**
57
	 * Set Mail Account.
58
	 *
59
	 * @param Account $account
60
	 *
61
	 * @return $this
62
	 */
63
	public function setAccount(Account $account)
64
	{
65
		$this->account = $account;
66
		return $this;
67
	}
68
69
	/**
70
	 * Run scanner.
71
	 *
72
	 * @param callable|null $callback Conditions for scanning subsequent emails
73
	 *
74
	 * @return void
75
	 */
76
	public function run(?callable $callback = null)
77
	{
78
		$folders = $this->account->getFolders();
79
		$actions = $this->account->getActions();
80
		if ($folders && $actions && ($imap = $this->getImapConnection()) && ($folders = array_intersect($folders, array_keys($imap->getFolders(false))))) {
0 ignored issues
show
introduced by
$folders is an empty array, thus is always false.
Loading history...
Bug Best Practice introduced by
The expression $folders of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
81
			$flagSeen = \App\Mail::getConfig('scanner', 'flag_seen');
82
			foreach ($folders as $folderName) {
83
				$this->log->start();
84
				$uid = $this->account->getLastUid($folderName);
85
				if (!\is_int($uid)) {
86
					continue;
87
				}
88
89
				$messageCollection = $imap->getMessagesGreaterThanUid($folderName, $uid, $this->limit);
90
				foreach ($messageCollection as $message) {
91
					if (!$this->log->isRunning()) {
92
						return;
93
					}
94
					if (($callback && $callback($this))) {
95
						break 2;
96
					}
97
					--$this->limit;
98
					$messageObject = (new Message\Imap())->setMessage($message);
99
					try {
100
						foreach ($actions as $action) {
101
							$this->getAction($action)->setAccount($this->account)->setMessage($messageObject)->process();
102
						}
103
						++$this->count;
104
						$this->account->setLastUid($messageObject->getMsgUid(), $folderName);
105
						$this->log->updateCount($this->count);
106
						if ($flagSeen) {
107
							$messageObject->setFlag('Seen');
108
						}
109
					} catch (\Throwable $th) {
110
						$message = $th->getMessage();
111
						\App\Log::error("Mail Scanner - Account: {$this->account->getSource()->getId()}, folder: {$folderName}, UID: {$messageObject->getMsgUid()}, message: " . $message);
112
						if ($th instanceof \App\Exceptions\AppException) {
113
							$message = $th->getDisplayMessage();
114
						}
115
						$this->log->close(ScannerLog::STATUS_ERROR, $message, $action);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $action does not seem to be defined for all execution paths leading up to this point.
Loading history...
116
						break;
117
					}
118
				}
119
			}
120
			$this->log->close();
121
		}
122
	}
123
124
	/**
125
	 * Get imap connection.
126
	 *
127
	 * @return Connections\Imap|null
128
	 */
129
	public function getImapConnection(): ?Connections\Imap
130
	{
131
		try {
132
			$imap = $this->account->openImap();
133
		} catch (\Throwable $th) {
134
			$this->account->lock($th->getMessage());
135
			$imap = null;
136
		}
137
138
		return $imap;
139
	}
140
141
	/**
142
	 * Get action object.
143
	 *
144
	 * @param string $name
145
	 *
146
	 * @return ScannerAction\Base
147
	 */
148
	public function getAction(string $name): ScannerAction\Base
149
	{
150
		$class = "App\\Mail\\ScannerAction\\{$name}";
151
		return new $class();
152
	}
153
154
	/**
155
	 * Check if ready.
156
	 *
157
	 * @return bool
158
	 */
159
	public function isReady(): bool
160
	{
161
		return !ScannerLog::isScannRunning();
162
	}
163
}
164