PdoAbstract class

MySQL pab driver implementation (part 2)
This commit is contained in:
RainLoop Team 2013-11-29 03:27:28 +04:00
parent b92f26e88b
commit c29be81a65
6 changed files with 462 additions and 53 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
/.idea
/local
/nbproject
/npm-debug.log
/node_modules

View 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.'\'';
}
}

View file

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

View file

@ -0,0 +1,10 @@
<?php
namespace RainLoop\Providers\PersonalAddressBook\Enumerations;
class ContactType
{
const DEFAULT_ = 0;
const SHARE = 1;
const AUTO = 2;
}

View file

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

View file

@ -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,