diff --git a/dev/Admin/Contacts.js b/dev/Admin/Contacts.js index 3cee6be7e..f494848b4 100644 --- a/dev/Admin/Contacts.js +++ b/dev/Admin/Contacts.js @@ -17,10 +17,52 @@ function AdminContacts() this.pdoDsnTrigger = ko.observable(Enums.SaveSettingsStep.Idle); this.pdoUserTrigger = ko.observable(Enums.SaveSettingsStep.Idle); this.pdoPasswordTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.testing = ko.observable(false); + this.testContactsSuccess = ko.observable(false); + this.testContactsError = ko.observable(false); + + this.testContactsCommand = Utils.createCommand(this, function () { + + this.testContactsSuccess(false); + this.testContactsError(false); + this.testing(true); + + RL.remote().testContacts(this.onTestContactsResponse, { + 'ContactsPdoDsn': this.pdoDsn(), + 'ContactsPdoUser': this.pdoUser(), + 'ContactsPdoPassword': this.pdoPassword() + }); + + }, function () { + return '' !== this.pdoDsn() && '' !== this.pdoUser(); + }); + + this.onTestContactsResponse = _.bind(this.onTestContactsResponse, this); } Utils.addSettingsViewModel(AdminContacts, 'AdminSettingsContacts', 'Contacts', 'contacts'); +AdminContacts.prototype.onTestContactsResponse = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.testContactsSuccess(true); + } + else + { + this.testContactsError(true); + } + + this.testing(false); +}; + +AdminContacts.prototype.onShow = function () +{ + this.testContactsSuccess(false); + this.testContactsError(false); +}; + AdminContacts.prototype.onBuild = function () { var self = this; diff --git a/dev/Admin/Security.js b/dev/Admin/Security.js index 2511343a3..3c7f3f38f 100644 --- a/dev/Admin/Security.js +++ b/dev/Admin/Security.js @@ -24,8 +24,6 @@ function AdminSecurity() this.adminPasswordUpdateSuccess(false); }, this); - this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this); - this.saveNewAdminPasswordCommand = Utils.createCommand(this, function () { this.adminPasswordUpdateError(false); @@ -39,6 +37,8 @@ function AdminSecurity() }, function () { return '' !== this.adminPassword() && '' !== this.adminPasswordNew(); }); + + this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this); } Utils.addSettingsViewModel(AdminSecurity, 'AdminSettingsSecurity', 'Security', 'security'); diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index e7e0b6664..7fa5ea747 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -492,7 +492,7 @@ Utils.fixLongSubject = function (sSubject) sSubject = sSubject.replace(/[\s]+/, ' '); return sSubject; -} +}; /** * @param {number} iNum diff --git a/dev/Storages/AdminAjaxRemote.js b/dev/Storages/AdminAjaxRemote.js index 661449869..0349e6602 100644 --- a/dev/Storages/AdminAjaxRemote.js +++ b/dev/Storages/AdminAjaxRemote.js @@ -218,6 +218,15 @@ AdminAjaxRemoteStorage.prototype.testConnectionForDomain = function (fCallback, }); }; +/** + * @param {?Function} fCallback + * @param {?} oData + */ +AdminAjaxRemoteStorage.prototype.testContacts = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'AdminContactsTest', oData); +}; + /** * @param {?Function} fCallback * @param {?} oData diff --git a/dev/Styles/MessageList.less b/dev/Styles/MessageList.less index 93a2403c1..a3ab09df9 100644 --- a/dev/Styles/MessageList.less +++ b/dev/Styles/MessageList.less @@ -36,7 +36,7 @@ html.rl-no-preview-pane { .e-quota { display: inline-block; - margin-left: 10px; + margin-top: 5px; font-size: 18px; cursor: help; } diff --git a/dev/Styles/_InputosaurusFix.less b/dev/Styles/_InputosaurusFix.less index ae5fbcab0..c8b9ab275 100644 --- a/dev/Styles/_InputosaurusFix.less +++ b/dev/Styles/_InputosaurusFix.less @@ -32,6 +32,10 @@ } } + span { + padding-right: 3px; + } + &.inputosaurus-required { padding-rigth: 5px; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php index cdb01ce8e..9e50fd30d 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Log/Logger.php @@ -222,7 +222,7 @@ class Logger extends \MailSo\Base\Collection */ public function WriteMixed($mData, $iDescType = null, $sName = '', $bSearchSecretWords = true) { - $iType = null === $iDescType ? \MailSo\Log\Enumerations\Type::INFO : $iType; + $iType = null === $iDescType ? \MailSo\Log\Enumerations\Type::INFO : $iDescType; if (\is_array($mData) || \is_object($mData)) { if ($mData instanceof \Exception) diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index c5a2977c3..5b81994c0 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -228,15 +228,13 @@ class Actions break; case 'personal-address-book': // \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface - if ($this->Config()->Get('contacts', 'enable', false)) - { - $sDsn = \trim($this->Config()->Get('contacts', 'pdo_dsn', '')); - $sUser = \trim($this->Config()->Get('contacts', 'pdo_user', '')); - $sPassword = (string) $this->Config()->Get('contacts', 'pdo_password', ''); + + $sDsn = \trim($this->Config()->Get('contacts', 'pdo_dsn', '')); + $sUser = \trim($this->Config()->Get('contacts', 'pdo_user', '')); + $sPassword = (string) $this->Config()->Get('contacts', 'pdo_password', ''); - $oResult = new \RainLoop\Providers\PersonalAddressBook\MySqlPersonalAddressBook($sDsn, $sUser, $sPassword); - $oResult->SetLogger($this->Logger()); - } + $oResult = new \RainLoop\Providers\PersonalAddressBook\PdoPersonalAddressBook($sDsn, $sUser, $sPassword); + $oResult->SetLogger($this->Logger()); break; case 'suggestions': // \RainLoop\Providers\Suggestions\SuggestionsInterface @@ -541,31 +539,19 @@ class Actions } /** + * @param \RainLoop\Account $oAccount = null + * @param bool $bForceEnable = false + * * @return \RainLoop\Providers\PersonalAddressBook */ - public function PersonalAddressBookProvider($oAccount = null) + public function PersonalAddressBookProvider($oAccount = null, $bForceEnable = false) { if (null === $this->oPersonalAddressBookProvider) { $this->oPersonalAddressBookProvider = new \RainLoop\Providers\PersonalAddressBook( - $this->fabrica('personal-address-book', $oAccount)); - - $sPabVersion = $this->oPersonalAddressBookProvider->Version(); - $sVersion = (string) $this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, 'PersonalAddressBookVersion', ''); - - if ($sVersion !== $sPabVersion && - $this->oPersonalAddressBookProvider->IsActive()) - { - if ($this->oPersonalAddressBookProvider->SynchronizeStorage()) - { - $this->StorageProvider()->Put(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - 'PersonalAddressBookVersion', $sPabVersion); - } - } + $this->Config()->Get('contacts', 'enable', false) || $bForceEnable ? $this->fabrica('personal-address-book', $oAccount) : null); } - - if ($oAccount) + else if ($oAccount && $this->oPersonalAddressBookProvider->IsSupported()) { $this->oPersonalAddressBookProvider->SetAccount($oAccount); } @@ -1035,7 +1021,7 @@ class Actions $aResult['DesktopNotifications'] = false; $aResult['UseThreads'] = false; $aResult['ReplySameFolder'] = false; - $aResult['UsePreviewPane'] = true; + $aResult['UsePreviewPane'] = (bool) $oConfig->Get('webmail', 'use_preview_pane', true); $aResult['UseCheckboxesInList'] = true; $aResult['DisplayName'] = ''; $aResult['ReplyTo'] = ''; @@ -1941,6 +1927,22 @@ class Actions return $this->DefaultResponse(__FUNCTION__, true); } + /** + * @return array + */ + public function DoAdminContactsTest() + { + $this->IsAdminLoggined(); + + $oConfig = $this->Config(); + + $this->setConfigFromParams($oConfig, 'ContactsPdoDsn', 'contacts', 'pdo_dsn', 'string'); + $this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string'); + $this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy'); + + return $this->DefaultResponse(__FUNCTION__, $this->PersonalAddressBookProvider()->Test()); + } + /** * @return array */ @@ -4026,7 +4028,7 @@ class Actions { $iCount = 0; $mResult = $this->PersonalAddressBookProvider($oAccount)->GetContacts($oAccount, - $iOffset, $iLimit, $sSearch, false, $iCount); + $iOffset, $iLimit, $sSearch, \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, $iCount); } return $this->DefaultResponse(__FUNCTION__, array( diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php index 7d9ef2e68..f8e989c8c 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php @@ -209,13 +209,14 @@ abstract class PdoAbstract { if ($this->oLogger) { - $this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQL'); + $this->oLogger->WriteMixed($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQL'); } } - + /** * @param string $sEmail * @param bool $bSkipInsert = false + * @param bool $bSkipUpdateTables = false * * @return int */ @@ -226,7 +227,7 @@ abstract class PdoAbstract { throw new \InvalidArgumentException('Empty Email argument'); } - + $oStmt = $this->prepareAndExecute('SELECT id_user FROM rainloop_users WHERE rl_email = :rl_email', array(':rl_email' => array($sEmail, \PDO::PARAM_STR))); @@ -271,17 +272,28 @@ abstract class PdoAbstract $oPdo = $this->getPDO(); if ($oPdo) { - $sQuery = 'SELECT * FROM rainloop_system WHERE sys_name = ?'; + if ($bReturnIntValue) + { + $sQuery = 'SELECT value_int FROM rainloop_system WHERE sys_name = ?'; + } + else + { + $sQuery = 'SELECT value_str FROM rainloop_system WHERE sys_name = ?'; + } + $this->writeLog($sQuery); $oStmt = $oPdo->prepare($sQuery); if ($oStmt->execute(array($sName))) { $mRow = $oStmt->fetchAll(\PDO::FETCH_ASSOC); - if ($mRow && isset($mRow[0]['sys_name'], $mRow[0]['value_int'], $mRow[0]['value_str'])) + $sKey = $bReturnIntValue ? 'value_int' : 'value_str'; + if ($mRow && isset($mRow[0][$sKey])) { - return $bReturnIntValue ? (int) $mRow[0]['value_int'] : (string) $mRow[0]['value_str']; + return $bReturnIntValue ? (int) $mRow[0][$sKey] : (string) $mRow[0][$sKey]; } + + return $bReturnIntValue ? 0 : ''; } } @@ -290,7 +302,6 @@ abstract class PdoAbstract /** * @param string $sType - * @param bool $bReturnIntValue = true * * @return int|string|bool */ @@ -356,18 +367,37 @@ abstract class PdoAbstract $aQ = array(); if ('mysql' === $this->sDbType) { - $aQ[] = 'CREATE TABLE IF NOT EXISTS `rainloop_system` ( - `sys_name` varchar(50) NOT NULL, - `value_int` int(11) UNSIGNED NOT NULL DEFAULT \'0\', - `value_str` varchar(255) NOT NULL DEFAULT \'\' + $aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_system ( + sys_name varchar(50) NOT NULL, + value_int int(11) UNSIGNED NOT NULL DEFAULT \'0\', + value_str varchar(128) NOT NULL DEFAULT \'\', + INDEX `sys_name_index` (`sys_name`) ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;'; - $aQ[] = 'CREATE TABLE IF NOT EXISTS `rainloop_users` ( - `id_user` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `rl_email` varchar(255) NOT NULL, - UNIQUE `email_unique` (`rl_email`), - PRIMARY KEY(`id_user`) -) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */;'; + $aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_users ( + id_user int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + rl_email varchar(128) NOT NULL DEFAULT \'\', + PRIMARY KEY(`id_user`), + INDEX `rl_email_index` (`rl_email`) +) /*!40000 ENGINE=INNODB */;'; + } + else if ('postgres' === $this->sDbType) + { + $aQ[] = 'CREATE TABLE rainloop_system ( + sys_name varchar(50) NOT NULL, + value_int integer NOT NULL DEFAULT 0, + value_str varchar(128) NOT NULL DEFAULT \'\' +);'; + + $aQ[] = 'CREATE INDEX sys_name_index ON rainloop_system (sys_name);'; + + $aQ[] = 'CREATE SEQUENCE rainloop_users_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;'; + + $aQ[] = 'CREATE TABLE rainloop_users ( + id_user integer DEFAULT nextval(\'rainloop_users_seq\'::text) PRIMARY KEY, + rl_email varchar(128) NOT NULL DEFAULT \'\' +);'; + $aQ[] = 'CREATE INDEX rl_email_index ON rainloop_users (rl_email);'; } if (0 < \count($aQ)) @@ -398,7 +428,7 @@ abstract class PdoAbstract { $oPdo->rollBack(); - $this->oLogger->WriteException($oException); + $this->writeLog($oException); throw $oException; } } @@ -415,23 +445,38 @@ abstract class PdoAbstract */ protected function dataBaseUpgrade($sName, $aData = array()) { - $this->initSystemTables(); - - $iFromVersion = $this->getVersion($sName); - - $bResult = false; - $oPdo = $this->getPDO(); - if ($oPdo) + $iFromVersion = null; + try { - $bResult = true; + $iFromVersion = $this->getVersion($sName); + } + catch (\PDOException $oException) + { + $this->writeLog($oException); + + $this->initSystemTables(); + + $iFromVersion = $this->getVersion($sName); + } + + if (0 <= $iFromVersion) + { + $oPdo = false; + $bResult = false; foreach ($aData as $iVersion => $aQuery) { - if ($iFromVersion < $iVersion) + if (!$oPdo) + { + $oPdo = $this->getPDO(); + $bResult = true; + } + + if ($iFromVersion < $iVersion && $oPdo) { try { $oPdo->beginTransaction(); - + foreach ($aQuery as $sQuery) { $this->writeLog($sQuery); @@ -461,7 +506,7 @@ abstract class PdoAbstract { break; } - + $this->setVersion($sName, $iVersion); } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook.php index d84922d36..c00fe194a 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook.php @@ -24,12 +24,13 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider } /** - * @return string + * @return bool */ - public function Version() + public function Test() { + \sleep(1); return $this->oDriver instanceof \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface ? - $this->oDriver->Version() : 'null'; + $this->oDriver->Test() : false; } /** @@ -77,16 +78,16 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider * @param int $iOffset = 0 * @param type $iLimit = 20 * @param string $sSearch = '' - * @param bool $bAutoOnly = false + * @param int $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_ * @param int $iResultCount = 0 * * @return array */ - public function GetContacts($oAccount, - $iOffset = 0, $iLimit = 20, $sSearch = '', $bAutoOnly = false, &$iResultCount = 0) + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', + $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0) { return $this->IsActive() ? $this->oDriver->GetContacts($oAccount, - $iOffset, $iLimit, $sSearch, $bAutoOnly, $iResultCount) : array(); + $iOffset, $iLimit, $sSearch, $iScopeType, $iResultCount) : array(); } /** @@ -114,13 +115,4 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider { return $this->IsActive() ? $this->oDriver->IncFrec($oAccount, $aEmails, $bCreateAuto) : false; } - - /** - * @return bool - */ - public function SynchronizeStorage() - { - return $this->IsActive() && \method_exists($this->oDriver, 'SynchronizeStorage') && - $this->oDriver->SynchronizeStorage(); - } -} \ No newline at end of file +} diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Contact.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Contact.php index ad04a092c..24d85c58a 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Contact.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Contact.php @@ -25,25 +25,15 @@ class Contact public $DisplayEmail; /** - * @var bool + * @var int */ - public $Auto; - - /** - * @var bool - */ - public $Shared; + public $ScopeType; /** * @var int */ public $Changed; - /** - * @var array - */ - public $Tags; - /** * @var int */ @@ -66,10 +56,8 @@ class Contact $this->Display = ''; $this->DisplayName = ''; $this->DisplayEmail = ''; - $this->Auto = false; - $this->Shared = false; + $this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; $this->Changed = \time(); - $this->Tags = array(); $this->IdPropertyFromSearch = 0; $this->Properties = array(); } @@ -83,6 +71,7 @@ class Contact { if ($oProperty) { + $oProperty->ScopeType = $this->ScopeType; $oProperty->UpdateDependentValues(); if ('' === $sDisplayName && \RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType::FULLNAME === $oProperty->Type && diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Property.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Property.php index e258d9aeb..919ebfc77 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Property.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Classes/Property.php @@ -16,6 +16,11 @@ class Property */ public $Type; + /** + * @var int + */ + public $ScopeType; + /** * @var string */ @@ -46,6 +51,7 @@ class Property $this->IdProperty = 0; $this->Type = PropertyType::UNKNOWN; + $this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; $this->TypeCustom = ''; $this->Value = ''; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Enumerations/ScopeType.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Enumerations/ScopeType.php new file mode 100644 index 000000000..d4d31a23e --- /dev/null +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/Enumerations/ScopeType.php @@ -0,0 +1,10 @@ +Sync(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); + $iIdContact = \strlen($oContact->IdContact) && \is_numeric($oContact->IdContact) ? (int) $oContact->IdContact : 0; $bUpdate = 0 < $iIdContact; @@ -57,7 +59,7 @@ class MySqlPersonalAddressBook $oContact->UpdateDependentValues(); $oContact->Changed = \time(); - if (!$oContact->Auto) + if (\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO !== $oContact->ScopeType) { $aEmail = $oContact->GetEmails(); if (0 < \count($aEmail)) @@ -80,8 +82,9 @@ class MySqlPersonalAddressBook // clear autocreated contacts $this->prepareAndExecute( - 'DELETE FROM `rainloop_pab_contacts` WHERE `id_user` = :id_user AND `auto` = 1 AND `display_email` IN ('.\implode(',', $aEmail).')', + 'DELETE FROM rainloop_pab_contacts WHERE id_user = :id_user AND scope_type = :scope_type AND display_email IN ('.\implode(',', $aEmail).')', array( + ':scope_type' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT) ) ); @@ -98,8 +101,8 @@ class MySqlPersonalAddressBook { $aFreq = $this->getContactFreq($iUserID, $iIdContact); - $sSql = 'UPDATE `rainloop_pab_contacts` SET `display` = :display, `display_name` = :display_name, `display_email` = :display_email, '. - '`auto` = :auto, `shared` = :shared, `changed` = :changed WHERE id_user = :id_user AND `id_contact` = :id_contact'; + $sSql = 'UPDATE rainloop_pab_contacts SET display = :display, display_name = :display_name, display_email = :display_email, '. + 'scope_type = :scope_type, changed = :changed WHERE id_user = :id_user AND id_contact = :id_contact'; $this->prepareAndExecute($sSql, array( @@ -108,15 +111,14 @@ class MySqlPersonalAddressBook ':display' => array($oContact->Display, \PDO::PARAM_STR), ':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR), ':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR), - ':auto' => array($oContact->Auto, \PDO::PARAM_INT), - ':shared' => array($oContact->Shared, \PDO::PARAM_INT), + ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), ':changed' => array($oContact->Changed, \PDO::PARAM_INT), ) ); // clear previos props $this->prepareAndExecute( - 'DELETE FROM `rainloop_pab_properties` WHERE `id_user` = :id_user AND `id_contact` = :id_contact', + 'DELETE FROM rainloop_pab_properties WHERE id_user = :id_user AND id_contact = :id_contact', array( ':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_contact' => array($iIdContact, \PDO::PARAM_INT) @@ -125,9 +127,9 @@ class MySqlPersonalAddressBook } else { - $sSql = 'INSERT INTO `rainloop_pab_contacts` '. - '(`id_user`, `display`, `display_name`, `display_email`, `auto`, `shared`, `changed`) VALUES '. - '(:id_user, :display, :display_name, :display_email, :auto, :shared, :changed)'; + $sSql = 'INSERT INTO rainloop_pab_contacts '. + '( id_user, display, display_name, display_email, scope_type, changed) VALUES '. + '(:id_user, :display, :display_name, :display_email, :scope_type, :changed)'; $this->prepareAndExecute($sSql, array( @@ -135,8 +137,7 @@ class MySqlPersonalAddressBook ':display' => array($oContact->Display, \PDO::PARAM_STR), ':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR), ':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR), - ':auto' => array($oContact->Auto, \PDO::PARAM_INT), - ':shared' => array($oContact->Shared, \PDO::PARAM_INT), + ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), ':changed' => array($oContact->Changed, \PDO::PARAM_INT) ) ); @@ -163,19 +164,18 @@ class MySqlPersonalAddressBook $aParams[] = array( ':id_contact' => array($iIdContact, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT), - ':type' => array($oProp->Type, \PDO::PARAM_INT), - ':type_custom' => array($oProp->TypeCustom, \PDO::PARAM_STR), - ':value' => array($oProp->Value, \PDO::PARAM_STR), - ':value_custom' => array($oProp->ValueClear, \PDO::PARAM_STR), - ':auto' => array($oContact->Auto, \PDO::PARAM_INT), - ':shared' => array($oContact->Shared, \PDO::PARAM_INT), - ':frec' => array($iFreq, \PDO::PARAM_INT), + ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), + ':prop_type' => array($oProp->Type, \PDO::PARAM_INT), + ':prop_type_custom' => array($oProp->TypeCustom, \PDO::PARAM_STR), + ':prop_value' => array($oProp->Value, \PDO::PARAM_STR), + ':prop_value_custom' => array($oProp->ValueClear, \PDO::PARAM_STR), + ':prop_frec' => array($iFreq, \PDO::PARAM_INT), ); } - $sSql = 'INSERT INTO `rainloop_pab_properties` '. - '(`id_contact`, `id_user`, `type`, `type_custom`, `value`, `value_custom`, `auto`, `shared`, `frec`) VALUES '. - '(:id_contact, :id_user, :type, :type_custom, :value, :value_custom, :auto, :shared, :frec)'; + $sSql = 'INSERT INTO rainloop_pab_properties '. + '( id_contact, id_user, prop_type, prop_type_custom, prop_value, prop_value_custom, scope_type, prop_frec) VALUES '. + '(:id_contact, :id_user, :prop_type, :prop_type_custom, :prop_value, :prop_value_custom, :scope_type, :prop_frec)'; $this->prepareAndExecute($sSql, $aParams, true); } @@ -199,6 +199,7 @@ class MySqlPersonalAddressBook */ public function DeleteContacts($oAccount, $aContactIds) { + $this->Sync(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); $aContactIds = \array_filter($aContactIds, function (&$mItem) { @@ -214,9 +215,9 @@ class MySqlPersonalAddressBook $sIDs = \implode(',', $aContactIds); $aParams = array(':id_user' => array($iUserID, \PDO::PARAM_INT)); - $this->prepareAndExecute('DELETE FROM `rainloop_pab_tags_contacts` WHERE `id_contact` IN ('.$sIDs.')'); - $this->prepareAndExecute('DELETE FROM `rainloop_pab_properties` WHERE `id_user` = :id_user AND `id_contact` IN ('.$sIDs.')', $aParams); - $this->prepareAndExecute('DELETE FROM `rainloop_pab_contacts` WHERE `id_user` = :id_user AND `id_contact` IN ('.$sIDs.')', $aParams); + $this->prepareAndExecute('DELETE FROM rainloop_pab_tags_contacts WHERE id_contact IN ('.$sIDs.')'); + $this->prepareAndExecute('DELETE FROM rainloop_pab_properties WHERE id_user = :id_user AND id_contact IN ('.$sIDs.')', $aParams); + $this->prepareAndExecute('DELETE FROM rainloop_pab_contacts WHERE id_user = :id_user AND id_contact IN ('.$sIDs.')', $aParams); return true; } @@ -229,6 +230,7 @@ class MySqlPersonalAddressBook */ public function DeleteTags($oAccount, $aTagsIds) { + $this->Sync(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); $aTagsIds = \array_filter($aTagsIds, function (&$mItem) { @@ -244,8 +246,8 @@ class MySqlPersonalAddressBook $sIDs = \implode(',', $aTagsIds); $aParams = array(':id_user' => array($iUserID, \PDO::PARAM_INT)); - $this->prepareAndExecute('DELETE FROM `rainloop_pab_tags_contacts` WHERE `id_tag` IN ('.$sIDs.')'); - $this->prepareAndExecute('DELETE FROM `rainloop_pab_tags` WHERE `id_user` = :id_user AND `id_tag` IN ('.$sIDs.')', $aParams); + $this->prepareAndExecute('DELETE FROM rainloop_pab_tags_contacts WHERE id_tag IN ('.$sIDs.')'); + $this->prepareAndExecute('DELETE FROM rainloop_pab_tags WHERE id_user = :id_user AND id_tag IN ('.$sIDs.')', $aParams); return true; } @@ -255,13 +257,16 @@ class MySqlPersonalAddressBook * @param int $iOffset = 0 * @param int $iLimit = 20 * @param string $sSearch = '' - * @param bool $bAutoOnly = false + * @param bool $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_ * @param int $iResultCount = 0 * * @return array */ - public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', $bAutoOnly = false, &$iResultCount = 0) + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', + $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0) { + $this->Sync(); + $iOffset = 0 <= $iOffset ? $iOffset : 0; $iLimit = 0 < $iLimit ? (int) $iLimit : 20; $sSearch = \trim($sSearch); @@ -274,10 +279,10 @@ class MySqlPersonalAddressBook if (0 < \strlen($sSearch)) { - $sSql = 'SELECT `id_prop`, `id_contact` FROM `rainloop_pab_properties` WHERE `id_user` = :id_user AND `auto` = :auto AND `value` LIKE :search ESCAPE \'=\' GROUP BY `id_contact`'; + $sSql = 'SELECT id_prop, id_contact FROM rainloop_pab_properties WHERE id_user = :id_user AND scope_type = :scope_type AND prop_value LIKE :search ESCAPE \'=\' GROUP BY id_contact'; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), - ':auto' => array($bAutoOnly ? 1 : 0, \PDO::PARAM_INT), + ':scope_type' => array($iScopeType, \PDO::PARAM_INT), ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR) ); @@ -303,10 +308,10 @@ class MySqlPersonalAddressBook } else { - $sSql = 'SELECT COUNT(DISTINCT `id_contact`) as `contact_count` FROM `rainloop_pab_properties` WHERE `id_user` = :id_user AND `auto` = :auto'; + $sSql = 'SELECT COUNT(DISTINCT id_contact) as contact_count FROM rainloop_pab_properties WHERE id_user = :id_user AND scope_type = :scope_type'; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), - ':auto' => array($bAutoOnly ? 1 : 0, \PDO::PARAM_INT) + ':scope_type' => array($iScopeType, \PDO::PARAM_INT) ); $oStmt = $this->prepareAndExecute($sSql, $aParams); @@ -324,18 +329,18 @@ class MySqlPersonalAddressBook if (0 < $iCount) { - $sSql = 'SELECT * FROM `rainloop_pab_contacts` WHERE id_user = :id_user AND `auto` = :auto'; + $sSql = 'SELECT * FROM rainloop_pab_contacts WHERE id_user = :id_user AND scope_type = :scope_type'; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), - ':auto' => array($bAutoOnly ? 1 : 0, \PDO::PARAM_INT) + ':scope_type' => array($iScopeType, \PDO::PARAM_INT) ); if (0 < \count($aSearchIds)) { - $sSql .= ' AND `id_contact` IN ('.implode(',', $aSearchIds).')'; + $sSql .= ' AND id_contact IN ('.implode(',', $aSearchIds).')'; } - $sSql .= ' ORDER BY `display` ASC LIMIT :limit OFFSET :offset'; + $sSql .= ' ORDER BY display ASC LIMIT :limit OFFSET :offset'; $aParams[':limit'] = array($iLimit, \PDO::PARAM_INT); $aParams[':offset'] = array($iOffset, \PDO::PARAM_INT); @@ -360,8 +365,10 @@ class MySqlPersonalAddressBook $oContact->Display = isset($aItem['display']) ? (string) $aItem['display'] : ''; $oContact->DisplayName = isset($aItem['display_name']) ? (string) $aItem['display_name'] : ''; $oContact->DisplayEmail = isset($aItem['display_email']) ? (string) $aItem['display_email'] : ''; - $oContact->Auto = isset($aItem['auto']) ? (bool) $aItem['auto'] : false; + $oContact->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] : + \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; $oContact->Changed = isset($aItem['changed']) ? (int) $aItem['changed'] : 0; + $oContact->IdPropertyFromSearch = isset($aPropertyFromSearchIds[$iIdContact]) && 0 < $aPropertyFromSearchIds[$iIdContact] ? $aPropertyFromSearchIds[$iIdContact] : 0; @@ -376,7 +383,7 @@ class MySqlPersonalAddressBook { $oStmt->closeCursor(); - $sSql = 'SELECT * FROM `rainloop_pab_properties` WHERE id_user = :id_user AND `id_contact` IN ('.\implode(',', $aIdContacts).')'; + $sSql = 'SELECT * FROM rainloop_pab_properties WHERE id_user = :id_user AND id_contact IN ('.\implode(',', $aIdContacts).')'; $oStmt = $this->prepareAndExecute($sSql, array( ':id_user' => array($iUserID, \PDO::PARAM_INT) )); @@ -388,18 +395,20 @@ class MySqlPersonalAddressBook { foreach ($aFetch as $aItem) { - if ($aItem && isset($aItem['id_prop'], $aItem['id_contact'], $aItem['type'], $aItem['value'])) + if ($aItem && isset($aItem['id_prop'], $aItem['id_contact'], $aItem['prop_type'], $aItem['prop_value'])) { $iId = (int) $aItem['id_contact']; if (0 < $iId && isset($aContacts[$iId])) { $oProperty = new \RainLoop\Providers\PersonalAddressBook\Classes\Property(); $oProperty->IdProperty = (int) $aItem['id_prop']; - $oProperty->Type = (int) $aItem['type']; - $oProperty->TypeCustom = isset($aItem['type_custom']) ? (string) $aItem['type_custom'] : ''; - $oProperty->Value = (string) $aItem['value']; - $oProperty->ValueClear = isset($aItem['value_clear']) ? (string) $aItem['value_clear'] : ''; - $oProperty->Frec = isset($aItem['frec']) ? (int) $aItem['frec'] : 0; + $oProperty->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] : + \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; + $oProperty->Type = (int) $aItem['prop_type']; + $oProperty->TypeCustom = isset($aItem['prop_type_custom']) ? (string) $aItem['prop_type_custom'] : ''; + $oProperty->Value = (string) $aItem['prop_value']; + $oProperty->ValueClear = isset($aItem['prop_value_clear']) ? (string) $aItem['prop_value_clear'] : ''; + $oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0; $aContacts[$iId]->Properties[] = $oProperty; } @@ -440,14 +449,15 @@ class MySqlPersonalAddressBook throw new \InvalidArgumentException('Empty Search argument'); } + $this->Sync(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); $sTypes = implode(',', array( PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME )); - $sSql = 'SELECT `id_contact`, `id_prop`, `type`, `value` FROM `rainloop_pab_properties` '. - 'WHERE id_user = :id_user AND `type` IN ('.$sTypes.') AND `value` LIKE :search ESCAPE \'=\''; + $sSql = 'SELECT id_contact, id_prop, prop_type, prop_value FROM rainloop_pab_properties '. + 'WHERE id_user = :id_user AND prop_type IN ('.$sTypes.') AND prop_value LIKE :search ESCAPE \'=\''; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), @@ -455,7 +465,7 @@ class MySqlPersonalAddressBook ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR) ); - $sSql .= ' ORDER BY `frec` DESC'; + $sSql .= ' ORDER BY prop_frec DESC'; $sSql .= ' LIMIT :limit'; $aResult = array(); @@ -475,7 +485,7 @@ class MySqlPersonalAddressBook if (0 < $iIdContact) { $aIdContacts[$iIdContact] = $iIdContact; - $iType = isset($aItem['type']) ? (int) $aItem['type'] : PropertyType::UNKNOWN; + $iType = isset($aItem['prop_type']) ? (int) $aItem['prop_type'] : PropertyType::UNKNOWN; if (\in_array($iType, array(PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME))) { @@ -489,8 +499,8 @@ class MySqlPersonalAddressBook $aFirstResult[] = array( 'id_prop' => isset($aItem['id_prop']) ? (int) $aItem['id_prop'] : 0, 'id_contact' => $iIdContact, - 'value' => isset($aItem['value']) ? (string) $aItem['value'] : '', - 'type' => $iType + 'prop_value' => isset($aItem['prop_value']) ? (string) $aItem['prop_value'] : '', + 'prop_type' => $iType ); } } @@ -509,8 +519,8 @@ class MySqlPersonalAddressBook PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME )); - $sSql = 'SELECT `id_prop`, `id_contact`, `type`, `value` FROM `rainloop_pab_properties` '. - 'WHERE id_user = :id_user AND `type` IN ('.$sTypes.') AND `id_contact` IN ('.\implode(',', $aIdContacts).')'; + $sSql = 'SELECT id_prop, id_contact, prop_type, prop_value FROM rainloop_pab_properties '. + 'WHERE id_user = :id_user AND prop_type IN ('.$sTypes.') AND id_contact IN ('.\implode(',', $aIdContacts).')'; $oStmt = $this->prepareAndExecute($sSql, array( ':id_user' => array($iUserID, \PDO::PARAM_INT) @@ -525,14 +535,14 @@ class MySqlPersonalAddressBook foreach ($aFetch as $aItem) { - if ($aItem && isset($aItem['id_prop'], $aItem['id_contact'], $aItem['type'], $aItem['value'])) + if ($aItem && isset($aItem['id_prop'], $aItem['id_contact'], $aItem['prop_type'], $aItem['prop_value'])) { $iIdContact = (int) $aItem['id_contact']; - $iType = (int) $aItem['type']; + $iType = (int) $aItem['prop_type']; if (PropertyType::FULLNAME === $iType) { - $aNames[$iIdContact] = $aItem['value']; + $aNames[$iIdContact] = $aItem['prop_value']; } else if (\in_array($iType, array(PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER))) @@ -542,17 +552,17 @@ class MySqlPersonalAddressBook $aEmails[$iIdContact] = array(); } - $aEmails[$iIdContact][] = $aItem['value']; + $aEmails[$iIdContact][] = $aItem['prop_value']; } } } foreach ($aFirstResult as $aItem) { - if ($aItem && !empty($aItem['value'])) + if ($aItem && !empty($aItem['prop_value'])) { $iIdContact = (int) $aItem['id_contact']; - $iType = (int) $aItem['type']; + $iType = (int) $aItem['prop_type']; if (PropertyType::FULLNAME === $iType) { @@ -562,7 +572,7 @@ class MySqlPersonalAddressBook { if (!empty($sEmail)) { - $aResult[] = array($sEmail, (string) $aItem['value']); + $aResult[] = array($sEmail, (string) $aItem['prop_value']); } } } @@ -570,7 +580,7 @@ class MySqlPersonalAddressBook else if (\in_array($iType, array(PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER))) { - $aResult[] = array((string) $aItem['value'], + $aResult[] = array((string) $aItem['prop_value'], isset($aNames[$iIdContact]) ? (string) $aNames[$iIdContact] : ''); } } @@ -601,8 +611,6 @@ class MySqlPersonalAddressBook */ public function IncFrec($oAccount, $aEmails, $bCreateAuto = true) { - $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); - $self = $this; $aEmailsObjects = \array_map(function ($mItem) { $oResult = null; @@ -619,6 +627,9 @@ class MySqlPersonalAddressBook throw new \InvalidArgumentException('Empty Emails argument'); } + $this->Sync(); + $iUserID = $this->getUserId($oAccount->ParentEmailHelper()); + $sTypes = \implode(',', array( PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER )); @@ -629,7 +640,7 @@ class MySqlPersonalAddressBook if ($bCreateAuto) { - $sSql = 'SELECT `value` FROM `rainloop_pab_properties` WHERE id_user = :id_user AND `type` IN ('.$sTypes.')'; + $sSql = 'SELECT prop_value FROM rainloop_pab_properties WHERE id_user = :id_user AND prop_type IN ('.$sTypes.')'; $oStmt = $this->prepareAndExecute($sSql, array( ':id_user' => array($iUserID, \PDO::PARAM_INT) )); @@ -641,9 +652,9 @@ class MySqlPersonalAddressBook { foreach ($aFetch as $aItem) { - if ($aItem && !empty($aItem['value'])) + if ($aItem && !empty($aItem['prop_value'])) { - $aExists[] = \strtolower(\trim($aItem['value'])); + $aExists[] = \strtolower(\trim($aItem['prop_value'])); } } } @@ -685,11 +696,12 @@ class MySqlPersonalAddressBook $oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact(); foreach ($aEmailsToCreate as $oEmail) { - $oContact->Auto = true; + $oContact->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO; if ('' !== \trim($oEmail->GetEmail())) { $oPropEmail = new \RainLoop\Providers\PersonalAddressBook\Classes\Property(); + $oPropEmail->ScopeType = $oContact->ScopeType; $oPropEmail->Type = \RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType::EMAIl_PERSONAL; $oPropEmail->Value = \strtolower(\trim($oEmail->GetEmail())); @@ -699,6 +711,7 @@ class MySqlPersonalAddressBook if ('' !== \trim($oEmail->GetDisplayName())) { $oPropName = new \RainLoop\Providers\PersonalAddressBook\Classes\Property(); + $oPropName->ScopeType = $oContact->ScopeType; $oPropName->Type = \RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType::FULLNAME; $oPropName->Value = \trim($oEmail->GetDisplayName()); @@ -714,7 +727,7 @@ class MySqlPersonalAddressBook } } - $sSql = 'UPDATE `rainloop_pab_properties` SET `frec` = `frec` + 1 WHERE id_user = :id_user AND `type` IN ('.$sTypes; + $sSql = 'UPDATE rainloop_pab_properties SET prop_frec = prop_frec + 1 WHERE id_user = :id_user AND prop_type IN ('.$sTypes; $aEmailsQuoted = \array_map(function ($mItem) use ($self) { return $self->quoteValue($mItem); @@ -722,11 +735,11 @@ class MySqlPersonalAddressBook if (1 === \count($aEmailsQuoted)) { - $sSql .= ') AND `value` = '.$aEmailsQuoted[0]; + $sSql .= ') AND prop_value = '.$aEmailsQuoted[0]; } else { - $sSql .= ') AND `value` IN ('.\implode(',', $aEmailsQuoted).')'; + $sSql .= ') AND prop_value IN ('.\implode(',', $aEmailsQuoted).')'; } return !!$this->prepareAndExecute($sSql, array( @@ -737,77 +750,78 @@ class MySqlPersonalAddressBook /** * @return string */ - public function Version() + public function Test() { - return 'MySqlPersonalAddressBookDriver-v14'; + $this->Sync(); + return 0 < $this->getVersion('mysql-pab-version'); } - + /** * @return bool */ - public function SynchronizeStorage() + public function Sync() { return $this->dataBaseUpgrade('mysql-pab-version', array( 1 => array( // -- rainloop_pab_contacts -- -'CREATE TABLE IF NOT EXISTS `rainloop_pab_contacts` ( +'CREATE TABLE IF NOT EXISTS rainloop_pab_contacts ( - `id_contact` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` int(11) UNSIGNED NOT NULL, - `display` varchar(255) NOT NULL DEFAULT \'\', - `display_name` varchar(255) NOT NULL DEFAULT \'\', - `display_email` varchar(255) NOT NULL DEFAULT \'\', - `auto` int(1) UNSIGNED NOT NULL DEFAULT \'0\', - `shared` int(1) UNSIGNED NOT NULL DEFAULT \'0\', - `changed` int(11) UNSIGNED NOT NULL DEFAULT \'0\', + id_contact int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + id_user int(11) UNSIGNED NOT NULL, + scope_type int(4) UNSIGNED NOT NULL DEFAULT 0, + display_name varchar(255) NOT NULL DEFAULT \'\', + display_email varchar(255) NOT NULL DEFAULT \'\', + display varchar(255) NOT NULL DEFAULT \'\', + changed int(11) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY(`id_contact`), - INDEX `id_user_index` (`id_user`) + PRIMARY KEY(id_contact), + INDEX id_user_scope_type_index (id_user, scope_type) -) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', +)/*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', // -- rainloop_pab_properties -- -'CREATE TABLE IF NOT EXISTS `rainloop_pab_properties` ( +'CREATE TABLE IF NOT EXISTS rainloop_pab_properties ( - `id_prop` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `id_contact` int(11) UNSIGNED NOT NULL, - `id_user` int(11) UNSIGNED NOT NULL, - `type` int(11) UNSIGNED NOT NULL, - `type_custom` varchar(50) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL DEFAULT \'\', - `value` varchar(255) NOT NULL DEFAULT \'\', - `value_custom` varchar(255) NOT NULL DEFAULT \'\', - `auto` int(1) UNSIGNED NOT NULL DEFAULT \'0\', - `shared` int(1) UNSIGNED NOT NULL DEFAULT \'0\', - `frec` int(11) UNSIGNED NOT NULL DEFAULT \'0\', + id_prop int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + id_contact int(11) UNSIGNED NOT NULL, + id_user int(11) UNSIGNED NOT NULL, + scope_type int(4) UNSIGNED NOT NULL DEFAULT 0, + prop_type int(11) UNSIGNED NOT NULL, + prop_type_custom varchar(50) /*!40101 CHARACTER SET ascii COLLATE ascii_general_ci */ NOT NULL DEFAULT \'\', + prop_value varchar(255) NOT NULL DEFAULT \'\', + prop_value_custom varchar(255) NOT NULL DEFAULT \'\', + prop_frec int(11) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY(`id_prop`), - INDEX `id_user_index` (`id_user`), - INDEX `id_user_id_contact_index` (`id_user`, `id_contact`) + PRIMARY KEY(id_prop), + INDEX id_user_index (id_user), + INDEX id_user_id_contact_scope_type_index (id_user, id_contact, scope_type) -) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', +)/*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', // -- rainloop_pab_tags -- -'CREATE TABLE IF NOT EXISTS `rainloop_pab_tags` ( +'CREATE TABLE IF NOT EXISTS rainloop_pab_tags ( - `id_tag` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `id_user` int(11) UNSIGNED NOT NULL, - `name` varchar(255) NOT NULL, + id_tag int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + id_user int(11) UNSIGNED NOT NULL, + tag_name varchar(255) NOT NULL, - PRIMARY KEY(`id_tag`), - INDEX `id_user_index` (`id_user`) + PRIMARY KEY(id_tag), + INDEX id_user_index (id_user), + INDEX id_user_name_index (id_user, tag_name) -) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', +)/*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;', // -- rainloop_pab_tags_contacts -- -'CREATE TABLE IF NOT EXISTS `rainloop_pab_tags_contacts` ( +'CREATE TABLE IF NOT EXISTS rainloop_pab_tags_contacts ( - `id_tag` int(11) UNSIGNED NOT NULL, - `id_contact` int(11) UNSIGNED NOT NULL, + id_tag int(11) UNSIGNED NOT NULL, + id_contact int(11) UNSIGNED NOT NULL, - INDEX `id_contact_id_tag_index` (`id_contact`, `id_tag`) + INDEX id_tag_index (id_tag), + INDEX id_contact_index (id_contact) -) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;' +)/*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;' ))); } @@ -824,7 +838,7 @@ class MySqlPersonalAddressBook PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER )); - $sSql = 'SELECT `value`, `frec` FROM `rainloop_pab_properties` WHERE id_user = :id_user AND `id_contact` = :id_contact AND `type` IN ('.$sTypes.')'; + $sSql = 'SELECT prop_value, prop_frec FROM rainloop_pab_properties WHERE id_user = :id_user AND id_contact = :id_contact AND prop_type IN ('.$sTypes.')'; $aParams = array( ':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_contact' => array($iIdContact, \PDO::PARAM_INT) @@ -838,9 +852,9 @@ class MySqlPersonalAddressBook { foreach ($aFetch as $aItem) { - if ($aItem && !empty($aItem['value']) && !empty($aItem['frec'])) + if ($aItem && !empty($aItem['prop_value']) && !empty($aItem['prop_frec'])) { - $aResult[$aItem['value']] = (int) $aItem['frec']; + $aResult[$aItem['prop_value']] = (int) $aItem['prop_frec']; } } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/PersonalAddressBookInterface.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/PersonalAddressBookInterface.php index 82eb513b1..c8f5887f4 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/PersonalAddressBookInterface.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/PersonalAddressBook/PersonalAddressBookInterface.php @@ -4,11 +4,6 @@ namespace RainLoop\Providers\PersonalAddressBook; interface PersonalAddressBookInterface { - /** - * @return string - */ - public function Version(); - /** * @return bool */ @@ -41,15 +36,15 @@ interface PersonalAddressBookInterface /** * @param \RainLoop\Account $oAccount * @param int $iOffset = 0 - * @param type $iLimit = 20 + * @param int $iLimit = 20 * @param string $sSearch = '' - * @param bool $bAutoOnly = false + * @param bool $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_ * @param int $iResultCount = 0 * * @return array */ - public function GetContacts($oAccount, - $iOffset = 0, $iLimit = 20, $sSearch = '', $bAutoOnly = false, &$iResultCount = 0); + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', + $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0); /** * @param \RainLoop\Account $oAccount diff --git a/rainloop/v/0.0.0/app/templates/Views/AdminSettingsContacts.html b/rainloop/v/0.0.0/app/templates/Views/AdminSettingsContacts.html index 05cd37709..7d3cacc1e 100644 --- a/rainloop/v/0.0.0/app/templates/Views/AdminSettingsContacts.html +++ b/rainloop/v/0.0.0/app/templates/Views/AdminSettingsContacts.html @@ -20,9 +20,12 @@ +
]*>/gim,"\n__bq__start__\n").replace(/<\/blockquote>/gim,"\n__bq__end__\n").replace(/]*>([\s\S]*?)<\/a>/gim,f).replace(/ /gi," ").replace(/<[^>]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,""),(a?ob.splitPlainText(b):b).replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__([\s\S]*)__bq__end__/gm,d).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")},j.prototype.getHtmlFromText=function(){return ob.convertPlainTextToHtml(this.textarea.val())},j.prototype.switchToggle=function(){this.isHtml()?this.switchToPlain():this.switchToHtml()},j.prototype.switchToPlain=function(c){c=ob.isUnd(c)?!0:c;var d=this.getTextFromHtml(),e=h.bind(function(a){a&&(this.toolbar.addClass("editorHideToolbar"),b(".editorSwitcher",this.toolbar).text(this.switcherLinkText(!1)),this.textarea.val(d),this.textarea.show(),this.htmlarea.hide(),this.fOnSwitch&&this.fOnSwitch(!1))},this);c&&0!==ob.trim(d).length?e(a.confirm(this.oOptions.LangSwitcherConferm)):e(!0)},j.prototype.switcherLinkText=function(a){return a?this.oOptions.LangSwitcherTextLabel:this.oOptions.LangSwitcherHtmlLabel},j.prototype.switchToHtml=function(){this.toolbar.removeClass("editorHideToolbar"),b(".editorSwitcher",this.toolbar).text(this.switcherLinkText(!0)),this.textarea.val(this.getHtmlFromText()),this.updateHtmlArea(),this.textarea.hide(),this.htmlarea.show(),this.fOnSwitch&&this.fOnSwitch(!0)},j.prototype.addButton=function(c,d){var e=this;b("").addClass("editorToolbarButtom").append(b('').addClass(c)).attr("title",d).click(function(d){ob.isUnd(j.htmlFunctions[c])?a.alert(c):j.htmlFunctions[c].apply(e,[b(this),d])}).appendTo(this.toolbar)},j.htmlInitToolbar=function(){this.bOnlyPlain||(this.addButton("bold","Bold"),this.addButton("italic","Italic"),this.addButton("underline","Underline"),this.addButton("strikethrough","Strikethrough"),this.addButton("removeformat","removeformat"),this.addButton("justifyleft","justifyleft"),this.addButton("justifycenter","justifycenter"),this.addButton("justifyright","justifyright"),this.addButton("horizontalrule","horizontalrule"),this.addButton("orderedlist","orderedlist"),this.addButton("unorderedlist","unorderedlist"),this.addButton("indent","indent"),this.addButton("outdent","outdent"),this.addButton("forecolor","forecolor"),function(a,b){a("").addClass("editorSwitcher").text(b.switcherLinkText(!0)).click(function(){b.switchToggle()}).appendTo(b.toolbar)}(b,this))},j.htmlInitEditor=function(){this.editor=this.htmlarea[0],this.editor.innerHTML=this.textarea.val()},j.htmlAttachEditorEvents=function(){var b=this,c=function(a){return a&&a.type&&0===a.type.indexOf("image/")},d=function(d){if(d=(d&&d.originalEvent?d.originalEvent:d)||a.event){d.stopPropagation(),d.preventDefault();var e=null,f=null,g=d.files||(d.dataTransfer?d.dataTransfer.files:null);g&&1===g.length&&c(g[0])&&(f=g[0],e=new a.FileReader,e.onload=function(a){return function(c){b.insertImage(c.target.result,a.name)}}(f),e.readAsDataURL(f))}b.htmlarea.removeClass("editorDragOver")},e=function(){b.htmlarea.removeClass("editorDragOver")},f=function(a){a.stopPropagation(),a.preventDefault(),b.htmlarea.addClass("editorDragOver")},g=function(d){var e=d&&d.clipboardData?d.clipboardData:d&&d.originalEvent&&d.originalEvent.clipboardData?d.originalEvent.clipboardData:null;e&&e.items&&h.each(e.items,function(d){if(c(d)&&d.getAsFile){var e=null,f=d.getAsFile();f&&(e=new a.FileReader,e.onload=function(a){return function(c){b.insertImage(c.target.result,a.name)}}(f),e.readAsDataURL(f))}})};this.bOnlyPlain||a.File&&a.FileReader&&a.FileList&&(this.htmlarea.bind("dragover",f),this.htmlarea.bind("dragleave",e),this.htmlarea.bind("drop",d),this.htmlarea.bind("paste",g)) },j.htmlColorPickerColors=function(){var a=[],b=[],c=0,d=0,e=0,f=0,g="";for(c=0;256>c;c+=85)g=c.toString(16),a.push(1===g.length?"0"+g:g);for(f=a.length,c=0;f>c;c++)for(d=0;f>d;d++)for(e=0;f>e;e++)b.push("#"+a[c]+a[d]+a[e]);return b}(),j.htmlFontPicker=function(){var c=b(a.document),d=!1,e=b(''),f=e.find(".editorFpFonts"),g=function(){};return b.each(["Arial","Arial Black","Courier New","Tahoma","Times New Roman","Verdana"],function(a,c){f.append(b(''+c+"").click(function(){g(c)})),f.append("
")}),e.hide(),function(f,h,i){d||(e.appendTo(i),d=!0),g=h,c.unbind("click.fpNamespace"),a.setTimeout(function(){c.one("click.fpNamespace",function(){e.hide()})},500);var j=b(f).position();e.css("top",5+j.top+b(f).height()+"px").css("left",j.left+"px").show()}}(),j.htmlColorPicker=function(){var c=b(a.document),d=!1,e=b(''),f=e.find(".editorCpColors"),g=function(){};return b.each(j.htmlColorPickerColors,function(a,b){f.append('')}),e.hide(),b(".editorCpColor",f).click(function(a){var c=1,d="#000000",e=b(a.target).css("background-color"),f=e.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);if(null!==f){for(delete f[0];3>=c;++c)f[c]=ob.pInt(f[c]).toString(16),1===f[c].length&&(f[c]="0"+f[c]);d="#"+f.join("")}else d=e;g(d)}),function(f,h,i){d||(e.appendTo(i),d=!0);var j=b(f).position();g=h,c.unbind("click.cpNamespace"),a.setTimeout(function(){c.one("click.cpNamespace",function(){e.hide()})},100),e.css("top",5+j.top+b(f).height()+"px").css("left",j.left+"px").show()}}(),j.htmlFunctions={bold:function(){this.ec("bold")},italic:function(){this.ec("italic")},underline:function(){this.ec("underline")},strikethrough:function(){this.ec("strikethrough")},indent:function(){this.ec("indent")},outdent:function(){this.ec("outdent")},justifyleft:function(){this.ec("justifyLeft")},justifycenter:function(){this.ec("justifyCenter")},justifyright:function(){this.ec("justifyRight")},horizontalrule:function(){this.ec("insertHorizontalRule",!1,"ht")},removeformat:function(){this.ec("removeFormat")},orderedlist:function(){this.ec("insertorderedlist")},unorderedlist:function(){this.ec("insertunorderedlist")},forecolor:function(a){j.htmlColorPicker(a,h.bind(function(a){this.setcolor("forecolor",a)},this),this.toolbar)},backcolor:function(a){j.htmlColorPicker(a,h.bind(function(a){this.setcolor("backcolor",a)},this),this.toolbar)},fontname:function(a){j.htmlFontPicker(a,h.bind(function(a){this.ec("fontname",!1,a)},this),this.toolbar)}},k.prototype.selectItemCallbacks=function(a){(this.oCallbacks.onItemSelect||this.emptyFunction)(a)},k.prototype.init=function(d,e){if(this.oContentVisible=d,this.oContentScrollable=e,this.oContentVisible&&this.oContentScrollable){var f=this;b(this.oContentVisible).on("click",this.sItemSelector,function(a){f.actionClick(c.dataFor(this),a)}).on("click",this.sItemCheckedSelector,function(a){var b=c.dataFor(this);b&&(a&&a.shiftKey?f.actionClick(b,a):(f.sLastUid=f.getItemUid(b),b.selected()?(b.checked(!1),f.selectedItem(null)):b.checked(!b.checked())))}),b(a.document).on("keydown",function(a){var b=!0;return a&&f.bUseKeyboard&&!ob.inFocus()&&(-10)if(m){if(m)if(mb.EventKeyCode.Down===b||mb.EventKeyCode.Up===b||mb.EventKeyCode.Insert===b)h.each(k,function(a){if(!i)switch(b){case mb.EventKeyCode.Up:m===a?i=!0:j=a;break;case mb.EventKeyCode.Down:case mb.EventKeyCode.Insert:g?(j=a,i=!0):m===a&&(g=!0)}});else if(mb.EventKeyCode.Home===b||mb.EventKeyCode.End===b)mb.EventKeyCode.Home===b?j=k[0]:mb.EventKeyCode.End===b&&(j=k[k.length-1]);else if(mb.EventKeyCode.PageDown===b){for(;l>e;e++)if(m===k[e]){e+=f,e=e>l-1?l-1:e,j=k[e];break}}else if(mb.EventKeyCode.PageUp===b)for(e=l;e>=0;e--)if(m===k[e]){e-=f,e=0>e?0:e,j=k[e];break}}else mb.EventKeyCode.Down===b||mb.EventKeyCode.Insert===b||mb.EventKeyCode.Home===b||mb.EventKeyCode.PageUp===b?j=k[0]:(mb.EventKeyCode.Up===b||mb.EventKeyCode.End===b||mb.EventKeyCode.PageDown===b)&&(j=k[k.length-1]);j?(m&&(c?(mb.EventKeyCode.Up===b||mb.EventKeyCode.Down===b)&&m.checked(!m.checked()):mb.EventKeyCode.Insert===b&&m.checked(!m.checked())),this.throttleSelection=!0,this.selectedItem(j),this.throttleSelection=!0,0!==this.iSelectTimer?(a.clearTimeout(this.iSelectTimer),this.iSelectTimer=a.setTimeout(function(){d.iSelectTimer=0,d.actionClick(j)},1e3)):(this.iSelectTimer=a.setTimeout(function(){d.iSelectTimer=0},200),this.actionClick(j)),this.scrollToSelected()):m&&(!c||mb.EventKeyCode.Up!==b&&mb.EventKeyCode.Down!==b?mb.EventKeyCode.Insert===b&&m.checked(!m.checked()):m.checked(!m.checked()))},k.prototype.scrollToSelected=function(){if(!this.oContentVisible||!this.oContentScrollable)return!1;var a=20,c=b(this.sItemSelectedSelector,this.oContentScrollable),d=c.position(),e=this.oContentVisible.height(),f=c.outerHeight();return d&&(d.top<0||d.top+f>e)?(d.top<0?this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop()+d.top-a):this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop()+d.top-e+f+a),!0):!1},k.prototype.eventClickFunction=function(a,b){var c=this.getItemUid(a),d=0,e=0,f=null,g="",h=!1,i=!1,j=[],k=!1;if(b&&b.shiftKey&&""!==c&&""!==this.sLastUid&&c!==this.sLastUid)for(j=this.list(),k=a.checked(),d=0,e=j.length;e>d;d++)f=j[d],g=this.getItemUid(f),h=!1,(g===this.sLastUid||g===c)&&(h=!0),h&&(i=!i),(i||h)&&f.checked(k);this.sLastUid=""===c?"":c},k.prototype.actionClick=function(a,b){if(a){var c=!0,d=this.getItemUid(a);b&&(b.shiftKey?(c=!1,""===this.sLastUid&&(this.sLastUid=d),a.checked(!a.checked()),this.eventClickFunction(a,b)):b.ctrlKey&&(c=!1,this.sLastUid=d,a.checked(!a.checked()))),c&&(this.selectedItem(a),this.sLastUid=d)}},k.prototype.on=function(a,b){this.oCallbacks[a]=b},l.supported=function(){return!0},l.prototype.set=function(a,c){var d=b.cookie(lb.Values.ClientSideCookieIndexName),e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[a]=c,b.cookie(lb.Values.ClientSideCookieIndexName,JSON.stringify(f),{expires:30}),e=!0}catch(g){}return e},l.prototype.get=function(a){var c=b.cookie(lb.Values.ClientSideCookieIndexName),d=null;try{d=null===c?null:JSON.parse(c),d=d&&!ob.isUnd(d[a])?d[a]:null}catch(e){}return d},m.supported=function(){return!!a.localStorage},m.prototype.set=function(b,c){var d=a.localStorage[lb.Values.ClientSideCookieIndexName]||null,e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[b]=c,a.localStorage[lb.Values.ClientSideCookieIndexName]=JSON.stringify(f),e=!0}catch(g){}return e},m.prototype.get=function(b){var c=a.localStorage[lb.Values.ClientSideCookieIndexName]||null,d=null;try{d=null===c?null:JSON.parse(c),d=d&&!ob.isUnd(d[b])?d[b]:null}catch(e){}return d},n.prototype.oDriver=null,n.prototype.set=function(a,b){return this.oDriver?this.oDriver.set("p"+a,b):!1},n.prototype.get=function(a){return this.oDriver?this.oDriver.get("p"+a):null},o.prototype.bootstart=function(){},p.prototype.sPosition="",p.prototype.sTemplate="",p.prototype.viewModelName="",p.prototype.viewModelDom=null,p.prototype.viewModelTemplate=function(){return this.sTemplate},p.prototype.viewModelPosition=function(){return this.sPosition},p.prototype.cancelCommand=p.prototype.closeCommand=function(){},q.prototype.oCross=null,q.prototype.sScreenName="",q.prototype.aViewModels=[],q.prototype.viewModels=function(){return this.aViewModels},q.prototype.screenName=function(){return this.sScreenName},q.prototype.routes=function(){return null},q.prototype.__cross=function(){return this.oCross},q.prototype.__start=function(){var a=this.routes(),b=null,c=null;ob.isNonEmptyArray(a)&&(c=h.bind(this.onRoute||ob.emptyFunction,this),b=d.create(),h.each(a,function(a){b.addRoute(a[0],c).rules=a[1]}),this.oCross=b)},r.constructorEnd=function(a){ob.isFunc(a.__constructor_end)&&a.__constructor_end.call(a)},r.prototype.sDefaultScreenName="",r.prototype.oScreens={},r.prototype.oBoot=null,r.prototype.oCurrentScreen=null,r.prototype.showLoading=function(){b("#rl-loading").show()},r.prototype.hideLoading=function(){b("#rl-loading").hide()},r.prototype.routeOff=function(){e.changed.active=!1},r.prototype.routeOn=function(){e.changed.active=!0},r.prototype.setBoot=function(a){return ob.isNormal(a)&&(this.oBoot=a),this},r.prototype.screen=function(a){return""===a||ob.isUnd(this.oScreens[a])?null:this.oScreens[a]},r.prototype.delegateRun=function(a,b,c){a&&a[b]&&a[b].apply(a,ob.isArray(c)?c:[])},r.prototype.buildViewModel=function(a,d){if(a&&!a.__builded){var e=new a(d),f=e.viewModelPosition(),g=b("#rl-content #rl-"+f.toLowerCase()),h=null;a.__builded=!0,a.__vm=e,e.data=Ab.data(),e.viewModelName=a.__name,g&&1===g.length?(h=b(" ").addClass("rl-view-model").addClass("RL-"+e.viewModelTemplate()).hide().attr("data-bind",'template: {name: "'+e.viewModelTemplate()+'"}, i18nInit: true'),h.appendTo(g),e.viewModelDom=h,a.__dom=h,"Popups"===f&&(e.cancelCommand=e.closeCommand=ob.createCommand(e,function(){tb.hideScreenPopup(a)})),pb.runHook("view-model-pre-build",[a.__name,e,h]),c.applyBindings(e,h[0]),this.delegateRun(e,"onBuild",[h]),pb.runHook("view-model-post-build",[a.__name,e,h])):ob.log("Cannot find view model position: "+f)}return a?a.__vm:null},r.prototype.applyExternal=function(a,b){a&&b&&c.applyBindings(a,b)},r.prototype.hideScreenPopup=function(a){a&&a.__vm&&a.__dom&&(a.__dom.hide(),a.__vm.modalVisibility(!1),this.delegateRun(a.__vm,"onHide"),this.popupVisibility(!1))},r.prototype.showScreenPopup=function(a,b){a&&(this.buildViewModel(a),a.__vm&&a.__dom&&(a.__dom.show(),a.__vm.modalVisibility(!0),this.delegateRun(a.__vm,"onShow",b||[]),this.popupVisibility(!0),pb.runHook("view-model-on-show",[a.__name,a.__vm,b||[]])))},r.prototype.screenOnRoute=function(a,b){var c=this,d=null,e=null;""===ob.pString(a)&&(a=this.sDefaultScreenName),""!==a&&(d=this.screen(a),d||(d=this.screen(this.sDefaultScreenName),d&&(b=a+"/"+b,a=this.sDefaultScreenName)),d&&d.__started&&(d.__builded||(d.__builded=!0,ob.isNonEmptyArray(d.viewModels())&&h.each(d.viewModels(),function(a){this.buildViewModel(a,d)},this),this.delegateRun(d,"onBuild")),h.defer(function(){c.oCurrentScreen&&(c.delegateRun(c.oCurrentScreen,"onHide"),ob.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.hide(),a.__vm.viewModelVisibility(!1),c.delegateRun(a.__vm,"onHide"))})),c.oCurrentScreen=d,c.oCurrentScreen&&(c.delegateRun(c.oCurrentScreen,"onShow"),pb.runHook("screen-on-show",[c.oCurrentScreen.screenName(),c.oCurrentScreen]),ob.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.show(),a.__vm.viewModelVisibility(!0),c.delegateRun(a.__vm,"onShow"),pb.runHook("view-model-on-show",[a.__name,a.__vm]))},c)),e=d.__cross(),e&&e.parse(b)})))},r.prototype.startScreens=function(a){h.each(a,function(a){var b=new a,c=b?b.screenName():"";b&&""!==c&&(""===this.sDefaultScreenName&&(this.sDefaultScreenName=c),this.oScreens[c]=b)},this),h.each(this.oScreens,function(a){a&&!a.__started&&a.__start&&(a.__started=!0,a.__start(),pb.runHook("screen-pre-start",[a.screenName(),a]),this.delegateRun(a,"onStart"),pb.runHook("screen-post-start",[a.screenName(),a]))},this);var b=d.create();b.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/,h.bind(this.screenOnRoute,this)),e.initialized.add(b.parse,b),e.changed.add(b.parse,b),e.init()},r.prototype.setHash=function(a,b,c){a="#"===a.substr(0,1)?a.substr(1):a,a="/"===a.substr(0,1)?a.substr(1):a,c=ob.isUnd(c)?!1:!!c,(ob.isUnd(b)?1:!b)?(e.changed.active=!0,e[c?"replaceHash":"setHash"](a),e.setHash(a)):(e.changed.active=!1,e[c?"replaceHash":"setHash"](a),e.changed.active=!0)},r.prototype.bootstart=function(){return this.oBoot&&this.oBoot.bootstart&&this.oBoot.bootstart(),this},tb=new r,s.newInstanceFromJson=function(a){var b=new s;return b.initByJson(a)?b:null},s.prototype.name="",s.prototype.email="",s.prototype.privateType=null,s.prototype.clear=function(){this.email="",this.name="",this.privateType=null},s.prototype.validate=function(){return""!==this.name||""!==this.email},s.prototype.hash=function(a){return"#"+(a?"":this.name)+"#"+this.email+"#"},s.prototype.clearDuplicateName=function(){this.name===this.email&&(this.name="")},s.prototype.type=function(){return null===this.privateType&&(this.email&&"@facebook.com"===this.email.substr(-13)&&(this.privateType=mb.EmailType.Facebook),null===this.privateType&&(this.privateType=mb.EmailType.Default)),this.privateType},s.prototype.search=function(a){return-1<(this.name+" "+this.email).toLowerCase().indexOf(a.toLowerCase())},s.prototype.parse=function(a){this.clear(),a=ob.trim(a);var b=/(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g,c=b.exec(a);c?(this.name=c[1]||"",this.email=c[2]||"",this.clearDuplicateName()):/^[^@]+@[^@]+$/.test(a)&&(this.name="",this.email=a)},s.prototype.initByJson=function(a){var b=!1;return a&&"Object/Email"===a["@Object"]&&(this.name=ob.trim(a.Name),this.email=ob.trim(a.Email),b=""!==this.email,this.clearDuplicateName()),b},s.prototype.toLine=function(a,b,c){var d="";return""!==this.email&&(b=ob.isUnd(b)?!1:!!b,c=ob.isUnd(c)?!1:!!c,a&&""!==this.name?d=b?'")+'" target="_blank" tabindex="-1">'+ob.encodeHtml(this.name)+"":c?ob.encodeHtml(this.name):this.name:(d=this.email,""!==this.name?b?d=ob.encodeHtml('"'+this.name+'" <')+'")+'" target="_blank" tabindex="-1">'+ob.encodeHtml(d)+""+ob.encodeHtml(">"):(d='"'+this.name+'" <'+d+">",c&&(d=ob.encodeHtml(d))):b&&(d=''+ob.encodeHtml(this.email)+""))),d},s.prototype.select2Result=function(){var a="",b=Ab.cache().getUserPic(this.email);return a+=""!==b?'':'
',mb.EmailType.Facebook===this.type()?(a+=""+(0
'):a+=""+(0 ('+this.name+")":this.email),a+""},s.prototype.select2Selection=function(a){var c="";if(mb.EmailType.Facebook===this.type()){if(c=0 ").text(c).appendTo(a),a.append(''),null}else c=0 b&&(b+=d),d="undefined"==typeof c?d:0>c?c+d:c+b,b>=a.length||0>b||b>d?!1:a.slice(b,d)},c=function(a,b,c,d){return 0>c&&(c+=a.length),d=void 0!==d?d:a.length,0>d&&(d=d+a.length-c),a.slice(0,c)+b.substr(0,d)+b.slice(d)+a.slice(c+d)},d="",e="",f="",g=!1,h=!1,i=!1,j=null,k=0,l=0,m=0;m 0&&0===d.length&&(d=b(a,0,m)),h=!0,k=m);break;case">":h&&(l=m,e=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,h=!1);break;case"(":g||h||i||(i=!0,k=m);break;case")":i&&(l=m,f=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,i=!1);break;case"\\":m++}m++}return 0===e.length&&(j=a.match(/[^@\s]+@\S+/i),j&&j[0]?e=j[0]:d=a),e.length>0&&0===d.length&&0===f.length&&(d=a.replace(e,"")),e=ob.trim(e).replace(/^[<]+/,"").replace(/[>]+$/,""),d=ob.trim(d).replace(/^["']+/,"").replace(/["']+$/,""),f=ob.trim(f).replace(/^[(]+/,"").replace(/[)]+$/,""),d=d.replace(/\\\\(.)/,"$1"),f=f.replace(/\\\\(.)/,"$1"),this.name=d,this.email=e,this.clearDuplicateName(),!0},s.prototype.inputoTagLine=function(){return 0 +$/,""),b=!0),b},v.prototype.isImage=function(){return-1 e;e++)d.push(a[e].toLine(b,c));return d.join(", ")},x.initEmailsFromJson=function(a){var b=0,c=0,d=null,e=[];if(ob.isNonEmptyArray(a))for(b=0,c=a.length;c>b;b++)d=s.newInstanceFromJson(a[b]),d&&e.push(d);return e},x.replyHelper=function(a,b,c){if(a&&0 d;d++)ob.isUnd(b[a[d].email])&&(b[a[d].email]=!0,c.push(a[d]))},x.prototype.initByJson=function(a){var b=!1;return a&&"Object/Message"===a["@Object"]&&(this.folderFullNameRaw=a.Folder,this.uid=a.Uid,this.requestHash=a.RequestHash,this.prefetched=!1,this.size(ob.pInt(a.Size)),this.from=x.initEmailsFromJson(a.From),this.to=x.initEmailsFromJson(a.To),this.cc=x.initEmailsFromJson(a.Cc),this.bcc=x.initEmailsFromJson(a.Bcc),this.replyTo=x.initEmailsFromJson(a.ReplyTo),this.subject(a.Subject),this.dateTimeStampInUTC(ob.pInt(a.DateTimeStampInUTC)),this.hasAttachments(!!a.HasAttachments),this.attachmentsMainType(a.AttachmentsMainType),this.fromEmailString(x.emailsToLine(this.from,!0)),this.toEmailsString(x.emailsToLine(this.to,!0)),this.parentUid(ob.pInt(a.ParentThread)),this.threads(ob.isArray(a.Threads)?a.Threads:[]),this.threadsLen(ob.pInt(a.ThreadsLen)),this.initFlagsByJson(a),this.computeSenderEmail(),b=!0),b},x.prototype.computeSenderEmail=function(){var a=Ab.data().sentFolder(),b=Ab.data().draftFolder();this.senderEmailsString(this.folderFullNameRaw===a||this.folderFullNameRaw===b?this.toEmailsString():this.fromEmailString())},x.prototype.initUpdateByMessageJson=function(a){var b=!1,c=mb.MessagePriority.Normal;return a&&"Object/Message"===a["@Object"]&&(c=ob.pInt(a.Priority),this.priority(-1 b;b++)d=v.newInstanceFromJson(a["@Collection"][b]),d&&(""!==d.cidWithOutTags&&0 +$/,""),b=h.find(c,function(b){return a===b.cidWithOutTags})),b||null},x.prototype.findAttachmentByContentLocation=function(a){var b=null,c=this.attachments();return ob.isNonEmptyArray(c)&&(b=h.find(c,function(b){return a===b.contentLocation})),b||null},x.prototype.messageId=function(){return this.sMessageId},x.prototype.inReplyTo=function(){return this.sInReplyTo},x.prototype.references=function(){return this.sReferences},x.prototype.fromAsSingleEmail=function(){return ob.isArray(this.from)&&this.from[0]?this.from[0].email:""},x.prototype.viewLink=function(){return Ab.link().messageViewLink(this.requestHash)},x.prototype.downloadLink=function(){return Ab.link().messageDownloadLink(this.requestHash)},x.prototype.replyEmails=function(a){var b=[],c=ob.isUnd(a)?{}:a;return x.replyHelper(this.replyTo,c,b),0===b.length&&x.replyHelper(this.from,c,b),b},x.prototype.replyAllEmails=function(a){var b=[],c=[],d=ob.isUnd(a)?{}:a;return x.replyHelper(this.replyTo,d,b),0===b.length&&x.replyHelper(this.from,d,b),x.replyHelper(this.to,d,b),x.replyHelper(this.cc,d,c),[b,c]},x.prototype.textBodyToString=function(){return this.body?this.body.html():""},x.prototype.attachmentsToStringLine=function(){var a=h.map(this.attachments(),function(a){return a.fileName+" ("+a.friendlySize+")"});return a&&0 =0&&e&&!f&&d.attr("src",e)}),c&&a.setTimeout(function(){d.print()},100))})},x.prototype.printMessage=function(){this.viewPopupMessage(!0)},x.prototype.generateUid=function(){return this.folderFullNameRaw+"/"+this.uid},x.prototype.populateByMessageListItem=function(a){return this.folderFullNameRaw=a.folderFullNameRaw,this.uid=a.uid,this.requestHash=a.requestHash,this.subject(a.subject()),this.size(a.size()),this.dateTimeStampInUTC(a.dateTimeStampInUTC()),this.priority(a.priority()),this.fromEmailString(a.fromEmailString()),this.toEmailsString(a.toEmailsString()),this.emails=a.emails,this.from=a.from,this.to=a.to,this.cc=a.cc,this.bcc=a.bcc,this.replyTo=a.replyTo,this.unseen(a.unseen()),this.flagged(a.flagged()),this.answered(a.answered()),this.forwarded(a.forwarded()),this.selected(a.selected()),this.checked(a.checked()),this.hasAttachments(a.hasAttachments()),this.attachmentsMainType(a.attachmentsMainType()),this.moment(a.moment()),this.body=null,this.priority(mb.MessagePriority.Normal),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid(a.parentUid()),this.threads(a.threads()),this.threadsLen(a.threadsLen()),this.computeSenderEmail(),this},x.prototype.showExternalImages=function(a){this.body&&this.body.data("rl-has-images")&&(a=ob.isUnd(a)?!1:a,this.hasImages(!1),this.body.data("rl-has-images",!1),b("[data-x-src]",this.body).each(function(){a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",b(this).attr("data-x-src")).removeAttr("data-x-src"):b(this).attr("src",b(this).attr("data-x-src")).removeAttr("data-x-src")}),b("[data-x-style-url]",this.body).each(function(){var a=ob.trim(b(this).attr("style"));a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+b(this).attr("data-x-style-url")).removeAttr("data-x-style-url")}),a&&(b("img.lazy",this.body).addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b(".RL-MailMessageView .messageView .messageItem .content")[0]}),xb.resize()),ob.windowResize(500))},x.prototype.showInternalImages=function(a){if(this.body&&!this.body.data("rl-init-internal-images")){a=ob.isUnd(a)?!1:a;var c=this;this.body.data("rl-init-internal-images",!0),b("[data-x-src-cid]",this.body).each(function(){var d=c.findAttachmentByCid(b(this).attr("data-x-src-cid"));d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-src-location]",this.body).each(function(){var d=c.findAttachmentByContentLocation(b(this).attr("data-x-src-location"));d||(d=c.findAttachmentByCid(b(this).attr("data-x-src-location"))),d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-style-cid]",this.body).each(function(){var a="",d="",e=c.findAttachmentByCid(b(this).attr("data-x-style-cid"));e&&e.linkPreview&&(d=b(this).attr("data-x-style-cid-name"),""!==d&&(a=ob.trim(b(this).attr("style")),a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+d+": url('"+e.linkPreview()+"')")))}),a&&!function(a,b){h.delay(function(){a.addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b})},300)}(b("img.lazy",c.body),b(".RL-MailMessageView .messageView .messageItem .content")[0]),ob.windowResize(500)}},y.newInstanceFromJson=function(a){var b=new y;return b.initByJson(a)?b.initComputed():null},y.prototype.initComputed=function(){return this.hasSubScribedSubfolders=c.computed(function(){return!!h.find(this.subFolders(),function(a){return a.subScribed()})},this),this.visible=c.computed(function(){var a=this.subScribed(),b=this.hasSubScribedSubfolders();return a||b&&(!this.existen||!this.selectable)},this),this.isSystemFolder=c.computed(function(){return mb.FolderType.User!==this.type()},this),this.hidden=c.computed(function(){var a=this.isSystemFolder(),b=this.hasSubScribedSubfolders();return this.isGmailFolder||a&&this.isNamespaceFolder||a&&!b },this),this.selectableForFolderList=c.computed(function(){return!this.isSystemFolder()&&this.selectable},this),this.messageCountAll=c.computed({read:this.privateMessageCountAll,write:function(a){ob.isPosNumeric(a,!0)?this.privateMessageCountAll(a):this.privateMessageCountAll.valueHasMutated()},owner:this}),this.messageCountUnread=c.computed({read:this.privateMessageCountUnread,write:function(a){ob.isPosNumeric(a,!0)?this.privateMessageCountUnread(a):this.privateMessageCountUnread.valueHasMutated()},owner:this}),this.printableUnreadCount=c.computed(function(){var a=this.messageCountAll(),b=this.messageCountUnread(),c=this.type();return b>0&&(mb.FolderType.Inbox===c||mb.FolderType.Spam===c)?""+b:a>0&&mb.FolderType.Draft===c?""+a:""},this),this.canBeDeleted=c.computed(function(){var a=this.isSystemFolder();return!a&&0===this.subFolders().length&&"INBOX"!==this.fullNameRaw},this),this.canBeSubScribed=c.computed(function(){return!this.isSystemFolder()&&this.selectable&&"INBOX"!==this.fullNameRaw},this),this.visible.subscribe(function(){ob.timeOutAction("folder-list-folder-visibility-change",function(){xb.trigger("folder-list-folder-visibility-change")},100)}),this.localName=c.computed(function(){rb.langChangeTick();var a=this.type(),b=this.name();if(this.isSystemFolder())switch(a){case mb.FolderType.Inbox:b=ob.i18n("FOLDER_LIST/INBOX_NAME");break;case mb.FolderType.SentItems:b=ob.i18n("FOLDER_LIST/SENT_NAME");break;case mb.FolderType.Draft:b=ob.i18n("FOLDER_LIST/DRAFTS_NAME");break;case mb.FolderType.Spam:b=ob.i18n("FOLDER_LIST/SPAM_NAME");break;case mb.FolderType.Trash:b=ob.i18n("FOLDER_LIST/TRASH_NAME")}return b},this),this.manageFolderSystemName=c.computed(function(){rb.langChangeTick();var a="",b=this.type(),c=this.name();if(this.isSystemFolder())switch(b){case mb.FolderType.Inbox:a="("+ob.i18n("FOLDER_LIST/INBOX_NAME")+")";break;case mb.FolderType.SentItems:a="("+ob.i18n("FOLDER_LIST/SENT_NAME")+")";break;case mb.FolderType.Draft:a="("+ob.i18n("FOLDER_LIST/DRAFTS_NAME")+")";break;case mb.FolderType.Spam:a="("+ob.i18n("FOLDER_LIST/SPAM_NAME")+")";break;case mb.FolderType.Trash:a="("+ob.i18n("FOLDER_LIST/TRASH_NAME")+")"}return(""!==a&&"("+c+")"===a||"(inbox)"===a.toLowerCase())&&(a=""),a},this),this.collapsed=c.computed({read:function(){return!this.hidden()&&this.collapsedPrivate()},write:function(a){this.collapsedPrivate(a)},owner:this}),this},y.prototype.fullName="",y.prototype.fullNameRaw="",y.prototype.fullNameHash="",y.prototype.delimiter="",y.prototype.namespace="",y.prototype.deep=0,y.prototype.isNamespaceFolder=!1,y.prototype.isGmailFolder=!1,y.prototype.isUnpaddigFolder=!1,y.prototype.collapsedCss=function(){return this.hasSubScribedSubfolders()?this.collapsed()?"icon-arrow-right-3 e-collapsed-sign":"icon-arrow-down-3 e-collapsed-sign":"icon-none e-collapsed-sign"},y.prototype.initByJson=function(a){var b=!1;return a&&"Object/Folder"===a["@Object"]&&(this.name(a.Name),this.delimiter=a.Delimiter,this.fullName=a.FullName,this.fullNameRaw=a.FullNameRaw,this.fullNameHash=a.FullNameHash,this.deep=a.FullNameRaw.split(this.delimiter).length-1,this.selectable=!!a.IsSelectable,this.existen=!!a.IsExisten,this.subScribed(!!a.IsSubscribed),this.type("INBOX"===this.fullNameRaw?mb.FolderType.Inbox:mb.FolderType.User),b=!0),b},y.prototype.printableFullName=function(){return this.fullName.split(this.delimiter).join(" / ")},z.prototype.email="",z.prototype.changeAccountLink=function(){return Ab.link().change(this.email)},A.prototype.formattedName=function(){var a=this.name();return""===a?this.email():a+" <"+this.email()+">"},A.prototype.formattedNameForCompose=function(){var a=this.name();return""===a?this.email():a+" ("+this.email()+")"},A.prototype.formattedNameForEmail=function(){var a=this.name();return""===a?this.email():'"'+ob.quoteName(a)+'" <'+this.email()+">"},ob.extendAsViewModel("PopupsFolderClearViewModel",B),B.prototype.clearPopup=function(){this.clearingProcess(!1),this.selectedFolder(null)},B.prototype.onShow=function(a){this.clearPopup(),a&&this.selectedFolder(a)},ob.extendAsViewModel("PopupsFolderCreateViewModel",C),C.prototype.sNoParentText="",C.prototype.simpleFolderNameValidation=function(a){return/^[^\\\/]+$/g.test(ob.trim(a))},C.prototype.clearPopup=function(){this.folderName(""),this.selectedParentValue(""),this.focusTrigger(!1)},C.prototype.onShow=function(){this.clearPopup(),this.focusTrigger(!0)},ob.extendAsViewModel("PopupsFolderSystemViewModel",D),D.prototype.sChooseOnText="",D.prototype.sUnuseText="",D.prototype.onShow=function(a){var b="";switch(a=ob.isUnd(a)?mb.SetSystemFoldersNotification.None:a){case mb.SetSystemFoldersNotification.Sent:b=ob.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SENT");break;case mb.SetSystemFoldersNotification.Draft:b=ob.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_DRAFTS");break;case mb.SetSystemFoldersNotification.Spam:b=ob.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SPAM");break;case mb.SetSystemFoldersNotification.Trash:b=ob.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_TRASH")}this.notification(b)},ob.extendAsViewModel("PopupsComposeViewModel",E),E.prototype.findIdentityIdByMessage=function(a,b){var c={},d="",e=function(a){return a&&a.email&&c[a.email]?(d=c[a.email],!0):!1};switch(this.bAllowIdentities&&h.each(this.identities(),function(a){c[a.email()]=a.id}),c[Ab.data().accountEmail()]=Ab.data().accountEmail(),a){case mb.ComposeType.Empty:d=Ab.data().accountEmail();break;case mb.ComposeType.Reply:case mb.ComposeType.ReplyAll:case mb.ComposeType.Forward:case mb.ComposeType.ForwardAsAttachment:h.find(h.union(b.to,b.cc,b.bcc),e);break;case mb.ComposeType.Draft:h.find(h.union(b.from,b.replyTo),e)}return d},E.prototype.selectIdentity=function(a){a&&this.currentIdentityID(a.optValue)},E.prototype.formattedFrom=function(a){var b=Ab.data().displayName(),c=Ab.data().accountEmail();return""===b?c:(ob.isUnd(a)?1:!a)?b+" ("+c+")":'"'+ob.quoteName(b)+'" <'+c+">"},E.prototype.sendMessageResponse=function(b,c){var d=!1;this.sending(!1),mb.StorageResultType.Success===b&&c&&c.Result&&(d=!0,this.modalVisibility()&&tb.delegateRun(this,"closeCommand")),this.modalVisibility()&&!d&&(c&&mb.Notification.CantSaveMessage===c.ErrorCode?(this.sendSuccessButSaveError(!0),a.alert(ob.trim(ob.i18n("COMPOSE/SAVED_ERROR_ON_SEND")))):(this.sendError(!0),a.alert(ob.getNotification(c&&c.ErrorCode?c.ErrorCode:mb.Notification.CantSendMessage))))},E.prototype.saveMessageResponse=function(b,c){var d=!1,e=null;this.saving(!1),mb.StorageResultType.Success===b&&c&&c.Result&&c.Result.NewFolder&&c.Result.NewUid&&(this.bFromDraft&&(e=Ab.data().message(),e&&this.draftFolder()===e.folderFullNameRaw&&this.draftUid()===e.uid&&Ab.data().message(null)),this.draftFolder(c.Result.NewFolder),this.draftUid(c.Result.NewUid),this.draftID(c.Result.NewID),this.modalVisibility()&&(this.savedTime(Math.round((new a.Date).getTime()/1e3)),this.savedOrSendingText(0 b;b++)d.push(a[b].toLine(!1));return d.join(", ")};if(c=c||null,c&&ob.isNormal(c)&&(t=ob.isArray(c)&&1===c.length?c[0]:ob.isArray(c)?null:c),null!==q&&(p[q]=!0,this.currentIdentityID(this.findIdentityIdByMessage(v,t))),this.reset(),ob.isNonEmptyArray(d)&&this.to(w(d)),""!==v&&t){switch(j=t.fullFormatDateValue(),k=t.subject(),s=t.aDraftInfo,l=b(t.body).clone(),ob.removeBlockquoteSwitcher(l),m=l.html(),v){case mb.ComposeType.Empty:break;case mb.ComposeType.Reply:this.to(w(t.replyEmails(p))),this.subject(ob.replySubjectAdd("Re",k)),this.prepearMessageAttachments(t,v),this.aDraftInfo=["reply",t.uid,t.folderFullNameRaw],this.sInReplyTo=t.sMessageId,this.sReferences=ob.trim(this.sInReplyTo+" "+t.sReferences),u=!0;break;case mb.ComposeType.ReplyAll:o=t.replyAllEmails(p),this.to(w(o[0])),this.cc(w(o[1])),this.subject(ob.replySubjectAdd("Re",k)),this.prepearMessageAttachments(t,v),this.aDraftInfo=["reply",t.uid,t.folderFullNameRaw],this.sInReplyTo=t.sMessageId,this.sReferences=ob.trim(this.sInReplyTo+" "+t.references()),u=!0;break;case mb.ComposeType.Forward:this.subject(ob.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(t,v),this.aDraftInfo=["forward",t.uid,t.folderFullNameRaw],this.sInReplyTo=t.sMessageId,this.sReferences=ob.trim(this.sInReplyTo+" "+t.sReferences);break;case mb.ComposeType.ForwardAsAttachment:this.subject(ob.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(t,v),this.aDraftInfo=["forward",t.uid,t.folderFullNameRaw],this.sInReplyTo=t.sMessageId,this.sReferences=ob.trim(this.sInReplyTo+" "+t.sReferences);break;case mb.ComposeType.Draft:this.to(w(t.to)),this.cc(w(t.cc)),this.bcc(w(t.bcc)),this.bFromDraft=!0,this.draftFolder(t.folderFullNameRaw),this.draftUid(t.uid),this.draftID(t.messageId()),this.subject(k),this.prepearMessageAttachments(t,v),this.aDraftInfo=ob.isNonEmptyArray(s)&&3===s.length?s:null,this.sInReplyTo=t.sInReplyTo,this.sReferences=t.sReferences}if(this.oEditor){switch(v){case mb.ComposeType.Reply:case mb.ComposeType.ReplyAll:f=t.fromToLine(!1,!0),n=ob.i18n("COMPOSE/REPLY_MESSAGE_TITLE",{DATETIME:j,EMAIL:f}),m="
"+n+":";break;case mb.ComposeType.Forward:f=t.fromToLine(!1,!0),g=t.toToLine(!1,!0),i=t.ccToLine(!1,!0),m="
"+m+"
"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TITLE")+"
"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_FROM")+": "+f+"
"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TO")+": "+g+(0"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_CC")+": "+i:"")+"
"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SENT")+": "+ob.encodeHtml(j)+"
"+ob.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT")+": "+ob.encodeHtml(k)+"
"+m;break;case mb.ComposeType.ForwardAsAttachment:m=""}this.oEditor.setRawText(m,t.isHtml())}}else this.oEditor&&mb.ComposeType.Empty===v?this.oEditor.setRawText("
"+ob.convertPlainTextToHtml(Ab.data().signature()),mb.EditorDefaultType.Html===Ab.data().editorDefaultType()):ob.isNonEmptyArray(c)&&h.each(c,function(a){e.addMessageAsAttachment(a)});r=this.getAttachmentsDownloadsForUpload(),ob.isNonEmptyArray(r)&&Ab.remote().messageUploadAttachments(function(a,b){if(mb.StorageResultType.Success===a&&b&&b.Result){var c=null,d="";if(!e.viewModelVisibility())for(d in b.Result)b.Result.hasOwnProperty(d)&&(c=e.getAttachmentById(b.Result[d]),c&&c.tempName(d))}else e.setMessageAttachmentFailedDowbloadText()},r),u&&this.oEditor&&this.oEditor.focus(),this.triggerForResize()},E.prototype.onBuild=function(){this.initEditor(),this.initUploader();var a=this,c=null;xb.on("keydown",function(b){var c=!0;return b&&a.modalVisibility()&&Ab.data().useKeyboardShortcuts()&&(b.ctrlKey&&mb.EventKeyCode.S===b.keyCode?(a.saveCommand(),c=!1):b.ctrlKey&&mb.EventKeyCode.Enter===b.keyCode&&(a.sendCommand(),c=!1)),c}),xb.on("resize",function(){a.triggerForResize()}),this.dropboxEnabled()&&(c=document.createElement("script"),c.type="text/javascript",c.src="https://www.dropbox.com/static/api/1/dropins.js",b(c).attr("id","dropboxjs").attr("data-app-key",Ab.settingsGet("DropboxApiKey")),document.body.appendChild(c))},E.prototype.getAttachmentById=function(a){for(var b=this.attachments(),c=0,d=b.length;d>c;c++)if(b[c]&&a===b[c].id)return b[c];return null},E.prototype.initEditor=function(){if(this.composeEditorTextArea()&&this.composeEditorHtmlArea()&&this.composeEditorToolbar()){var a=this;this.oEditor=new j(this.composeEditorTextArea(),this.composeEditorHtmlArea(),this.composeEditorToolbar(),{onSwitch:function(b){b||a.removeLinkedAttachments()}}),this.oEditor.initLanguage(ob.i18n("EDITOR/TEXT_SWITCHER_CONFIRM"),ob.i18n("EDITOR/TEXT_SWITCHER_PLAINT_TEXT"),ob.i18n("EDITOR/TEXT_SWITCHER_RICH_FORMATTING"))}},E.prototype.initUploader=function(){if(this.composeUploaderButton()){var a={},b=ob.pInt(Ab.settingsGet("AttachmentLimit")),c=new g({action:Ab.link().upload(),name:"uploader",queueSize:2,multipleSizeLimit:50,disableFolderDragAndDrop:!1,clickElement:this.composeUploaderButton(),dragAndDropElement:this.composeUploaderDropPlace()});c?(c.on("onDragEnter",h.bind(function(){this.dragAndDropOver(!0)},this)).on("onDragLeave",h.bind(function(){this.dragAndDropOver(!1)},this)).on("onBodyDragEnter",h.bind(function(){this.dragAndDropVisible(!0)},this)).on("onBodyDragLeave",h.bind(function(){this.dragAndDropVisible(!1)},this)).on("onProgress",h.bind(function(b,c,d){var e=null;ob.isUnd(a[b])?(e=this.getAttachmentById(b),e&&(a[b]=e)):e=a[b],e&&e.progress(" - "+Math.floor(c/d*100)+"%")},this)).on("onSelect",h.bind(function(a,d){this.dragAndDropOver(!1);var e=this,f=ob.isUnd(d.FileName)?"":d.FileName.toString(),g=ob.isNormal(d.Size)?ob.pInt(d.Size):null,h=new w(a,f,g);return h.cancel=function(a){return function(){e.attachments.remove(function(b){return b&&b.id===a}),c&&c.cancel(a)}}(a),this.attachments.push(h),g>0&&b>0&&g>b?(h.error(ob.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):!0},this)).on("onStart",h.bind(function(b){var c=null;ob.isUnd(a[b])?(c=this.getAttachmentById(b),c&&(a[b]=c)):c=a[b],c&&(c.waiting(!1),c.uploading(!0))},this)).on("onComplete",h.bind(function(b,c,d){var e="",f=null,g=null,h=this.getAttachmentById(b);g=c&&d&&d.Result&&d.Result.Attachment?d.Result.Attachment:null,f=d&&d.Result&&d.Result.ErrorCode?d.Result.ErrorCode:null,null!==f?e=ob.getUploadErrorDescByCode(f):g||(e=ob.i18n("UPLOAD/ERROR_UNKNOWN")),h&&(""!==e&&00&&d>0&&f>d?(e.uploading(!1),e.error(ob.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):(Ab.remote().composeUploadExternals(function(a,b){var c=!1;e.uploading(!1),mb.StorageResultType.Success===a&&b&&b.Result&&b.Result[e.id]&&(c=!0,e.tempName(b.Result[e.id])),c||e.error(ob.getUploadErrorDescByCode(mb.UploadErrorCode.FileNoUploaded))},[a.link]),!0)},E.prototype.prepearMessageAttachments=function(a,b){if(a){var c=this,d=ob.isNonEmptyArray(a.attachments())?a.attachments():[],e=0,f=d.length,g=null,h=null,i=!1,j=function(a){return function(){c.attachments.remove(function(b){return b&&b.id===a})}};if(mb.ComposeType.ForwardAsAttachment===b)this.addMessageAsAttachment(a);else for(;f>e;e++){switch(h=d[e],i=!1,b){case mb.ComposeType.Reply:case mb.ComposeType.ReplyAll:i=h.isLinked;break;case mb.ComposeType.Forward:case mb.ComposeType.Draft:i=!0}i=!0,i&&(g=new w(h.download,h.fileName,h.estimatedSize,h.isInline,h.isLinked,h.cid,h.contentLocation),g.fromMessage=!0,g.cancel=j(h.download),g.waiting(!1).uploading(!0),this.attachments.push(g))}}},E.prototype.removeLinkedAttachments=function(){this.attachments.remove(function(a){return a&&a.isLinked})},E.prototype.setMessageAttachmentFailedDowbloadText=function(){h.each(this.attachments(),function(a){a&&a.fromMessage&&a.waiting(!1).uploading(!1).error(ob.getUploadErrorDescByCode(mb.UploadErrorCode.FileNoUploaded))},this)},E.prototype.isEmptyForm=function(a){a=ob.isUnd(a)?!0:!!a;var b=a?0===this.attachments().length:0===this.attachmentsInReady().length;return 0===this.to().length&&0===this.cc().length&&0===this.bcc().length&&0===this.subject().length&&b&&""===this.oEditor.getTextForRequest()},E.prototype.reset=function(){this.to(""),this.cc(""),this.bcc(""),this.replyTo(""),this.subject(""),this.aDraftInfo=null,this.sInReplyTo="",this.bFromDraft=!1,this.sReferences="",this.bReloadFolder=!1,this.sendError(!1),this.sendSuccessButSaveError(!1),this.savedError(!1),this.savedTime(0),this.savedOrSendingText(""),this.emptyToError(!1),this.showCcAndBcc(!1),this.attachments([]),this.dragAndDropOver(!1),this.dragAndDropVisible(!1),this.draftFolder(""),this.draftUid(""),this.draftID(""),this.sending(!1),this.saving(!1),this.oEditor&&this.oEditor.clear()},E.prototype.getAttachmentsDownloadsForUpload=function(){return h.map(h.filter(this.attachments(),function(a){return a&&""===a.tempName()}),function(a){return a.id})},E.prototype.triggerForResize=function(){this.resizer(!this.resizer())},ob.extendAsViewModel("PopupsContactsViewModel",F),F.prototype.addNewEmail=function(){var a=new u(mb.ContactPropertyType.EmailPersonal,"");a.focused(!0),this.viewProperties.push(a)},F.prototype.addNewPhone=function(){var a=new u(mb.ContactPropertyType.PhonePersonal,"");a.focused(!0),this.viewProperties.push(a)},F.prototype.removeCheckedOrSelectedContactsFromList=function(){var a=this,b=this.contacts,c=this.currentContact(),d=this.contacts().length,e=this.contactsCheckedOrSelected();0 =d&&(this.bDropPageAfterDelete=!0),h.delay(function(){h.each(e,function(a){b.remove(a)})},500))},F.prototype.deleteSelectedContacts=function(){0 0?d:0),b.contactsCount(d),b.contacts(e),b.viewClearSearch(""!==b.search()),b.contacts.loading(!1),""!==b.viewID()&&!b.currentContact()&&b.contacts.setSelectedByUid&&b.contacts.setSelectedByUid(""+b.viewID())},c,lb.Defaults.ContactsPerPage,this.search())},F.prototype.onBuild=function(a){this.oContentVisible=b(".b-list-content",a),this.oContentScrollable=b(".content",this.oContentVisible),this.selector.init(this.oContentVisible,this.oContentScrollable);var d=this;c.computed(function(){var a=this.modalVisibility(),b=Ab.data().useKeyboardShortcuts();this.selector.useKeyboard(a&&b)},this).extend({notify:"always"}),a.on("click",".e-pagenator .e-page",function(){var a=c.dataFor(this);a&&(d.contactsPage(ob.pInt(a.value)),d.reloadContactList())})},F.prototype.onShow=function(){tb.routeOff(),this.reloadContactList(!0)},F.prototype.onHide=function(){tb.routeOn(),this.currentContact(null),this.emptySelection(!0),this.search(""),h.each(this.contacts(),function(a){a.checked(!1)})},ob.extendAsViewModel("PopupsAdvancedSearchViewModel",G),G.prototype.buildSearchStringValue=function(a){return-1 0&&g.messageCountUnread(0<=g.messageCountUnread()-e?g.messageCountUnread()-e:0)),i&&(i.messageCountAll(i.messageCountAll()+b.length),e>0&&i.messageCountUnread(i.messageCountUnread()+e)),0