1<?php 2 3declare(strict_types=1); 4/** 5 * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com> 6 * 7 * @license GNU AGPL version 3 or any later version 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Affero General Public License as 11 * published by the Free Software Foundation, either version 3 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Affero General Public License for more details. 18 * 19 * You should have received a copy of the GNU Affero General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 * 22 */ 23 24namespace OCA\Talk\Service; 25 26use OCA\Talk\Model\Attendee; 27use OCA\Talk\Model\Session; 28use OCA\Talk\Model\SessionMapper; 29use OCP\DB\Exception; 30use OCP\DB\QueryBuilder\IQueryBuilder; 31use OCP\IDBConnection; 32use OCP\Security\ISecureRandom; 33 34class SessionService { 35 /** @var SessionMapper */ 36 protected $sessionMapper; 37 /** @var IDBConnection */ 38 protected $connection; 39 /** @var ISecureRandom */ 40 protected $secureRandom; 41 42 public function __construct(SessionMapper $sessionMapper, 43 IDBConnection $connection, 44 ISecureRandom $secureRandom) { 45 $this->sessionMapper = $sessionMapper; 46 $this->connection = $connection; 47 $this->secureRandom = $secureRandom; 48 } 49 50 /** 51 * Update last ping for multiple sessions 52 * 53 * Since this function is called by the HPB with potentially hundreds of 54 * sessions, we do not use the SessionMapper to get the entities first, as 55 * that would just not scale good enough. 56 * 57 * @param string[] $sessionIds 58 * @param int $lastPing 59 */ 60 public function updateMultipleLastPings(array $sessionIds, int $lastPing): void { 61 $update = $this->connection->getQueryBuilder(); 62 $update->update('talk_sessions') 63 ->set('last_ping', $update->createNamedParameter($lastPing, IQueryBuilder::PARAM_INT)) 64 ->where($update->expr()->in('session_id', $update->createNamedParameter($sessionIds, IQueryBuilder::PARAM_STR_ARRAY))); 65 66 $update->executeStatement(); 67 } 68 69 public function updateLastPing(Session $session, int $lastPing): void { 70 $session->setLastPing($lastPing); 71 $this->sessionMapper->update($session); 72 } 73 74 /** 75 * @param int[] $ids 76 */ 77 public function deleteSessionsById(array $ids): void { 78 $this->sessionMapper->deleteByIds($ids); 79 } 80 81 /** 82 * @param Attendee $attendee 83 * @return Session[] 84 */ 85 public function getAllSessionsForAttendee(Attendee $attendee): array { 86 return $this->sessionMapper->findByAttendeeId($attendee->getId()); 87 } 88 89 /** 90 * @param Attendee $attendee 91 * @param string $forceSessionId 92 * @return Session 93 * @throws Exception 94 */ 95 public function createSessionForAttendee(Attendee $attendee, string $forceSessionId = ''): Session { 96 $session = new Session(); 97 $session->setAttendeeId($attendee->getId()); 98 99 if ($forceSessionId !== '') { 100 $session->setSessionId($forceSessionId); 101 $this->sessionMapper->insert($session); 102 } else { 103 while (true) { 104 $sessionId = $this->secureRandom->generate(255); 105 $session->setSessionId($sessionId); 106 try { 107 $this->sessionMapper->insert($session); 108 break; 109 } catch (Exception $e) { 110 // 255 chars are not unique? Try again... 111 if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) { 112 throw $e; 113 } 114 } 115 } 116 } 117 118 return $session; 119 } 120} 121