'Admin', 'user' => 'User'); protected $_defaultTimeout = 60; protected $_timeout; protected $_userRole; protected $_userRoleTitle = array('user' => 'User', 'admin' => 'Administrator'); protected $_userId; protected $_sessionId; /** * @param $userRole string * @param $userId int * @param $sessionId string * @throws Qs_Exception */ public function __construct($userRole, $userId, $sessionId) { if (empty($userRole)) { throw new Qs_Exception('User role is not defined'); } if (empty($userId)) { throw new Qs_Exception('User ID is not defined'); } if (empty($sessionId)) { throw new Qs_Exception('User session is not defined'); } $this->_userRole = $userRole; $this->_userId = $userId; $this->_sessionId = $sessionId; parent::__construct(); } /** * @param $timeout int * @return Qs_Lock_RoleObj */ public function setTimeout($timeout) { $this->_timeout = (int) $timeout; return $this; } /** * @return int */ public function getTimeout() { if (!$this->_timeout) { $this->_timeout = (int) App_Settings_Obj::get('lockObjectTimeout'); if (!$this->_timeout) { $this->_timeout = $this->_defaultTimeout; } } return $this->_timeout; } /** * @param $resourceName string * @param $objectId int * @return bool */ public function lock($resourceName, $objectId) { if (!empty($resourceName) && !empty($objectId)) { try { if (!$this->isLocked($resourceName, $objectId)) { $data = array( 'resourceName' => $resourceName, 'objectId' => $objectId, 'userRole' => $this->_userRole, 'userId' => $this->_userId, 'sessionId' => $this->_sessionId, 'accessTime' => new Zend_Db_Expr('NOW()'), ); $this->_setLock($data); return true; } } catch (Qs_Exception $e) { Qs_Debug::log($e->getMessage()); } } return false; } /** * @param array $data * @return int affected rows */ protected function _setLock(array $data) { $primary = $this->getPrimary(); $cols = $vals = $onDuplicate = array(); $colIndex = $iterationIndex = 0; foreach ($data as $col => $val) { $cols[] = $this->_db->quoteIdentifier($col, true); if ($val instanceof Zend_Db_Expr) { /** @var Zend_Db_Expr $val */ $vals[] = $val->__toString(); unset($data[$col]); } else { unset($data[$col]); $data[':col' . $colIndex] = $val; $vals[] = ':col' . $colIndex; $colIndex++; } if (!in_array($col, $primary)) { $onDuplicate[] = $cols[$iterationIndex] . ' = ' . $vals[$iterationIndex]; } $iterationIndex++; } // build the statement $sql = "INSERT INTO " . $this->_getQuotedTableName() . ' (' . implode(', ', $cols) . ') ' . 'VALUES (' . implode(', ', $vals) . ') ' . 'ON DUPLICATE KEY UPDATE ' . implode(', ', $onDuplicate); $stmt = $this->_db->query($sql, $data); return $stmt->rowCount(); } /** * @param $resourceName string * @param $objectId int * @return bool */ public function unlock($resourceName, $objectId) { $timeout = $this->getTimeout(); $sql = 'DELETE FROM ' . $this->_db->quoteIdentifier($this->_getTableName($this->_tableAlias)) . ' ' . 'WHERE `resourceName` = ' . $this->_db->quote($resourceName) . ' ' . 'AND `objectId` = ' . $this->_db->quote($objectId, Qs_Db::INT_TYPE) . ' ' . 'AND (' . ' (' . ' `userRole` = ' . $this->_db->quote($this->_userRole) . ' AND `userId` = ' . $this->_db->quote($this->_userId, Qs_Db::INT_TYPE) . ' ) OR (' . ' DATE_ADD(`accessTime`, INTERVAL ' . $this->_db->quote($timeout, Qs_Db::INT_TYPE) . ' SECOND) < NOW()' . ' )' . ')'; return (bool) $this->_db->query($sql); } /** * @param $columns array | string * @param $resourceName string * @param $objectId int * @return Zend_Db_Select */ protected function _getLockSelect($columns, $resourceName, $objectId) { $select = $this->_db->select(); $select->from($this->_getPair(), $columns); $select->where('`resourceName` = ?', (string) $resourceName); $select->where('`objectId` = ?', (string) $objectId, Qs_Db::INT_TYPE); $select->where('DATE_ADD(`accessTime`, INTERVAL ? SECOND) >= NOW()', $this->getTimeout(), Qs_Db::INT_TYPE); return $select; } /** * @param $resourceName string * @param $objectId int * @return bool */ public function isLocked($resourceName, $objectId) { $select = $this->_getLockSelect(array(new Zend_Db_Expr('1')), $resourceName, $objectId); $where = '`userRole` != ' . $this->_db->quote($this->_userRole) . ' OR `userId` != ' . $this->_db->quote($this->_userId, Qs_Db::INT_TYPE) . ' OR `sessionId` != ' . $this->_db->quote($this->_sessionId); $select->where($where); return (bool) $this->_db->fetchOne($select); } /** * @param $resourceName string * @param $objectId int * @return array */ public function getLockerData($resourceName, $objectId) { $select = $this->_getLockSelect(array('userRole', 'userId'), $resourceName, $objectId); $locker = $this->_db->fetchRow($select); if (!empty($locker)) { $table = $this->_getTable($this->_userTableAlias[$locker['userRole']]); if ($table) { $row = $table->findRow($locker['userId']); if ($row) { $locker = array_merge($row->toArray(), $locker); } } $locker['userRoleTitle'] = $this->_getUserRoleTitle($locker['userRole']); } return $locker; } /** * @param string $userRole * @return string */ protected function _getUserRoleTitle($userRole) { $title = Qs_Array::get($this->_userRoleTitle, $userRole, $userRole); return $title; } }