mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-29 19:12:26 +08:00
Added support for PostgreSQL and SQLite in contacts (beta)
This commit is contained in:
parent
5877ff77dd
commit
76ce119980
11 changed files with 658 additions and 148 deletions
|
@ -7,9 +7,86 @@ function AdminContacts()
|
|||
{
|
||||
// var oData = RL.data();
|
||||
|
||||
this.contactsSupported = !!RL.settingsGet('ContactsIsSupported');
|
||||
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
|
||||
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
|
||||
|
||||
var
|
||||
aTypes = ['sqlite', 'mysql', 'pgsql'],
|
||||
aSupportedTypes = [],
|
||||
getTypeName = function(sName) {
|
||||
switch (sName)
|
||||
{
|
||||
case 'sqlite':
|
||||
sName = 'SQLite';
|
||||
break;
|
||||
case 'mysql':
|
||||
sName = 'MySQL';
|
||||
break;
|
||||
case 'pgsql':
|
||||
sName = 'PostgreSQL';
|
||||
break;
|
||||
}
|
||||
|
||||
return sName;
|
||||
}
|
||||
;
|
||||
|
||||
if (!!RL.settingsGet('SQLiteIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('sqlite');
|
||||
}
|
||||
if (!!RL.settingsGet('MySqlIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('mysql');
|
||||
}
|
||||
if (!!RL.settingsGet('PostgreSqlIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('pgsql');
|
||||
}
|
||||
|
||||
this.contactsSupported = 0 < aSupportedTypes.length;
|
||||
|
||||
this.contactsTypes = ko.observableArray([]);
|
||||
this.contactsTypesOptions = this.contactsTypes.map(function (sValue) {
|
||||
var bDisabled = -1 === Utils.inArray(sValue, aSupportedTypes);
|
||||
return {
|
||||
'id': sValue,
|
||||
'name': getTypeName(sValue) + (bDisabled ? ' (not supported)' : ''),
|
||||
'disable': bDisabled
|
||||
};
|
||||
});
|
||||
|
||||
this.contactsTypes(aTypes);
|
||||
this.contactsType = ko.observable('');
|
||||
|
||||
this.mainContactsType = ko.computed({
|
||||
'owner': this,
|
||||
'read': this.contactsType,
|
||||
'write': function (sValue) {
|
||||
if (sValue !== this.contactsType())
|
||||
{
|
||||
if (-1 < Utils.inArray(sValue, aSupportedTypes))
|
||||
{
|
||||
this.contactsType(sValue);
|
||||
}
|
||||
else if (0 < aSupportedTypes.length)
|
||||
{
|
||||
this.contactsType('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.contactsType.valueHasMutated();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.contactsType.subscribe(function () {
|
||||
this.testContactsSuccess(false);
|
||||
this.testContactsError(false);
|
||||
this.testContactsErrorMessage('');
|
||||
}, this);
|
||||
|
||||
this.pdoDsn = ko.observable(RL.settingsGet('ContactsPdoDsn'));
|
||||
this.pdoUser = ko.observable(RL.settingsGet('ContactsPdoUser'));
|
||||
this.pdoPassword = ko.observable(RL.settingsGet('ContactsPdoPassword'));
|
||||
|
@ -17,6 +94,7 @@ function AdminContacts()
|
|||
this.pdoDsnTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.pdoUserTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.pdoPasswordTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.contactsTypeTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
|
||||
this.testing = ko.observable(false);
|
||||
this.testContactsSuccess = ko.observable(false);
|
||||
|
@ -31,6 +109,7 @@ function AdminContacts()
|
|||
this.testing(true);
|
||||
|
||||
RL.remote().testContacts(this.onTestContactsResponse, {
|
||||
'ContactsPdoType': this.contactsType(),
|
||||
'ContactsPdoDsn': this.pdoDsn(),
|
||||
'ContactsPdoUser': this.pdoUser(),
|
||||
'ContactsPdoPassword': this.pdoPassword()
|
||||
|
@ -40,6 +119,8 @@ function AdminContacts()
|
|||
return '' !== this.pdoDsn() && '' !== this.pdoUser();
|
||||
});
|
||||
|
||||
this.contactsType(RL.settingsGet('ContactsPdoType'));
|
||||
|
||||
this.onTestContactsResponse = _.bind(this.onTestContactsResponse, this);
|
||||
}
|
||||
|
||||
|
@ -58,7 +139,14 @@ AdminContacts.prototype.onTestContactsResponse = function (sResult, oData)
|
|||
else
|
||||
{
|
||||
this.testContactsError(true);
|
||||
this.testContactsErrorMessage(oData.Result.Message || '');
|
||||
if (oData && oData.Result)
|
||||
{
|
||||
this.testContactsErrorMessage(oData.Result.Message || '');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.testContactsErrorMessage('');
|
||||
}
|
||||
}
|
||||
|
||||
this.testing(false);
|
||||
|
@ -78,8 +166,9 @@ AdminContacts.prototype.onBuild = function ()
|
|||
|
||||
var
|
||||
f1 = Utils.settingsSaveHelperSimpleFunction(self.pdoDsnTrigger, self),
|
||||
f2 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self),
|
||||
f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self)
|
||||
f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self),
|
||||
f4 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self),
|
||||
f5 = Utils.settingsSaveHelperSimpleFunction(self.contactsTypeTrigger, self)
|
||||
;
|
||||
|
||||
self.enableContacts.subscribe(function (bValue) {
|
||||
|
@ -88,23 +177,31 @@ AdminContacts.prototype.onBuild = function ()
|
|||
});
|
||||
});
|
||||
|
||||
self.contactsType.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f5, {
|
||||
'ContactsPdoType': sValue
|
||||
});
|
||||
});
|
||||
|
||||
self.pdoDsn.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f1, {
|
||||
'ContactsPdoDsn': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
self.pdoUser.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f2, {
|
||||
RL.remote().saveAdminConfig(f3, {
|
||||
'ContactsPdoUser': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
self.pdoPassword.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f3, {
|
||||
RL.remote().saveAdminConfig(f4, {
|
||||
'ContactsPdoPassword': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsType(RL.settingsGet('ContactsPdoType'));
|
||||
|
||||
}, 50);
|
||||
};
|
||||
|
|
|
@ -402,7 +402,7 @@ ko.bindingHandlers.saveTrigger = {
|
|||
|
||||
var $oEl = $(oElement);
|
||||
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],select,textarea') ? 'input' : 'custom');
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom');
|
||||
|
||||
if ('custom' === $oEl.data('save-trigger-type'))
|
||||
{
|
||||
|
|
|
@ -233,7 +233,17 @@ class Actions
|
|||
$sUser = \trim($this->Config()->Get('contacts', 'pdo_user', ''));
|
||||
$sPassword = (string) $this->Config()->Get('contacts', 'pdo_password', '');
|
||||
|
||||
$oResult = new \RainLoop\Providers\PersonalAddressBook\PdoPersonalAddressBook($sDsn, $sUser, $sPassword);
|
||||
$sDsnType = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite')));
|
||||
if ('sqlite' === $sDsnType)
|
||||
{
|
||||
$oResult = new \RainLoop\Providers\PersonalAddressBook\PdoPersonalAddressBook(
|
||||
'sqlite:'.APP_PRIVATE_DATA.'PersonalAddressBook.sqlite', '', '', 'sqlite');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResult = new \RainLoop\Providers\PersonalAddressBook\PdoPersonalAddressBook($sDsn, $sUser, $sPassword, $sDsnType);
|
||||
}
|
||||
|
||||
$oResult->SetLogger($this->Logger());
|
||||
break;
|
||||
case 'suggestions':
|
||||
|
@ -974,10 +984,15 @@ class Actions
|
|||
$aResult['UseTokenProtection'] = (bool) $oConfig->Get('security', 'csrf_protection', true);
|
||||
$aResult['EnabledPlugins'] = (bool) $oConfig->Get('plugins', 'enable', false);
|
||||
|
||||
$aResult['ContactsIsSupported'] = (bool) $this->PersonalAddressBookProvider(null, true)->IsSupported();
|
||||
|
||||
$aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array();
|
||||
$aResult['MySqlIsSupported'] = \is_array($aDrivers) ? \in_array('mysql', $aDrivers) : false;
|
||||
$aResult['SQLiteIsSupported'] = \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false;
|
||||
$aResult['PostgreSqlIsSupported'] = \is_array($aDrivers) ? \in_array('pgsql', $aDrivers) : false;
|
||||
|
||||
$aResult['ContactsEnable'] = (bool) $oConfig->Get('contacts', 'enable', false);
|
||||
$aResult['ContactsPdoType'] = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite')));
|
||||
$aResult['ContactsPdoDsn'] = (string) $oConfig->Get('contacts', 'pdo_dsn', '');
|
||||
$aResult['ContactsPdoType'] = (string) $oConfig->Get('contacts', 'type', '');
|
||||
$aResult['ContactsPdoUser'] = (string) $oConfig->Get('contacts', 'pdo_user', '');
|
||||
$aResult['ContactsPdoPassword'] = APP_DUMMY;
|
||||
|
||||
|
@ -1854,6 +1869,10 @@ class Actions
|
|||
$this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
|
||||
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoType', 'contacts', 'type', 'string', function ($sType) use ($self) {
|
||||
return $self->ValidateContactPdoType($sType);
|
||||
});
|
||||
|
||||
$this->setConfigFromParams($oConfig, 'AllowAdditionalAccounts', 'webmail', 'allow_additional_accounts', 'bool');
|
||||
$this->setConfigFromParams($oConfig, 'AllowIdentities', 'webmail', 'allow_identities', 'bool');
|
||||
|
||||
|
@ -1941,6 +1960,11 @@ class Actions
|
|||
$this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
|
||||
|
||||
$self = $this;
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoType', 'contacts', 'type', 'string', function ($sType) use ($self) {
|
||||
return $self->ValidateContactPdoType($sType);
|
||||
});
|
||||
|
||||
$sTestMessage = $this->PersonalAddressBookProvider(null, true)->Test();
|
||||
return $this->DefaultResponse(__FUNCTION__, array(
|
||||
'Result' => '' === $sTestMessage,
|
||||
|
@ -5097,21 +5121,31 @@ class Actions
|
|||
*/
|
||||
public function ValidateTheme($sTheme)
|
||||
{
|
||||
return in_array($sTheme, $this->GetThemes()) ?
|
||||
return \in_array($sTheme, $this->GetThemes()) ?
|
||||
$sTheme : $this->Config()->Get('themes', 'default', 'Default');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sLanguage $sLanguage
|
||||
* @param string $sLanguage
|
||||
*
|
||||
* @return $sLanguage
|
||||
* @return string
|
||||
*/
|
||||
public function ValidateLanguage($sLanguage)
|
||||
{
|
||||
return in_array($sLanguage, $this->GetLanguages()) ?
|
||||
return \in_array($sLanguage, $this->GetLanguages()) ?
|
||||
$sLanguage : $this->Config()->Get('i18n', 'default', 'en');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ValidateContactPdoType($sType)
|
||||
{
|
||||
return \in_array($sType, array('mysql', 'pgsql', 'sqlite')) ? $sType : 'sqlite';
|
||||
}
|
||||
|
||||
/**
|
||||
* @staticvar array $aCache
|
||||
* @param bool $bAdmin = false
|
||||
|
|
|
@ -48,6 +48,14 @@ abstract class PdoAbstract
|
|||
return array('', '', '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function isTransactionSupported()
|
||||
{
|
||||
return \in_array($this->sDbType, array('mysql'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PDO
|
||||
*
|
||||
|
@ -67,6 +75,11 @@ abstract class PdoAbstract
|
|||
|
||||
$sType = $sDsn = $sDbLogin = $sDbPassword = '';
|
||||
list($sType, $sDsn, $sDbLogin, $sDbPassword) = $this->getPdoAccessData();
|
||||
if (!\in_array($sType, array('mysql', 'sqlite', 'pgsql')))
|
||||
{
|
||||
throw new \Exception('Unknown PDO SQL connection type');
|
||||
}
|
||||
|
||||
$this->sDbType = $sType;
|
||||
|
||||
$oPdo = false;
|
||||
|
@ -76,7 +89,7 @@ abstract class PdoAbstract
|
|||
if ($oPdo)
|
||||
{
|
||||
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
if ('mysql' === $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME))
|
||||
if ('mysql' === $sType && 'mysql' === $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME))
|
||||
{
|
||||
$oPdo->exec('SET NAMES utf8 COLLATE utf8_general_ci');
|
||||
// $oPdo->exec('SET NAMES utf8');
|
||||
|
@ -111,7 +124,7 @@ abstract class PdoAbstract
|
|||
}
|
||||
|
||||
/**
|
||||
* @return nool
|
||||
* @return bool
|
||||
*/
|
||||
protected function beginTransaction()
|
||||
{
|
||||
|
@ -119,7 +132,7 @@ abstract class PdoAbstract
|
|||
}
|
||||
|
||||
/**
|
||||
* @return nool
|
||||
* @return bool
|
||||
*/
|
||||
protected function commit()
|
||||
{
|
||||
|
@ -127,7 +140,7 @@ abstract class PdoAbstract
|
|||
}
|
||||
|
||||
/**
|
||||
* @return nool
|
||||
* @return bool
|
||||
*/
|
||||
protected function rollBack()
|
||||
{
|
||||
|
@ -322,7 +335,10 @@ abstract class PdoAbstract
|
|||
$oPdo = $this->getPDO();
|
||||
if ($oPdo)
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
}
|
||||
|
||||
$sQuery = 'DELETE FROM rainloop_system WHERE sys_name = ? AND value_int <= ?;';
|
||||
$this->writeLog($sQuery);
|
||||
|
@ -341,13 +357,16 @@ abstract class PdoAbstract
|
|||
}
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
if ($bResult)
|
||||
{
|
||||
$oPdo->commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,17 +390,17 @@ abstract class PdoAbstract
|
|||
sys_name varchar(50) NOT NULL,
|
||||
value_int int UNSIGNED NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\',
|
||||
INDEX `sys_name_index` (`sys_name`)
|
||||
INDEX sys_name_rainloop_system_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 UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\',
|
||||
PRIMARY KEY(`id_user`),
|
||||
INDEX `rl_email_index` (`rl_email`)
|
||||
PRIMARY KEY(id_user),
|
||||
INDEX rl_email_rainloop_users_index (rl_email)
|
||||
) /*!40000 ENGINE=INNODB */;';
|
||||
}
|
||||
else if ('postgres' === $this->sDbType)
|
||||
else if ('pgsql' === $this->sDbType)
|
||||
{
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
|
@ -389,22 +408,41 @@ abstract class PdoAbstract
|
|||
value_str varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
|
||||
$aQ[] = 'CREATE INDEX sys_name_index ON rainloop_system (sys_name);';
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_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 SEQUENCE id_user 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,
|
||||
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_index ON rainloop_users (rl_email);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
}
|
||||
else if ('sqlite' === $this->sDbType)
|
||||
{
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name text NOT NULL,
|
||||
value_int integer NOT NULL default 0,
|
||||
value_str text NOT NULL default \'\'
|
||||
);';
|
||||
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer NOT NULL PRIMARY KEY,
|
||||
rl_email text NOT NULL default \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
}
|
||||
|
||||
if (0 < \count($aQ))
|
||||
{
|
||||
try
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
}
|
||||
|
||||
foreach ($aQ as $sQuery)
|
||||
{
|
||||
|
@ -412,23 +450,37 @@ abstract class PdoAbstract
|
|||
{
|
||||
$this->writeLog($sQuery);
|
||||
$bResult = false !== $oPdo->exec($sQuery);
|
||||
if (!$bResult)
|
||||
{
|
||||
$this->writeLog('Result=false');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->writeLog('Result=true');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->commit();
|
||||
if ($bResult)
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
|
||||
$this->writeLog($oException);
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
|
||||
throw $oException;
|
||||
}
|
||||
}
|
||||
|
@ -453,18 +505,32 @@ abstract class PdoAbstract
|
|||
catch (\PDOException $oException)
|
||||
{
|
||||
$this->writeLog($oException);
|
||||
|
||||
$this->initSystemTables();
|
||||
|
||||
$iFromVersion = $this->getVersion($sName);
|
||||
|
||||
try
|
||||
{
|
||||
$this->initSystemTables();
|
||||
|
||||
$iFromVersion = $this->getVersion($sName);
|
||||
}
|
||||
catch (\PDOException $oSubException)
|
||||
{
|
||||
$this->writeLog($oSubException);
|
||||
throw $oSubException;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 <= $iFromVersion)
|
||||
if (\is_int($iFromVersion) && 0 <= $iFromVersion)
|
||||
{
|
||||
$oPdo = false;
|
||||
$bResult = false;
|
||||
|
||||
foreach ($aData as $iVersion => $aQuery)
|
||||
{
|
||||
if (0 === \count($aQuery))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$oPdo)
|
||||
{
|
||||
$oPdo = $this->getPDO();
|
||||
|
@ -475,30 +541,44 @@ abstract class PdoAbstract
|
|||
{
|
||||
try
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->beginTransaction();
|
||||
}
|
||||
|
||||
foreach ($aQuery as $sQuery)
|
||||
{
|
||||
$this->writeLog($sQuery);
|
||||
if (false === $oPdo->exec($sQuery))
|
||||
$bExec = $oPdo->exec($sQuery);
|
||||
if (false === $bExec)
|
||||
{
|
||||
$this->writeLog('Result: false');
|
||||
|
||||
$bResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
if ($bResult)
|
||||
{
|
||||
$oPdo->commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
$this->writeLog($oException);
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$oPdo->rollBack();
|
||||
}
|
||||
|
||||
throw $oException;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ class Application extends \RainLoop\Config\AbstractConfig
|
|||
'contacts' => array(
|
||||
'enable' => array(false, 'Enable contacts'),
|
||||
'suggestions_limit' => array(30),
|
||||
'type' => array('mysql', ''),
|
||||
'type' => array('sqlite', ''),
|
||||
'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''),
|
||||
'pdo_user' => array('root', ''),
|
||||
'pdo_password' => array('', ''),
|
||||
|
|
|
@ -12,6 +12,11 @@ class PdoPersonalAddressBook
|
|||
* @var string
|
||||
*/
|
||||
private $sDsn;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDsnType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -23,11 +28,12 @@ class PdoPersonalAddressBook
|
|||
*/
|
||||
private $sPassword;
|
||||
|
||||
public function __construct($sDsn, $sUser, $sPassword)
|
||||
public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql')
|
||||
{
|
||||
$this->sDsn = $sDsn;
|
||||
$this->sUser = $sUser;
|
||||
$this->sPassword = $sPassword;
|
||||
$this->sDsnType = $sDsnType;
|
||||
|
||||
$this->bExplain = false;
|
||||
}
|
||||
|
@ -38,7 +44,7 @@ class PdoPersonalAddressBook
|
|||
public function IsSupported()
|
||||
{
|
||||
$aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array();
|
||||
return \is_array($aDrivers) ? \in_array('mysql', $aDrivers) : false;
|
||||
return \is_array($aDrivers) ? \in_array($this->sDsnType, $aDrivers) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +100,10 @@ class PdoPersonalAddressBook
|
|||
|
||||
try
|
||||
{
|
||||
$this->beginTransaction();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$this->beginTransaction();
|
||||
}
|
||||
|
||||
$aFreq = array();
|
||||
if ($bUpdate)
|
||||
|
@ -182,11 +191,18 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->rollBack();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$this->rollBack();
|
||||
}
|
||||
|
||||
throw $oException;
|
||||
}
|
||||
|
||||
$this->commit();
|
||||
if ($this->isTransactionSupported())
|
||||
{
|
||||
$this->commit();
|
||||
}
|
||||
|
||||
return 0 < $iIdContact;
|
||||
}
|
||||
|
@ -199,7 +215,6 @@ class PdoPersonalAddressBook
|
|||
*/
|
||||
public function DeleteContacts($oAccount, $aContactIds)
|
||||
{
|
||||
$this->Sync();
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
|
||||
$aContactIds = \array_filter($aContactIds, function (&$mItem) {
|
||||
|
@ -279,7 +294,9 @@ class PdoPersonalAddressBook
|
|||
|
||||
if (0 < \strlen($sSearch))
|
||||
{
|
||||
$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';
|
||||
$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, id_prop';
|
||||
|
||||
$aParams = array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':scope_type' => array($iScopeType, \PDO::PARAM_INT),
|
||||
|
@ -756,8 +773,7 @@ class PdoPersonalAddressBook
|
|||
try
|
||||
{
|
||||
$this->Sync();
|
||||
|
||||
if (0 >= $this->getVersion('mysql-pab-version'))
|
||||
if (0 >= $this->getVersion($this->sDsnType.'-pab-version'))
|
||||
{
|
||||
$sResult = 'Unknown database error';
|
||||
}
|
||||
|
@ -779,73 +795,214 @@ class PdoPersonalAddressBook
|
|||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function Sync()
|
||||
private function getInitialTablesArray($sDbType)
|
||||
{
|
||||
return $this->dataBaseUpgrade('mysql-pab-version', array(
|
||||
1 => array(
|
||||
$sInitial = '';
|
||||
$aResult = array();
|
||||
|
||||
switch ($sDbType)
|
||||
{
|
||||
case 'mysql':
|
||||
$sInitial = <<<MYSQLINITIAL
|
||||
CREATE TABLE IF NOT EXISTS rainloop_pab_contacts (
|
||||
|
||||
// -- rainloop_pab_contacts --
|
||||
'CREATE TABLE IF NOT EXISTS rainloop_pab_contacts (
|
||||
|
||||
id_contact bigint UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
id_user int UNSIGNED NOT NULL,
|
||||
scope_type tinyint 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 \'\',
|
||||
display_name varchar(255) NOT NULL DEFAULT '',
|
||||
display_email varchar(255) NOT NULL DEFAULT '',
|
||||
display varchar(255) NOT NULL DEFAULT '',
|
||||
changed int UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
PRIMARY KEY(id_contact),
|
||||
INDEX id_user_scope_type_index (id_user, scope_type)
|
||||
INDEX id_user_scope_type_rainloop_pab_contacts_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 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rainloop_pab_properties (
|
||||
|
||||
// -- rainloop_pab_properties --
|
||||
'CREATE TABLE IF NOT EXISTS rainloop_pab_properties (
|
||||
|
||||
id_prop bigint UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
id_contact bigint UNSIGNED NOT NULL,
|
||||
id_user int UNSIGNED NOT NULL,
|
||||
scope_type tinyint UNSIGNED NOT NULL DEFAULT 0,
|
||||
prop_type tinyint 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_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 UNSIGNED NOT NULL DEFAULT 0,
|
||||
|
||||
PRIMARY KEY(id_prop),
|
||||
INDEX id_user_index (id_user),
|
||||
INDEX id_user_id_contact_scope_type_index (id_user, id_contact, scope_type)
|
||||
INDEX id_user_rainloop_pab_properties_index (id_user),
|
||||
INDEX id_user_id_contact_scope_type_rainloop_pab_properties_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 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rainloop_pab_tags (
|
||||
|
||||
// -- rainloop_pab_tags --
|
||||
'CREATE TABLE IF NOT EXISTS rainloop_pab_tags (
|
||||
|
||||
id_tag int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
id_user int UNSIGNED NOT NULL,
|
||||
tag_name varchar(255) NOT NULL,
|
||||
|
||||
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 */;',
|
||||
INDEX id_user_rainloop_pab_tags_index (id_user),
|
||||
INDEX id_user_name_rainloop_pab_tags_index (id_user, tag_name)
|
||||
|
||||
)/*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
// -- rainloop_pab_tags_contacts --
|
||||
'CREATE TABLE IF NOT EXISTS rainloop_pab_tags_contacts (
|
||||
|
||||
|
||||
id_tag int UNSIGNED NOT NULL,
|
||||
id_contact bigint UNSIGNED NOT NULL,
|
||||
|
||||
INDEX id_tag_index (id_tag),
|
||||
INDEX id_contact_index (id_contact)
|
||||
INDEX id_tag_rainloop_pab_tags_contacts_index (id_tag),
|
||||
INDEX id_contact_rainloop_pab_tags_contacts_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 */;
|
||||
MYSQLINITIAL;
|
||||
break;
|
||||
|
||||
case 'pgsql':
|
||||
$sInitial = <<<POSTGRESINITIAL
|
||||
CREATE SEQUENCE id_contact START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;
|
||||
|
||||
CREATE TABLE rainloop_pab_contacts (
|
||||
id_contact integer DEFAULT nextval('id_contact'::text) PRIMARY KEY,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL DEFAULT 0,
|
||||
display_name varchar(128) NOT NULL DEFAULT '',
|
||||
display_email varchar(128) NOT NULL DEFAULT '',
|
||||
display varchar(128) NOT NULL DEFAULT '',
|
||||
changed integer NOT NULL default 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_scope_type_rainloop_pab_contacts_index ON rainloop_pab_contacts (id_user, scope_type);
|
||||
|
||||
CREATE SEQUENCE id_prop START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;
|
||||
|
||||
CREATE TABLE rainloop_pab_properties (
|
||||
id_prop integer DEFAULT nextval('id_prop'::text) PRIMARY KEY,
|
||||
id_contact integer NOT NULL,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL DEFAULT 0,
|
||||
prop_type integer NOT NULL,
|
||||
prop_type_custom varchar(50) NOT NULL DEFAULT '',
|
||||
prop_value varchar(128) NOT NULL DEFAULT '',
|
||||
prop_value_custom varchar(128) NOT NULL DEFAULT '',
|
||||
prop_frec integer NOT NULL default 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_rainloop_pab_properties_index ON rainloop_pab_properties (id_user);
|
||||
CREATE INDEX id_user_id_contact_scope_type_rainloop_pab_properties_index ON rainloop_pab_properties (id_user, id_contact, scope_type);
|
||||
|
||||
CREATE SEQUENCE id_tag START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;
|
||||
|
||||
CREATE TABLE rainloop_pab_tags (
|
||||
id_tag integer DEFAULT nextval('id_tag'::text) PRIMARY KEY,
|
||||
id_user integer NOT NULL,
|
||||
tag_name varchar(128) NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_rainloop_pab_tags_index ON rainloop_pab_tags (id_user);
|
||||
CREATE INDEX id_user_name_rainloop_pab_tags_index ON rainloop_pab_tags (id_user, tag_name);
|
||||
|
||||
CREATE TABLE rainloop_pab_tags_contacts (
|
||||
id_tag integer NOT NULL,
|
||||
id_contact integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX id_tag_rainloop_pab_tags_index ON rainloop_pab_tags_contacts (id_tag);
|
||||
CREATE INDEX id_contact_rainloop_pab_tags_index ON rainloop_pab_tags_contacts (id_contact);
|
||||
POSTGRESINITIAL;
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
$sInitial = <<<SQLITEINITIAL
|
||||
CREATE TABLE rainloop_pab_contacts (
|
||||
id_contact integer NOT NULL PRIMARY KEY,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL default 0,
|
||||
display_name text NOT NULL default '',
|
||||
display_email text NOT NULL default '',
|
||||
display text NOT NULL default '',
|
||||
changed integer NOT NULL default 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_scope_type_rainloop_pab_contacts_index ON rainloop_pab_contacts (id_user, scope_type);
|
||||
|
||||
CREATE TABLE rainloop_pab_properties (
|
||||
id_prop integer NOT NULL PRIMARY KEY,
|
||||
id_contact integer NOT NULL,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL default 0,
|
||||
prop_type integer NOT NULL,
|
||||
prop_type_custom text NOT NULL default '',
|
||||
prop_value text NOT NULL default '',
|
||||
prop_value_custom text NOT NULL default '',
|
||||
prop_frec integer NOT NULL default 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_rainloop_pab_properties_index ON rainloop_pab_properties (id_user);
|
||||
CREATE INDEX id_user_id_contact_scope_type_rainloop_pab_properties_index ON rainloop_pab_properties (id_user, id_contact, scope_type);
|
||||
|
||||
CREATE TABLE rainloop_pab_tags (
|
||||
id_tag integer NOT NULL PRIMARY KEY,
|
||||
id_user integer NOT NULL,
|
||||
tag_name text NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_rainloop_pab_tags_index ON rainloop_pab_tags (id_user);
|
||||
CREATE INDEX id_user_name_rainloop_pab_tags_index ON rainloop_pab_tags (id_user, tag_name);
|
||||
|
||||
CREATE TABLE rainloop_pab_tags_contacts (
|
||||
id_tag integer NOT NULL,
|
||||
id_contact integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX id_tag_rainloop_pab_tags_index ON rainloop_pab_tags_contacts (id_tag);
|
||||
CREATE INDEX id_contact_rainloop_pab_tags_index ON rainloop_pab_tags_contacts (id_contact);
|
||||
|
||||
SQLITEINITIAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 < strlen($sInitial))
|
||||
{
|
||||
$aList = \explode(';', \trim($sInitial));
|
||||
foreach ($aList as $sV)
|
||||
{
|
||||
$sV = \trim($sV);
|
||||
if (0 < \strlen($sV))
|
||||
{
|
||||
$aResult[] = $sV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function Sync()
|
||||
{
|
||||
switch ($this->sDsnType)
|
||||
{
|
||||
case 'mysql':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
));
|
||||
case 'pgsql':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
));
|
||||
case 'sqlite':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -902,6 +1059,6 @@ class PdoPersonalAddressBook
|
|||
*/
|
||||
protected function getPdoAccessData()
|
||||
{
|
||||
return array('mysql', $this->sDsn, $this->sUser, $this->sPassword);
|
||||
return array($this->sDsnType, $this->sDsn, $this->sUser, $this->sPassword);
|
||||
}
|
||||
}
|
|
@ -5,10 +5,11 @@
|
|||
<br />
|
||||
Your system doesn't support contacts.
|
||||
<br />
|
||||
You need to install or enable <strong>PDO (MySQL)</strong> exstenstion on your web server.
|
||||
You need to install or enable <strong>PDO (SQLite / MySQL / PostgreSQL)</strong> exstenstion on your server.
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-horizontal" data-bind="visible: contactsSupported">
|
||||
<div class="form-horizontal">
|
||||
<div class="legend">
|
||||
Contacts
|
||||
</div>
|
||||
|
@ -20,43 +21,87 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="legend">
|
||||
PDO (MySQL)
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
Dsn
|
||||
</label>
|
||||
<label class="control-label">
|
||||
Type
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="span6" data-bind="value: pdoDsn, saveTrigger: pdoDsnTrigger" />
|
||||
<div data-bind="saveTrigger: pdoDsnTrigger"></div>
|
||||
<select data-bind="options: contactsTypesOptions, value: mainContactsType,
|
||||
optionsText: 'name', optionsValue: 'id', optionsAfterRender: defautOptionsAfterRender, saveTrigger: contactsTypeTrigger"></select>
|
||||
<div data-bind="saveTrigger: contactsTypeTrigger"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
User
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="text" data-bind="value: pdoUser, saveTrigger: pdoUserTrigger" />
|
||||
<div data-bind="saveTrigger: pdoUserTrigger"></div>
|
||||
<div data-bind="visible: 'sqlite' !== contactsType()">
|
||||
<div class="legend">
|
||||
PDO (MySQL / PostgreSQL / ...)
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
Dsn
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="span6" data-bind="value: pdoDsn, saveTrigger: pdoDsnTrigger" />
|
||||
<div data-bind="saveTrigger: pdoDsnTrigger"></div>
|
||||
<blockquote style="margin-top: 10px">
|
||||
<p class="muted">
|
||||
<strong>Examples:</strong>
|
||||
<br />
|
||||
mysql:host=127.0.0.1;port=3306;dbname=rainloop
|
||||
<br />
|
||||
pgsql:host=127.0.0.1;port=5432;dbname=rainloop
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
User
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="text" data-bind="value: pdoUser, saveTrigger: pdoUserTrigger" />
|
||||
<div data-bind="saveTrigger: pdoUserTrigger"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
Password
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="password" data-bind="value: pdoPassword, saveTrigger: pdoPasswordTrigger" />
|
||||
<div data-bind="saveTrigger: pdoPasswordTrigger"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a class="btn" data-bind="command: testContactsCommand, css: { 'btn-success': testContactsSuccess, 'btn-danger': testContactsError }">
|
||||
<i data-bind="css: {'icon-info': !testing(), 'icon-spinner-2 animated': testing(), 'icon-white': testContactsSuccess() || testContactsError() }"></i>
|
||||
|
||||
Test
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">
|
||||
Password
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="password" data-bind="value: pdoPassword, saveTrigger: pdoPasswordTrigger" />
|
||||
<div data-bind="saveTrigger: pdoPasswordTrigger"></div>
|
||||
<div data-bind="visible: 'sqlite' === contactsType()">
|
||||
<div class="legend">
|
||||
PDO (SQLite)
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a class="btn" data-bind="command: testContactsCommand, css: { 'btn-success': testContactsSuccess, 'btn-danger': testContactsError }">
|
||||
<i data-bind="css: {'icon-info': !testing(), 'icon-spinner-2 animated': testing(), 'icon-white': testContactsSuccess() || testContactsError() }"></i>
|
||||
|
||||
Test
|
||||
</a>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<div class="alert alert-null-left-margin span8">
|
||||
<h4>Notice!</h4>
|
||||
<br />
|
||||
Don't use this type of database with a large number of active users.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<a class="btn" data-bind="command: testContactsCommand, css: { 'btn-success': testContactsSuccess, 'btn-danger': testContactsError }">
|
||||
<i data-bind="css: {'icon-info': !testing(), 'icon-spinner-2 animated': testing(), 'icon-white': testContactsSuccess() || testContactsError() }"></i>
|
||||
|
||||
Test
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="visible: '' !== testContactsErrorMessage()">
|
||||
|
|
|
@ -2655,7 +2655,7 @@ ko.bindingHandlers.saveTrigger = {
|
|||
|
||||
var $oEl = $(oElement);
|
||||
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],select,textarea') ? 'input' : 'custom');
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom');
|
||||
|
||||
if ('custom' === $oEl.data('save-trigger-type'))
|
||||
{
|
||||
|
@ -5252,9 +5252,86 @@ function AdminContacts()
|
|||
{
|
||||
// var oData = RL.data();
|
||||
|
||||
this.contactsSupported = !!RL.settingsGet('ContactsIsSupported');
|
||||
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
|
||||
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
|
||||
|
||||
var
|
||||
aTypes = ['sqlite', 'mysql', 'pgsql'],
|
||||
aSupportedTypes = [],
|
||||
getTypeName = function(sName) {
|
||||
switch (sName)
|
||||
{
|
||||
case 'sqlite':
|
||||
sName = 'SQLite';
|
||||
break;
|
||||
case 'mysql':
|
||||
sName = 'MySQL';
|
||||
break;
|
||||
case 'pgsql':
|
||||
sName = 'PostgreSQL';
|
||||
break;
|
||||
}
|
||||
|
||||
return sName;
|
||||
}
|
||||
;
|
||||
|
||||
if (!!RL.settingsGet('SQLiteIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('sqlite');
|
||||
}
|
||||
if (!!RL.settingsGet('MySqlIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('mysql');
|
||||
}
|
||||
if (!!RL.settingsGet('PostgreSqlIsSupported'))
|
||||
{
|
||||
aSupportedTypes.push('pgsql');
|
||||
}
|
||||
|
||||
this.contactsSupported = 0 < aSupportedTypes.length;
|
||||
|
||||
this.contactsTypes = ko.observableArray([]);
|
||||
this.contactsTypesOptions = this.contactsTypes.map(function (sValue) {
|
||||
var bDisabled = -1 === Utils.inArray(sValue, aSupportedTypes);
|
||||
return {
|
||||
'id': sValue,
|
||||
'name': getTypeName(sValue) + (bDisabled ? ' (not supported)' : ''),
|
||||
'disable': bDisabled
|
||||
};
|
||||
});
|
||||
|
||||
this.contactsTypes(aTypes);
|
||||
this.contactsType = ko.observable('');
|
||||
|
||||
this.mainContactsType = ko.computed({
|
||||
'owner': this,
|
||||
'read': this.contactsType,
|
||||
'write': function (sValue) {
|
||||
if (sValue !== this.contactsType())
|
||||
{
|
||||
if (-1 < Utils.inArray(sValue, aSupportedTypes))
|
||||
{
|
||||
this.contactsType(sValue);
|
||||
}
|
||||
else if (0 < aSupportedTypes.length)
|
||||
{
|
||||
this.contactsType('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.contactsType.valueHasMutated();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.contactsType.subscribe(function () {
|
||||
this.testContactsSuccess(false);
|
||||
this.testContactsError(false);
|
||||
this.testContactsErrorMessage('');
|
||||
}, this);
|
||||
|
||||
this.pdoDsn = ko.observable(RL.settingsGet('ContactsPdoDsn'));
|
||||
this.pdoUser = ko.observable(RL.settingsGet('ContactsPdoUser'));
|
||||
this.pdoPassword = ko.observable(RL.settingsGet('ContactsPdoPassword'));
|
||||
|
@ -5262,6 +5339,7 @@ function AdminContacts()
|
|||
this.pdoDsnTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.pdoUserTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.pdoPasswordTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
this.contactsTypeTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
|
||||
|
||||
this.testing = ko.observable(false);
|
||||
this.testContactsSuccess = ko.observable(false);
|
||||
|
@ -5276,6 +5354,7 @@ function AdminContacts()
|
|||
this.testing(true);
|
||||
|
||||
RL.remote().testContacts(this.onTestContactsResponse, {
|
||||
'ContactsPdoType': this.contactsType(),
|
||||
'ContactsPdoDsn': this.pdoDsn(),
|
||||
'ContactsPdoUser': this.pdoUser(),
|
||||
'ContactsPdoPassword': this.pdoPassword()
|
||||
|
@ -5285,6 +5364,8 @@ function AdminContacts()
|
|||
return '' !== this.pdoDsn() && '' !== this.pdoUser();
|
||||
});
|
||||
|
||||
this.contactsType(RL.settingsGet('ContactsPdoType'));
|
||||
|
||||
this.onTestContactsResponse = _.bind(this.onTestContactsResponse, this);
|
||||
}
|
||||
|
||||
|
@ -5303,7 +5384,14 @@ AdminContacts.prototype.onTestContactsResponse = function (sResult, oData)
|
|||
else
|
||||
{
|
||||
this.testContactsError(true);
|
||||
this.testContactsErrorMessage(oData.Result.Message || '');
|
||||
if (oData && oData.Result)
|
||||
{
|
||||
this.testContactsErrorMessage(oData.Result.Message || '');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.testContactsErrorMessage('');
|
||||
}
|
||||
}
|
||||
|
||||
this.testing(false);
|
||||
|
@ -5323,8 +5411,9 @@ AdminContacts.prototype.onBuild = function ()
|
|||
|
||||
var
|
||||
f1 = Utils.settingsSaveHelperSimpleFunction(self.pdoDsnTrigger, self),
|
||||
f2 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self),
|
||||
f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self)
|
||||
f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self),
|
||||
f4 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self),
|
||||
f5 = Utils.settingsSaveHelperSimpleFunction(self.contactsTypeTrigger, self)
|
||||
;
|
||||
|
||||
self.enableContacts.subscribe(function (bValue) {
|
||||
|
@ -5333,24 +5422,32 @@ AdminContacts.prototype.onBuild = function ()
|
|||
});
|
||||
});
|
||||
|
||||
self.contactsType.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f5, {
|
||||
'ContactsPdoType': sValue
|
||||
});
|
||||
});
|
||||
|
||||
self.pdoDsn.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f1, {
|
||||
'ContactsPdoDsn': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
self.pdoUser.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f2, {
|
||||
RL.remote().saveAdminConfig(f3, {
|
||||
'ContactsPdoUser': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
self.pdoPassword.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f3, {
|
||||
RL.remote().saveAdminConfig(f4, {
|
||||
'ContactsPdoPassword': Utils.trim(sValue)
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsType(RL.settingsGet('ContactsPdoType'));
|
||||
|
||||
}, 50);
|
||||
};
|
||||
|
||||
|
|
6
rainloop/v/0.0.0/static/js/admin.min.js
vendored
6
rainloop/v/0.0.0/static/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -2655,7 +2655,7 @@ ko.bindingHandlers.saveTrigger = {
|
|||
|
||||
var $oEl = $(oElement);
|
||||
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],select,textarea') ? 'input' : 'custom');
|
||||
$oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom');
|
||||
|
||||
if ('custom' === $oEl.data('save-trigger-type'))
|
||||
{
|
||||
|
|
2
rainloop/v/0.0.0/static/js/app.min.js
vendored
2
rainloop/v/0.0.0/static/js/app.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue