[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Session; 11 12 use Joomla\Application\AbstractApplication; 13 use Joomla\CMS\Application\CMSApplication; 14 use Joomla\CMS\User\User; 15 use Joomla\Database\DatabaseInterface; 16 use Joomla\Database\Exception\ExecutionFailureException; 17 use Joomla\Database\ParameterType; 18 use Joomla\Session\SessionInterface; 19 20 // phpcs:disable PSR1.Files.SideEffects 21 \defined('JPATH_PLATFORM') or die; 22 // phpcs:enable PSR1.Files.SideEffects 23 24 /** 25 * Manager for optional session metadata. 26 * 27 * @since 3.8.6 28 * @internal 29 */ 30 final class MetadataManager 31 { 32 /** 33 * Internal variable indicating a session record exists. 34 * 35 * @var integer 36 * @since 4.0.0 37 * @note Once PHP 7.1 is the minimum supported version this should become a private constant 38 */ 39 private static $sessionRecordExists = 1; 40 41 /** 42 * Internal variable indicating a session record does not exist. 43 * 44 * @var integer 45 * @since 4.0.0 46 * @note Once PHP 7.1 is the minimum supported version this should become a private constant 47 */ 48 private static $sessionRecordDoesNotExist = 0; 49 50 /** 51 * Internal variable indicating an unknown session record statue. 52 * 53 * @var integer 54 * @since 4.0.0 55 * @note Once PHP 7.1 is the minimum supported version this should become a private constant 56 */ 57 private static $sessionRecordUnknown = -1; 58 59 /** 60 * Application object. 61 * 62 * @var AbstractApplication 63 * @since 3.8.6 64 */ 65 private $app; 66 67 /** 68 * Database driver. 69 * 70 * @var DatabaseInterface 71 * @since 3.8.6 72 */ 73 private $db; 74 75 /** 76 * MetadataManager constructor. 77 * 78 * @param AbstractApplication $app Application object. 79 * @param DatabaseInterface $db Database driver. 80 * 81 * @since 3.8.6 82 */ 83 public function __construct(AbstractApplication $app, DatabaseInterface $db) 84 { 85 $this->app = $app; 86 $this->db = $db; 87 } 88 89 /** 90 * Create the metadata record if it does not exist. 91 * 92 * @param SessionInterface $session The session to create the metadata record for. 93 * @param User $user The user to associate with the record. 94 * 95 * @return void 96 * 97 * @since 3.8.6 98 * @throws \RuntimeException 99 */ 100 public function createRecordIfNonExisting(SessionInterface $session, User $user) 101 { 102 $exists = $this->checkSessionRecordExists($session->getId()); 103 104 // Only touch the database if the record does not already exist 105 if ($exists !== self::$sessionRecordExists) { 106 return; 107 } 108 109 $this->createSessionRecord($session, $user); 110 } 111 112 /** 113 * Create the metadata record if it does not exist. 114 * 115 * @param SessionInterface $session The session to create or update the metadata record for. 116 * @param User $user The user to associate with the record. 117 * 118 * @return void 119 * 120 * @since 4.0.0 121 * @throws \RuntimeException 122 */ 123 public function createOrUpdateRecord(SessionInterface $session, User $user) 124 { 125 $exists = $this->checkSessionRecordExists($session->getId()); 126 127 // Do not try to touch the database if we can't determine the record state 128 if ($exists === self::$sessionRecordUnknown) { 129 return; 130 } 131 132 if ($exists === self::$sessionRecordDoesNotExist) { 133 $this->createSessionRecord($session, $user); 134 135 return; 136 } 137 138 $this->updateSessionRecord($session, $user); 139 } 140 141 /** 142 * Delete records with a timestamp prior to the given time. 143 * 144 * @param integer $time The time records should be deleted if expired before. 145 * 146 * @return void 147 * 148 * @since 3.8.6 149 */ 150 public function deletePriorTo($time) 151 { 152 $query = $this->db->getQuery(true) 153 ->delete($this->db->quoteName('#__session')) 154 ->where($this->db->quoteName('time') . ' < :time') 155 ->bind(':time', $time, ParameterType::INTEGER); 156 157 $this->db->setQuery($query); 158 159 try { 160 $this->db->execute(); 161 } catch (ExecutionFailureException $exception) { 162 // Since garbage collection does not result in a fatal error when run in the session API, we don't allow it here either. 163 } 164 } 165 166 /** 167 * Check if the session record exists 168 * 169 * @param string $sessionId The session ID to check 170 * 171 * @return integer Status value for record presence 172 * 173 * @since 4.0.0 174 */ 175 private function checkSessionRecordExists(string $sessionId): int 176 { 177 $query = $this->db->getQuery(true) 178 ->select($this->db->quoteName('session_id')) 179 ->from($this->db->quoteName('#__session')) 180 ->where($this->db->quoteName('session_id') . ' = :session_id') 181 ->bind(':session_id', $sessionId) 182 ->setLimit(1); 183 184 $this->db->setQuery($query); 185 186 try { 187 $exists = $this->db->loadResult(); 188 } catch (ExecutionFailureException $e) { 189 return self::$sessionRecordUnknown; 190 } 191 192 if ($exists) { 193 return self::$sessionRecordExists; 194 } 195 196 return self::$sessionRecordDoesNotExist; 197 } 198 199 /** 200 * Create the session record 201 * 202 * @param SessionInterface $session The session to create the metadata record for. 203 * @param User $user The user to associate with the record. 204 * 205 * @return void 206 * 207 * @since 4.0.0 208 */ 209 private function createSessionRecord(SessionInterface $session, User $user) 210 { 211 $query = $this->db->getQuery(true); 212 213 $time = $session->isNew() ? time() : $session->get('session.timer.start'); 214 215 $columns = [ 216 $this->db->quoteName('session_id'), 217 $this->db->quoteName('guest'), 218 $this->db->quoteName('time'), 219 $this->db->quoteName('userid'), 220 $this->db->quoteName('username'), 221 ]; 222 223 // Add query placeholders 224 $values = [ 225 ':session_id', 226 ':guest', 227 ':time', 228 ':user_id', 229 ':username', 230 ]; 231 232 // Bind query values 233 $sessionId = $session->getId(); 234 $userIsGuest = $user->guest; 235 $userId = $user->id; 236 $username = $user->username === null ? '' : $user->username; 237 238 $query->bind(':session_id', $sessionId) 239 ->bind(':guest', $userIsGuest, ParameterType::INTEGER) 240 ->bind(':time', $time) 241 ->bind(':user_id', $userId, ParameterType::INTEGER) 242 ->bind(':username', $username); 243 244 if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false)) { 245 $clientId = $this->app->getClientId(); 246 247 $columns[] = $this->db->quoteName('client_id'); 248 $values[] = ':client_id'; 249 250 $query->bind(':client_id', $clientId, ParameterType::INTEGER); 251 } 252 253 $query->insert($this->db->quoteName('#__session')) 254 ->columns($columns) 255 ->values(implode(', ', $values)); 256 257 $this->db->setQuery($query); 258 259 try { 260 $this->db->execute(); 261 } catch (ExecutionFailureException $e) { 262 // This failure isn't critical, we can go on without the metadata 263 } 264 } 265 266 /** 267 * Update the session record 268 * 269 * @param SessionInterface $session The session to update the metadata record for. 270 * @param User $user The user to associate with the record. 271 * 272 * @return void 273 * 274 * @since 4.0.0 275 */ 276 private function updateSessionRecord(SessionInterface $session, User $user) 277 { 278 $query = $this->db->getQuery(true); 279 280 $time = time(); 281 282 $setValues = [ 283 $this->db->quoteName('guest') . ' = :guest', 284 $this->db->quoteName('time') . ' = :time', 285 $this->db->quoteName('userid') . ' = :user_id', 286 $this->db->quoteName('username') . ' = :username', 287 ]; 288 289 // Bind query values 290 $sessionId = $session->getId(); 291 $userIsGuest = $user->guest; 292 $userId = $user->id; 293 $username = $user->username === null ? '' : $user->username; 294 295 $query->bind(':session_id', $sessionId) 296 ->bind(':guest', $userIsGuest, ParameterType::INTEGER) 297 ->bind(':time', $time) 298 ->bind(':user_id', $userId, ParameterType::INTEGER) 299 ->bind(':username', $username); 300 301 if ($this->app instanceof CMSApplication && !$this->app->get('shared_session', false)) { 302 $clientId = $this->app->getClientId(); 303 304 $setValues[] = $this->db->quoteName('client_id') . ' = :client_id'; 305 306 $query->bind(':client_id', $clientId, ParameterType::INTEGER); 307 } 308 309 $query->update($this->db->quoteName('#__session')) 310 ->set($setValues) 311 ->where($this->db->quoteName('session_id') . ' = :session_id'); 312 313 $this->db->setQuery($query); 314 315 try { 316 $this->db->execute(); 317 } catch (ExecutionFailureException $e) { 318 // This failure isn't critical, we can go on without the metadata 319 } 320 } 321 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |