db = $db; } /** * Close the session * * @return boolean True on success, false otherwise * * @since 2.0.0 */ #[\ReturnTypeWillChange] public function close() { if ($this->gcCalled) { $query = $this->db->getQuery(true) ->delete($this->db->quoteName('#__session')) ->where($this->db->quoteName('time') . ' < ?') ->bind(1, $this->gcLifetime, ParameterType::INTEGER); // Remove expired sessions from the database. $this->db->setQuery($query)->execute(); $this->gcCalled = false; $this->gcLifetime = null; } $this->db->disconnect(); return true; } /** * Creates the session database table * * @return boolean * * @since 2.0.0 * @throws CreateSessionTableException * @throws UnsupportedDatabaseDriverException */ public function createDatabaseTable(): bool { switch ($this->db->getName()) { case 'mysql': case 'mysqli': $filename = 'mysql.sql'; break; case 'postgresql': $filename = 'pgsql.sql'; break; case 'sqlsrv': case 'sqlazure': $filename = 'sqlsrv.sql'; break; case 'sqlite': $filename = 'sqlite.sql'; break; default: throw new UnsupportedDatabaseDriverException(sprintf('The %s database driver is not supported.', $this->db->getName())); } $path = \dirname(__DIR__, 2) . '/meta/sql/' . $filename; if (!is_readable($path)) { throw new CreateSessionTableException( sprintf('Database schema could not be read from %s. Please ensure the file exists and is readable.', $path) ); } $queries = DatabaseDriver::splitSql(file_get_contents($path)); foreach ($queries as $query) { $query = trim($query); if ($query !== '') { try { $this->db->setQuery($query)->execute(); } catch (ExecutionFailureException $exception) { throw new CreateSessionTableException('Failed to create the session table.', 0, $exception); } } } return true; } /** * Destroy a session * * @param integer $session_id The session ID being destroyed * * @return boolean True on success, false otherwise * * @since 2.0.0 */ public function destroy($session_id): bool { try { $query = $this->db->getQuery(true) ->delete($this->db->quoteName('#__session')) ->where($this->db->quoteName('session_id') . ' = ' . $this->db->quote($session_id)); // Remove a session from the database. $this->db->setQuery($query)->execute(); return true; } catch (\Exception $e) { return false; } } /** * Cleanup old sessions * * @param integer $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed * * @return boolean True on success, false otherwise * * @since 2.0.0 */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { // We'll delay garbage collection until the session is closed to prevent potential issues mid-cycle $this->gcLifetime = time() - $maxlifetime; $this->gcCalled = true; return true; } /** * Test to see if the HandlerInterface is available * * @return boolean True on success, false otherwise * * @since 2.0.0 */ public static function isSupported(): bool { return interface_exists(DatabaseInterface::class); } /** * Initialize session * * @param string $save_path The path where to store/retrieve the session * @param string $session_id The session id * * @return boolean True on success, false otherwise * * @since 2.0.0 */ #[\ReturnTypeWillChange] public function open($save_path, $session_id) { $this->db->connect(); return true; } /** * Read session data * * @param string $session_id The session id to read data for * * @return string The session data * * @since 2.0.0 */ #[\ReturnTypeWillChange] public function read($session_id) { try { // Get the session data from the database table. $query = $this->db->getQuery(true) ->select($this->db->quoteName('data')) ->from($this->db->quoteName('#__session')) ->where($this->db->quoteName('session_id') . ' = ?') ->bind(1, $session_id); $this->db->setQuery($query); return (string) $this->db->loadResult(); } catch (\Exception $e) { return ''; } } /** * Write session data * * @param string $session_id The session id * @param string $session_data The encoded session data * * @return boolean True on success, false otherwise * * @since 2.0.0 */ #[\ReturnTypeWillChange] public function write($session_id, $session_data) { try { // Figure out if a row exists for the session ID $query = $this->db->getQuery(true) ->select($this->db->quoteName('session_id')) ->from($this->db->quoteName('#__session')) ->where($this->db->quoteName('session_id') . ' = ?') ->bind(1, $session_id); $idExists = $this->db->setQuery($query)->loadResult(); $query = $this->db->getQuery(true); $time = time(); if ($idExists) { $query->update($this->db->quoteName('#__session')) ->set($this->db->quoteName('data') . ' = ?') ->set($this->db->quoteName('time') . ' = ?') ->where($this->db->quoteName('session_id') . ' = ?') ->bind(1, $session_data) ->bind(2, $time, ParameterType::INTEGER) ->bind(3, $session_id); } else { $query->insert($this->db->quoteName('#__session')) ->columns([$this->db->quoteName('data'), $this->db->quoteName('time'), $this->db->quoteName('session_id')]) ->values('?, ?, ?') ->bind(1, $session_data) ->bind(2, $time, ParameterType::INTEGER) ->bind(3, $session_id); } // Try to insert the session data in the database table. $this->db->setQuery($query)->execute(); return true; } catch (\Exception $e) { return false; } } }