Bugfix: get MessageList using ThreadUid

This commit is contained in:
djmaze 2021-11-17 12:18:59 +01:00
parent 7d077b0997
commit ed7ebb066a
3 changed files with 96 additions and 92 deletions

View file

@ -975,58 +975,55 @@ class MailClient
* @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Net\Exceptions\Exception
* @throws \MailSo\Imap\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception
*/ */
public function MessageList(string $sFolderName, int $iOffset = 0, int $iLimit = 10, public function MessageList(\MailSo\Mail\MessageListParams $oParams) : MessageCollection
string $sSearch = '', int $iPrevUidNext = 0, ?\MailSo\Cache\CacheClient $oCacher = null,
bool $bUseSortIfSupported = false, bool $bUseThreadSortIfSupported = false,
int $iThreadUid = 0, string $sSort = '') : MessageCollection
{ {
if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || if (!\MailSo\Base\Validator::RangeInt($oParams->iOffset, 0) ||
!\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) !\MailSo\Base\Validator::RangeInt($oParams->iLimit, 0, 999))
{ {
throw new \MailSo\Base\Exceptions\InvalidArgumentException; throw new \MailSo\Base\Exceptions\InvalidArgumentException;
} }
$sSearch = \trim($sSearch); $sSearch = \trim($oParams->sSearch);
list($iMessageRealCount, $iMessageUnseenCount, $iUidNext, $iHighestModSeq) = $this->initFolderValues($sFolderName); list($iMessageRealCount, $iMessageUnseenCount, $iUidNext, $iHighestModSeq) = $this->initFolderValues($oParams->sFolderName);
$this->oImapClient->FolderSelect($sFolderName); $this->oImapClient->FolderSelect($oParams->sFolderName);
$oMessageCollection = new MessageCollection; $oMessageCollection = new MessageCollection;
$oMessageCollection->FolderName = $sFolderName; $oMessageCollection->FolderName = $oParams->sFolderName;
$oMessageCollection->Offset = $iOffset; $oMessageCollection->Offset = $oParams->iOffset;
$oMessageCollection->Limit = $iLimit; $oMessageCollection->Limit = $oParams->iLimit;
$oMessageCollection->Search = $sSearch; $oMessageCollection->Search = $sSearch;
$oMessageCollection->ThreadUid = $iThreadUid; $oMessageCollection->ThreadUid = $oParams->iThreadUid;
$oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter; $oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter;
$aUids = array(); $aUids = array();
$mAllThreads = null; $aAllThreads = [];
$bUseSortIfSupported = $bUseSortIfSupported && $this->oImapClient->IsSupported('SORT'); $bUseSortIfSupported = $oParams->bUseSortIfSupported && $this->oImapClient->IsSupported('SORT');
$bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $bUseThreads = $oParams->bUseThreads ?
($this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT')) : false; ($this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT')) : false;
if ($iThreadUid && !$bUseThreadSortIfSupported) if ($oParams->iThreadUid && !$bUseThreads)
{ {
throw new \MailSo\Base\Exceptions\InvalidArgumentException; throw new \MailSo\Base\Exceptions\InvalidArgumentException('THREAD not supported');
} }
if (!$oCacher || !($oCacher instanceof \MailSo\Cache\CacheClient)) if (!$oParams->oCacher || !($oParams->oCacher instanceof \MailSo\Cache\CacheClient))
{ {
$oCacher = null; $oParams->oCacher = null;
} }
$oMessageCollection->FolderHash = $this->GenerateFolderHash( $oMessageCollection->FolderHash = $this->GenerateFolderHash(
$sFolderName, $iMessageRealCount, $iUidNext, $iHighestModSeq); $oParams->sFolderName, $iMessageRealCount, $iUidNext, $iHighestModSeq);
$oMessageCollection->UidNext = $iUidNext; $oMessageCollection->UidNext = $iUidNext;
if (!$iThreadUid && $iPrevUidNext && 'INBOX' === $sFolderName) if (!$oParams->iThreadUid && $oParams->iPrevUidNext && 'INBOX' === $oParams->sFolderName)
{ {
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation( $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation(
$sFolderName, $iPrevUidNext, $iUidNext); $oParams->sFolderName, $oParams->iPrevUidNext, $iUidNext);
} }
$bSearch = false; $bSearch = false;
@ -1036,23 +1033,22 @@ class MailClient
if ($bMessageListOptimization) if ($bMessageListOptimization)
{ {
$bUseSortIfSupported = false; $bUseSortIfSupported = false;
$bUseThreadSortIfSupported = false; $bUseThreads = false;
} }
if (0 < $iMessageRealCount && !$bMessageListOptimization) if (0 < $iMessageRealCount && !$bMessageListOptimization)
{ {
$aUids = $this->GetUids($oCacher, '', $aUids = $this->GetUids($oParams->oCacher, '',
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $sSort); $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $oParams->sSort);
$mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap( if ($bUseThreads) {
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oCacher) : null; if (0 < $oParams->iThreadUid)
if ($bUseThreadSortIfSupported && $mAllThreads) {
if (0 < $iThreadUid)
{ {
$aAllThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oParams->oCacher);
$aUids = [$oParams->iThreadUid];
// Only show the selected thread messages // Only show the selected thread messages
foreach ($mAllThreads as $aMap) { foreach ($aAllThreads as $aMap) {
if (\in_array($iThreadUid, $aMap)) { if (\in_array($oParams->iThreadUid, $aMap)) {
$aUids = \array_intersect($aUids, $aMap); $aUids = \array_intersect($aUids, $aMap);
break; break;
} }
@ -1060,17 +1056,13 @@ class MailClient
} }
else else
{ {
// $aUids = \array_diff($aUids, $mAllThreads); // $aUids = \array_diff($aUids, $aAllThreads);
} }
} }
else
{
$bUseThreadSortIfSupported = false;
}
if (\strlen($sSearch) && \is_array($aUids)) if (\strlen($sSearch) && \is_array($aUids))
{ {
$aSearchedUids = $this->GetUids($oCacher, $sSearch, $aSearchedUids = $this->GetUids($oParams->oCacher, $sSearch,
$oMessageCollection->FolderName, $oMessageCollection->FolderHash); $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
if (\count($aSearchedUids)) if (\count($aSearchedUids))
@ -1086,9 +1078,9 @@ class MailClient
{ {
$aNewUids[] = $iUid; $aNewUids[] = $iUid;
} }
else if ($bUseThreadSortIfSupported && !$iThreadUid && isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid])) else if ($bUseThreads && !$oParams->iThreadUid && isset($aAllThreads[$iUid]) && \is_array($aAllThreads[$iUid]))
{ {
foreach ($mAllThreads[$iUid] as $iSubUid) foreach ($aAllThreads[$iUid] as $iSubUid)
{ {
if (isset($aFlippedSearchedUids[$iSubUid])) if (isset($aFlippedSearchedUids[$iSubUid]))
{ {
@ -1116,7 +1108,7 @@ class MailClient
if (\count($aUids)) if (\count($aUids))
{ {
$aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $aRequestUids = \array_slice($aUids, $oParams->iOffset, $oParams->iLimit);
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true);
} }
} }
@ -1134,14 +1126,14 @@ class MailClient
if (\strlen($sSearch)) if (\strlen($sSearch))
{ {
$aUids = $this->GetUids($oCacher, $sSearch, $aUids = $this->GetUids($oParams->oCacher, $sSearch,
$oMessageCollection->FolderName, $oMessageCollection->FolderHash); $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
if (\count($aUids)) if (\count($aUids))
{ {
$oMessageCollection->MessageResultCount = \count($aUids); $oMessageCollection->MessageResultCount = \count($aUids);
$aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $aRequestUids = \array_slice($aUids, $oParams->iOffset, $oParams->iLimit);
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true);
} }
else else
@ -1155,24 +1147,24 @@ class MailClient
if (1 < $iMessageRealCount) if (1 < $iMessageRealCount)
{ {
$aRequestIndexes = \array_slice(\array_reverse(\range(1, $iMessageRealCount)), $iOffset, $iLimit); $aRequestIndexes = \array_slice(\array_reverse(\range(1, $iMessageRealCount)), $oParams->iOffset, $oParams->iLimit);
} }
else else
{ {
$aRequestIndexes = \array_slice(array(1), $iOffset, $iLimit); $aRequestIndexes = \array_slice(array(1), $oParams->iOffset, $oParams->iLimit);
} }
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexes, false); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexes, false);
} }
} }
if ($bUseThreadSortIfSupported && 0 === $iThreadUid && \is_array($mAllThreads) && \count($mAllThreads)) if ($bUseThreads && 0 === $oParams->iThreadUid && \count($aAllThreads))
{ {
foreach ($oMessageCollection as $oMessage) { foreach ($oMessageCollection as $oMessage) {
$iUid = $oMessage->Uid(); $iUid = $oMessage->Uid();
if (isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]) && \count($mAllThreads[$iUid])) if (isset($aAllThreads[$iUid]) && \is_array($aAllThreads[$iUid]) && \count($aAllThreads[$iUid]))
{ {
$aSubThreads = $mAllThreads[$iUid]; $aSubThreads = $aAllThreads[$iUid];
\array_unshift($aSubThreads, $iUid); \array_unshift($aSubThreads, $iUid);
$oMessage->SetThreads(\array_map('trim', $aSubThreads)); $oMessage->SetThreads(\array_map('trim', $aSubThreads));

View file

@ -0,0 +1,27 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2014 Usenko Timur
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MailSo\Mail;
class MessageListParams
{
public
$sFolderName, // string
$iOffset = 0, // int
$iLimit = 10, // int
$sSearch = '', // string
$iPrevUidNext = 0, // int
$oCacher = null, // ?\MailSo\Cache\CacheClient
$bUseSortIfSupported = false, // bool
$bUseThreads = false, // bool
$iThreadUid = 0, // int
$sSort = ''; // string
}

View file

@ -16,50 +16,40 @@ trait Messages
{ {
// \sleep(1); // \sleep(1);
// throw new ClientException(Notifications::CantGetMessageList); // throw new ClientException(Notifications::CantGetMessageList);
$oParams = new \MailSo\Mail\MessageListParams;
$sFolder = '';
$iOffset = 0;
$iLimit = 20;
$sSearch = '';
$iUidNext = 0;
$bUseThreads = false;
$iThreadUid = 0;
$sSort = '';
$sRawKey = $this->GetActionParam('RawKey', ''); $sRawKey = $this->GetActionParam('RawKey', '');
$aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true); $aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true);
if ($aValues && 7 < \count($aValues)) if ($aValues && 7 < \count($aValues))
{ {
$sFolder = (string) $aValues['Folder'];
$iOffset = (int) $aValues['Offset'];
$iLimit = (int) $aValues['Limit'];
$sSearch = (string) $aValues['Search'];
$iUidNext = (int) $aValues['UidNext'];
$bUseThreads = !empty($aValues['UseThreads']);
if ($bUseThreads) {
$iThreadUid = (int) $aValues['ThreadUid'];
}
$sSort = (string) $aValues['Sort'];
$this->verifyCacheByKey($sRawKey); $this->verifyCacheByKey($sRawKey);
$oParams->sFolderName = (string) $aValues['Folder'];
$oParams->iOffset = (int) $aValues['Offset'];
$oParams->iLimit = (int) $aValues['Limit'];
$oParams->sSearch = (string) $aValues['Search'];
$oParams->sSort = (string) $aValues['Sort'];
$oParams->iPrevUidNext = (int) $aValues['UidNext'];
$oParams->bUseThreads = !empty($aValues['UseThreads']);
if ($oParams->bUseThreads) {
$oParams->iThreadUid = (int) $aValues['ThreadUid'];
}
} }
else else
{ {
$sFolder = $this->GetActionParam('Folder', ''); $oParams->sFolderName = $this->GetActionParam('Folder', '');
$iOffset = (int) $this->GetActionParam('Offset', 0); $oParams->iOffset = (int) $this->GetActionParam('Offset', 0);
$iLimit = (int) $this->GetActionParam('Limit', 10); $oParams->iLimit = (int) $this->GetActionParam('Limit', 10);
$sSearch = $this->GetActionParam('Search', ''); $oParams->sSearch = $this->GetActionParam('Search', '');
$sSort = $this->GetActionParam('Sort', ''); $oParams->sSort = $this->GetActionParam('Sort', '');
$iUidNext = (int) $this->GetActionParam('UidNext', 0); $oParams->iPrevUidNext = (int) $this->GetActionParam('UidNext', 0);
$bUseThreads = !empty($this->GetActionParam('UseThreads', '0')); $oParams->bUseThreads = !empty($this->GetActionParam('UseThreads', '0'));
if ($oParams->bUseThreads) {
if ($bUseThreads) $oParams->iThreadUid = (int) $this->GetActionParam('ThreadUid', '');
{
$iThreadUid = (int) $this->GetActionParam('ThreadUid', '');
} }
} }
if (!\strlen($sFolder)) if (!\strlen($oParams->sFolderName))
{ {
throw new ClientException(Notifications::CantGetMessageList); throw new ClientException(Notifications::CantGetMessageList);
} }
@ -68,19 +58,14 @@ trait Messages
try try
{ {
if (!$this->Config()->Get('labs', 'use_imap_thread', false)) if (!$this->Config()->Get('labs', 'use_imap_thread', false)) {
{ $oParams->bUseThreads = false;
$bUseThreads = false;
} }
$oMessageList = $this->MailClient()->MessageList( $oParams->oCacher = $this->cacherForUids();
$sFolder, $iOffset, $iLimit, $sSearch, $iUidNext, $oParams->bUseSortIfSupported = !!$this->Config()->Get('labs', 'use_imap_sort', true);
$this->cacherForUids(),
!!$this->Config()->Get('labs', 'use_imap_sort', true), $oMessageList = $this->MailClient()->MessageList($oParams);
$bUseThreads,
$iThreadUid,
$sSort
);
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {