[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Session/ -> MetadataManager.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer