Improved sort when using message_list_limit in a virtual \All mailbox

https://github.com/the-djmaze/snappymail/issues/796#issuecomment-1367846187
This commit is contained in:
the-djmaze 2022-12-30 11:31:49 +01:00
parent 201d2e3c94
commit d1b31c6822
2 changed files with 38 additions and 15 deletions

View file

@ -409,19 +409,20 @@ class MailClient
protected function MessageListThreadsMap(MessageCollection $oMessageCollection, ?\MailSo\Cache\CacheClient $oCacher) : array protected function MessageListThreadsMap(MessageCollection $oMessageCollection, ?\MailSo\Cache\CacheClient $oCacher) : array
{ {
$sFolderName = $oMessageCollection->FolderName; $sFolderName = $oMessageCollection->FolderName;
// $iThreadLimit = $this->oImapClient->Settings->thread_limit;
$sSearchHash = ''; $sSearch = 'ALL';
/*
if ('' === \trim($sSearchHash)) { $iThreadLimit = $this->oImapClient->Settings->thread_limit;
$sSearchHash = 'ALL'; if ($iThreadLimit && $iThreadLimit < $oMessageCollection->FolderInfo->MESSAGES) {
$sSearch = ($oMessageCollection->FolderInfo->MESSAGES - $iThreadLimit) . ':*';
} }
*/
$sSerializedHashKey = null; $sSerializedHashKey = null;
if ($oCacher && $oCacher->IsInited()) { if ($oCacher && $oCacher->IsInited()) {
$sSerializedHashKey = $sSerializedHashKey =
"ThreadsMapSorted/{$sSearchHash}/{$sFolderName}/{$oMessageCollection->FolderHash}"; "ThreadsMapSorted/{$sSearch}/{$sFolderName}/{$oMessageCollection->FolderHash}";
// "ThreadsMapSorted/{$sSearchHash}/{$iThreadLimit}/{$sFolderName}/{$oMessageCollection->FolderHash}"; // "ThreadsMapSorted/{$sSearch}/{$iThreadLimit}/{$sFolderName}/{$oMessageCollection->FolderHash}";
if ($this->oLogger) { if ($this->oLogger) {
$this->oLogger->Write($sSerializedHashKey); $this->oLogger->Write($sSerializedHashKey);
@ -432,7 +433,7 @@ class MailClient
$aSerializedUids = \json_decode($sSerializedUids, true); $aSerializedUids = \json_decode($sSerializedUids, true);
if (isset($aSerializedUids['ThreadsUids']) && \is_array($aSerializedUids['ThreadsUids'])) { if (isset($aSerializedUids['ThreadsUids']) && \is_array($aSerializedUids['ThreadsUids'])) {
if ($this->oLogger) { if ($this->oLogger) {
$this->oLogger->Write('Get Serialized Thread UIDS from cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aSerializedUids['ThreadsUids']).']'); $this->oLogger->Write('Get Serialized Thread UIDS from cache ("'.$sFolderName.'" / '.$sSearch.') [count:'.\count($aSerializedUids['ThreadsUids']).']');
} }
return $aSerializedUids['ThreadsUids']; return $aSerializedUids['ThreadsUids'];
} }
@ -444,7 +445,7 @@ class MailClient
$aResult = array(); $aResult = array();
try try
{ {
foreach ($this->oImapClient->MessageSimpleThread($sSearchHash) as $mItem) { foreach ($this->oImapClient->MessageSimpleThread($sSearch) as $mItem) {
// Flatten to single level // Flatten to single level
$aMap = []; $aMap = [];
\array_walk_recursive($mItem, function($a) use (&$aMap) { $aMap[] = $a; }); \array_walk_recursive($mItem, function($a) use (&$aMap) { $aMap[] = $a; });
@ -463,7 +464,7 @@ class MailClient
))); )));
if ($this->oLogger) { if ($this->oLogger) {
$this->oLogger->Write('Save Serialized Thread UIDS to cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aResult).']'); $this->oLogger->Write('Save Serialized Thread UIDS to cache ("'.$sFolderName.'" / '.$sSearch.') [count:'.\count($aResult).']');
} }
} }
@ -563,6 +564,13 @@ class MailClient
*/ */
$sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch); $sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch);
$bReturnUid = true;
if ($oParams->oSequenceSet) {
$bReturnUid = $oParams->oSequenceSet->UID;
$sSearchCriterias = $oParams->oSequenceSet . ' ' . $sSearchCriterias;
}
// Disabled for now as there are many cases that change the result // Disabled for now as there are many cases that change the result
$bUseCacheAfterSearch = false; $bUseCacheAfterSearch = false;
if ($bUseCacheAfterSearch) { if ($bUseCacheAfterSearch) {
@ -601,11 +609,11 @@ class MailClient
} }
// $this->oImapClient->hasCapability('ESORT') // $this->oImapClient->hasCapability('ESORT')
// $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL']; // $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL'];
$aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias); $aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias, $bReturnUid);
} else { } else {
// $this->oImapClient->hasCapability('ESEARCH') // $this->oImapClient->hasCapability('ESEARCH')
// $aResultUids = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, null, true, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8') // $aResultUids = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, null, $bReturnUid, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8')
$aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8'); $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bReturnUid, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8');
} }
if ($bUseCacheAfterSearch) { if ($bUseCacheAfterSearch) {
@ -666,12 +674,13 @@ class MailClient
} }
if ($oInfo->MESSAGES) { if ($oInfo->MESSAGES) {
if (0 < $this->oImapClient->Settings->message_list_limit && $this->oImapClient->Settings->message_list_limit < $oInfo->MESSAGES) { $message_list_limit = $this->oImapClient->Settings->message_list_limit;
if (0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES) {
// Don't use SORT nor THREAD // Don't use SORT nor THREAD
$oMessageCollection->Limited = true; $oMessageCollection->Limited = true;
if ($this->oLogger) { if ($this->oLogger) {
$this->oLogger->Write('List optimization (count: '.$oInfo->MESSAGES. $this->oLogger->Write('List optimization (count: '.$oInfo->MESSAGES.
', limit:'.$this->oImapClient->Settings->message_list_limit.')'); ', limit:'.$message_list_limit.')');
} }
if (\strlen($sSearch)) { if (\strlen($sSearch)) {
$aUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash); $aUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash);
@ -685,10 +694,19 @@ class MailClient
} else { } else {
$oMessageCollection->totalEmails = $oInfo->MESSAGES; $oMessageCollection->totalEmails = $oInfo->MESSAGES;
if (1 < $oInfo->MESSAGES) { if (1 < $oInfo->MESSAGES) {
// Attempt to sort REVERSE DATE with a bigger range then $oParams->iLimit
$end = \min($oInfo->MESSAGES, \max(1, $oInfo->MESSAGES - $oParams->iOffset + $oParams->iLimit));
$start = \max(1, $end - ($oParams->iLimit * 3) + 1);
$oParams->oSequenceSet = new SequenceSet(\range($end, $start), false);
$aRequestIndexes = $this->GetUids($oParams, '', $oMessageCollection->FolderHash, true);
// Attempt to get the correct $oParams->iLimit slice
$aRequestIndexes = \array_slice($aRequestIndexes, $oParams->iOffset ? $oParams->iLimit : 0, $oParams->iLimit);
/*
$end = \max(1, $oInfo->MESSAGES - $oParams->iOffset); $end = \max(1, $oInfo->MESSAGES - $oParams->iOffset);
$start = \max(1, $end - $oParams->iLimit + 1); $start = \max(1, $end - $oParams->iLimit + 1);
// Attempt to sort REVERSE DATE // Attempt to sort REVERSE DATE
$aRequestIndexes = \range($end, $start); $aRequestIndexes = \range($end, $start);
*/
} else { } else {
$aRequestIndexes = \array_slice([1], $oParams->iOffset, 1); $aRequestIndexes = \array_slice([1], $oParams->iOffset, 1);
} }

View file

@ -32,6 +32,11 @@ class MessageListParams
$iPrevUidNext = 0, // used to check for new messages $iPrevUidNext = 0, // used to check for new messages
$iThreadUid = 0; $iThreadUid = 0;
/**
* Messages with message sequence numbers corresponding to the specified message sequence number set.
*/
public ?\MailSo\Imap\SequenceSet $oSequenceSet = null;
public function __get($k) public function __get($k)
{ {
return \property_exists($this, $k) ? $this->$k : null; return \property_exists($this, $k) ? $this->$k : null;