mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-08 22:18:28 +03:00
Added: Sync contacts tags
Fixed: IMAP search
This commit is contained in:
parent
e88c41c90a
commit
79e686f412
14 changed files with 28963 additions and 29048 deletions
|
|
@ -9,7 +9,7 @@ ko.bindingHandlers.tooltip = {
|
|||
sClass = $oEl.data('tooltip-class') || '',
|
||||
sPlacement = $oEl.data('tooltip-placement') || 'top'
|
||||
;
|
||||
|
||||
|
||||
$oEl.tooltip({
|
||||
'delay': {
|
||||
'show': 500,
|
||||
|
|
@ -826,4 +826,3 @@ ko.observable.fn.validateFunc = function (fFunc)
|
|||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1742,4 +1742,4 @@ Utils.detectDropdownVisibility = _.debounce(function () {
|
|||
Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) {
|
||||
return oItem.hasClass('open');
|
||||
}));
|
||||
}, 50);
|
||||
}, 50);
|
||||
|
|
|
|||
|
|
@ -735,8 +735,9 @@ PopupsContactsViewModel.prototype.onHide = function ()
|
|||
this.currentContact(null);
|
||||
this.emptySelection(true);
|
||||
this.search('');
|
||||
|
||||
_.each(this.contacts(), function (oItem) {
|
||||
oItem.checked(false);
|
||||
});
|
||||
this.contactsCount(0);
|
||||
this.contacts([]);
|
||||
// _.each(this.contacts(), function (oItem) {
|
||||
// oItem.checked(false);
|
||||
// });
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace MailSo\Imap;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Imap
|
||||
*/
|
||||
class SearchBuilder
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aList;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
*/
|
||||
public static function NewInstance()
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
*/
|
||||
public function Clear()
|
||||
{
|
||||
$this->aList = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sValue = ''
|
||||
*
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
*/
|
||||
public function AddAnd($sName, $sValue = '')
|
||||
{
|
||||
return $this->addCri('AND', $sName, $sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sValue = ''
|
||||
*
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
*/
|
||||
public function AddOr($sName, $sValue = '')
|
||||
{
|
||||
return $this->addCri('OR', $sName, $sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Complete()
|
||||
{
|
||||
$sResult = '';
|
||||
foreach ($this->aList as $iIndex => $aItem)
|
||||
{
|
||||
$sResult = trim((0 < $iIndex && 'OR' === $aItem[0] ? $aItem[0] : '').
|
||||
(0 === strlen($sResult) ? '' : ' ('.$sResult.')').' '.$aItem[1].
|
||||
(0 < strlen($aItem[2]) ? ' '.$aItem[2] : ''));
|
||||
}
|
||||
|
||||
if (0 === strlen($sResult))
|
||||
{
|
||||
$sResult = 'ALL';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->Complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
* @param string $sName
|
||||
* @param string $sValue = ''
|
||||
*
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
*/
|
||||
private function addCri($sType, $sName, $sValue = '')
|
||||
{
|
||||
$this->aList[] = array($sType, $sName, $sValue);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
@ -1058,11 +1058,11 @@ class MailClient
|
|||
* @param string $sSearch
|
||||
* @param int $iTimeZoneOffset = 0
|
||||
*
|
||||
* @return \MailSo\Imap\SearchBuilder
|
||||
* @return string
|
||||
*/
|
||||
private function getSearchBuilder($sSearch, $iTimeZoneOffset = 0)
|
||||
private function getImapSearchCriterias($sSearch, $iTimeZoneOffset = 0)
|
||||
{
|
||||
$oSearchBuilder = \MailSo\Imap\SearchBuilder::NewInstance();
|
||||
$aCriteriasResult = array();
|
||||
if (0 < \strlen(\trim($sSearch)))
|
||||
{
|
||||
$sGmailRawSearch = '';
|
||||
|
|
@ -1077,10 +1077,15 @@ class MailClient
|
|||
{
|
||||
$sValue = $this->escapeSearchString($aLines['OTHER']);
|
||||
|
||||
$oSearchBuilder->AddOr('FROM', $sValue);
|
||||
$oSearchBuilder->AddOr('TO', $sValue);
|
||||
$oSearchBuilder->AddOr('CC', $sValue);
|
||||
$oSearchBuilder->AddOr('SUBJECT', $sValue);
|
||||
$aCriteriasResult[] = 'OR OR OR';
|
||||
$aCriteriasResult[] = 'FROM';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'TO';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'CC';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'SUBJECT';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1101,9 +1106,14 @@ class MailClient
|
|||
{
|
||||
$sValue = $this->escapeSearchString($aLines['EMAIL']);
|
||||
|
||||
$oSearchBuilder->AddOr('FROM', $sValue);
|
||||
$oSearchBuilder->AddOr('TO', $sValue);
|
||||
$oSearchBuilder->AddOr('CC', $sValue);
|
||||
$aCriteriasResult[] = 'OR OR';
|
||||
$aCriteriasResult[] = 'FROM';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'TO';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'CC';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
|
||||
unset($aLines['EMAIL']);
|
||||
}
|
||||
|
||||
|
|
@ -1111,8 +1121,12 @@ class MailClient
|
|||
{
|
||||
$sValue = $this->escapeSearchString($aLines['TO']);
|
||||
|
||||
$oSearchBuilder->AddAnd('TO', $this->escapeSearchString($aLines['TO']));
|
||||
$oSearchBuilder->AddOr('CC', $this->escapeSearchString($aLines['TO']));
|
||||
$aCriteriasResult[] = 'OR';
|
||||
$aCriteriasResult[] = 'TO';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
$aCriteriasResult[] = 'CC';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
|
||||
unset($aLines['TO']);
|
||||
}
|
||||
|
||||
|
|
@ -1128,10 +1142,12 @@ class MailClient
|
|||
switch ($sName)
|
||||
{
|
||||
case 'FROM':
|
||||
$oSearchBuilder->AddAnd('FROM', $sValue);
|
||||
$aCriteriasResult[] = 'FROM';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
break;
|
||||
case 'SUBJECT':
|
||||
$oSearchBuilder->AddAnd('SUBJECT', $sValue);
|
||||
$aCriteriasResult[] = 'SUBJECT';
|
||||
$aCriteriasResult[] = $sValue;
|
||||
break;
|
||||
case 'OTHER':
|
||||
case 'TEXT':
|
||||
|
|
@ -1151,7 +1167,11 @@ class MailClient
|
|||
else
|
||||
{
|
||||
// Simple, is not detailed search (Sometimes doesn't work)
|
||||
$oSearchBuilder->AddAnd('HEADER CONTENT-TYPE', '"MULTIPART/MIXED"');
|
||||
$aCriteriasResult[] = 'OR OR OR';
|
||||
$aCriteriasResult[] = 'HEADER Content-Type application/';
|
||||
$aCriteriasResult[] = 'HEADER Content-Type multipart/m';
|
||||
$aCriteriasResult[] = 'HEADER Content-Type multipart/signed';
|
||||
$aCriteriasResult[] = 'HEADER Content-Type multipart/report';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1163,30 +1183,32 @@ class MailClient
|
|||
$aCompareArray2 = array('unflag', 'unflagged', 'unstar', 'unstarred', 'unpinned');
|
||||
if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue)))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('FLAGGED');
|
||||
$aCriteriasResult[] = 'FLAGGED';
|
||||
}
|
||||
else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue)))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('UNFLAGGED');
|
||||
$aCriteriasResult[] = 'UNFLAGGED';
|
||||
}
|
||||
|
||||
$aCompareArray = array('unread', 'unseen');
|
||||
$aCompareArray2 = array('read', 'seen');
|
||||
if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue)))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('UNSEEN');
|
||||
$aCriteriasResult[] = 'UNSEEN';
|
||||
}
|
||||
else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue)))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('SEEN');
|
||||
$aCriteriasResult[] = 'SEEN';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'LARGER':
|
||||
$oSearchBuilder->AddAnd('LARGER', $this->parseFriendlySize($sRawValue));
|
||||
$aCriteriasResult[] = 'LARGER';
|
||||
$aCriteriasResult[] = $this->parseFriendlySize($sRawValue);
|
||||
break;
|
||||
case 'SMALLER':
|
||||
$oSearchBuilder->AddAnd('SMALLER', $this->parseFriendlySize($sRawValue));
|
||||
$aCriteriasResult[] = 'SMALLER';
|
||||
$aCriteriasResult[] = $this->parseFriendlySize($sRawValue);
|
||||
break;
|
||||
case 'DATE':
|
||||
$iDateStampFrom = $iDateStampTo = 0;
|
||||
|
|
@ -1218,12 +1240,14 @@ class MailClient
|
|||
|
||||
if (0 < $iDateStampFrom)
|
||||
{
|
||||
$oSearchBuilder->AddAnd('SINCE', \gmdate('j-M-Y', $iDateStampFrom));
|
||||
$aCriteriasResult[] = 'SINCE';
|
||||
$aCriteriasResult[] = \gmdate('j-M-Y', $iDateStampFrom);
|
||||
}
|
||||
|
||||
if (0 < $iDateStampTo)
|
||||
{
|
||||
$oSearchBuilder->AddAnd('BEFORE', \gmdate('j-M-Y', $iDateStampTo));
|
||||
$aCriteriasResult[] = 'BEFORE';
|
||||
$aCriteriasResult[] = \gmdate('j-M-Y', $iDateStampTo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1246,17 +1270,25 @@ class MailClient
|
|||
$sGmailRawSearch = \trim($sGmailRawSearch);
|
||||
if ($bIsGmail && 0 < \strlen($sGmailRawSearch))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('X-GM-RAW', $this->escapeSearchString($sGmailRawSearch, false));
|
||||
$aCriteriasResult[] = 'X-GM-RAW';
|
||||
$aCriteriasResult[] = $this->escapeSearchString($sGmailRawSearch, false);
|
||||
}
|
||||
|
||||
$sResultBodyTextSearch = \trim($sResultBodyTextSearch);
|
||||
if (0 < \strlen($sResultBodyTextSearch))
|
||||
{
|
||||
$oSearchBuilder->AddAnd('TEXT', $this->escapeSearchString($sResultBodyTextSearch));
|
||||
$aCriteriasResult[] = 'TEXT';
|
||||
$aCriteriasResult[] = $this->escapeSearchString($sResultBodyTextSearch);
|
||||
}
|
||||
}
|
||||
|
||||
return $oSearchBuilder;
|
||||
$sCriteriasResult = \trim(\implode(' ', $aCriteriasResult));
|
||||
if ('' === $sCriteriasResult)
|
||||
{
|
||||
$sCriteriasResult = 'ALL';
|
||||
}
|
||||
|
||||
return $sCriteriasResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1594,7 +1626,7 @@ class MailClient
|
|||
$bIndexAsUid = true;
|
||||
$aIndexOrUids = null;
|
||||
|
||||
$sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete();
|
||||
$sSearchCriterias = $this->getImapSearchCriterias($sSearch);
|
||||
|
||||
if ($iMessageCacheCount < $iMessageRealCount && $oCacher && $oCacher->IsInited())
|
||||
{
|
||||
|
|
@ -1835,11 +1867,8 @@ class MailClient
|
|||
|
||||
$this->oImapClient->FolderExamine($sFolderName);
|
||||
|
||||
$sSearchCriterias = \MailSo\Imap\SearchBuilder::NewInstance()
|
||||
->AddAnd('HEADER MESSAGE-ID', $sMessageId)
|
||||
->Complete();
|
||||
|
||||
$aUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true);
|
||||
$aUids = $this->oImapClient->MessageSimpleSearch(
|
||||
'HEADER Message-ID '.$sMessageId, true);
|
||||
|
||||
return \is_array($aUids) && 1 === \count($aUids) && \is_numeric($aUids[0]) ? (int) $aUids[0] : null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ final class Version
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
const APP_VERSION = '1.3.2';
|
||||
const APP_VERSION = '1.3.3';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
|
|
|||
|
|
@ -5011,25 +5011,6 @@ class Actions
|
|||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function DoContactTags()
|
||||
{
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$mResult = false;
|
||||
if ($this->AddressBookProvider($oAccount)->IsActive())
|
||||
{
|
||||
$mResult = $this->AddressBookProvider($oAccount)->GetContactTags($oAccount->ParentEmailHelper());
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, array(
|
||||
'List' => $mResult
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -125,12 +125,13 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider
|
|||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param bool $bCache = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContactTags($sEmail)
|
||||
public function GetContactTags($sEmail, $bCache = true)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->GetContactTags($sEmail) : array();
|
||||
return $this->IsActive() ? $this->oDriver->GetContactTags($sEmail, $bCache) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,58 +8,4 @@ interface AddressBookInterface
|
|||
* @return bool
|
||||
*/
|
||||
public function IsSupported();
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param \RainLoop\Providers\AddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ContactSave($sEmail, &$oContact);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aContactIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteContacts($sEmail, $aContactIds);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aTagsIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTags($sEmail, $aTagsIds);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
* @param int $iResultCount = 0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContacts($sEmail, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sSearch
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function GetSuggestions($sEmail, $sSearch, $iLimit = 20);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aEmails
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncFrec($sEmail, $aEmails);
|
||||
}
|
||||
|
|
@ -149,6 +149,8 @@ class Contact
|
|||
{
|
||||
$this->Properties[] = new \RainLoop\Providers\AddressBook\Classes\Property(PropertyType::FULLNAME, $this->Display);
|
||||
}
|
||||
|
||||
$this->Tags = \array_map('trim', $this->Tags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,7 +211,7 @@ class Contact
|
|||
$oVCard->VERSION = '3.0';
|
||||
$oVCard->PRODID = '-//RainLoop//'.APP_VERSION.'//EN';
|
||||
|
||||
unset($oVCard->FN, $oVCard->EMAIL, $oVCard->TEL, $oVCard->URL);
|
||||
unset($oVCard->FN, $oVCard->EMAIL, $oVCard->TEL, $oVCard->URL, $oVCard->{'X-RL-TAGS'});
|
||||
|
||||
$sFirstName = $sLastName = $sMiddleName = $sSuffix = $sPrefix = '';
|
||||
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty)
|
||||
|
|
@ -270,6 +272,11 @@ class Contact
|
|||
$oVCard->N = array($sLastName, $sFirstName, $sMiddleName, $sPrefix, $sSuffix);
|
||||
$oVCard->REV = \gmdate('Ymd', $this->Changed).'T'.\gmdate('His', $this->Changed).'Z';
|
||||
|
||||
if (0 < \count($this->Tags))
|
||||
{
|
||||
$oVCard->{'X-RL-TAGS'} = \implode(';', $this->Tags);
|
||||
}
|
||||
|
||||
return (string) $oVCard->serialize();
|
||||
}
|
||||
|
||||
|
|
@ -582,6 +589,12 @@ class Contact
|
|||
}
|
||||
|
||||
$this->Properties = $aProperties;
|
||||
|
||||
if (isset($oVCard->{'X-RL-TAGS'}) && 0 < \strlen($oVCard->{'X-RL-TAGS'}))
|
||||
{
|
||||
$this->Tags = \explode(';', $oVCard->{'X-RL-TAGS'});
|
||||
$this->Tags = \array_map('trim', $this->Tags);
|
||||
}
|
||||
}
|
||||
|
||||
$this->UpdateDependentValues();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ class PdoAddressBook
|
|||
*/
|
||||
private $sPassword;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aTagsCache;
|
||||
|
||||
public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql')
|
||||
{
|
||||
$this->sDsn = $sDsn;
|
||||
|
|
@ -36,6 +41,7 @@ class PdoAddressBook
|
|||
$this->sDsnType = $sDsnType;
|
||||
|
||||
$this->bExplain = false; // debug
|
||||
$this->aTagsCache = array(); // debug
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -174,7 +180,7 @@ class PdoAddressBook
|
|||
$oResponse = 'PUT' === $sCmd && null !== $mData ?
|
||||
$oClient->request($sCmd, $sUrl, $mData) : $oClient->request($sCmd, $sUrl);
|
||||
|
||||
if ('GET' === $sCmd || false)
|
||||
if ('GET' === $sCmd && false)
|
||||
{
|
||||
$this->oLogger->WriteDump($oResponse, \MailSo\Log\Enumerations\Type::INFO, 'DAV');
|
||||
}
|
||||
|
|
@ -523,11 +529,14 @@ class PdoAddressBook
|
|||
);
|
||||
}
|
||||
|
||||
$sSql = 'INSERT INTO rainloop_ab_properties '.
|
||||
'( id_contact, id_user, prop_type, prop_type_str, prop_value, prop_value_custom, prop_frec) VALUES '.
|
||||
'(:id_contact, :id_user, :prop_type, :prop_type_str, :prop_value, :prop_value_custom, :prop_frec)';
|
||||
if (0 < \count($aParams))
|
||||
{
|
||||
$sSql = 'INSERT INTO rainloop_ab_properties '.
|
||||
'( id_contact, id_user, prop_type, prop_type_str, prop_value, prop_value_custom, prop_frec) VALUES '.
|
||||
'(:id_contact, :id_user, :prop_type, :prop_type_str, :prop_value, :prop_value_custom, :prop_frec)';
|
||||
|
||||
$this->prepareAndExecute($sSql, $aParams, true);
|
||||
$this->prepareAndExecute($sSql, $aParams, true);
|
||||
}
|
||||
|
||||
$aTags = array();
|
||||
$aContactTags = $this->GetContactTags($sEmail);
|
||||
|
|
@ -564,8 +573,11 @@ class PdoAddressBook
|
|||
}
|
||||
}
|
||||
|
||||
$sSql = 'INSERT INTO rainloop_ab_tags_contacts (id_tag, id_contact) VALUES (:id_tag, :id_contact)';
|
||||
$this->prepareAndExecute($sSql, $aTags, true);
|
||||
if (0 < \count($aTags))
|
||||
{
|
||||
$sSql = 'INSERT INTO rainloop_ab_tags_contacts (id_tag, id_contact) VALUES (:id_tag, :id_contact)';
|
||||
$this->prepareAndExecute($sSql, $aTags, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
|
|
@ -602,6 +614,8 @@ class PdoAddressBook
|
|||
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$this->aTagsCache = array();
|
||||
|
||||
$mResult = false;
|
||||
try
|
||||
{
|
||||
|
|
@ -707,6 +721,8 @@ class PdoAddressBook
|
|||
return false;
|
||||
}
|
||||
|
||||
$this->aTagsCache = array();
|
||||
|
||||
$sIDs = \implode(',', $aTagsIds);
|
||||
$aParams = array(':id_user' => array($iUserID, \PDO::PARAM_INT));
|
||||
|
||||
|
|
@ -716,6 +732,99 @@ class PdoAddressBook
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array|\RainLoop\Providers\AddressBook\Classes\Contact $mContactOrContacts
|
||||
*/
|
||||
private function populateContactsByTags($sEmail, &$mContactOrContacts)
|
||||
{
|
||||
$aContacts = array();
|
||||
if ($mContactOrContacts)
|
||||
{
|
||||
$aContacts = is_array($mContactOrContacts) ? $mContactOrContacts : array(&$mContactOrContacts);
|
||||
}
|
||||
|
||||
if (\is_array($aContacts) && 0 < \count($aContacts))
|
||||
{
|
||||
$aIdContacts = array();
|
||||
$aIdTagsContacts = array();
|
||||
|
||||
$aTags = $this->GetContactTags($sEmail);
|
||||
|
||||
if (\is_array($aTags) && 0 < \count($aTags))
|
||||
{
|
||||
foreach ($aContacts as $oItem)
|
||||
{
|
||||
$aIdContacts[$oItem->IdContact] = true;
|
||||
}
|
||||
|
||||
if (0 < \count($aIdContacts))
|
||||
{
|
||||
$sSql = 'SELECT id_tag, id_contact FROM rainloop_ab_tags_contacts WHERE id_contact IN ('.\implode(',', \array_keys($aIdContacts)).')';
|
||||
$oStmt = $this->prepareAndExecute($sSql);
|
||||
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
if ($aItem && isset($aItem['id_tag'], $aItem['id_contact']))
|
||||
{
|
||||
$sID = (string) $aItem['id_contact'];
|
||||
if (!isset($aIdTagsContacts[$sID]))
|
||||
{
|
||||
$aIdTagsContacts[$sID] = array();
|
||||
}
|
||||
|
||||
$aIdTagsContacts[$sID][] = (string) $aItem['id_tag'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
}
|
||||
|
||||
if (0 < \count($aIdTagsContacts))
|
||||
{
|
||||
$fFindFunc = function ($sID) use ($aTags) {
|
||||
|
||||
foreach ($aTags as $oItem)
|
||||
{
|
||||
if ($oItem && (string) $oItem->IdContactTag === $sID)
|
||||
{
|
||||
return\trim($oItem->Name);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
foreach ($aContacts as &$oItem)
|
||||
{
|
||||
$sID = $oItem ? (string) $oItem->IdContact : '';
|
||||
if (0 < \strlen($sID) && isset($aIdTagsContacts[$sID]) && \is_array($aIdTagsContacts[$sID]))
|
||||
{
|
||||
$aNames = array();
|
||||
foreach ($aIdTagsContacts[$sID] as $sSubID)
|
||||
{
|
||||
$sName = $fFindFunc($sSubID);
|
||||
if (0 < \strlen($sName))
|
||||
{
|
||||
$aNames[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
$oItem->Tags = $aNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param int $iOffset = 0
|
||||
|
|
@ -908,95 +1017,23 @@ class PdoAddressBook
|
|||
}
|
||||
}
|
||||
|
||||
if (\is_array($aResult) && 0 < \count($aResult))
|
||||
{
|
||||
$aIdContacts = array();
|
||||
$aIdTagsContacts = array();
|
||||
$aTags = $this->GetContactTags($sEmail);
|
||||
|
||||
if (\is_array($aTags) && 0 < \count($aTags))
|
||||
{
|
||||
foreach ($aResult as $oItem)
|
||||
{
|
||||
$aIdContacts[$oItem->IdContact] = true;
|
||||
}
|
||||
|
||||
if (0 < \count($aIdContacts))
|
||||
{
|
||||
$sSql = 'SELECT id_tag, id_contact FROM rainloop_ab_tags_contacts WHERE id_contact IN ('.\implode(',', \array_keys($aIdContacts)).')';
|
||||
$oStmt = $this->prepareAndExecute($sSql);
|
||||
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
if ($aItem && isset($aItem['id_tag'], $aItem['id_contact']))
|
||||
{
|
||||
$sID = (string) $aItem['id_contact'];
|
||||
if (!isset($aIdTagsContacts[$sID]))
|
||||
{
|
||||
$aIdTagsContacts[$sID] = array();
|
||||
}
|
||||
|
||||
$aIdTagsContacts[$sID][] = (string) $aItem['id_tag'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
}
|
||||
|
||||
if (0 < \count($aIdTagsContacts))
|
||||
{
|
||||
$fFindFunc = function ($sID) use ($aTags) {
|
||||
|
||||
foreach ($aTags as $oItem)
|
||||
{
|
||||
if ($oItem && (string) $oItem->IdContactTag === $sID)
|
||||
{
|
||||
return\trim($oItem->Name);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
foreach ($aResult as &$oItem)
|
||||
{
|
||||
$sID = $oItem ? (string) $oItem->IdContact : '';
|
||||
if (0 < \strlen($sID) && isset($aIdTagsContacts[$sID]) && \is_array($aIdTagsContacts[$sID]))
|
||||
{
|
||||
$aNames = array();
|
||||
foreach ($aIdTagsContacts[$sID] as $sSubID)
|
||||
{
|
||||
$sName = $fFindFunc($sSubID);
|
||||
if (0 < \strlen($sName))
|
||||
{
|
||||
$aNames[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
$oItem->Tags = $aNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->populateContactsByTags($sEmail, $aResult);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param bool $bCache = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContactTags($sEmail)
|
||||
public function GetContactTags($sEmail, $bCache = true)
|
||||
{
|
||||
if ($bCache && isset($this->aTagsCache[$sEmail]))
|
||||
{
|
||||
return $this->aTagsCache[$sEmail];
|
||||
}
|
||||
|
||||
$this->SyncDatabase();
|
||||
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
|
@ -1031,6 +1068,11 @@ class PdoAddressBook
|
|||
}
|
||||
}
|
||||
|
||||
if ($bCache)
|
||||
{
|
||||
$this->aTagsCache[$sEmail] = $aResult;
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
|
|
@ -1133,6 +1175,11 @@ class PdoAddressBook
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($oContact)
|
||||
{
|
||||
$this->populateContactsByTags($sEmail, $oContact);
|
||||
}
|
||||
|
||||
return $oContact;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
20
rainloop/v/0.0.0/static/js/app.min.js
vendored
20
rainloop/v/0.0.0/static/js/app.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue