Added: Sync contacts tags

Fixed: IMAP search
This commit is contained in:
RainLoop Team 2014-05-14 19:58:04 +04:00
parent e88c41c90a
commit 79e686f412
14 changed files with 28963 additions and 29048 deletions

View file

@ -826,4 +826,3 @@ ko.observable.fn.validateFunc = function (fFunc)
return this; return this;
}; };

View file

@ -735,8 +735,9 @@ PopupsContactsViewModel.prototype.onHide = function ()
this.currentContact(null); this.currentContact(null);
this.emptySelection(true); this.emptySelection(true);
this.search(''); this.search('');
this.contactsCount(0);
_.each(this.contacts(), function (oItem) { this.contacts([]);
oItem.checked(false); // _.each(this.contacts(), function (oItem) {
}); // oItem.checked(false);
// });
}; };

View file

@ -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;
}
}

View file

@ -1058,11 +1058,11 @@ class MailClient
* @param string $sSearch * @param string $sSearch
* @param int $iTimeZoneOffset = 0 * @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))) if (0 < \strlen(\trim($sSearch)))
{ {
$sGmailRawSearch = ''; $sGmailRawSearch = '';
@ -1077,10 +1077,15 @@ class MailClient
{ {
$sValue = $this->escapeSearchString($aLines['OTHER']); $sValue = $this->escapeSearchString($aLines['OTHER']);
$oSearchBuilder->AddOr('FROM', $sValue); $aCriteriasResult[] = 'OR OR OR';
$oSearchBuilder->AddOr('TO', $sValue); $aCriteriasResult[] = 'FROM';
$oSearchBuilder->AddOr('CC', $sValue); $aCriteriasResult[] = $sValue;
$oSearchBuilder->AddOr('SUBJECT', $sValue); $aCriteriasResult[] = 'TO';
$aCriteriasResult[] = $sValue;
$aCriteriasResult[] = 'CC';
$aCriteriasResult[] = $sValue;
$aCriteriasResult[] = 'SUBJECT';
$aCriteriasResult[] = $sValue;
} }
else else
{ {
@ -1101,9 +1106,14 @@ class MailClient
{ {
$sValue = $this->escapeSearchString($aLines['EMAIL']); $sValue = $this->escapeSearchString($aLines['EMAIL']);
$oSearchBuilder->AddOr('FROM', $sValue); $aCriteriasResult[] = 'OR OR';
$oSearchBuilder->AddOr('TO', $sValue); $aCriteriasResult[] = 'FROM';
$oSearchBuilder->AddOr('CC', $sValue); $aCriteriasResult[] = $sValue;
$aCriteriasResult[] = 'TO';
$aCriteriasResult[] = $sValue;
$aCriteriasResult[] = 'CC';
$aCriteriasResult[] = $sValue;
unset($aLines['EMAIL']); unset($aLines['EMAIL']);
} }
@ -1111,8 +1121,12 @@ class MailClient
{ {
$sValue = $this->escapeSearchString($aLines['TO']); $sValue = $this->escapeSearchString($aLines['TO']);
$oSearchBuilder->AddAnd('TO', $this->escapeSearchString($aLines['TO'])); $aCriteriasResult[] = 'OR';
$oSearchBuilder->AddOr('CC', $this->escapeSearchString($aLines['TO'])); $aCriteriasResult[] = 'TO';
$aCriteriasResult[] = $sValue;
$aCriteriasResult[] = 'CC';
$aCriteriasResult[] = $sValue;
unset($aLines['TO']); unset($aLines['TO']);
} }
@ -1128,10 +1142,12 @@ class MailClient
switch ($sName) switch ($sName)
{ {
case 'FROM': case 'FROM':
$oSearchBuilder->AddAnd('FROM', $sValue); $aCriteriasResult[] = 'FROM';
$aCriteriasResult[] = $sValue;
break; break;
case 'SUBJECT': case 'SUBJECT':
$oSearchBuilder->AddAnd('SUBJECT', $sValue); $aCriteriasResult[] = 'SUBJECT';
$aCriteriasResult[] = $sValue;
break; break;
case 'OTHER': case 'OTHER':
case 'TEXT': case 'TEXT':
@ -1151,7 +1167,11 @@ class MailClient
else else
{ {
// Simple, is not detailed search (Sometimes doesn't work) // 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'); $aCompareArray2 = array('unflag', 'unflagged', 'unstar', 'unstarred', 'unpinned');
if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue))) if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue)))
{ {
$oSearchBuilder->AddAnd('FLAGGED'); $aCriteriasResult[] = 'FLAGGED';
} }
else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue))) else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue)))
{ {
$oSearchBuilder->AddAnd('UNFLAGGED'); $aCriteriasResult[] = 'UNFLAGGED';
} }
$aCompareArray = array('unread', 'unseen'); $aCompareArray = array('unread', 'unseen');
$aCompareArray2 = array('read', 'seen'); $aCompareArray2 = array('read', 'seen');
if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue))) if (\count($aCompareArray) > \count(\array_diff($aCompareArray, $aValue)))
{ {
$oSearchBuilder->AddAnd('UNSEEN'); $aCriteriasResult[] = 'UNSEEN';
} }
else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue))) else if (\count($aCompareArray2) > \count(\array_diff($aCompareArray2, $aValue)))
{ {
$oSearchBuilder->AddAnd('SEEN'); $aCriteriasResult[] = 'SEEN';
} }
break; break;
case 'LARGER': case 'LARGER':
$oSearchBuilder->AddAnd('LARGER', $this->parseFriendlySize($sRawValue)); $aCriteriasResult[] = 'LARGER';
$aCriteriasResult[] = $this->parseFriendlySize($sRawValue);
break; break;
case 'SMALLER': case 'SMALLER':
$oSearchBuilder->AddAnd('SMALLER', $this->parseFriendlySize($sRawValue)); $aCriteriasResult[] = 'SMALLER';
$aCriteriasResult[] = $this->parseFriendlySize($sRawValue);
break; break;
case 'DATE': case 'DATE':
$iDateStampFrom = $iDateStampTo = 0; $iDateStampFrom = $iDateStampTo = 0;
@ -1218,12 +1240,14 @@ class MailClient
if (0 < $iDateStampFrom) if (0 < $iDateStampFrom)
{ {
$oSearchBuilder->AddAnd('SINCE', \gmdate('j-M-Y', $iDateStampFrom)); $aCriteriasResult[] = 'SINCE';
$aCriteriasResult[] = \gmdate('j-M-Y', $iDateStampFrom);
} }
if (0 < $iDateStampTo) if (0 < $iDateStampTo)
{ {
$oSearchBuilder->AddAnd('BEFORE', \gmdate('j-M-Y', $iDateStampTo)); $aCriteriasResult[] = 'BEFORE';
$aCriteriasResult[] = \gmdate('j-M-Y', $iDateStampTo);
} }
break; break;
} }
@ -1246,17 +1270,25 @@ class MailClient
$sGmailRawSearch = \trim($sGmailRawSearch); $sGmailRawSearch = \trim($sGmailRawSearch);
if ($bIsGmail && 0 < \strlen($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); $sResultBodyTextSearch = \trim($sResultBodyTextSearch);
if (0 < \strlen($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; $bIndexAsUid = true;
$aIndexOrUids = null; $aIndexOrUids = null;
$sSearchCriterias = $this->getSearchBuilder($sSearch)->Complete(); $sSearchCriterias = $this->getImapSearchCriterias($sSearch);
if ($iMessageCacheCount < $iMessageRealCount && $oCacher && $oCacher->IsInited()) if ($iMessageCacheCount < $iMessageRealCount && $oCacher && $oCacher->IsInited())
{ {
@ -1835,11 +1867,8 @@ class MailClient
$this->oImapClient->FolderExamine($sFolderName); $this->oImapClient->FolderExamine($sFolderName);
$sSearchCriterias = \MailSo\Imap\SearchBuilder::NewInstance() $aUids = $this->oImapClient->MessageSimpleSearch(
->AddAnd('HEADER MESSAGE-ID', $sMessageId) 'HEADER Message-ID '.$sMessageId, true);
->Complete();
$aUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true);
return \is_array($aUids) && 1 === \count($aUids) && \is_numeric($aUids[0]) ? (int) $aUids[0] : null; return \is_array($aUids) && 1 === \count($aUids) && \is_numeric($aUids[0]) ? (int) $aUids[0] : null;
} }

View file

@ -10,7 +10,7 @@ final class Version
/** /**
* @var string * @var string
*/ */
const APP_VERSION = '1.3.2'; const APP_VERSION = '1.3.3';
/** /**
* @var string * @var string

View file

@ -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 * @return array
*/ */

View file

@ -125,12 +125,13 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider
/** /**
* @param string $sEmail * @param string $sEmail
* @param bool $bCache = true
* *
* @return array * @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();
} }
/** /**

View file

@ -8,58 +8,4 @@ interface AddressBookInterface
* @return bool * @return bool
*/ */
public function IsSupported(); 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);
} }

View file

@ -149,6 +149,8 @@ class Contact
{ {
$this->Properties[] = new \RainLoop\Providers\AddressBook\Classes\Property(PropertyType::FULLNAME, $this->Display); $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->VERSION = '3.0';
$oVCard->PRODID = '-//RainLoop//'.APP_VERSION.'//EN'; $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 = ''; $sFirstName = $sLastName = $sMiddleName = $sSuffix = $sPrefix = '';
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty) 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->N = array($sLastName, $sFirstName, $sMiddleName, $sPrefix, $sSuffix);
$oVCard->REV = \gmdate('Ymd', $this->Changed).'T'.\gmdate('His', $this->Changed).'Z'; $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(); return (string) $oVCard->serialize();
} }
@ -582,6 +589,12 @@ class Contact
} }
$this->Properties = $aProperties; $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(); $this->UpdateDependentValues();

View file

@ -28,6 +28,11 @@ class PdoAddressBook
*/ */
private $sPassword; private $sPassword;
/**
* @var array
*/
private $aTagsCache;
public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql') public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql')
{ {
$this->sDsn = $sDsn; $this->sDsn = $sDsn;
@ -36,6 +41,7 @@ class PdoAddressBook
$this->sDsnType = $sDsnType; $this->sDsnType = $sDsnType;
$this->bExplain = false; // debug $this->bExplain = false; // debug
$this->aTagsCache = array(); // debug
} }
/** /**
@ -174,7 +180,7 @@ class PdoAddressBook
$oResponse = 'PUT' === $sCmd && null !== $mData ? $oResponse = 'PUT' === $sCmd && null !== $mData ?
$oClient->request($sCmd, $sUrl, $mData) : $oClient->request($sCmd, $sUrl); $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'); $this->oLogger->WriteDump($oResponse, \MailSo\Log\Enumerations\Type::INFO, 'DAV');
} }
@ -523,11 +529,14 @@ class PdoAddressBook
); );
} }
if (0 < \count($aParams))
{
$sSql = 'INSERT INTO rainloop_ab_properties '. $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) VALUES '.
'(:id_contact, :id_user, :prop_type, :prop_type_str, :prop_value, :prop_value_custom, :prop_frec)'; '(: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(); $aTags = array();
$aContactTags = $this->GetContactTags($sEmail); $aContactTags = $this->GetContactTags($sEmail);
@ -564,10 +573,13 @@ class PdoAddressBook
} }
} }
if (0 < \count($aTags))
{
$sSql = 'INSERT INTO rainloop_ab_tags_contacts (id_tag, id_contact) VALUES (:id_tag, :id_contact)'; $sSql = 'INSERT INTO rainloop_ab_tags_contacts (id_tag, id_contact) VALUES (:id_tag, :id_contact)';
$this->prepareAndExecute($sSql, $aTags, true); $this->prepareAndExecute($sSql, $aTags, true);
} }
} }
}
catch (\Exception $oException) catch (\Exception $oException)
{ {
if ($this->isTransactionSupported()) if ($this->isTransactionSupported())
@ -602,6 +614,8 @@ class PdoAddressBook
$iUserID = $this->getUserId($sEmail); $iUserID = $this->getUserId($sEmail);
$this->aTagsCache = array();
$mResult = false; $mResult = false;
try try
{ {
@ -707,6 +721,8 @@ class PdoAddressBook
return false; return false;
} }
$this->aTagsCache = array();
$sIDs = \implode(',', $aTagsIds); $sIDs = \implode(',', $aTagsIds);
$aParams = array(':id_user' => array($iUserID, \PDO::PARAM_INT)); $aParams = array(':id_user' => array($iUserID, \PDO::PARAM_INT));
@ -716,6 +732,99 @@ class PdoAddressBook
return true; 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 string $sEmail
* @param int $iOffset = 0 * @param int $iOffset = 0
@ -908,95 +1017,23 @@ class PdoAddressBook
} }
} }
if (\is_array($aResult) && 0 < \count($aResult)) $this->populateContactsByTags($sEmail, $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;
}
}
}
}
}
}
return $aResult; return $aResult;
} }
/** /**
* @param string $sEmail * @param string $sEmail
* @param bool $bCache = true
* *
* @return array * @return array
*/ */
public function GetContactTags($sEmail) public function GetContactTags($sEmail, $bCache = true)
{ {
if ($bCache && isset($this->aTagsCache[$sEmail]))
{
return $this->aTagsCache[$sEmail];
}
$this->SyncDatabase(); $this->SyncDatabase();
$iUserID = $this->getUserId($sEmail); $iUserID = $this->getUserId($sEmail);
@ -1031,6 +1068,11 @@ class PdoAddressBook
} }
} }
if ($bCache)
{
$this->aTagsCache[$sEmail] = $aResult;
}
return $aResult; return $aResult;
} }
@ -1134,6 +1176,11 @@ class PdoAddressBook
} }
} }
if ($oContact)
{
$this->populateContactsByTags($sEmail, $oContact);
}
return $oContact; return $oContact;
} }

View file

@ -2474,6 +2474,7 @@ Utils.detectDropdownVisibility = _.debounce(function () {
return oItem.hasClass('open'); return oItem.hasClass('open');
})); }));
}, 50); }, 50);
// Base64 encode / decode // Base64 encode / decode
// http://www.webtoolkit.info/ // http://www.webtoolkit.info/
@ -10584,10 +10585,11 @@ PopupsContactsViewModel.prototype.onHide = function ()
this.currentContact(null); this.currentContact(null);
this.emptySelection(true); this.emptySelection(true);
this.search(''); this.search('');
this.contactsCount(0);
_.each(this.contacts(), function (oItem) { this.contacts([]);
oItem.checked(false); // _.each(this.contacts(), function (oItem) {
}); // oItem.checked(false);
// });
}; };
/** /**