mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-11-02 09:35:34 +08:00
PdoAbstract class
MySQL pab driver implementation (part 2)
This commit is contained in:
parent
b92f26e88b
commit
c29be81a65
6 changed files with 462 additions and 53 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
/.idea
|
||||
/local
|
||||
/nbproject
|
||||
/npm-debug.log
|
||||
/node_modules
|
||||
|
|
|
|||
182
rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php
Normal file
182
rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Common;
|
||||
|
||||
abstract class PdoAbstract
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
protected $oLogger;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsSupported()
|
||||
{
|
||||
return !!\class_exists('PDO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
$this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPdoAccessData(\RainLoop\Account $oAccount)
|
||||
{
|
||||
$aResult = array('mysql', '', '', '');
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @staticvar array $aPdoCache
|
||||
*
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getPDO(\RainLoop\Account $oAccount)
|
||||
{
|
||||
static $aPdoCache = array();
|
||||
|
||||
$sEmail = $oAccount->ParentEmailHelper();
|
||||
if (isset($aPdoCache[$sEmail]))
|
||||
{
|
||||
return $aPdoCache[$sEmail];
|
||||
}
|
||||
|
||||
if (!\class_exists('PDO'))
|
||||
{
|
||||
throw new \Exception('Class PDO does not exist');
|
||||
}
|
||||
|
||||
// TODO
|
||||
$sType = $sDsn = $sDbLogin = $sDbPassword = '';
|
||||
list($sType, $sDsn, $sDbLogin, $sDbPassword) = $this->getPdoAccessData($oAccount);
|
||||
|
||||
$oPdo = false;
|
||||
try
|
||||
{
|
||||
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword);
|
||||
if ($oPdo)
|
||||
{
|
||||
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
if ('mysql' === $sType)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
throw $oException;
|
||||
}
|
||||
|
||||
if ($oPdo)
|
||||
{
|
||||
$aPdoCache[$sEmail] = $oPdo;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception('PDO = false');
|
||||
}
|
||||
|
||||
return $oPdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sSql
|
||||
* @param array $aParams
|
||||
*
|
||||
* @return \PDOStatement|null
|
||||
*/
|
||||
protected function prepareAndExecute(\RainLoop\Account $oAccount, $sSql, $aParams = array())
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQL');
|
||||
}
|
||||
|
||||
$mResult = null;
|
||||
$oStmt = $this->getPDO($oAccount)->prepare($sSql);
|
||||
if ($oStmt)
|
||||
{
|
||||
foreach ($aParams as $sName => $aValue)
|
||||
{
|
||||
$oStmt->bindValue($sName, $aValue[0], $aValue[1]);
|
||||
}
|
||||
|
||||
$mResult = $oStmt->execute() ? $oStmt : null;
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param bool $bSkipInsert = false
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getUserId(\RainLoop\Account $oAccount, $bSkipInsert = false)
|
||||
{
|
||||
$sEmail = \strtolower($oAccount->ParentEmailHelper());
|
||||
|
||||
$oStmt = $this->prepareAndExecute($oAccount,
|
||||
'SELECT `id_user` FROM `rainloop_users` WHERE `email` = :email LIMIT 1',
|
||||
array(
|
||||
':email' => array($sEmail, \PDO::PARAM_STR)
|
||||
));
|
||||
|
||||
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
|
||||
if ($mRow && isset($mRow['id_user']) && \is_numeric($mRow['id_user']))
|
||||
{
|
||||
return (int) $mRow['id_user'];
|
||||
}
|
||||
|
||||
if (!$bSkipInsert)
|
||||
{
|
||||
$oStmt->closeCursor();
|
||||
|
||||
$oStmt = $this->prepareAndExecute($oAccount,
|
||||
'INSERT INTO rainloop_users (`email`) VALUES (:email)',
|
||||
array(
|
||||
':email' => array($sEmail, \PDO::PARAM_STR)
|
||||
));
|
||||
|
||||
return $this->getUserId($oAccount, true);
|
||||
}
|
||||
|
||||
throw new \Exception('id_user = 0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function convertSearchValue($sSearch)
|
||||
{
|
||||
return '%'.$sSearch.'%';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sValue
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function quoteValue($sValue)
|
||||
{
|
||||
return '\''.$sValue.'\'';
|
||||
}
|
||||
}
|
||||
|
|
@ -14,20 +14,25 @@ class Contact
|
|||
*/
|
||||
public $IdUser;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $DisplayName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $DisplayEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $DisplayInList;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var int
|
||||
*/
|
||||
public $IsAuto;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $IsShare;
|
||||
public $Type;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
|
|
@ -47,7 +52,7 @@ class Contact
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $Tags;
|
||||
public $TagsIds;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
|
|
@ -63,12 +68,14 @@ class Contact
|
|||
{
|
||||
$this->IdContact = 0;
|
||||
$this->IdUser = 0;
|
||||
$this->DisplayName = '';
|
||||
$this->DisplayEmail = '';
|
||||
$this->DisplayInList = '';
|
||||
$this->IsAuto = false;
|
||||
$this->Type = \RainLoop\Providers\PersonalAddressBook\Enumerations\ContactType::DEFAULT_;
|
||||
$this->IsShare = false;
|
||||
$this->CanBeChanged = false;
|
||||
$this->Changed = \time();
|
||||
$this->Tags = array();
|
||||
$this->TagsIds = array();
|
||||
$this->Properties = array();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\PersonalAddressBook\Enumerations;
|
||||
|
||||
class ContactType
|
||||
{
|
||||
const DEFAULT_ = 0;
|
||||
const SHARE = 1;
|
||||
const AUTO = 2;
|
||||
}
|
||||
|
|
@ -2,21 +2,15 @@
|
|||
|
||||
namespace RainLoop\Providers\PersonalAddressBook;
|
||||
|
||||
class MySqlPersonalAddressBook implements \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface
|
||||
use
|
||||
\RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType,
|
||||
\RainLoop\Providers\PersonalAddressBook\Enumerations\ContactType
|
||||
;
|
||||
|
||||
class MySqlPersonalAddressBook
|
||||
extends \RainLoop\Common\PdoAbstract
|
||||
implements \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
private $oLogger;
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger = null
|
||||
*/
|
||||
public function __construct($oLogger = null)
|
||||
{
|
||||
$this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
|
@ -28,48 +22,263 @@ class MySqlPersonalAddressBook implements \RainLoop\Providers\PersonalAddressBoo
|
|||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @staticvar array $aPdoCache
|
||||
* @return \PDO
|
||||
* @param int $iIdContact
|
||||
*
|
||||
* @return \RainLoop\Providers\PersonalAddressBook\Classes\Contact|null
|
||||
*/
|
||||
private function getPDO($oAccount)
|
||||
public function GetContactById($oAccount, $iIdContact)
|
||||
{
|
||||
static $aPdoCache = array();
|
||||
return null;
|
||||
}
|
||||
|
||||
$sEmail = $oAccount->ParentEmailHelper();
|
||||
if (isset($aPdoCache[$sEmail]))
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function CreateContact($oAccount, &$oContact)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function UpdateContact($oAccount, &$oContact)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param array $aContactIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteContacts($oAccount, $aContactIds)
|
||||
{
|
||||
$iUserID = $this->getUserId($oAccount);
|
||||
|
||||
$aContactIds = \array_filter($aContactIds, function (&$mItem) {
|
||||
$mItem = (int) $mItem;
|
||||
return 0 < $mItem;
|
||||
});
|
||||
|
||||
if (0 === \count($aContactIds))
|
||||
{
|
||||
return $aPdoCache[$sEmail];
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!\class_exists('PDO'))
|
||||
return !!$this->prepareAndExecute($oAccount,
|
||||
'DELETE FROM `rainloop_pab_contacts` WHERE id_user = :id_user AND `id_contact` IN ('.\implode(',', $aContactIds).')',
|
||||
array(':id_user' => array($iUserID, \PDO::PARAM_INT)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param int $iType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ContactType::DEFAULT_
|
||||
* @param int $iOffset = 0
|
||||
* @param type $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContacts($oAccount,
|
||||
$iType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ContactType::DEFAULT_,
|
||||
$iOffset = 0, $iLimit = 20, $sSearch = '')
|
||||
{
|
||||
$iOffset = 0 <= $iOffset ? $iOffset : 0;
|
||||
$iLimit = 0 < $iLimit ? (int) $iLimit : 20;
|
||||
$sSearch = \trim($sSearch);
|
||||
|
||||
$iUserID = $this->getUserId($oAccount);
|
||||
|
||||
if (!\in_array($iType, array(ContactType::SHARE, ContactType::AUTO)))
|
||||
{
|
||||
throw new \Exception('class_exists=PDO');
|
||||
$iType = ContactType::DEFAULT_;
|
||||
}
|
||||
|
||||
$sDsn = '';
|
||||
$sDbLogin = '';
|
||||
$sDbPassword = '';
|
||||
|
||||
$oPdo = false;
|
||||
try
|
||||
$sSql = 'SELECT * FROM `rainloop_pab_contacts` WHERE id_user = :id_user AND `type` = :type';
|
||||
$aParams = array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':type' => array($iType, \PDO::PARAM_INT)
|
||||
);
|
||||
|
||||
if (0 < \strlen($sSearch))
|
||||
{
|
||||
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword);
|
||||
if ($oPdo)
|
||||
$sSql .= ' AND `id_contact` IN ('.
|
||||
'SELECT DISTINCT `id_contact` FROM `rainloop_pab_prop` WHERE id_user = :id_user AND `value` LIKE :search'.
|
||||
')';
|
||||
|
||||
$aParams[':search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
$sSql .= ' ORDER BY `display_in_list` ASC LIMIT :limit OFFSET :offset';
|
||||
$aParams[':limit'] = array($iLimit, \PDO::PARAM_INT);
|
||||
$aParams[':offset'] = array($iOffset, \PDO::PARAM_INT);
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sSearch
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function GetSuggestions($oAccount, $sSearch)
|
||||
{
|
||||
$iLimit = 20;
|
||||
|
||||
$sSearch = \trim($sSearch);
|
||||
if (0 === \strlen($sSearch))
|
||||
{
|
||||
throw new \InvalidArgumentException('$sSearch');
|
||||
}
|
||||
|
||||
$iUserID = $this->getUserId($oAccount);
|
||||
|
||||
$sTypes = implode(',', array(
|
||||
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME
|
||||
));
|
||||
|
||||
$sSql = 'SELECT DISTINCT `id_contact` FROM `rainloop_pab_prop` '.
|
||||
'WHERE id_user = :id_user AND `type` IN ('.$sTypes.') AND `value` LIKE :search';
|
||||
|
||||
$aParams = array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':limit' => array($iLimit, \PDO::PARAM_INT),
|
||||
':search' => array($this->convertSearchValue($sSearch), \PDO::PARAM_STR)
|
||||
);
|
||||
|
||||
$sSql .= ' ORDER BY `frec` ASC LIMIT :limit';
|
||||
|
||||
$oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams);
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$aIdContacts = array();
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
$iIdContact = $aItem && isset($aItem['id_contact']) ? (int) $aItem['id_contact'] : 0;
|
||||
if (0 < $iIdContact)
|
||||
{
|
||||
$aIdContacts[] = $iIdContact;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
|
||||
if (0 < count($aIdContacts))
|
||||
{
|
||||
$oStmt->closeCursor();
|
||||
|
||||
$sTypes = implode(',', array(
|
||||
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME
|
||||
));
|
||||
|
||||
$sSql = 'SELECT `id_contact`, `type`, `value` FROM `rainloop_pab_prop` '.
|
||||
'WHERE id_user = :id_user AND `type` IN ('.$sTypes.') AND `id_contact` IN ('.\implode(',', $aIdContacts).')';
|
||||
|
||||
$oStmt = $this->prepareAndExecute($oAccount, $sSql, array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT)
|
||||
));
|
||||
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$aResult = array();
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
if ($aItem && isset($aItem['id_contact'], $aItem['type'], $aItem['value']))
|
||||
{
|
||||
$iId = $aItem['id_contact'];
|
||||
if (!isset($aResult[$iId]))
|
||||
{
|
||||
$aResult[$iId] = array('', '');
|
||||
}
|
||||
|
||||
if ('' === $aResult[$iId][0] && \in_array((int) $aItem['type'],
|
||||
array(PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER)))
|
||||
{
|
||||
$aResult[$iId][0] = $aItem['value'];
|
||||
}
|
||||
else if ('' === $aResult[$iId][1] &&\in_array((int) $aItem['type'], array(PropertyType::FULLNAME)))
|
||||
{
|
||||
$aResult[$iId][1] = $aItem['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aResult = array_filter($aResult, function ($aItem) {
|
||||
return '' !== $aItem[0];
|
||||
});
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
|
||||
return \array_values($aResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param array $aEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncFrec($oAccount, $aEmail)
|
||||
{
|
||||
$iUserID = $this->getUserId($oAccount);
|
||||
|
||||
$self = $this;
|
||||
$aEmail = \array_filter($aEmail, function (&$mItem) use ($self) {
|
||||
$mItem = \strtolower(\trim($mItem));
|
||||
if (0 < \strlen($mItem))
|
||||
{
|
||||
$mItem = $self->quoteValue($mItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (0 === \count($aEmail))
|
||||
{
|
||||
// throw $oException;
|
||||
$oPdo = false;
|
||||
throw new \InvalidArgumentException('$aEmail');
|
||||
}
|
||||
|
||||
$sTypes = implode(',', array(
|
||||
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER
|
||||
));
|
||||
|
||||
$sSql = 'UPDATE `rainloop_pab_prop` SET `frec` = `frec` + 1 WHERE id_user = :id_user AND `type` IN ('.$sTypes;
|
||||
|
||||
if (1 === \count($aEmail))
|
||||
{
|
||||
$sSql .= ') AND `value` = '.$aEmail[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSql .= ') AND `value` IN ('.\implode(',', $aEmail).')';
|
||||
}
|
||||
|
||||
if ($oPdo)
|
||||
{
|
||||
$aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo;
|
||||
}
|
||||
|
||||
return $oPdo;
|
||||
return !!$this->prepareAndExecute($oAccount, $sSql, array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -23,8 +23,7 @@ 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_in_list` varchar(255) NOT NULL DEFAULT '',
|
||||
`is_auto` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`is_share` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`type` int(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`changed` int(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
|
||||
CONSTRAINT `id_user_fk_rainloop_pab_contacts` FOREIGN KEY (`id_user`)
|
||||
|
|
@ -34,6 +33,7 @@ CREATE TABLE IF NOT EXISTS `rainloop_pab_contacts` (
|
|||
|
||||
-- Table structure for table `rainloop_pab_prop`
|
||||
CREATE TABLE IF NOT EXISTS `rainloop_pab_prop` (
|
||||
`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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue