mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-25 10:09:20 +03:00
Merge f2648a54c0 into c154d23cfe
This commit is contained in:
commit
439da0ac39
1 changed files with 228 additions and 193 deletions
|
|
@ -2,212 +2,247 @@
|
||||||
|
|
||||||
class SearchFiltersPlugin extends \RainLoop\Plugins\AbstractPlugin
|
class SearchFiltersPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
public const
|
public const
|
||||||
NAME = 'Search Filters',
|
NAME = 'Search Filters',
|
||||||
AUTHOR = 'AbdoBnHesham',
|
AUTHOR = 'AbdoBnHesham',
|
||||||
URL = 'https://github.com/the-djmaze/snappymail/pull/1673',
|
URL = 'https://github.com/the-djmaze/snappymail/pull/1673',
|
||||||
VERSION = '0.2',
|
VERSION = '0.2',
|
||||||
RELEASE = '2024-06-28',
|
RELEASE = '2024-06-28',
|
||||||
REQUIRED = '2.36.3',
|
REQUIRED = '2.36.3',
|
||||||
CATEGORY = 'General',
|
CATEGORY = 'General',
|
||||||
LICENSE = 'MIT',
|
LICENSE = 'MIT',
|
||||||
DESCRIPTION = 'Add filters to search queries';
|
DESCRIPTION = 'Add filters to search queries';
|
||||||
|
|
||||||
public function Init(): void
|
public function Init(): void
|
||||||
{
|
{
|
||||||
$this->UseLangs(true);
|
$this->UseLangs(true);
|
||||||
|
|
||||||
$this->addHook('imap.after-login', 'ApplyFilters');
|
$this->addHook('imap.after-login', 'ApplyFilters');
|
||||||
|
|
||||||
$this->addTemplate('templates/STabSearchFilters.html');
|
$this->addTemplate('templates/STabSearchFilters.html');
|
||||||
|
|
||||||
$this->addTemplate('templates/PopupsSearchFilters.html');
|
$this->addTemplate('templates/PopupsSearchFilters.html');
|
||||||
$this->addTemplate('templates/PopupsSTabAdvancedSearch.html');
|
$this->addTemplate('templates/PopupsSTabAdvancedSearch.html');
|
||||||
$this->addJs('js/SearchFilters.js');
|
$this->addJs('js/SearchFilters.js');
|
||||||
|
|
||||||
$this->addJsonHook('SGetFilters', 'GetFilters');
|
$this->addJsonHook('SGetFilters', 'GetFilters');
|
||||||
$this->addJsonHook('SAddEditFilter', 'AddEditFilter');
|
$this->addJsonHook('SAddEditFilter', 'AddEditFilter');
|
||||||
$this->addJsonHook('SUpdateSearchQ', 'UpdateSearchQ');
|
$this->addJsonHook('SUpdateSearchQ', 'UpdateSearchQ');
|
||||||
$this->addJsonHook('SDeleteFilter', 'DeleteFilter');
|
$this->addJsonHook('SDeleteFilter', 'DeleteFilter');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ApplyFilters(
|
public function ApplyFilters(
|
||||||
\RainLoop\Model\Account $oAccount,
|
\RainLoop\Model\Account $oAccount,
|
||||||
\MailSo\Imap\ImapClient $oImapClient,
|
\MailSo\Imap\ImapClient $oImapClient,
|
||||||
bool $bSuccess,
|
bool $bSuccess,
|
||||||
\MailSo\Imap\Settings $oSettings
|
\MailSo\Imap\Settings $oSettings
|
||||||
) {
|
) {
|
||||||
if (!$bSuccess) {
|
if (!$bSuccess) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aSettings = $this->getUserSettings();
|
$aSettings = $this->getUserSettings();
|
||||||
if (empty($aSettings['SFilters'])) {
|
if (empty($aSettings['SFilters'])) {
|
||||||
$aSettings['SFilters'] = [];
|
$aSettings['SFilters'] = [];
|
||||||
$this->saveUserSettings($aSettings);
|
$this->saveUserSettings($aSettings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Filters = $aSettings['SFilters'];
|
$Filters = $aSettings['SFilters'];
|
||||||
|
|
||||||
foreach ($Filters as $filter) {
|
foreach ($Filters as $filter) {
|
||||||
$this->Manager()->logWrite(json_encode([
|
$this->Manager()->logWrite(json_encode(['filter' => $filter]), LOG_WARNING);
|
||||||
'filter' => $filter,
|
|
||||||
]), LOG_WARNING);
|
|
||||||
|
|
||||||
$folder = 'INBOX';
|
$searchQ = $filter['searchQ'];
|
||||||
$searchQ = $filter['searchQ'];
|
|
||||||
$uids = $this->searchMessages($oImapClient, $searchQ, "INBOX");
|
|
||||||
|
|
||||||
//Mark as read/seen
|
// obsługa keyword (multi-folder)
|
||||||
if ($filter['fSeen']) {
|
if (stripos($searchQ, 'keyword=') !== false) {
|
||||||
foreach ($uids as $uid) {
|
$oMailClient = $this->Manager()->Actions()->MailClient();
|
||||||
$oRange = new MailSo\Imap\SequenceSet([$uid]);
|
|
||||||
$this->Manager()->Actions()->MailClient()->MessageSetFlag(
|
|
||||||
$folder,
|
|
||||||
$oRange,
|
|
||||||
MailSo\Imap\Enumerations\MessageFlag::SEEN
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Flag/Star message
|
// Pobieramy wszystkie foldery top-level
|
||||||
if ($filter['fFlag']) {
|
$folders = $oMailClient->Folders('', false, '');
|
||||||
foreach ($uids as $uid) {
|
foreach ($folders as $f) {
|
||||||
$oRange = new MailSo\Imap\SequenceSet([$uid]);
|
$folder = $f->FullName ?? null;
|
||||||
$this->Manager()->Actions()->MailClient()->MessageSetFlag(
|
if (!$folder) continue;
|
||||||
$folder,
|
|
||||||
$oRange,
|
|
||||||
MailSo\Imap\Enumerations\MessageFlag::FLAGGED
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to folder
|
$uids = $this->searchMessages($oImapClient, $searchQ, $folder);
|
||||||
if ($filter['fFolder']) {
|
if (!empty($uids)) {
|
||||||
$folder = $filter['fFolder'];
|
$this->applyActions($oImapClient, $filter, $uids, $folder);
|
||||||
foreach ($uids as $uid) {
|
}
|
||||||
$oRange = new MailSo\Imap\SequenceSet([$uid]);
|
}
|
||||||
$oImapClient->MessageMove("INBOX", $folder, $oRange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function searchMessages(
|
continue; // przechodzimy do następnego filtra
|
||||||
\MailSo\Imap\ImapClient $imapClient,
|
}
|
||||||
string $search,
|
|
||||||
string $folder = "INBOX"
|
|
||||||
): array {
|
|
||||||
$oParams = new \MailSo\Mail\MessageListParams();
|
|
||||||
$oParams->sSearch = $search;
|
|
||||||
$oParams->sFolderName = $folder;
|
|
||||||
|
|
||||||
$bUseCache = false;
|
// normalny search w INBOX
|
||||||
$oSearchCriterias = \MailSo\Imap\SearchCriterias::fromString(
|
$uids = $this->searchMessages($oImapClient, $searchQ, 'INBOX');
|
||||||
$imapClient,
|
if (!empty($uids)) {
|
||||||
$folder,
|
$this->applyActions($oImapClient, $filter, $uids, 'INBOX');
|
||||||
$search,
|
}
|
||||||
true,
|
}
|
||||||
$bUseCache
|
|
||||||
);
|
|
||||||
|
|
||||||
$imapClient->FolderSelect($folder);
|
|
||||||
return $imapClient->MessageSearch($oSearchCriterias, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetFilters()
|
|
||||||
{
|
|
||||||
$aSettings = $this->getUserSettings();
|
|
||||||
$Filters = $aSettings['SFilters'] ?? [];
|
|
||||||
|
|
||||||
$Search = $this->jsonParam('SSearchQ');
|
|
||||||
if (!$Search) {
|
|
||||||
return $this->jsonResponse(__FUNCTION__, ['SFilters' => $Filters]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$Filter = null;
|
|
||||||
foreach ($aSettings['SFilters'] as $filter) {
|
|
||||||
if ($filter['searchQ'] == $Search) {
|
|
||||||
$Filter = $filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->jsonResponse(__FUNCTION__, ['SFilter' => $Filter]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function AddEditFilter()
|
|
||||||
{
|
|
||||||
$SFilter = $this->jsonParam('SFilter');
|
|
||||||
$newFilter = [
|
|
||||||
'searchQ' => $SFilter['searchQ'],
|
|
||||||
'priority' => $SFilter['priority'] ?? 1,
|
|
||||||
'fFolder' => $SFilter['fFolder'],
|
|
||||||
'fSeen' => $SFilter['fSeen'],
|
|
||||||
'fFlag' => $SFilter['fFlag'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$aSettings = $this->getUserSettings();
|
|
||||||
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
|
||||||
|
|
||||||
$foundIndex = null;
|
|
||||||
foreach ($aSettings['SFilters'] as $index => $filter) {
|
|
||||||
if ($filter['searchQ'] == $SFilter['searchQ']) {
|
|
||||||
if ($filter['priority'] != $SFilter['priority']) {
|
|
||||||
array_splice($aSettings['SFilters'], $index, 1);
|
|
||||||
} else {
|
|
||||||
$foundIndex = $index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($foundIndex === null) {
|
|
||||||
$insertIndex = 0;
|
|
||||||
foreach ($aSettings['SFilters'] as $index => $filter)
|
|
||||||
if ($filter['priority'] >= $newFilter['priority'])
|
|
||||||
$insertIndex = $index + 1;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
array_splice($aSettings['SFilters'], $insertIndex, 0, [$newFilter]);
|
|
||||||
} else {
|
|
||||||
$aSettings['SFilters'][$foundIndex] = $newFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function UpdateSearchQ()
|
|
||||||
{
|
|
||||||
$SFilter = $this->jsonParam('SFilter');
|
|
||||||
|
|
||||||
$aSettings = $this->getUserSettings();
|
|
||||||
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
|
||||||
|
|
||||||
foreach ($aSettings['SFilters'] as $index => $filter) {
|
|
||||||
if ($filter['searchQ'] == $SFilter['oldSearchQ']) {
|
|
||||||
$filter['searchQ'] = $SFilter['searchQ'];
|
|
||||||
$aSettings['SFilters'][$index] = $filter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DeleteFilter()
|
|
||||||
{
|
|
||||||
$Search = $this->jsonParam('SSearchQ');
|
|
||||||
|
|
||||||
$aSettings = $this->getUserSettings();
|
|
||||||
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
|
||||||
|
|
||||||
foreach ($aSettings['SFilters'] as $index => $filter) {
|
|
||||||
if ($filter['searchQ'] == $Search) {
|
|
||||||
array_splice($aSettings['SFilters'], $index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function searchMessages(
|
||||||
|
\MailSo\Imap\ImapClient $imapClient,
|
||||||
|
string $search,
|
||||||
|
string $folder = "INBOX"
|
||||||
|
): array {
|
||||||
|
try {
|
||||||
|
$bUseCache = false;
|
||||||
|
$oSearchCriterias = \MailSo\Imap\SearchCriterias::fromString(
|
||||||
|
$imapClient,
|
||||||
|
$folder,
|
||||||
|
$search,
|
||||||
|
true,
|
||||||
|
$bUseCache
|
||||||
|
);
|
||||||
|
|
||||||
|
$imapClient->FolderSelect($folder);
|
||||||
|
return $imapClient->MessageSearch($oSearchCriterias, true);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->Manager()->logWrite(
|
||||||
|
'SearchFilters IMAP error in folder "' . $folder .
|
||||||
|
'" for search "' . $search . '": ' . $e->getMessage(),
|
||||||
|
LOG_ERR
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function applyActions(
|
||||||
|
\MailSo\Imap\ImapClient $imapClient,
|
||||||
|
array $filter,
|
||||||
|
array $uids,
|
||||||
|
string $folder
|
||||||
|
) {
|
||||||
|
// Mark as read/seen
|
||||||
|
if (!empty($filter['fSeen'])) {
|
||||||
|
foreach ($uids as $uid) {
|
||||||
|
$oRange = new \MailSo\Imap\SequenceSet([$uid]);
|
||||||
|
$this->Manager()->Actions()->MailClient()->MessageSetFlag(
|
||||||
|
$folder,
|
||||||
|
$oRange,
|
||||||
|
\MailSo\Imap\Enumerations\MessageFlag::SEEN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag/Star message
|
||||||
|
if (!empty($filter['fFlag'])) {
|
||||||
|
foreach ($uids as $uid) {
|
||||||
|
$oRange = new \MailSo\Imap\SequenceSet([$uid]);
|
||||||
|
$this->Manager()->Actions()->MailClient()->MessageSetFlag(
|
||||||
|
$folder,
|
||||||
|
$oRange,
|
||||||
|
\MailSo\Imap\Enumerations\MessageFlag::FLAGGED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to folder
|
||||||
|
if (!empty($filter['fFolder']) && $filter['fFolder'] !== -1) {
|
||||||
|
foreach ($uids as $uid) {
|
||||||
|
$oRange = new \MailSo\Imap\SequenceSet([$uid]);
|
||||||
|
$imapClient->MessageMove('INBOX', $filter['fFolder'], $oRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function GetFilters()
|
||||||
|
{
|
||||||
|
$aSettings = $this->getUserSettings();
|
||||||
|
$Filters = $aSettings['SFilters'] ?? [];
|
||||||
|
|
||||||
|
$Search = $this->jsonParam('SSearchQ');
|
||||||
|
if (!$Search) {
|
||||||
|
return $this->jsonResponse(__FUNCTION__, ['SFilters' => $Filters]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$Filter = null;
|
||||||
|
foreach ($aSettings['SFilters'] as $filter) {
|
||||||
|
if ($filter['searchQ'] == $Search) {
|
||||||
|
$Filter = $filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->jsonResponse(__FUNCTION__, ['SFilter' => $Filter]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AddEditFilter()
|
||||||
|
{
|
||||||
|
$SFilter = $this->jsonParam('SFilter');
|
||||||
|
$newFilter = [
|
||||||
|
'searchQ' => $SFilter['searchQ'],
|
||||||
|
'priority' => $SFilter['priority'] ?? 1,
|
||||||
|
'fFolder' => $SFilter['fFolder'],
|
||||||
|
'fSeen' => $SFilter['fSeen'],
|
||||||
|
'fFlag' => $SFilter['fFlag'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$aSettings = $this->getUserSettings();
|
||||||
|
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
||||||
|
|
||||||
|
$foundIndex = null;
|
||||||
|
foreach ($aSettings['SFilters'] as $index => $filter) {
|
||||||
|
if ($filter['searchQ'] == $SFilter['searchQ']) {
|
||||||
|
if ($filter['priority'] != $SFilter['priority']) {
|
||||||
|
array_splice($aSettings['SFilters'], $index, 1);
|
||||||
|
} else {
|
||||||
|
$foundIndex = $index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($foundIndex === null) {
|
||||||
|
$insertIndex = 0;
|
||||||
|
foreach ($aSettings['SFilters'] as $index => $filter)
|
||||||
|
if ($filter['priority'] >= $newFilter['priority'])
|
||||||
|
$insertIndex = $index + 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
array_splice($aSettings['SFilters'], $insertIndex, 0, [$newFilter]);
|
||||||
|
} else {
|
||||||
|
$aSettings['SFilters'][$foundIndex] = $newFilter;
|
||||||
|
}
|
||||||
|
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function UpdateSearchQ()
|
||||||
|
{
|
||||||
|
$SFilter = $this->jsonParam('SFilter');
|
||||||
|
|
||||||
|
$aSettings = $this->getUserSettings();
|
||||||
|
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
||||||
|
|
||||||
|
foreach ($aSettings['SFilters'] as $index => $filter) {
|
||||||
|
if ($filter['searchQ'] == $SFilter['oldSearchQ']) {
|
||||||
|
$filter['searchQ'] = $SFilter['searchQ'];
|
||||||
|
$aSettings['SFilters'][$index] = $filter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function DeleteFilter()
|
||||||
|
{
|
||||||
|
$Search = $this->jsonParam('SSearchQ');
|
||||||
|
|
||||||
|
$aSettings = $this->getUserSettings();
|
||||||
|
$aSettings['SFilters'] = $aSettings['SFilters'] ?? [];
|
||||||
|
|
||||||
|
foreach ($aSettings['SFilters'] as $index => $filter) {
|
||||||
|
if ($filter['searchQ'] == $Search) {
|
||||||
|
array_splice($aSettings['SFilters'], $index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->jsonResponse(__FUNCTION__, $this->saveUserSettings($aSettings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue