Uploading and preparing the repository to the dev version.

Original unminified source code (dev folder - js, css, less) (fixes #6)
Grunt build system
Multiple identities correction (fixes #9)
Compose html editor (fixes #12)
New general settings - Loading Description
New warning about default admin password
Split general and login screen settings
This commit is contained in:
RainLoop Team 2013-11-16 02:21:12 +04:00
parent afad45137e
commit 4cc2207513
846 changed files with 99453 additions and 2123 deletions

View file

@ -0,0 +1,14 @@
<?php
namespace RainLoop\Providers;
abstract class AbstractProvider
{
/**
* @return bool
*/
public function IsActive()
{
return false;
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace RainLoop\Providers;
class ChangePassword extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Actions
*/
private $oActions;
/**
* @var \RainLoop\Providers\ChangePassword\ChangePasswordInterface
*/
private $oDriver;
/**
* @param \RainLoop\Actions $oActions
* @param \RainLoop\Providers\ChangePassword\ChangePasswordInterface|null $oDriver = null
*
* @return void
*/
public function __construct($oActions, $oDriver = null)
{
$this->oActions = $oActions;
$this->oDriver = $oDriver;
}
/**
* @param \RainLoop\Account $oAccount
*
* @return bool
*/
public function PasswordChangePossibility($oAccount)
{
return $this->IsActive() &&
$oAccount instanceof \RainLoop\Account &&
$this->oDriver && $this->oDriver->PasswordChangePossibility($oAccount)
;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sPrevPassword
* @param string $sNewPassword
*
* @return bool
*/
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
{
$bResult = false;
if ($this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface &&
$this->PasswordChangePossibility($oAccount) && $sPrevPassword === $oAccount->Password())
{
if ($this->oDriver->ChangePassword($oAccount, $sPrevPassword, $sNewPassword))
{
$oAccount->SetPassword($sNewPassword);
$this->oActions->SetAuthToken($oAccount);
$bResult = true;
}
}
return $bResult;
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface;
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace RainLoop\Providers\ChangePassword;
interface ChangePasswordInterface
{
/**
* @param \RainLoop\Account $oAccount
*
* @return bool
*/
public function PasswordChangePossibility($oAccount);
/**
* @param \RainLoop\Account $oAccount
* @param string $sPrevPassword
* @param string $sNewPassword
*
* @return bool
*/
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword);
}

View file

@ -0,0 +1,120 @@
<?php
namespace RainLoop\Providers;
class Contacts extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Contacts\ContactsInterface
*/
private $oDriver;
/**
* @param \RainLoop\Providers\Contacts\ContactsInterface $oDriver
*
* @return void
*/
public function __construct($oDriver)
{
$this->oDriver = null;
if ($oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface)
{
$this->oDriver = $oDriver;
}
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface;
}
/**
* @return bool
*/
public function IsSupported()
{
return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface &&
$this->oDriver->IsSupported();
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return array
*/
public function GetContactById($oAccount, $iIdContact)
{
return $this->oDriver ? $this->oDriver->GetContactById($oAccount, $iIdContact) : null;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '')
{
return $this->oDriver ? $this->oDriver->GetContacts($oAccount, $iOffset, $iLimit, $sSearch) : array();
}
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount)
{
return $this->oDriver ? $this->oDriver->GetContactsImageHashes($oAccount) : array();
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact)
{
return $this->oDriver ? $this->oDriver->CreateContact($oAccount, $oContact) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact)
{
return $this->oDriver ? $this->oDriver->UpdateContact($oAccount, $oContact) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds)
{
return $this->oDriver ? $this->oDriver->DeleteContacts($oAccount, $aContactIds) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds)
{
return $this->oDriver ? $this->oDriver->IncFrec($oAccount, $aContactIds) : false;
}
}

View file

@ -0,0 +1,111 @@
<?php
namespace RainLoop\Providers\Contacts\Classes;
class Contact
{
/**
* @var int
*/
public $IdContact;
/**
* @var int
*/
public $IdUser;
/**
* @var int
*/
public $Type;
/**
* @var int
*/
public $Frec;
/**
* @var string
*/
public $ListName;
/**
* @var string
*/
public $Name;
/**
* @var array
*/
public $Emails;
/**
* @var string
*/
public $ImageHash;
/**
* @var array
*/
public $Data;
public function __construct()
{
$this->Clear();
}
public function Clear()
{
$this->IdContact = 0;
$this->IdUser = 0;
$this->Type = 0;
$this->Frec = 0;
$this->ListName = '';
$this->Name = '';
$this->ImageHash = '';
$this->Emails = array();
$this->Data = array();
}
/**
* @return string
*/
public function GenarateListName()
{
return 0 < \strlen($this->Name) ? $this->Name : (!empty($this->Emails[0]) ? $this->Emails[0] : '');
}
/**
* @return string
*/
public function EmailsAsString()
{
return \trim(\implode(' ', $this->Emails));
}
/**
* @return string
*/
public function DataAsString()
{
return @\serialize($this->Data);
}
/**
* @param string $sData
*/
public function ParseData($sData)
{
$sData = (string) $sData;
$sData = \trim($sData);
if (!empty($sData))
{
$aData = @\unserialize($sData);
if (\is_array($aData))
{
$this->Data = $aData;
}
}
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace RainLoop\Providers\Contacts\Classes;
class Db
{
/**
* @return int
*/
static public function Version()
{
return 1;
}
/**
* @return array
*/
static public function Strucure()
{
return array(
'rlContactsUsers' => array(
'IdUser' => 'INTEGER PRIMARY KEY',
'Email' => 'TEXT'
),
'rlContactsItems' => array(
'IdContact' => 'INTEGER PRIMARY KEY',
'IdUser' => 'INTEGER',
'Type' => 'INTEGER',
'Frec' => 'INTEGER',
'ImageHash' => 'TEXT',
'ListName' => 'TEXT',
'Name' => 'TEXT',
'Emails' => 'TEXT',
'Data' => 'TEXT'
)
);
}
}

View file

@ -0,0 +1,68 @@
<?php
namespace RainLoop\Providers\Contacts;
interface ContactsInterface
{
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return $oContact|null
*/
public function GetContactById($oAccount, $iIdContact);
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '');
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount);
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact);
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact);
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds);
/**
* @return bool
*/
public function IsSupported();
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds);
}

View file

@ -0,0 +1,600 @@
<?php
namespace RainLoop\Providers\Contacts;
class DefaultContacts implements \RainLoop\Providers\Contacts\ContactsInterface
{
/**
* @var \MailSo\Log\Logger
*/
private $oLogger;
/**
* @var bool
*/
private $bUseDbPerUser;
/**
* @param \MailSo\Log\Logger $oLogger = null
*/
public function __construct($oLogger = null)
{
$this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null;
$this->bUseDbPerUser = true;
}
/**
* @param \RainLoop\Account $oAccount
* @staticvar array $aPdoCache
* @return \PDO
*/
private function getPDO($oAccount)
{
static $aPdoCache = array();
$sEmail = $oAccount->ParentEmailHelper();
if (isset($aPdoCache[$sEmail]))
{
return $aPdoCache[$sEmail];
}
if (!\class_exists('PDO'))
{
throw new \Exception('class_exists=PDO');
}
$sVersionFile = '';
$sDsn = '';
if ($this->bUseDbPerUser)
{
$sSubPath = APP_PRIVATE_DATA.'storage/contacts/'.\rtrim(\substr($sEmail, 0, 2), '@').'/'.$sEmail.'/';
if (!\is_dir($sSubPath))
{
if (\mkdir($sSubPath, 0755, true) && \is_dir($sSubPath))
{
$sVersionFile = $sSubPath.'.version';
$sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite';
}
}
else
{
$sVersionFile = $sSubPath.'.version';
$sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite';
}
}
else
{
$sVersionFile = APP_PRIVATE_DATA.'.version';
$sDsn = 'sqlite:'.APP_PRIVATE_DATA.'contacts.sqlite';
}
$sDbLogin = '';
$sDbPassword = '';
$oPdo = false;
try
{
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword);
if ($oPdo)
{
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
if (!@\file_exists($sVersionFile) ||
(string) @file_get_contents($sVersionFile) !== (string) \RainLoop\Providers\Contacts\Classes\Db::Version())
{
$this->syncTables($oPdo, $sVersionFile);
}
$oPdo->sqliteCreateFunction('SIMPLESEARCH', function ($sEmailValue, $sNameValue, $sMask) {
return \preg_match('/'.\preg_quote($sMask, '/').'/ui',
$sEmailValue.' '.$sNameValue) ? 1 : 0;
});
}
}
catch (\Exception $oException)
{
throw $oException;
$oPdo = false;
}
if ($oPdo)
{
$aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo;
}
return $oPdo;
}
protected function getWantedColumnsInfo($sTableName, $aCurrent)
{
$aColumns = array();
foreach ($aCurrent as $sName => $sType)
{
$sSql = $sName.' '.$sType;
switch ($sType)
{
case 'INTEGER':
$sSql .= ' DEFAILT \'0\'';
break;
case 'TEXT':
$sSql .= ' DEFAILT \'\'';
break;
}
$aColumns[$sName] = $sSql;
}
if (0 === \count($aColumns))
{
return '';
}
return 'CREATE TABLE '.$sTableName.' (' .\implode(', ', $aColumns).')';
}
/**
* @param \PDO $oAccount
* @param string $sTableName
*/
protected function getCurrentColumnsInfo($oPdo, $sTableName)
{
$oStmt = $this->prepareAndExecute($oPdo, 'SELECT `sql` FROM `sqlite_master` WHERE `tbl_name` = :TableName AND `type` = :Type', array(
':TableName' => array($sTableName, \PDO::PARAM_STR),
':Type' => array('table', \PDO::PARAM_STR)
));
if ($oStmt)
{
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
if ($mRow && isset($mRow['sql']))
{
return (string) $mRow['sql'];
}
}
return '';
}
/**
* @param \PDO $oPdo
* @param string $sVersionFile = ''
*/
private function syncTables($oPdo, $sVersionFile = '')
{
if ($this->oLogger)
{
$this->oLogger->Write('Start to sync', \MailSo\Log\Enumerations\Type::INFO);
}
$aStrucure = \RainLoop\Providers\Contacts\Classes\Db::Strucure();
foreach ($aStrucure as $sTableName => $aField)
{
$sCurrent = $this->getCurrentColumnsInfo($oPdo, $sTableName);
$sWanted = $this->getWantedColumnsInfo($sTableName, $aField);
if (empty($sCurrent))
{
$this->prepareAndExecute($oPdo, $sWanted);
}
else if ($sCurrent !== $sWanted)
{
$this->prepareAndExecute($oPdo, 'DROP TABLE IF EXISTS `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, 'ALTER TABLE `'.$sTableName.'` RENAME TO `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, $sWanted);
$aNewKeys = array();
$aOldKeys = array();
foreach ($aField as $sKey => $sType)
{
$aNewKeys[] = $sKey;
$aOldKeys[] = false !== \strpos($sCurrent, $sKey.' ') ? $sKey :
(0 === \strpos($sType, 'INT') ? '\'0\'' : '\'\'');
}
$sNewKeys = \implode(', ', $aNewKeys);
$sOldKeys = \implode(', ', $aOldKeys);
$this->prepareAndExecute($oPdo, 'INSERT INTO `'.$sTableName.'` ('.$sNewKeys.') SELECT '.$sOldKeys.' FROM `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, 'DROP TABLE `'.$sTableName.'_old`');
}
}
@\file_put_contents($sVersionFile, \RainLoop\Providers\Contacts\Classes\Db::Version());
if ($this->oLogger)
{
$this->oLogger->Write('Stop to sync', \MailSo\Log\Enumerations\Type::INFO);
}
}
/**
* @param \RainLoop\Account|\PDO $oAccountOrPdo
* @param string $sSql
* @param array $aParams
*
* @return \PDOStatement|null
*/
private function prepareAndExecute($oAccountOrPdo, $sSql, $aParams = array())
{
if ($this->oLogger)
{
$this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
}
$oPdo = $oAccountOrPdo instanceof \PDO ? $oAccountOrPdo : $this->getPDO($oAccountOrPdo);
$oStmt = $oPdo->prepare($sSql);
foreach ($aParams as $sName => $aValue)
{
$oStmt->bindValue($sName, $aValue[0], $aValue[1]);
}
// $sLogSql = $sSql;
// foreach($aParams as $sName => $aValue)
// {
// $sLogSql = \str_replace($sName, $aValue[1] === \PDO::PARAM_INT ? $aValue[0] : '\''.$aValue[0].'\'', $sLogSql);
// }
//
// if ($this->oLogger)
// {
// $this->oLogger->Write($sLogSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
// }
$mResult = $oStmt->execute() ? $oStmt : null;
// if ($this->oLogger)
// {
// $this->oLogger->Write('RESULT: '.($mResult ? 'true' : 'false'), \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
// }
return $mResult;
}
/**
* @param \RainLoop\Account|null $oAccount
* @param bool $bSkipInsert = false
*
* @return int
*/
private function getUserId($oAccount, $bSkipInsert = false)
{
if (!$this->bUseDbPerUser)
{
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT IdUser FROM rlContactsUsers WHERE Email = :Email LIMIT 1',
array(
':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR)
));
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
if ($mRow && isset($mRow['IdUser']) && \is_numeric($mRow['IdUser']))
{
return (int) $mRow['IdUser'];
}
if (!$bSkipInsert)
{
$oStmt->closeCursor();
$oStmt = $this->prepareAndExecute($oAccount,
'INSERT INTO rlContactsUsers (Email) VALUES (:Email)',
array(
':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR)
));
return $this->getUserId($oAccount, true);
}
throw new \Exception('IdUser=0');
}
return 0;
}
/**
* @param string $sSearch
* @return string
*/
private function convertSearchValue($sSearch)
{
return '%'.$sSearch.'%';
}
private function populateContactFromDB($iUserID, $aItem)
{
$oContact = null;
if (isset($aItem['IdContact']))
{
$oContact = new \RainLoop\Providers\Contacts\Classes\Contact();
$oContact->IdContact = (int) $aItem['IdContact'];
$oContact->IdUser = $iUserID;
$oContact->Type = (int) $aItem['Type'];
$oContact->Frec = (int) $aItem['Frec'];
$oContact->ListName = (string) $aItem['ListName'];
$oContact->Name = (string) $aItem['Name'];
$oContact->Emails = \explode(' ', \trim((string) $aItem['Emails']));
$oContact->ImageHash = (string) $aItem['ImageHash'];
$oContact->ParseData($aItem['Data']);
}
return $oContact;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return $oContact|null
*/
public function GetContactById($oAccount, $iIdContact)
{
$oResultContact = null;
$iUserID = $this->getUserId($oAccount);
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'.
' FROM rlContactsItems WHERE IdContact = :IdContact AND IdUser = :IdUser LIMIT 1',
array(
':IdContact' => array($iIdContact, \PDO::PARAM_INT),
':IdUser' => array($iUserID, \PDO::PARAM_INT)
));
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
if (\is_array($aFetch) && isset($aFetch[0]) && \is_array($aFetch[0]))
{
$oContact = $this->populateContactFromDB($iUserID, $aFetch[0]);
if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact)
{
$oResultContact = $oContact;
}
}
return $oResultContact;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '')
{
$iOffset = 0 <= $iOffset ? $iOffset : 0;
$iLimit = 0 < $iLimit ? (int) $iLimit : 0;
$sSearch = \trim($sSearch);
$iUserID = $this->getUserId($oAccount);
$sSql = 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'.
' FROM rlContactsItems WHERE IdUser = :IdUser'
;
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
':limit' => array($iLimit, \PDO::PARAM_INT),
':offset' => array($iOffset, \PDO::PARAM_INT)
);
if (0 < strlen($sSearch))
{
if (\MailSo\Base\Utils::IsAscii($sSearch))
{
$sSql .= ' AND Name LIKE :Search OR Emails LIKE :Search';
$aParams[':Search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR);
}
else
{
$sSql .= ' AND SIMPLESEARCH(Emails, Name, :Search)';
$aParams[':Search'] = array($sSearch, \PDO::PARAM_STR);
}
}
$sSql .= ' ORDER BY ListName ASC LIMIT :limit OFFSET :offset';
$oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams);
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
$aResult = array();
if (\is_array($aFetch) && 0 < \count($aFetch))
{
foreach ($aFetch as $aItem)
{
$oContact = $this->populateContactFromDB($iUserID, $aItem);
if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact)
{
$aResult[] = $oContact;
}
}
}
unset($aFetch);
return $aResult;
}
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount)
{
$iUserID = $this->getUserId($oAccount);
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT Emails, ImageHash FROM rlContactsItems WHERE IdUser = :IdUser AND ImageHash <> :ImageHash',
array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
':ImageHash' => array('', \PDO::PARAM_STR)
));
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
$aResult = array();
if (\is_array($aFetch) && 0 < \count($aFetch))
{
foreach ($aFetch as $aItem)
{
if (!empty($aItem['Emails']) && !empty($aItem['ImageHash']))
{
$aEmails = \explode(' ', $aItem['Emails']);
foreach ($aEmails as $sEmail)
{
$sEmail = \trim($sEmail);
if (0 < strlen($sEmail))
{
$aResult[$sEmail] = $aItem['ImageHash'];
}
}
}
}
}
unset($aFetch);
return $aResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact)
{
$iUserID = $this->getUserId($oAccount);
$oContact->IdUser = $iUserID;
$oStmt = $this->prepareAndExecute($oAccount,
'INSERT INTO rlContactsItems '.
'( IdUser, Type, Frec, ListName, Name, Emails, ImageHash, Data) VALUES '.
'(:IdUser, :Type, 0, :ListName, :Name, :Emails, :ImageHash, :Data)',
array(
':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT),
':Type' => array($oContact->Type, \PDO::PARAM_INT),
':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR),
':Name' => array($oContact->Name, \PDO::PARAM_STR),
':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR),
':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR),
':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR),
));
if ($oStmt)
{
$iContactID = $this->getPDO($oAccount)->lastInsertId('IdContact');
if (is_numeric($iContactID) && 0 < (int) $iContactID)
{
$oContact->IdContact = (int) $iContactID;
return true;
}
}
throw new \Exception('CreateContact');
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact)
{
$iUserID = $this->getUserId($oAccount);
$oContact->IdUser = $iUserID;
return !!$this->prepareAndExecute($oAccount,
'UPDATE rlContactsItems SET'.
' Type = :Type, ListName = :ListName, Name = :Name, Emails = :Emails,'.
' ImageHash = :ImageHash, Data = :Data'.
' WHERE IdContact = :IdContact AND IdUser = :IdUser',
array(
':IdContact' => array($oContact->IdContact, \PDO::PARAM_INT),
':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT),
':Type' => array($oContact->Type, \PDO::PARAM_INT),
':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR),
':Name' => array($oContact->Name, \PDO::PARAM_STR),
':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR),
':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR),
':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR),
));
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds)
{
$iUserID = $this->getUserId($oAccount);
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
);
$aInQuery = array();
foreach ($aContactIds as $iIndex => $iId)
{
$aInQuery[] = ':IdContact_'.$iIndex;
$aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT);
}
if (0 === \count($aInQuery))
{
return false;
}
return !!$this->prepareAndExecute($oAccount,
'DELETE FROM rlContactsItems WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')',
$aParams);
}
/**
* @return bool
*/
public function IsSupported()
{
$aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array();
return \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds)
{
if (\is_array($aContactIds) && 0 < \count($aContactIds))
{
$iUserID = $this->getUserId($oAccount);
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
);
$aInQuery = array();
foreach ($aContactIds as $iIndex => $iId)
{
$aInQuery[] = ':IdContact_'.$iIndex;
$aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT);
}
return !!$this->prepareAndExecute($oAccount,
'UPDATE rlContactsItems SET Frec = Frec + 1 WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')',
$aParams);
}
return false;
}
}

View file

@ -0,0 +1,161 @@
<?php
namespace RainLoop\Providers;
class Domain extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Domain\DomainInterface
*/
private $oDriver;
/**
* @var bool
*/
private $bAdmin;
/**
* @param \RainLoop\Providers\Domain\DomainInterface $oDriver
*
* @return void
*/
public function __construct(\RainLoop\Providers\Domain\DomainInterface $oDriver)
{
$this->oDriver = $oDriver;
$this->bAdmin = $this->oDriver instanceof \RainLoop\Providers\Domain\DomainAdminInterface;
}
/**
* @return bool
*/
public function IsAdmin()
{
return $this->bAdmin;
}
/**
* @param string $sName
*
* @return \RainLoop\Domain | null
*/
public function Load($sName)
{
return $this->oDriver->Load($sName);
}
/**
* @param \RainLoop\Domain $oDomain
*
* @return bool
*/
public function Save(\RainLoop\Domain $oDomain)
{
return $this->bAdmin ? $this->oDriver->Save($oDomain) : false;
}
/**
* @param string $sName
*
* @return bool
*/
public function Delete($sName)
{
return $this->bAdmin ? $this->oDriver->Delete($sName) : false;
}
/**
* @param string $sName
* @param bool $bDisabled
*
* @return bool
*/
public function Disable($sName, $bDisabled)
{
return $this->bAdmin ? $this->oDriver->Disable($sName, $bDisabled) : false;
}
/**
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetList($iOffset = 0, $iLimit = 20, $sSearch = '')
{
return $this->bAdmin ? $this->oDriver->GetList($iOffset, $iLimit, $sSearch) : array();
}
/**
* @param string $sSearch = ''
*
* @return int
*/
public function Count($sSearch = '')
{
return $this->oDriver->Count($sSearch);
}
/**
* @param \RainLoop\Actions $oActions
* @param string $sNameForTest = ''
*
* @return \RainLoop\Domain | null
*/
public function LoadOrCreateNewFromAction(\RainLoop\Actions $oActions, $sNameForTest = '')
{
$oDomain = null;
if ($this->bAdmin)
{
$bCreate = '1' === (string) $oActions->GetActionParam('Create', '0');
$sName = (string) $oActions->GetActionParam('Name', '');
$sIncHost = (string) $oActions->GetActionParam('IncHost', '');
$iIncPort = (int) $oActions->GetActionParam('IncPort', 143);
$iIncSecure = (int) $oActions->GetActionParam('IncSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
$bIncShortLogin = '1' === (string) $oActions->GetActionParam('IncShortLogin', '0');
$sOutHost = (string) $oActions->GetActionParam('OutHost', '');
$iOutPort = (int) $oActions->GetActionParam('OutPort', 25);
$iOutSecure = (int) $oActions->GetActionParam('OutSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
$bOutShortLogin = '1' === (string) $oActions->GetActionParam('OutShortLogin', '0');
$bOutAuth = '1' === (string) $oActions->GetActionParam('OutAuth', '1');
$sWhiteList = (string) $oActions->GetActionParam('WhiteList', '');
if (0 < strlen($sName) || 0 < strlen($sNameForTest))
{
$oDomain = 0 < strlen($sNameForTest) ? null : $this->Load($sName);
if ($oDomain instanceof \RainLoop\Domain)
{
if ($bCreate)
{
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainAlreadyExists);
}
else
{
$oDomain->UpdateInstance(
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth,
\RainLoop\Domain::DEFAULT_FORWARDED_FLAG, $sWhiteList);
}
}
else
{
$oDomain = \RainLoop\Domain::NewInstance(0 < strlen($sNameForTest) ? $sNameForTest : $sName,
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth,
\RainLoop\Domain::DEFAULT_FORWARDED_FLAG, $sWhiteList);
}
}
}
return $oDomain;
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Domain\DomainInterface;
}
}

View file

@ -0,0 +1,172 @@
<?php
namespace RainLoop\Providers\Domain;
class DefaultDomain implements \RainLoop\Providers\Domain\DomainAdminInterface
{
/**
* @var string
*/
protected $sDomainPath;
/**
* @param string $sDomainPath
*
* @return void
*/
public function __construct($sDomainPath)
{
$this->sDomainPath = rtrim(trim($sDomainPath), '\\/');
}
/**
* @param string $sName
* @param bool $bDisable
*
* @return bool
*/
public function Disable($sName, $bDisable)
{
$sFile = '';
if (file_exists($this->sDomainPath.'/disabled'))
{
$sFile = @file_get_contents($this->sDomainPath.'/disabled');
}
$aResult = array();
$aNames = explode(',', $sFile);
if ($bDisable)
{
array_push($aNames, $sName);
$aResult = $aNames;
}
else
{
foreach ($aNames as $sItem)
{
if ($sName !== $sItem)
{
$aResult[] = $sItem;
}
}
}
$aResult = array_unique($aResult);
return false !== file_put_contents($this->sDomainPath.'/disabled', trim(implode(',', $aResult), ', '));
}
/**
* @param string $sName
*
* @return \RainLoop\Domain | null
*/
public function Load($sName)
{
$mResult = null;
$sName = strtolower($sName);
if (file_exists($this->sDomainPath.'/'.$sName.'.ini'))
{
$mResult = \RainLoop\Domain::NewInstanceFromDomainConfigArray(
$sName, @parse_ini_file($this->sDomainPath.'/'.$sName.'.ini'));
if ($mResult instanceof \RainLoop\Domain)
{
if (file_exists($this->sDomainPath.'/disabled'))
{
$sDisabled = @file_get_contents($this->sDomainPath.'/disabled');
if (false !== $sDisabled && 0 < strlen($sDisabled))
{
$mResult->SetDisabled(false !== strpos(strtolower(','.$sDisabled.','), strtolower(','.$sName.',')));
}
}
}
}
return $mResult;
}
/**
* @param \RainLoop\Domain $oDomain
*
* @return bool
*/
public function Save(\RainLoop\Domain $oDomain)
{
$mResult = file_put_contents($this->sDomainPath.'/'.strtolower($oDomain->Name()).'.ini', $oDomain->ToIniString());
return is_int($mResult) && 0 < $mResult;
}
/**
* @param string $sName
*
* @return bool
*/
public function Delete($sName)
{
$bResult = true;
$sName = strtolower($sName);
if (0 < strlen($sName) && file_exists($this->sDomainPath.'/'.$sName.'.ini'))
{
$bResult = unlink($this->sDomainPath.'/'.$sName.'.ini');
}
return $bResult;
}
/**
* @param int $iOffset
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetList($iOffset, $iLimit = 20, $sSearch = '')
{
$aResult = array();
$aList = glob($this->sDomainPath.'/*.ini');
$sSearch = strtolower($sSearch);
foreach ($aList as $sFile)
{
$sName = strtolower(substr(basename($sFile), 0, -4));
if (0 === strlen($sSearch) || false !== strpos($sName, $sSearch))
{
$aResult[] = $sName;
}
}
$iOffset = (0 > $iOffset) ? 0 : $iOffset;
$iLimit = (0 > $iLimit) ? 0 : ((999 < $iLimit) ? 999 : $iLimit);
$aResult = array_slice($aResult, $iOffset, $iLimit);
$aDisabledNames = array();
if (0 < count($aResult) && file_exists($this->sDomainPath.'/disabled'))
{
$sDisabled = @file_get_contents($this->sDomainPath.'/disabled');
if (false !== $sDisabled && 0 < strlen($sDisabled))
{
$aDisabledNames = explode(',', strtolower($sDisabled));
$aDisabledNames = array_unique($aDisabledNames);
}
}
$aReturn = array();
foreach ($aResult as $sName)
{
$aReturn[$sName] = !in_array(strtolower($sName), $aDisabledNames);
}
return $aReturn;
}
/**
* @param string $sSearch = ''
*
* @return int
*/
public function Count($sSearch = '')
{
return count($this->GetList(0, 999, $sSearch));
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace RainLoop\Providers\Domain;
interface DomainAdminInterface extends DomainInterface
{
/**
* @param string $sName
* @param bool $bDisable
*
* @return bool
*/
public function Disable($sName, $bDisable);
/**
* @param string $sName
*
* @return \RainLoop\Domain | null
*/
public function Load($sName);
/**
* @param \RainLoop\Domain $oDomain
*
* @return bool
*/
public function Save(\RainLoop\Domain $oDomain);
/**
* @param string $sName
*
* @return bool
*/
public function Delete($sName);
/**
* @param int $iOffset
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetList($iOffset, $iLimit = 20, $sSearch = '');
/**
* @param string $sSearch = ''
*
* @return int
*/
public function Count($sSearch = '');
}

View file

@ -0,0 +1,7 @@
<?php
namespace RainLoop\Providers\Domain;
interface DomainInterface
{
}

View file

@ -0,0 +1,13 @@
<?php
namespace RainLoop\Providers\Domain;
interface DomainSimpleInterface extends DomainInterface
{
/**
* @param string $sName
*
* @return \RainLoop\Domain | null
*/
public function Load($sName);
}

View file

@ -0,0 +1,117 @@
<?php
namespace RainLoop\Providers;
class Files extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Files\FilesInterface
*/
private $oDriver;
/**
* @return void
*/
public function __construct(\RainLoop\Providers\Files\FilesInterface $oDriver)
{
$this->oDriver = $oDriver;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param resource $rSource
*
* @return bool
*/
public function PutFile($oAccount, $sKey, $rSource)
{
return $this->oDriver->PutFile($oAccount, $sKey, $rSource);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param string $sSource
*
* @return bool
*/
public function MoveUploadedFile($oAccount, $sKey, $sSource)
{
return $this->oDriver->MoveUploadedFile($oAccount, $sKey, $sSource);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param string $sOpenMode = 'rb'
*
* @return resource|bool
*/
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb')
{
return $this->oDriver->GetFile($oAccount, $sKey, $sOpenMode);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return string | bool
*/
public function GetFileName($oAccount, $sKey)
{
return $this->oDriver->GetFileName($oAccount, $sKey);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $sKey)
{
return $this->oDriver->Clear($oAccount, $sKey);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return int|bool
*/
public function FileSize($oAccount, $sKey)
{
return $this->oDriver->FileSize($oAccount, $sKey);
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function FileExists($oAccount, $sKey)
{
return $this->oDriver->FileExists($oAccount, $sKey);
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Files\FilesInterface;
}
}

View file

@ -0,0 +1,186 @@
<?php
namespace RainLoop\Providers\Files;
class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
{
/**
* @var string
*/
private $sDataPath;
/**
* @param string $sStoragePath
*
* @return void
*/
public function __construct($sStoragePath)
{
$this->sDataPath = \rtrim(\trim($sStoragePath), '\\/');
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param resource $rSource
*
* @return bool
*/
public function PutFile($oAccount, $sKey, $rSource)
{
$bResult = false;
if ($rSource)
{
$rOpenOutput = @\fopen($this->generateFileName($oAccount, $sKey, true), 'w+b');
if ($rOpenOutput)
{
$bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput)));
@\fclose($rOpenOutput);
}
}
return $bResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param string $sSource
*
* @return bool
*/
public function MoveUploadedFile($oAccount, $sKey, $sSource)
{
return @\move_uploaded_file($sSource,
$this->generateFileName($oAccount, $sKey, true));
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param string $sOpenMode = 'rb'
*
* @return resource|bool
*/
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb')
{
$mResult = false;
$bCreate = !!\preg_match('/[wac]/', $sOpenMode);
$sFileName = $this->generateFileName($oAccount, $sKey, $bCreate);
if ($bCreate || \file_exists($sFileName))
{
$mResult = @\fopen($sFileName, $sOpenMode);
}
return $mResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return string|bool
*/
public function GetFileName($oAccount, $sKey)
{
$mResult = false;
$sFileName = $this->generateFileName($oAccount, $sKey);
if (\file_exists($sFileName))
{
$mResult = $sFileName;
}
return $mResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $sKey)
{
$mResult = true;
$sFileName = $this->generateFileName($oAccount, $sKey);
if (\file_exists($sFileName))
{
$mResult = @\unlink($sFileName);
}
return $mResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return int|bool
*/
public function FileSize($oAccount, $sKey)
{
$mResult = false;
$sFileName = $this->generateFileName($oAccount, $sKey);
if (\file_exists($sFileName))
{
$mResult = \filesize($sFileName);
}
return $mResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function FileExists($oAccount, $sKey)
{
return @\file_exists($this->generateFileName($oAccount, $sKey));
}
/**
* @param int $iTimeToClearInHours = 24
*
* @return bool
*/
public function GC($iTimeToClearInHours = 24)
{
if (0 < $iTimeToClearInHours)
{
\MailSo\Base\Utils::RecTimeDirRemove($this->sDataPath, 60 * 60 * $iTimeToClearInHours, \time());
return true;
}
return false;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param bool $bMkDir = false
*
* @return string
*/
private function generateFileName($oAccount, $sKey, $bMkDir = false)
{
$sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_',
('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email());
$sKeyPath = \sha1($sKey);
$sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath;
$sFilePath = $this->sDataPath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath;
if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath)))
{
if (!@\mkdir(\dirname($sFilePath), 0755, true))
{
throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"');
}
}
return $sFilePath;
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace RainLoop\Providers\Files;
interface FilesInterface
{
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param resource $rSource
*
* @return bool
*/
public function PutFile($oAccount, $sKey, $rSource);
/**
* @param CAccount $oAccount
* @param string $sKey
* @param string $sSource
*
* @return bool
*/
public function MoveUploadedFile($oAccount, $sKey, $sSource);
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
* @param string $sOpenMode = 'rb'
*
* @return resource|bool
*/
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb');
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return string|bool
*/
public function GetFileName($oAccount, $sKey);
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $sKey);
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return int | bool
*/
public function FileSize($oAccount, $sKey);
/**
* @param \RainLoop\Account $oAccount
* @param string $sKey
*
* @return bool
*/
public function FileExists($oAccount, $sKey);
/**
* @param int $iTimeToClearInHours = 24
* @return bool
*/
public function GC($iTimeToClearInHours = 24);
}

View file

@ -0,0 +1,61 @@
<?php
namespace RainLoop\Providers;
class Login extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Login\LoginInterface
*/
private $oDriver;
/**
* @var \RainLoop\Providers\Domain
*/
private $oDomainProvider;
/**
* @param \RainLoop\Providers\Login\LoginInterface $oDriver
* @param \RainLoop\Providers\Domain $oDomainProvider
*
* @return void
*/
public function __construct(\RainLoop\Providers\Login\LoginInterface $oDriver,
\RainLoop\Providers\Domain $oDomainProvider)
{
$this->oDriver = $oDriver;
$this->oDomainProvider = $oDomainProvider;
}
/**
* @param string $sEmail
* @param string $sLogin
* @param string $sPassword
* @param bool $sSignMeToken = ''
*
* @return \RainLoop\Account|null
*/
public function Provide($sEmail, $sLogin, $sPassword, $sSignMeToken = '')
{
$oResult = null;
if ($this->oDriver->ProvideParameters($sEmail, $sLogin, $sPassword))
{
$oDomain = $this->oDomainProvider->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail));
if ($oDomain instanceof \RainLoop\Domain && !$oDomain->Disabled() && $oDomain->ValidateWhiteList($sEmail, $sLogin))
{
$oResult = \RainLoop\Account::NewInstance($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken);
}
}
return $oResult;
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Login\LoginInterface;
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace RainLoop\Providers\Login;
class DefaultLogin implements \RainLoop\Providers\Login\LoginInterface
{
/**
* @param string $sEmail
* @param string $sLogin
* @param string $sPassword
*
* @return bool
*/
public function ProvideParameters(&$sEmail, &$sLogin, &$sPassword)
{
return 0 < strlen($sEmail) && 0 < strlen($sLogin) && 0 < strlen($sPassword);
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace RainLoop\Providers\Login;
interface LoginInterface
{
/**
* @param string $sEmail
* @param string $sLogin
* @param string $sPassword
*
* @return bool
*/
public function ProvideParameters(&$sEmail, &$sLogin, &$sPassword);
}

View file

@ -0,0 +1,52 @@
<?php
namespace RainLoop\Providers;
class Settings extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Settings\SettingsInterface
*/
private $oDriver;
/**
* @param \RainLoop\Providers\Settings\SettingsInterface $oDriver
*
* @return void
*/
public function __construct(\RainLoop\Providers\Settings\SettingsInterface $oDriver)
{
$this->oDriver = $oDriver;
}
/**
* @param \RainLoop\Account $oAccount
*
* @return \RainLoop\Settings
*/
public function Load(\RainLoop\Account $oAccount)
{
$oSettings = new \RainLoop\Settings();
$oSettings->InitData($this->oDriver->Load($oAccount));
return $oSettings;
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Settings $oSettings
*
* @return bool
*/
public function Save(\RainLoop\Account $oAccount, \RainLoop\Settings $oSettings)
{
return $this->oDriver->Save($oAccount, $oSettings->DataAsArray());
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Settings\SettingsInterface;
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace RainLoop\Providers\Settings;
class DefaultSettings implements \RainLoop\Providers\Settings\SettingsInterface
{
const FILE_NAME = 'settings';
/**
* @var \RainLoop\Providers\Storage
*/
private $oStorageProvider;
/**
* @param \RainLoop\Providers\Storage $oStorageProvider
*/
public function __construct(\RainLoop\Providers\Storage $oStorageProvider)
{
$this->oStorageProvider = $oStorageProvider;
}
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function Load(\RainLoop\Account $oAccount)
{
$sValue = $this->oStorageProvider->Get($oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
\RainLoop\Providers\Settings\DefaultSettings::FILE_NAME);
$aSettings = array();
if (\is_string($sValue))
{
$aData = \json_decode($sValue, true);
if (\is_array($aData))
{
$aSettings = $aData;
}
}
return $aSettings;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aSettings
*
* @return bool
*/
public function Save(\RainLoop\Account $oAccount, array $aSettings)
{
return $this->oStorageProvider->Put($oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
\RainLoop\Providers\Settings\DefaultSettings::FILE_NAME,
\json_encode($aSettings));
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace RainLoop\Providers\Settings;
interface SettingsInterface
{
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function Load(\RainLoop\Account $oAccount);
/**
* @param \RainLoop\Account $oAccount
* @param array $aSettings
*
* @return bool
*/
public function Save(\RainLoop\Account $oAccount, array $aSettings);
}

View file

@ -0,0 +1,80 @@
<?php
namespace RainLoop\Providers;
class Storage extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Storage\StorageInterface
*/
private $oDriver;
/**
* @return void
*/
public function __construct(\RainLoop\Providers\Storage\StorageInterface $oDriver)
{
$this->oDriver = $oDriver;
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $iStorageType
* @param string $sValue
*
* @return bool
*/
public function Put($oAccount, $iStorageType, $sKey, $sValue)
{
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account))
{
return false;
}
return $this->oDriver->Put($oAccount, $iStorageType, $sKey, $sValue);
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param mixed $mDefault = false
*
* @return mixed
*/
public function Get($oAccount, $iStorageType, $sKey, $mDefault = false)
{
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account))
{
return $mDefault;
}
return $this->oDriver->Get($oAccount, $iStorageType, $sKey, $mDefault);
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $iStorageType, $sKey)
{
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && !($oAccount instanceof \RainLoop\Account))
{
return false;
}
return $this->oDriver->Clear($oAccount, $iStorageType, $sKey);
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Storage\StorageInterface;
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace RainLoop\Providers\Storage;
class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface
{
/**
* @var string
*/
private $sDataPath;
/**
* @param string $sStoragePath
*
* @return void
*/
public function __construct($sStoragePath)
{
$this->sDataPath = \rtrim(\trim($sStoragePath), '\\/');
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Put($oAccount, $iStorageType, $sKey, $sValue)
{
return false !== @\file_put_contents(
$this->generateFileName($oAccount, $iStorageType, $sKey, true), $sValue);
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param mixed $mDefault = false
*
* @return mixed
*/
public function Get($oAccount, $iStorageType, $sKey, $mDefault = false)
{
$mValue = false;
$sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey);
if (\file_exists($sFileName))
{
$mValue = \file_get_contents($sFileName);
}
return false === $mValue ? $mDefault : $mValue;
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $iStorageType, $sKey)
{
$mResult = true;
$sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey);
if (\file_exists($sFileName))
{
$mResult = @\unlink($sFileName);
}
return $mResult;
}
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param bool $bMkDir = false
*
* @return string
*/
private function generateFileName($oAccount, $iStorageType, $sKey, $bMkDir = false)
{
if (!$oAccount)
{
$iStorageType = \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY;
}
$sEmail = $oAccount ? \preg_replace('/[^a-z0-9\-\.@]+/', '_',
('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email()) : '';
$sTypePath = $sKeyPath = '';
switch ($iStorageType)
{
default:
case \RainLoop\Providers\Storage\Enumerations\StorageType::USER:
case \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY:
$sTypePath = 'data';
$sKeyPath = \md5($sKey);
$sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath;
break;
case \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG:
$sTypePath = 'cfg';
$sKeyPath = \preg_replace('/[_]+/', '_', \preg_replace('/[^a-zA-Z0-9\/]/', '_', $sKey));
break;
}
$sFilePath = '';
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY === $iStorageType)
{
$sFilePath = $this->sDataPath.'/'.$sTypePath.'/__nobody__/'.$sKeyPath;
}
else if (!empty($sEmail))
{
$sFilePath = $this->sDataPath.'/'.$sTypePath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath;
}
if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath)))
{
if (!@\mkdir(\dirname($sFilePath), 0755, true))
{
throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"');
}
}
return $sFilePath;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace RainLoop\Providers\Storage\Enumerations;
class StorageType
{
const USER = 1;
const CONFIG = 2;
const NOBODY = 3;
}

View file

@ -0,0 +1,35 @@
<?php
namespace RainLoop\Providers\Storage;
interface StorageInterface
{
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param string $sValue
*
* @return bool
*/
public function Put($oAccount, $iStorageType, $sKey, $sValue);
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
* @param mixed $mDefault = false
*
* @return mixed
*/
public function Get($oAccount, $iStorageType, $sKey, $mDefault = false);
/**
* @param \RainLoop\Account|null $oAccount
* @param int $iStorageType
* @param string $sKey
*
* @return bool
*/
public function Clear($oAccount, $iStorageType, $sKey);
}

View file

@ -0,0 +1,40 @@
<?php
namespace RainLoop\Providers;
class Suggestions extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Suggestions\SuggestionsInterface
*/
private $oDriver;
/**
* @param \RainLoop\Providers\Suggestions\SuggestionsInterface|null $oDriver = null
*
* @return void
*/
public function __construct($oDriver = null)
{
$this->oDriver = $oDriver;
}
/**
* @param \RainLoop\Account $oAccount
* @param string $sQuery
*
* @return array
*/
public function Process(\RainLoop\Account $oAccount, $sQuery)
{
return $this->oDriver && $this->IsActive() && 0 < \strlen($sQuery) ? $this->oDriver->Process($oAccount, $sQuery) : array();
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Suggestions\SuggestionsInterface;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace RainLoop\Providers\Suggestions;
interface SuggestionsInterface
{
/**
* @param \RainLoop\Account $oAccount
* @param string $sQuery
*
* @return array
*/
public function Process(\RainLoop\Account $oAccount, $sQuery);
}