Add Session Management instances (including Depenency Injection)
- Prerequesite for mocking Sessions - Reduce "App" class complexity
This commit is contained in:
parent
009a8bb939
commit
555513e4b4
10 changed files with 408 additions and 143 deletions
|
@ -5,119 +5,50 @@
|
|||
*/
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Cache\ICache;
|
||||
use Friendica\Core\Session\CacheSessionHandler;
|
||||
use Friendica\Core\Session\DatabaseSessionHandler;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Core\Session\ISession;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Util\Strings;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* High-level Session service class
|
||||
*
|
||||
* @author Hypolite Petovan <hypolite@mrpetovan.com>
|
||||
*/
|
||||
class Session
|
||||
class Session extends BaseObject
|
||||
{
|
||||
public static $exists = false;
|
||||
public static $expire = 180000;
|
||||
|
||||
public static function init()
|
||||
{
|
||||
ini_set('session.gc_probability', 50);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
|
||||
if (Config::get('system', 'ssl_policy') == App\BaseURL::SSL_POLICY_FULL) {
|
||||
ini_set('session.cookie_secure', 1);
|
||||
}
|
||||
|
||||
$session_handler = Config::get('system', 'session_handler', 'database');
|
||||
if ($session_handler != 'native') {
|
||||
if ($session_handler == 'cache' && Config::get('system', 'cache_driver', 'database') != 'database') {
|
||||
$SessionHandler = new CacheSessionHandler(
|
||||
BaseObject::getClass(ICache::class),
|
||||
BaseObject::getClass(LoggerInterface::class),
|
||||
$_SERVER
|
||||
);
|
||||
} else {
|
||||
$SessionHandler = new DatabaseSessionHandler(
|
||||
BaseObject::getClass(Database::class),
|
||||
BaseObject::getClass(LoggerInterface::class),
|
||||
$_SERVER
|
||||
);
|
||||
}
|
||||
|
||||
session_set_save_handler($SessionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public static function exists($name)
|
||||
{
|
||||
return isset($_SESSION[$name]);
|
||||
return self::getClass(ISession::class)->exists($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a key from the session super global or the defaults if the key is missing or the value is falsy.
|
||||
*
|
||||
* Handle the case where session_start() hasn't been called and the super global isn't available.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $defaults
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($name, $defaults = null)
|
||||
{
|
||||
return $_SESSION[$name] ?? $defaults;
|
||||
return self::getClass(ISession::class)->get($name, $defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a single session variable.
|
||||
* Overrides value of existing key.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function set($name, $value)
|
||||
{
|
||||
$_SESSION[$name] = $value;
|
||||
self::getClass(ISession::class)->set($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets multiple session variables.
|
||||
* Overrides values for existing keys.
|
||||
*
|
||||
* @param array $values
|
||||
*/
|
||||
public static function setMultiple(array $values)
|
||||
{
|
||||
$_SESSION = $values + $_SESSION;
|
||||
self::getClass(ISession::class)->setMultiple($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a session variable.
|
||||
* Ignores missing keys.
|
||||
*
|
||||
* @param $name
|
||||
*/
|
||||
public static function remove($name)
|
||||
{
|
||||
unset($_SESSION[$name]);
|
||||
self::getClass(ISession::class)->remove($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current session array
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
session_unset();
|
||||
session_start();
|
||||
$_SESSION = [];
|
||||
self::getClass(ISession::class)->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,16 +115,8 @@ class Session
|
|||
return $_SESSION['authenticated'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kills the "Friendica" cookie and all session data
|
||||
*/
|
||||
public static function delete()
|
||||
{
|
||||
/** @var User\Cookie $cookie */
|
||||
$cookie = BaseObject::getClass(User\Cookie::class);
|
||||
$cookie->clear();
|
||||
$_SESSION = [];
|
||||
session_unset();
|
||||
session_destroy();
|
||||
self::getClass(ISession::class)->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
namespace Friendica\Core\Session;
|
||||
|
||||
use Friendica\Core\Cache\ICache;
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Session;
|
||||
use Friendica\Model\User\Cookie;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SessionHandlerInterface;
|
||||
|
||||
|
@ -12,7 +14,7 @@ use SessionHandlerInterface;
|
|||
*
|
||||
* @author Hypolite Petovan <hypolite@mrpetovan.com>
|
||||
*/
|
||||
class CacheSessionHandler implements SessionHandlerInterface
|
||||
final class CacheSession extends NativeSession implements SessionHandlerInterface
|
||||
{
|
||||
/** @var ICache */
|
||||
private $cache;
|
||||
|
@ -21,18 +23,15 @@ class CacheSessionHandler implements SessionHandlerInterface
|
|||
/** @var array The $_SERVER array */
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* CacheSessionHandler constructor.
|
||||
*
|
||||
* @param ICache $cache
|
||||
* @param LoggerInterface $logger
|
||||
* @param array $server
|
||||
*/
|
||||
public function __construct(ICache $cache, LoggerInterface $logger, array $server)
|
||||
public function __construct(Configuration $config, Cookie $cookie, ICache $cache, LoggerInterface $logger, array $server)
|
||||
{
|
||||
parent::__construct($config, $cookie);
|
||||
|
||||
$this->cache = $cache;
|
||||
$this->logger = $logger;
|
||||
$this->server = $server;
|
||||
|
||||
session_set_save_handler($this);
|
||||
}
|
||||
|
||||
public function open($save_path, $session_name)
|
||||
|
@ -64,8 +63,9 @@ class CacheSessionHandler implements SessionHandlerInterface
|
|||
* on the case. Uses the Session::expire for existing session, 5 minutes
|
||||
* for newly created session.
|
||||
*
|
||||
* @param string $session_id Session ID with format: [a-z0-9]{26}
|
||||
* @param string $session_data Serialized session data
|
||||
* @param string $session_id Session ID with format: [a-z0-9]{26}
|
||||
* @param string $session_data Serialized session data
|
||||
*
|
||||
* @return boolean Returns false if parameters are missing, true otherwise
|
||||
* @throws \Exception
|
||||
*/
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Friendica\Core\Session;
|
||||
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\Core\Session;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\User\Cookie;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SessionHandlerInterface;
|
||||
|
||||
|
@ -12,7 +14,7 @@ use SessionHandlerInterface;
|
|||
*
|
||||
* @author Hypolite Petovan <hypolite@mrpetovan.com>
|
||||
*/
|
||||
class DatabaseSessionHandler implements SessionHandlerInterface
|
||||
final class DatabaseSession extends NativeSession implements SessionHandlerInterface
|
||||
{
|
||||
/** @var Database */
|
||||
private $dba;
|
||||
|
@ -28,11 +30,15 @@ class DatabaseSessionHandler implements SessionHandlerInterface
|
|||
* @param LoggerInterface $logger
|
||||
* @param array $server
|
||||
*/
|
||||
public function __construct(Database $dba, LoggerInterface $logger, array $server)
|
||||
public function __construct(Configuration $config, Cookie $cookie, Database $dba, LoggerInterface $logger, array $server)
|
||||
{
|
||||
parent::__construct($config, $cookie);
|
||||
|
||||
$this->dba = $dba;
|
||||
$this->logger = $logger;
|
||||
$this->server = $server;
|
||||
|
||||
session_set_save_handler($this);
|
||||
}
|
||||
|
||||
public function open($save_path, $session_name)
|
||||
|
@ -64,8 +70,9 @@ class DatabaseSessionHandler implements SessionHandlerInterface
|
|||
* on the case. Uses the Session::expire global for existing session, 5 minutes
|
||||
* for newly created session.
|
||||
*
|
||||
* @param string $session_id Session ID with format: [a-z0-9]{26}
|
||||
* @param string $session_data Serialized session data
|
||||
* @param string $session_id Session ID with format: [a-z0-9]{26}
|
||||
* @param string $session_data Serialized session data
|
||||
*
|
||||
* @return boolean Returns false if parameters are missing, true otherwise
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
@ -79,11 +86,11 @@ class DatabaseSessionHandler implements SessionHandlerInterface
|
|||
return true;
|
||||
}
|
||||
|
||||
$expire = time() + Session::$expire;
|
||||
$expire = time() + Session::$expire;
|
||||
$default_expire = time() + 300;
|
||||
|
||||
if (Session::$exists) {
|
||||
$fields = ['data' => $session_data, 'expire' => $expire];
|
||||
$fields = ['data' => $session_data, 'expire' => $expire];
|
||||
$condition = ["`sid` = ? AND (`data` != ? OR `expire` != ?)", $session_id, $session_data, $expire];
|
||||
$this->dba->update('session', $fields, $condition);
|
||||
} else {
|
70
src/Core/Session/ISession.php
Normal file
70
src/Core/Session/ISession.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Session;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
|
||||
interface ISession
|
||||
{
|
||||
/**
|
||||
* Start the current session
|
||||
*
|
||||
* @return self The own Session instance
|
||||
*/
|
||||
public function start();
|
||||
|
||||
/**
|
||||
* Checks if the key exists in this session
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return boolean True, if it exists
|
||||
*/
|
||||
public function exists(string $name);
|
||||
|
||||
/**
|
||||
* Retrieves a key from the session super global or the defaults if the key is missing or the value is falsy.
|
||||
*
|
||||
* Handle the case where session_start() hasn't been called and the super global isn't available.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $defaults
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string $name, $defaults = null);
|
||||
|
||||
/**
|
||||
* Sets a single session variable.
|
||||
* Overrides value of existing key.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set(string $name, $value);
|
||||
|
||||
/**
|
||||
* Sets multiple session variables.
|
||||
* Overrides values for existing keys.
|
||||
*
|
||||
* @param array $values
|
||||
*/
|
||||
public function setMultiple(array $values);
|
||||
|
||||
/**
|
||||
* Removes a session variable.
|
||||
* Ignores missing keys.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function remove(string $name);
|
||||
|
||||
/**
|
||||
* Clears the current session array
|
||||
*/
|
||||
public function clear();
|
||||
|
||||
/**
|
||||
* Kills the "Friendica" cookie and all session data
|
||||
*/
|
||||
public function delete();
|
||||
}
|
84
src/Core/Session/MemorySession.php
Normal file
84
src/Core/Session/MemorySession.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Session;
|
||||
|
||||
/**
|
||||
* Native Session functions for internal Session usage.
|
||||
*
|
||||
* Usable for backend processes (daemon/worker) and testing
|
||||
*/
|
||||
final class MemorySession implements ISession
|
||||
{
|
||||
private $data = [];
|
||||
|
||||
public function start()
|
||||
{
|
||||
$this->clear();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function exists(string $name)
|
||||
{
|
||||
return isset($this->data[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get(string $name, $defaults = null)
|
||||
{
|
||||
return $this->data[$name] ?? $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function set(string $name, $value)
|
||||
{
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setMultiple(array $values)
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function remove(string $name)
|
||||
{
|
||||
if ($this->exists($name)) {
|
||||
unset($this->data[$name]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->data = [];
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->data = [];
|
||||
return true;
|
||||
}
|
||||
}
|
94
src/Core/Session/NativeSession.php
Normal file
94
src/Core/Session/NativeSession.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Session;
|
||||
|
||||
use Friendica\Core\Config\Configuration;
|
||||
use Friendica\App;
|
||||
use Friendica\Model\User\Cookie;
|
||||
|
||||
class NativeSession implements ISession
|
||||
{
|
||||
/** @var Cookie */
|
||||
protected $cookie;
|
||||
|
||||
public function __construct(Configuration $config, Cookie $cookie)
|
||||
{
|
||||
ini_set('session.gc_probability', 50);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
|
||||
if ($config->get('system', 'ssl_policy') == App\BaseURL::SSL_POLICY_FULL) {
|
||||
ini_set('session.cookie_secure', 1);
|
||||
}
|
||||
|
||||
$this->cookie = $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
session_start();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}}
|
||||
*/
|
||||
public function exists(string $name)
|
||||
{
|
||||
return isset($_SESSION[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get(string $name, $defaults = null)
|
||||
{
|
||||
return $_SESSION[$name] ?? $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function set(string $name, $value)
|
||||
{
|
||||
$_SESSION[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setMultiple(array $values)
|
||||
{
|
||||
$_SESSION = $values + $_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function remove(string $name)
|
||||
{
|
||||
unset($_SESSION[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$_SESSION = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kills the "Friendica" cookie and all session data
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->cookie->clear();
|
||||
$_SESSION = [];
|
||||
session_unset();
|
||||
session_destroy();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue