/**
* Create a session handler based on the application configuration.
*
* @param array $options The options used to instantiate the SessionInterface instance.
*
* @return HandlerInterface
*
* @since 4.0.0
*/
public function createSessionHandler(array $options) : HandlerInterface
{
$resolver = new OptionsResolver();
$this->configureSessionHandlerOptions($resolver);
$options = $resolver->resolve($options);
/** @var Registry $config */
$config = $this->getContainer()->get('config');
$handlerType = $config->get('session_handler', 'filesystem');
switch ($handlerType) {
case 'apcu':
if (!Handler\ApcuHandler::isSupported()) {
throw new RuntimeException('APCu is not supported on this system.');
}
return new Handler\ApcuHandler();
case 'database':
return new Handler\DatabaseHandler($this->getContainer()->get(DatabaseInterface::class));
case 'filesystem':
case 'none':
// Try to use a custom configured path, fall back to the path in the PHP runtime configuration
$path = $config->get('session_filesystem_path', ini_get('session.save_path'));
// If we still have no path, as a last resort fall back to the system's temporary directory
if (empty($path)) {
$path = sys_get_temp_dir();
}
return new Handler\FilesystemHandler($path);
case 'memcached':
if (!Handler\MemcachedHandler::isSupported()) {
throw new RuntimeException('Memcached is not supported on this system.');
}
$host = $config->get('session_memcached_server_host', 'localhost');
$port = $config->get('session_memcached_server_port', 11211);
$memcached = new Memcached($config->get('session_memcached_server_id', 'joomla_cms'));
$memcached->addServer($host, $port);
ini_set('session.save_path', "{$host}:{$port}");
ini_set('session.save_handler', 'memcached');
return new Handler\MemcachedHandler($memcached, ['ttl' => $options['expire']]);
case 'redis':
if (!Handler\RedisHandler::isSupported()) {
throw new RuntimeException('Redis is not supported on this system.');
}
$redis = new Redis();
$host = $config->get('session_redis_server_host', '127.0.0.1');
// Use default port if connecting over a socket whatever the config value
$port = $host[0] === '/' ? 0 : $config->get('session_redis_server_port', 6379);
if ($config->get('session_redis_persist', true)) {
$redis->pconnect($host, $port);
} else {
$redis->connect($host, $port);
}
if (!empty($config->get('session_redis_server_auth', ''))) {
$redis->auth($config->get('session_redis_server_auth', null));
}
$db = (int) $config->get('session_redis_server_db', 0);
if ($db !== 0) {
$redis->select($db);
}
return new Handler\RedisHandler($redis, ['ttl' => $options['expire']]);
case 'wincache':
if (!Handler\WincacheHandler::isSupported()) {
throw new RuntimeException('Wincache is not supported on this system.');
}
return new Handler\WincacheHandler();
default:
throw new InvalidArgumentException(sprintf('The "%s" session handler is not recognised.', $handlerType));
}
}