mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Speedup Contacts Suggestions handling
This commit is contained in:
parent
731ac52564
commit
2e3e1fa5fe
3 changed files with 58 additions and 122 deletions
|
|
@ -18,16 +18,12 @@ trait User
|
||||||
use Attachments;
|
use Attachments;
|
||||||
use Pgp;
|
use Pgp;
|
||||||
|
|
||||||
/**
|
private ?Suggestions $oSuggestionsProvider = null;
|
||||||
* @var \RainLoop\Providers\Suggestions
|
|
||||||
*/
|
|
||||||
private $oSuggestionsProvider = null;
|
|
||||||
|
|
||||||
public function SuggestionsProvider(): Suggestions
|
public function SuggestionsProvider(): Suggestions
|
||||||
{
|
{
|
||||||
if (null === $this->oSuggestionsProvider) {
|
if (null === $this->oSuggestionsProvider) {
|
||||||
$this->oSuggestionsProvider = new Suggestions(
|
$this->oSuggestionsProvider = new Suggestions($this->fabrica('suggestions'));
|
||||||
$this->fabrica('suggestions'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->oSuggestionsProvider;
|
return $this->oSuggestionsProvider;
|
||||||
|
|
@ -51,16 +47,13 @@ trait User
|
||||||
$this->Plugins()->RunHook('login.success', array($oAccount));
|
$this->Plugins()->RunHook('login.success', array($oAccount));
|
||||||
|
|
||||||
$sLanguage = $this->GetActionParam('Language', '');
|
$sLanguage = $this->GetActionParam('Language', '');
|
||||||
if ($oAccount && $sLanguage)
|
if ($oAccount && $sLanguage) {
|
||||||
{
|
|
||||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||||
if ($oSettings)
|
if ($oSettings) {
|
||||||
{
|
|
||||||
$sLanguage = $this->ValidateLanguage($sLanguage);
|
$sLanguage = $this->ValidateLanguage($sLanguage);
|
||||||
$sCurrentLanguage = $oSettings->GetConf('Language', '');
|
$sCurrentLanguage = $oSettings->GetConf('Language', '');
|
||||||
|
|
||||||
if ($sCurrentLanguage !== $sLanguage)
|
if ($sCurrentLanguage !== $sLanguage) {
|
||||||
{
|
|
||||||
$oSettings->SetConf('Language', $sLanguage);
|
$oSettings->SetConf('Language', $sLanguage);
|
||||||
$this->SettingsProvider()->Save($oAccount, $oSettings);
|
$this->SettingsProvider()->Save($oAccount, $oSettings);
|
||||||
}
|
}
|
||||||
|
|
@ -98,20 +91,17 @@ trait User
|
||||||
$iMainCacheTime = !empty($aTimers[0]) && \is_numeric($aTimers[0]) ? (int) $aTimers[0] : 0;
|
$iMainCacheTime = !empty($aTimers[0]) && \is_numeric($aTimers[0]) ? (int) $aTimers[0] : 0;
|
||||||
$iFilesCacheTime = !empty($aTimers[1]) && \is_numeric($aTimers[1]) ? (int) $aTimers[1] : 0;
|
$iFilesCacheTime = !empty($aTimers[1]) && \is_numeric($aTimers[1]) ? (int) $aTimers[1] : 0;
|
||||||
|
|
||||||
if (0 === $iMainCacheTime || $iMainCacheTime + $iOneDay1 < \time())
|
if (0 === $iMainCacheTime || $iMainCacheTime + $iOneDay1 < \time()) {
|
||||||
{
|
|
||||||
$bMainCache = true;
|
$bMainCache = true;
|
||||||
$iMainCacheTime = \time();
|
$iMainCacheTime = \time();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 === $iFilesCacheTime || $iFilesCacheTime + $iOneDay2 < \time())
|
if (0 === $iFilesCacheTime || $iFilesCacheTime + $iOneDay2 < \time()) {
|
||||||
{
|
|
||||||
$bFilesCache = true;
|
$bFilesCache = true;
|
||||||
$iFilesCacheTime = \time();
|
$iFilesCacheTime = \time();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bMainCache || $bFilesCache)
|
if ($bMainCache || $bFilesCache) {
|
||||||
{
|
|
||||||
if (!$this->StorageProvider()->Put(null,
|
if (!$this->StorageProvider()->Put(null,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers',
|
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers',
|
||||||
\implode(',', array($iMainCacheTime, $iFilesCacheTime))))
|
\implode(',', array($iMainCacheTime, $iFilesCacheTime))))
|
||||||
|
|
@ -120,8 +110,7 @@ trait User
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bMainCache)
|
if ($bMainCache) {
|
||||||
{
|
|
||||||
$this->Logger()->Write('Cacher GC: Begin');
|
$this->Logger()->Write('Cacher GC: Begin');
|
||||||
$this->Cacher()->GC(48);
|
$this->Cacher()->GC(48);
|
||||||
$this->Logger()->Write('Cacher GC: End');
|
$this->Logger()->Write('Cacher GC: End');
|
||||||
|
|
@ -129,9 +118,7 @@ trait User
|
||||||
$this->Logger()->Write('Storage GC: Begin');
|
$this->Logger()->Write('Storage GC: Begin');
|
||||||
$this->StorageProvider()->GC();
|
$this->StorageProvider()->GC();
|
||||||
$this->Logger()->Write('Storage GC: End');
|
$this->Logger()->Write('Storage GC: End');
|
||||||
}
|
} else if ($bFilesCache) {
|
||||||
else if ($bFilesCache)
|
|
||||||
{
|
|
||||||
$this->Logger()->Write('Files GC: Begin');
|
$this->Logger()->Write('Files GC: Begin');
|
||||||
$this->FilesProvider()->GC(48);
|
$this->FilesProvider()->GC(48);
|
||||||
$this->Logger()->Write('Files GC: End');
|
$this->Logger()->Write('Files GC: End');
|
||||||
|
|
@ -152,29 +139,23 @@ trait User
|
||||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||||
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
|
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
|
||||||
|
|
||||||
if ($oConfig->Get('webmail', 'allow_languages_on_settings', true))
|
if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) {
|
||||||
{
|
|
||||||
$this->setSettingsFromParams($oSettings, 'Language', 'string', function ($sLanguage) use ($self) {
|
$this->setSettingsFromParams($oSettings, 'Language', 'string', function ($sLanguage) use ($self) {
|
||||||
return $self->ValidateLanguage($sLanguage);
|
return $self->ValidateLanguage($sLanguage);
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// $oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en')));
|
// $oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en')));
|
||||||
}
|
}
|
||||||
$this->setSettingsFromParams($oSettings, 'hourCycle', 'string');
|
$this->setSettingsFromParams($oSettings, 'hourCycle', 'string');
|
||||||
|
|
||||||
if ($this->GetCapa(Capa::THEMES))
|
if ($this->GetCapa(Capa::THEMES)) {
|
||||||
{
|
|
||||||
$this->setSettingsFromParams($oSettingsLocal, 'Theme', 'string', function ($sTheme) use ($self) {
|
$this->setSettingsFromParams($oSettingsLocal, 'Theme', 'string', function ($sTheme) use ($self) {
|
||||||
return $self->ValidateTheme($sTheme);
|
return $self->ValidateTheme($sTheme);
|
||||||
});
|
});
|
||||||
$this->setSettingsFromParams($oSettings, 'fontSansSerif', 'string');
|
$this->setSettingsFromParams($oSettings, 'fontSansSerif', 'string');
|
||||||
$this->setSettingsFromParams($oSettings, 'fontSerif', 'string');
|
$this->setSettingsFromParams($oSettings, 'fontSerif', 'string');
|
||||||
$this->setSettingsFromParams($oSettings, 'fontMono', 'string');
|
$this->setSettingsFromParams($oSettings, 'fontMono', 'string');
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// $oSettingsLocal->SetConf('Theme', $this->ValidateTheme($oConfig->Get('webmail', 'theme', 'Default')));
|
// $oSettingsLocal->SetConf('Theme', $this->ValidateTheme($oConfig->Get('webmail', 'theme', 'Default')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,8 +210,7 @@ trait User
|
||||||
{
|
{
|
||||||
$oAccount = $this->initMailClientConnection();
|
$oAccount = $this->initMailClientConnection();
|
||||||
|
|
||||||
if (!$this->GetCapa(Capa::QUOTA))
|
if (!$this->GetCapa(Capa::QUOTA)) {
|
||||||
{
|
|
||||||
return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0));
|
return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,34 +233,25 @@ trait User
|
||||||
$sQuery = \trim($this->GetActionParam('Query', ''));
|
$sQuery = \trim($this->GetActionParam('Query', ''));
|
||||||
$iLimit = (int) $this->Config()->Get('contacts', 'suggestions_limit', 20);
|
$iLimit = (int) $this->Config()->Get('contacts', 'suggestions_limit', 20);
|
||||||
|
|
||||||
$aResult = array();
|
|
||||||
|
|
||||||
$this->Plugins()->RunHook('json.suggestions-input-parameters', array(&$sQuery, &$iLimit, $oAccount));
|
$this->Plugins()->RunHook('json.suggestions-input-parameters', array(&$sQuery, &$iLimit, $oAccount));
|
||||||
|
|
||||||
$iLimit = (int) $iLimit;
|
$iLimit = \max(5, (int) $iLimit);
|
||||||
if (5 > $iLimit)
|
|
||||||
{
|
|
||||||
$iLimit = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->Plugins()->RunHook('json.suggestions-pre', array(&$aResult, $sQuery, $oAccount, $iLimit));
|
$aResult = array();
|
||||||
|
|
||||||
if ($iLimit > \count($aResult) && \strlen($sQuery))
|
if (\strlen($sQuery)) {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Address Book
|
// Address Book
|
||||||
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
||||||
if ($oAddressBookProvider && $oAddressBookProvider->IsActive())
|
if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) {
|
||||||
{
|
|
||||||
$aSuggestions = $oAddressBookProvider->GetSuggestions($sQuery, $iLimit);
|
$aSuggestions = $oAddressBookProvider->GetSuggestions($sQuery, $iLimit);
|
||||||
if (!\count($aResult))
|
foreach ($aSuggestions as $aItem) {
|
||||||
{
|
// Unique email address
|
||||||
$aResult = $aSuggestions;
|
$sLine = \mb_strtolower($aItem[0]);
|
||||||
|
if (!isset($aResult[$sLine])) {
|
||||||
|
$aResult[$sLine] = $aItem;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$aResult = \array_merge($aResult, $aSuggestions);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -288,34 +259,20 @@ trait User
|
||||||
{
|
{
|
||||||
$this->Logger()->WriteException($oException);
|
$this->Logger()->WriteException($oException);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($iLimit > \count($aResult) && \strlen($sQuery))
|
if ($iLimit > \count($aResult)) {
|
||||||
{
|
|
||||||
$oSuggestionsProvider = $this->SuggestionsProvider();
|
$oSuggestionsProvider = $this->SuggestionsProvider();
|
||||||
if ($oSuggestionsProvider && $oSuggestionsProvider->IsActive())
|
if ($oSuggestionsProvider && $oSuggestionsProvider->IsActive()) {
|
||||||
{
|
$aSuggestions = $oSuggestionsProvider->Process($oAccount, $sQuery, $iLimit);
|
||||||
$aSuggestionsProviderResult = $oSuggestionsProvider->Process($oAccount, $sQuery, $iLimit);
|
foreach ($aSuggestions as $sLine => $aItem) {
|
||||||
if (\is_array($aSuggestionsProviderResult) && \count($aSuggestionsProviderResult))
|
if (!isset($aResult[$sLine])) {
|
||||||
{
|
$aResult[$sLine] = $aItem;
|
||||||
$aResult = \array_merge($aResult, $aSuggestionsProviderResult);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
$aResult = \array_slice(\array_values($aResult), 0, $iLimit);
|
||||||
|
|
||||||
$aResult = Utils::RemoveSuggestionDuplicates($aResult);
|
|
||||||
if ($iLimit < \count($aResult))
|
|
||||||
{
|
|
||||||
$aResult = \array_slice($aResult, 0, $iLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->Plugins()->RunHook('json.suggestions-post', array(&$aResult, $sQuery, $oAccount, $iLimit));
|
|
||||||
|
|
||||||
$aResult = Utils::RemoveSuggestionDuplicates($aResult);
|
|
||||||
if ($iLimit < \count($aResult))
|
|
||||||
{
|
|
||||||
$aResult = \array_slice($aResult, 0, $iLimit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->DefaultResponse(__FUNCTION__, $aResult);
|
return $this->DefaultResponse(__FUNCTION__, $aResult);
|
||||||
|
|
@ -325,14 +282,12 @@ trait User
|
||||||
{
|
{
|
||||||
$oAccount = $this->getAccountFromToken();
|
$oAccount = $this->getAccountFromToken();
|
||||||
|
|
||||||
if (!$this->GetCapa(Capa::USER_BACKGROUND))
|
if (!$this->GetCapa(Capa::USER_BACKGROUND)) {
|
||||||
{
|
|
||||||
return $this->FalseResponse(__FUNCTION__);
|
return $this->FalseResponse(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||||
if ($oAccount && $oSettings)
|
if ($oAccount && $oSettings) {
|
||||||
{
|
|
||||||
$this->StorageProvider()->Clear($oAccount,
|
$this->StorageProvider()->Clear($oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||||
'background'
|
'background'
|
||||||
|
|
@ -348,8 +303,7 @@ trait User
|
||||||
|
|
||||||
private function setSettingsFromParams(\RainLoop\Settings $oSettings, string $sConfigName, string $sType = 'string', ?callable $cCallback = null) : void
|
private function setSettingsFromParams(\RainLoop\Settings $oSettings, string $sConfigName, string $sType = 'string', ?callable $cCallback = null) : void
|
||||||
{
|
{
|
||||||
if ($this->HasActionParam($sConfigName))
|
if ($this->HasActionParam($sConfigName)) {
|
||||||
{
|
|
||||||
$sValue = $this->GetActionParam($sConfigName, '');
|
$sValue = $this->GetActionParam($sConfigName, '');
|
||||||
switch ($sType)
|
switch ($sType)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,14 @@ class Suggestions extends \RainLoop\Providers\AbstractProvider
|
||||||
/**
|
/**
|
||||||
* @var \RainLoop\Providers\Suggestions\ISuggestions[]
|
* @var \RainLoop\Providers\Suggestions\ISuggestions[]
|
||||||
*/
|
*/
|
||||||
private $aDrivers;
|
private ?array $aDrivers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \RainLoop\Providers\Suggestions\ISuggestions[]|null $aDriver = null
|
* @param \RainLoop\Providers\Suggestions\ISuggestions[]|null $aDriver = null
|
||||||
*/
|
*/
|
||||||
public function __construct(?array $aDriver = null)
|
public function __construct(?array $aDriver = null)
|
||||||
{
|
{
|
||||||
if (\is_array($aDriver))
|
if (\is_array($aDriver)) {
|
||||||
{
|
|
||||||
$aDriver = \array_filter($aDriver, function ($oDriver) {
|
$aDriver = \array_filter($aDriver, function ($oDriver) {
|
||||||
return $oDriver instanceof \RainLoop\Providers\Suggestions\ISuggestions;
|
return $oDriver instanceof \RainLoop\Providers\Suggestions\ISuggestions;
|
||||||
});
|
});
|
||||||
|
|
@ -26,31 +25,30 @@ class Suggestions extends \RainLoop\Providers\AbstractProvider
|
||||||
|
|
||||||
public function Process(\RainLoop\Model\Account $oAccount, string $sQuery, int $iLimit = 20) : array
|
public function Process(\RainLoop\Model\Account $oAccount, string $sQuery, int $iLimit = 20) : array
|
||||||
{
|
{
|
||||||
$aSuggestions = array();
|
$aResult = array();
|
||||||
if ($this->IsActive() && \is_array($this->aDrivers) && \strlen($sQuery))
|
if (\strlen($sQuery) && $this->IsActive()) {
|
||||||
{
|
foreach ($this->aDrivers as $oDriver) {
|
||||||
foreach ($this->aDrivers as $oDriver)
|
if ($oDriver) try {
|
||||||
{
|
|
||||||
$aSubs = null;
|
|
||||||
if ($oDriver)
|
|
||||||
{
|
|
||||||
$aSubs = $oDriver->Process($oAccount, $sQuery, $iLimit);
|
$aSubs = $oDriver->Process($oAccount, $sQuery, $iLimit);
|
||||||
if (\is_array($aSubs) && \count($aSubs))
|
if ($aSubs) {
|
||||||
{
|
foreach ($aSubs as $aItem) {
|
||||||
$aSuggestions = \array_merge($aSuggestions, $aSubs);
|
// Unique email address
|
||||||
|
$sLine = \mb_strtolower($aItem[0]);
|
||||||
|
if (!isset($aResult[$sLine])) {
|
||||||
|
$aResult[$sLine] = $aItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($iLimit < \count($aResult)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Throwable $oException) {
|
||||||
|
$this->oLogger && $this->oLogger->WriteException($oException);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aResult = \RainLoop\Utils::RemoveSuggestionDuplicates($aSuggestions);
|
return \array_slice($aResult, 0, $iLimit);
|
||||||
|
|
||||||
if ($iLimit < \count($aResult))
|
|
||||||
{
|
|
||||||
$aResult = \array_slice($aResult, 0, $iLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $aResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsActive() : bool
|
public function IsActive() : bool
|
||||||
|
|
|
||||||
|
|
@ -251,22 +251,6 @@ class Utils
|
||||||
return self::WebVersionPath() . 'static/' . $path;
|
return self::WebVersionPath() . 'static/' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function RemoveSuggestionDuplicates(array $aSuggestions) : array
|
|
||||||
{
|
|
||||||
$aResult = array();
|
|
||||||
|
|
||||||
foreach ($aSuggestions as $aItem)
|
|
||||||
{
|
|
||||||
$sLine = \implode('~~', $aItem);
|
|
||||||
if (!isset($aResult[$sLine]))
|
|
||||||
{
|
|
||||||
$aResult[$sLine] = $aItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_values($aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function inOpenBasedir(string $name) : string
|
public static function inOpenBasedir(string $name) : string
|
||||||
{
|
{
|
||||||
static $open_basedir;
|
static $open_basedir;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue