/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param \MailSo\Cache\CacheClient|null $oCacher = null * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param bool $bUseESearchOrESortRequest = false * @param string $sThreadUid = '' * @param string $sFilter = '' * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '', $sFilter = '') { $sFilter = \trim($sFilter); $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $bUseFilter = '' !== $sFilter; $this->oImapClient->FolderSelect($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $oMessageCollection->ThreadUid = $sThreadUid; $oMessageCollection->Filtered = '' !== \MailSo\Config::$MessageListPermanentFilter; $aUids = array(); $mAllSortedUids = null; $mAllThreads = null; $iThreadUid = empty($sThreadUid) ? 0 : (int) $sThreadUid; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $sHighestModSeq = ''; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!empty($sThreadUid) && !$bUseThreadSortIfSupported) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); if ($bUseFilter) { $iMessageUnseenCount = 0; } $oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq); $oMessageCollection->UidNext = $sUidNext; if (empty($sThreadUid) && 0 < \strlen($sPrevUidNext) && 'INBOX' === $sFolderName) { $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); } $bSearch = false; $bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger && \MailSo\Config::$MessageListCountLimitTrigger < $iMessageRealCount; if ($bMessageListOptimization) { $bUseSortIfSupported = false; $bUseThreadSortIfSupported = false; } if (0 < $iMessageRealCount && !$bMessageListOptimization) { $mAllSortedUids = $this->GetUids($oCacher, '', $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported); $mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $mAllSortedUids, $oCacher) : null; if ($bUseThreadSortIfSupported && 0 < $iThreadUid && \is_array($mAllThreads)) { $aUids = array(); $iResultRootUid = 0; if (isset($mAllThreads[$iThreadUid])) { $iResultRootUid = $iThreadUid; if (\is_array($mAllThreads[$iThreadUid])) { $aUids = $mAllThreads[$iThreadUid]; } } else { foreach ($mAllThreads as $iRootUid => $mSubUids) { if (\is_array($mSubUids) && \in_array($iThreadUid, $mSubUids)) { $iResultRootUid = $iRootUid; $aUids = $mSubUids; continue; } } } if (0 < $iResultRootUid && \in_array($iResultRootUid, $mAllSortedUids)) { \array_unshift($aUids, $iResultRootUid); } } else { if ($bUseThreadSortIfSupported && \is_array($mAllThreads)) { $aUids = \array_keys($mAllThreads); } else { $bUseThreadSortIfSupported = false; $aUids = $mAllSortedUids; } } if (0 < \strlen($sSearch) && \is_array($aUids)) { $aSearchedUids = $this->GetUids($oCacher, $sSearch, $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash); if (\is_array($aSearchedUids) && 0 < \count($aSearchedUids)) { $aFlippedSearchedUids = \array_flip($aSearchedUids); $bSearch = true; $aNewUids = array(); foreach ($aUids as $iUid) { if (isset($aFlippedSearchedUids[$iUid])) { $aNewUids[] = $iUid; } else { if ($bUseThreadSortIfSupported && 0 === $iThreadUid && isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid])) { foreach ($mAllThreads[$iUid] as $iSubUid) { if (isset($aFlippedSearchedUids[$iSubUid])) { $aNewUids[] = $iUid; continue; } } } } } $aUids = \array_unique($aNewUids); unset($aNewUids); } else { $aUids = array(); } } if (\is_array($aUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = \count($aUids); if (0 < \count($aUids)) { $aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); } } } else { if (0 < $iMessageRealCount) { if ($this->oLogger) { $this->oLogger->Write('List optimization (count: ' . $iMessageRealCount . ', limit:' . \MailSo\Config::$MessageListCountLimitTrigger . ')'); } $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; if (0 < \strlen($sSearch) || $bUseFilter) { $aUids = $this->GetUids($oCacher, $sSearch, $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash); if (0 < \count($aUids)) { $oMessageCollection->MessageResultCount = \count($aUids); $aRequestUids = \array_slice($aUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true); } else { $oMessageCollection->MessageResultCount = 0; } } else { $oMessageCollection->MessageResultCount = $iMessageRealCount; if (1 < $iMessageRealCount) { $aRequestIndexes = \array_slice(array_reverse(range(1, $iMessageRealCount)), $iOffset, $iLimit); } else { $aRequestIndexes = \array_slice(array(1), $iOffset, $iLimit); } $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexes, false); } } } if ($bUseThreadSortIfSupported && 0 === $iThreadUid && \is_array($mAllThreads) && 0 < \count($mAllThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($mAllThreads) { $iUid = $oMessage->Uid(); if (isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]) && 0 < \count($mAllThreads[$iUid])) { $aSubThreads = $mAllThreads[$iUid]; \array_unshift($aSubThreads, $iUid); $oMessage->SetThreads(\array_map('trim', $aSubThreads)); unset($aSubThreads); } }); } return $oMessageCollection; }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param mixed $oCacher = null * @param string $sCachePrefix = '' * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array()) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999) || !is_string($sSearch)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $this->oImapClient->FolderExamine($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $aLastCollapsedThreadUids = array(); $aThreads = array(); $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $sSerializedHash = ''; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $iMessageCount = $iMessageRealCount; $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); $bCacher = false; $bSearch = false; if (0 < $iMessageRealCount) { $bIndexAsUid = false; $aIndexOrUids = array(); $bSearch = 0 < \strlen($sSearch); if ($bSearch || $bUseSortIfSupported && !$bUseThreadSortIfSupported) { $bIndexAsUid = true; $aIndexOrUids = null; $sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete(); if ($oCacher && $oCacher->IsInited()) { $sSerializedHash = ($bUseSortIfSupported ? 'S' : 'N') . '/' . ($bUseThreadSortIfSupported ? 'T' : 'N') . '/' . $this->oImapClient->GetLogginedUser() . '@' . $this->oImapClient->GetConnectedHost() . ':' . $this->oImapClient->GetConnectedPort() . '/' . $oMessageCollection->FolderName . '/' . $oMessageCollection->FolderHash . '/' . $sSearchCriterias; $sSerializedUids = $oCacher->Get($sSerializedHash); if (!empty($sSerializedUids)) { $aSerializedUids = @\unserialize($sSerializedUids); if (\is_array($aSerializedUids)) { $aIndexOrUids = $aSerializedUids; $bCacher = true; } } } if (!\is_array($aIndexOrUids)) { if ($bUseSortIfSupported && !$bUseThreadSortIfSupported) { $aIndexOrUids = $this->oImapClient->MessageSimpleSort(array('ARRIVAL'), $sSearchCriterias, $bIndexAsUid); } else { if (!\MailSo\Base\Utils::IsAscii($sSearch)) { try { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid, 'UTF-8'); } catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) { $oException = null; $aIndexOrUids = null; } } if (null === $aIndexOrUids) { $aIndexOrUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bIndexAsUid); } } } } else { if ($bUseThreadSortIfSupported && 1 < $iMessageCount) { $bIndexAsUid = true; $aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oCacher); $aIndexOrUids = $this->compileLineThreadUids($aThreads, $aLastCollapsedThreadUids, $aExpandedThreadsUids, 0); $iMessageCount = count($aIndexOrUids); } else { $bIndexAsUid = false; $aIndexOrUids = array(1); if (1 < $iMessageCount) { $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); } } } if ($bIndexAsUid && !$bCacher && \is_array($aIndexOrUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash)) { $oCacher->Set($sSerializedHash, \serialize($aIndexOrUids)); } if (\is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) ? $iMessageCount : \count($aIndexOrUids); if (0 < count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); } } } $aLastCollapsedThreadUidsForPage = array(); if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) { $iUid = $oMessage->Uid(); if (in_array($iUid, $aLastCollapsedThreadUids)) { $aLastCollapsedThreadUidsForPage[] = $iUid; } if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); $oMessage->SetThreadsLen(\count($aThreads[$iUid])); } else { if (!isset($aThreads[$iUid])) { foreach ($aThreads as $iKeyUid => $mSubItem) { if (is_array($mSubItem) && in_array($iUid, $mSubItem)) { $oMessage->SetParentThread($iKeyUid); $oMessage->SetThreadsLen(\count($mSubItem)); } } } } }); $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; } return $oMessageCollection; }
/** * @param string $sFolderName * @param int $iOffset = 0 * @param int $iLimit = 10 * @param string $sSearch = '' * @param string $sPrevUidNext = '' * @param \MailSo\Cache\CacheClient|null $oCacher = null * @param bool $bUseSortIfSupported = false * @param bool $bUseThreadSortIfSupported = false * @param array $aExpandedThreadsUids = array() * @param bool $bUseESearchOrESortRequest = false * * @return \MailSo\Mail\MessageCollection * * @throws \MailSo\Base\Exceptions\InvalidArgumentException * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $aExpandedThreadsUids = array(), $bUseESearchOrESortRequest = false) { $sSearch = \trim($sSearch); if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) || !\MailSo\Base\Validator::RangeInt($iLimit, 0, 999)) { throw new \MailSo\Base\Exceptions\InvalidArgumentException(); } $this->oImapClient->FolderExamine($sFolderName); $oMessageCollection = MessageCollection::NewInstance(); $oMessageCollection->FolderName = $sFolderName; $oMessageCollection->Offset = $iOffset; $oMessageCollection->Limit = $iLimit; $oMessageCollection->Search = $sSearch; $aLastCollapsedThreadUids = array(); $aThreads = array(); $iMessageCount = 0; $iMessageRealCount = 0; $iMessageUnseenCount = 0; $sUidNext = '0'; $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $this->oImapClient->IsSupported('THREAD=REFS') || $this->oImapClient->IsSupported('THREAD=REFERENCES') || $this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT') : false; if (!$oCacher || !$oCacher instanceof \MailSo\Cache\CacheClient) { $oCacher = null; } $this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $iMessageCount = $iMessageRealCount; $oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext); $oMessageCollection->UidNext = $sUidNext; $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext); $bSearch = false; $bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger && \MailSo\Config::$MessageListCountLimitTrigger < $iMessageRealCount; if ($bMessageListOptimization) { $bUseSortIfSupported = false; $bUseThreadSortIfSupported = false; $bUseESearchOrESortRequest = false; } if (0 < $iMessageRealCount) { $bIndexAsUid = false; $aIndexOrUids = array(); if (0 < \strlen($sSearch)) { $aIndexOrUids = $this->getSearchUidsResult($sSearch, $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $bIndexAsUid = true; } else { if ($bUseThreadSortIfSupported && 1 < $iMessageCount) { $aIndexOrUids = $this->getSearchUidsResult('', $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $aIndexOrUids, $oCacher, \MailSo\Config::$LargeThreadLimit); $aExpandedThreadsUids = \is_array($aExpandedThreadsUids) ? $aExpandedThreadsUids : array(); $bWatchExpanded = 0 < \count($aExpandedThreadsUids); $aNewIndexOrUids = array(); foreach ($aIndexOrUids as $iUid) { if (isset($aThreads[$iUid])) { $aNewIndexOrUids[] = $iUid; if (\is_array($aThreads[$iUid])) { if ($bWatchExpanded && \in_array($iUid, $aExpandedThreadsUids)) { $aSubArray = $aThreads[$iUid]; foreach ($aSubArray as $iSubRootUid) { $aNewIndexOrUids[] = $iSubRootUid; } } else { $aLastCollapsedThreadUids[] = $iUid; } } } } $aIndexOrUids = $aNewIndexOrUids; unset($aNewIndexOrUids); $iMessageCount = \count($aIndexOrUids); $bIndexAsUid = true; } else { $aIndexOrUids = array(1); $bIndexAsUid = false; if (1 < $iMessageCount) { if ($bMessageListOptimization || 0 === \MailSo\Config::$MessageListDateFilter) { $aIndexOrUids = \array_reverse(\range(1, $iMessageCount)); } else { $aIndexOrUids = $this->getSearchUidsResult('', $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher); $bIndexAsUid = true; } } } } if (\is_array($aIndexOrUids)) { $oMessageCollection->MessageCount = $iMessageRealCount; $oMessageCollection->MessageUnseenCount = $iMessageUnseenCount; $oMessageCollection->MessageResultCount = 0 === \strlen($sSearch) ? $iMessageCount : \count($aIndexOrUids); if (0 < \count($aIndexOrUids)) { $iOffset = 0 > $iOffset ? 0 : $iOffset; $aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit); $this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid); } } } $aLastCollapsedThreadUidsForPage = array(); if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads)) { $oMessageCollection->ForeachList(function ($oMessage) use($aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage) { $iUid = $oMessage->Uid(); if (\in_array($iUid, $aLastCollapsedThreadUids)) { $aLastCollapsedThreadUidsForPage[] = $iUid; } if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid])) { $oMessage->SetThreads($aThreads[$iUid]); $oMessage->SetThreadsLen(\count($aThreads[$iUid])); } else { if (!isset($aThreads[$iUid])) { foreach ($aThreads as $iKeyUid => $mSubItem) { if (\is_array($mSubItem) && \in_array($iUid, $mSubItem)) { $oMessage->SetParentThread($iKeyUid); $oMessage->SetThreadsLen(\count($mSubItem)); } } } } }); $oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage; } return $oMessageCollection; }