PageRenderTime 40ms CodeModel.GetById 19ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/packages/Chat/Chat/Managers/ChatSessionManager.class.php

https://bitbucket.org/alexamiryan/stingle
PHP | 334 lines | 258 code | 58 blank | 18 comment | 27 complexity | 8a6f558b2fef022467499577c74416f6 MD5 | raw file
  1<?php
  2class ChatSessionManager extends DbAccessor
  3{
  4	const TBL_CHAT_SESSIONS = 'chat_sessions';
  5	const TBL_CHAT_SESSIONS_LOG = 'chat_sessions_log';
  6	
  7	const CLOSED_STATUS_NO = 0; 
  8	const CLOSED_STATUS_YES = 1; 
  9	
 10	const CLOSED_REASON_CLOSE = 1; 
 11	const CLOSED_REASON_OFFLINE = 2; 
 12	const CLOSED_REASON_MONEY = 3;
 13	const CLOSED_REASON_SYNC_UI = 4;
 14	
 15	private $sessionClearTimeout = 10;  // in minutes
 16	
 17	public function __construct(Config $config, $instanceName = null){
 18		parent::__construct($instanceName);
 19		
 20		if(isset($config->sessionClearTimeout)){
 21			$this->sessionClearTimeout = $config->sessionClearTimeout;
 22		}
 23	}
 24	
 25	public static function getInterlocutorsFromSessions($chatSessions){
 26		$interlocutorIds = array();
 27		foreach($chatSessions as $chatSession){
 28			array_push($interlocutorIds, $chatSession->interlocutorUser->userId);
 29		}
 30		
 31		return $interlocutorIds;
 32	}
 33	
 34	public static function fillSessionsWithMessages($chatSessions, $chatMessages){
 35		foreach($chatMessages as $chatMessage){
 36			foreach($chatSessions as &$chatSession){
 37				// Check if this message belongs to this session.
 38				if(
 39					(
 40						$chatMessage->senderUser->userId == $chatSession->interlocutorUser->userId
 41							and
 42						$chatMessage->receiverUser->userId == $chatSession->chatterUser->userId
 43					)
 44					or
 45					(
 46						$chatMessage->senderUser->userId == $chatSession->chatterUser->userId
 47							and
 48						$chatMessage->receiverUser->userId == $chatSession->interlocutorUser->userId
 49					)
 50				){
 51					array_push($chatSession->messages, $chatMessage);
 52				}
 53			}
 54		}
 55		return $chatSessions;
 56	}
 57	
 58	/**
 59	 * Sessions list
 60	 * @param ChatSessionFilter $filter
 61	 * @param unknown_type $myUserId
 62	 */
 63	public function getChatSessions(ChatSessionFilter $filter = null, $myUserId = null){
 64		$chatSessions = array();
 65		
 66		if($filter == null){
 67			$filter = new ChatSessionFilter();
 68		}
 69		
 70		$sqlQuery = $filter->getSQL();
 71		
 72		$sessionRows = $this->query->exec($sqlQuery)->fetchRecords();
 73										
 74		foreach ($sessionRows as $sessionRow){
 75			array_push($chatSessions, $this->getChatSessionObject($sessionRow, $myUserId));
 76		}
 77		
 78		return $chatSessions;
 79	}
 80	
 81	/**
 82	 * Sessions count
 83	 * @param ProfileViewsFilter $filter
 84	 * @param Integer $cacheMinutes
 85	 * @return Integer
 86	 */
 87	public function getChatSessionsCount(ChatSessionFilter $filter = null){
 88	
 89		if($filter == null){
 90			$filter = new ChatSessionFilter();
 91		}
 92		$filter->setSelectCount();
 93	
 94		$sqlQuery = $filter->getSQL();
 95	
 96		$this->query->exec($sqlQuery);
 97		return $this->query->fetchField('cnt');
 98	}
 99	
100	public function getChatSession(ChatSessionFilter $filter = null, $myUserId = null){
101		$sessions = $this->getChatSessions($filter, $myUserId);
102		if(count($sessions) !== 1){
103			throw new ChatSessionException("There is no such chat session or it is not unique.");
104		}
105		return $sessions[0];
106	}
107	
108	public function getChatSessionById($sessionId, $myUserId = null){
109		$filter = new ChatSessionFilter();
110		$filter->setId($sessionId);
111		$session = $this->getChatSession($filter);
112		return $session;
113	}
114	
115	protected function getChatSessionObject($sessionRow, $myUserId = null){
116		if(empty($sessionRow) or !is_array($sessionRow)){
117			throw new InvalidArgumentException("Invalid \$sessionRow specified!");
118		}
119		
120		$chatSession = new ChatSession();
121		
122		if($myUserId !== null){
123			if($sessionRow['inviter_user_id'] == $myUserId){
124				$interlocutorUserId = $sessionRow['invited_user_id'];
125			}
126			else{
127				$interlocutorUserId = $sessionRow['inviter_user_id'];
128			}
129			
130			$chatSession->chatterUser = ChatUser::getObject($myUserId);
131			$chatSession->interlocutorUser = ChatUser::getObject($interlocutorUserId);
132		}
133		else{
134			$chatSession->chatterUser = ChatUser::getObject($sessionRow['inviter_user_id']);
135			$chatSession->interlocutorUser = ChatUser::getObject($sessionRow['invited_user_id']);
136		}
137		
138		$chatSession->id = $sessionRow['id'];
139		$chatSession->startDate = $sessionRow['date'];
140		$chatSession->closed = $sessionRow['closed'];
141		$chatSession->closedBy = $sessionRow['closed_by'];
142		$chatSession->closedReason = $sessionRow['closed_reason'];
143		$chatSession->closedDate = $sessionRow['closed_date'];
144		
145		return $chatSession;
146	}
147	
148	public function getInterlocutorsIds($userId){
149		if(empty($userId) or !is_numeric($userId)){
150			throw new InvalidArgumentException("Invalid userId specified!");
151		}
152		
153		$filter = new ChatSessionFilter();
154		$filter->setEitherUserId($userId);
155		$chatSessions = $this->getChatSessions($filter, $userId);
156		
157		$interlocutorIds = array();
158		foreach($chatSessions as $chatSession){
159			array_push($interlocutorIds, $chatSession->interlocutorUser->userId);
160		}
161		
162		return $interlocutorIds;
163	}
164	
165	public function insertSession($inviterUserId, $invitedUserId){
166		if(empty($inviterUserId) or !is_numeric($inviterUserId)){
167			throw new InvalidArgumentException("Invalid inviterUser specified!");
168		}
169		if(empty($invitedUserId) or !is_numeric($invitedUserId)){
170			throw new InvalidArgumentException("Invalid invitedUser specified!");
171		}
172		$qb = new QueryBuilder();
173		$qb->insertIgnore(Tbl::get('TBL_CHAT_SESSIONS'))
174			->values(array(
175							'inviter_user_id' => $inviterUserId,
176							'invited_user_id' => $invitedUserId
177			));
178		$this->query->exec($qb->getSQL());
179		
180		$newSessionId = $this->query->getLastInsertId();
181		//$this->insertSessionLog($inviterUserId, $invitedUserId);
182		
183		return $newSessionId;
184	}
185	
186	public function deleteSession($sessionId){
187		if(empty($sessionId) or !is_numeric($sessionId)){
188			throw new InvalidArgumentException("Invalid session ID specified!");
189		}
190		$qb = new QueryBuilder();
191		$qb->delete(Tbl::get('TBL_CHAT_SESSIONS'))
192			->where($qb->expr()->equal(new Field('id'), $sessionId));
193		$this->query->exec($qb->getSQL());
194	}
195	
196	public function closeSession(ChatSession $session, ChatUser $closerUser, $reason = null){
197		
198		$qb = new QueryBuilder();
199		$qb->update(Tbl::get('TBL_CHAT_SESSIONS'))
200			->set(new Field('closed'), static::CLOSED_STATUS_YES)
201			->set(new Field('closed_date'), new Func('NOW'))
202			->set(new Field('closed_by'), $closerUser->userId)
203			->where($qb->expr()->equal(new Field('id'), $session->id));
204		if($reason !== null){
205			$qb->set(new Field('closed_reason'), $reason);
206			$session->closedReason = $reason;
207		}	
208		$this->query->exec($qb->getSQL());
209		
210		$session->closed = static::CLOSED_STATUS_YES;
211		$session->closedBy = $closerUser->userId;
212	}
213	
214	public function clearTimedOutSessions(){
215		$qb = new QueryBuilder();
216		$qb->delete(Tbl::get('TBL_CHAT_SESSIONS'))
217			->where($qb->expr()->equal(new Field('closed'), 1))
218			->andWhere(
219						$qb->expr()->greaterEqual(
220								$qb->expr()->diff(new Func('NOW'), new Field('closed_date')),
221								$qb->expr()->prod($this->sessionClearTimeout, 60)
222						 ));
223						 
224		$this->query->exec($qb->getSQL());
225		return $this->query->affected();
226	}
227	
228	public function getChatSessionsLog(MysqlPager $pager = null, $myUserId = null, $cacheMinutes = 0){
229		$sessions = array();
230		$qb = new QueryBuilder();
231		$qb->select(new Field("*", "chat_sess_log"))->from(Tbl::get('TBL_CHAT_SESSIONS_LOG'), "chat_sess_log");
232
233		if($myUserId !== null){
234			$orClause = new Orx();
235			$orClause->add($qb->expr()->equal(new Field("user1_id", "chat_sess_log"), $myUserId));
236			$orClause->add($qb->expr()->equal(new Field("user2_id", "chat_sess_log"), $myUserId));
237			$qb->andWhere($orClause);
238		}
239		
240		$qb->orderBy(new Field("datetime", "chat_sess_log"), MySqlDatabase::ORDER_DESC);
241		$sqlQuery = $qb->getSQL();
242		
243		if($pager !== null){
244			$this->query = $pager->executePagedSQL($sqlQuery, $cacheMinutes);
245		}
246		else{
247			$this->query->exec($sqlQuery, $cacheMinutes);
248		}
249		
250		if($this->query->countRecords()){
251			while(($sesLogRow = $this->query->fetchRecord()) != null){
252				$chatSession = new ChatSessionLog();
253
254				$chatSession->user1 = ChatUser::getObject($sesLogRow['user1_id']);
255				$chatSession->user2 = ChatUser::getObject($sesLogRow['user2_id']);
256				
257				$chatSession->id = $sesLogRow['id'];
258				$chatSession->closedDate = $sesLogRow['datetime'];
259				
260				array_push($sessions, $chatSession);
261			}
262		}
263		
264		return $sessions;
265	}
266	
267	public function getChatSessionsLogCount($myUserId = null){
268		
269		$qb = new QueryBuilder();
270		$qb->select($qb->expr()->count(new Field('*'), 'cnt'))->from(Tbl::get('TBL_CHAT_SESSIONS_LOG'), "chat_sess_log");
271		if($myUserId !== null){
272			$orClause = new Orx();
273			$orClause->add($qb->expr()->equal(new Field("user1_id", "chat_sess_log"), $myUserId));
274			$orClause->add($qb->expr()->equal(new Field("user2_id", "chat_sess_log"), $myUserId));
275			$qb->andWhere($orClause);
276		}
277		
278		$sqlQuery = $qb->getSQL();
279		$this->query->exec($sqlQuery);
280		return $this->query->fetchField('cnt');
281	}
282	/**
283	 * @param integer $inviterUserId
284	 * @param integer $invitedUserId
285	 * @deprecated Sessions log insertd by mysql TRIGGER chat_sessions_log 
286	 */
287	protected function insertSessionLog($inviterUserId, $invitedUserId){
288		if($inviterUserId > $invitedUserId){
289			$userId1 = $inviterUserId;
290			$userId2 = $invitedUserId;
291		}
292		else{
293			$userId1 = $invitedUserId;
294			$userId2 = $inviterUserId;
295		}
296		$qb = new QueryBuilder();
297		$qb->select(new Field('id'))->from(Tbl::get('TBL_CHAT_SESSIONS_LOG'));
298		
299		$andClause1 = new Andx();
300		$andClause1->add($qb->expr()->equal(new Field('user1_id', Tbl::get('TBL_CHAT_SESSIONS_LOG')), $userId1));
301		$andClause1->add($qb->expr()->equal(new Field('user2_id', Tbl::get('TBL_CHAT_SESSIONS_LOG')), $userId2));
302		
303		$andClause2 = new Andx();
304		$andClause2->add($qb->expr()->equal(new Field('user1_id', Tbl::get('TBL_CHAT_SESSIONS_LOG')), $userId2));
305		$andClause2->add($qb->expr()->equal(new Field('user2_id', Tbl::get('TBL_CHAT_SESSIONS_LOG')), $userId1));
306		
307		$orClause = new Orx();
308		$orClause->add($andClause1);
309		$orClause->add($andClause2);
310		
311		$qb->andWhere($orClause);
312		$this->query->exec($qb->getSQL());
313		
314		$qb = new QueryBuilder();
315		if($this->query->countRecords()){
316			$sesionId = $this->query->fetchField("id");
317			$qb->update(Tbl::get('TBL_CHAT_SESSIONS_LOG'))
318			->set(new Field('datetime'), date(DEFAULT_DATETIME_FORMAT))
319			->where($qb->expr()->equal(new Field('id'), $sesionId));
320			
321		}
322		else{
323			$qb->insert(Tbl::get('TBL_CHAT_SESSIONS_LOG'))
324			->values(array(
325					'user1_id' => $userId1,
326					'user2_id' => $userId2,
327					'datetime' => date(DEFAULT_DATETIME_FORMAT)
328			));
329		}
330		$this->query->exec($qb->getSQL());
331		
332		return $this->query->affected();
333	}
334}