<?php
/**
* Part of the Joomla Framework Session Package
*
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\Session\Handler;
use Joomla\Session\HandlerInterface;
/**
* Memcached session storage handler
*
* @since 2.0.0
*/
class MemcachedHandler implements HandlerInterface
{
/**
* Memcached driver
*
* @var \Memcached
* @since 2.0.0
*/
private $memcached;
/**
* Session ID prefix to avoid naming conflicts
*
* @var string
* @since 2.0.0
*/
private $prefix;
/**
* Time to live in seconds
*
* @var integer
* @since 2.0.0
*/
private $ttl;
/**
* Constructor
*
* @param \Memcached $memcached A Memcached instance
* @param array $options Associative array of options to configure the handler
*
* @since 2.0.0
*/
public function __construct(\Memcached $memcached, array $options = [])
{
$this->memcached = $memcached;
// Set the default time-to-live based on the Session object's default configuration
$this->ttl = isset($options['ttl']) ? (int) $options['ttl'] : 900;
// Namespace our session IDs to avoid potential conflicts
$this->prefix = $options['prefix'] ?? 'jfw';
}
/**
* Close the session
*
* @return boolean True on success, false otherwise
*
* @since 2.0.0
*/
public function close()
{
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
{
return $this->memcached->delete($this->prefix . $session_id);
}
/**
* 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
*/
public function gc($maxlifetime)
{
// Memcached manages garbage collection on its own
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
{
/*
* GAE and HHVM have both had instances where Memcached the class was defined but no extension was loaded.
* If the class is there, we can assume it works.
*/
return class_exists('Memcached');
}
/**
* 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
*/
public function open($save_path, $session_id)
{
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
*/
public function read($session_id)
{
return $this->memcached->get($this->prefix . $session_id) ?: '';
}
/**
* 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
*/
public function write($session_id, $session_data)
{
return $this->memcached->set($this->prefix . $session_id, $session_data, time() + $this->ttl);
}
}