- First commit

This commit is contained in:
Dave M. 2019-11-18 10:25:25 -05:00
commit 3797b91f23
4 changed files with 280 additions and 0 deletions

17
composer.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "mcnd/storage",
"description": "A session and cookie handler which integrates itself as a middleware",
"keywords": ["storage","session","cookie","psr15","middleware"],
"license": "MIT",
"authors": [
{
"name": "Dave Mc Nicoll",
"email": "dave.mcnicoll@cslsj.qc.ca"
}
],
"autoload": {
"psr-4": {
"Storage\\": "src/"
}
}
}

116
src/Cookie.php Normal file
View File

@ -0,0 +1,116 @@
<?php
namespace Storage;
class Cookie {
protected array $options = [
'name' => '',
'expires' => 0,
'path' => null,
'domain' => null,
'secure' => false,
'httponly' => true,
'samesite' => "Strict",
];
protected array $options;
protected string $secureHash;
public function __construct(array $options, string $secureHash) {
$this->options = $options;
$this->secureHash = $secureHash;
}
/**
* Sets a cookie with the given parameters.
* @param string cookie name or array of config options
* @param string cookie value
* @param integer number of seconds before the cookie expires
* @param string URL path to allow
* @param string URL domain to allow
* @param boolean HTTPS only
* @param boolean HTTP only (requires PHP 5.2 or higher)
* @return boolean
*/
public static function set(
?string $name,
?string $value = null,
?int $expires = null,
?string $path = null,
?string $domain = null,
?bool $secure = null,
?bool $httponly = null,
?string $samesite = null,
?bool $raw = false
) {
if ( headers_sent() ) {
return false;
}
$expire = ($expire == 0) ? 0 : time() + (int) $expire;
$_COOKIE[$name] = $value;
$options = [
'expires' => $this->options['expires'] ?? ( $expires ?: 0 ),
'path' => $this->options['path'] ?? ( $path ?: "" ),
'domain' => $this->options['domain'] ?? ( $domain ?: "" ),
'secure' => $this->options['secure'] ?? ( $secure ?: false ),
'httponly' => $this->options['httponly'] ?? ( $httponly ?: false ),
'samesite' => $this->options['samesite'] ?? ( $samesite ?: "" ),
];
return $raw ? setrawcookie($name, $value ?: "", $options) : setcookie($name, $value ?: "", $options);
}
/**
* Fetch a cookie value, using the Input library.
* @param string cookie name
* @param mixed default value
* @return string
*/
public static function get(string $key, $default = null)
{
return array_key_exists($key, $_COOKIE) ? $_COOKIE[$key] : $default;
}
/**
* Nullify and unset a cookie.
* @param string cookie name
* @param string URL path
* @param string URL domain
* @return boolean
*/
public static function delete(string $name, ?string $path = null, ?string $domain = null) {
if ( ! $this->__isset($name) ) {
return false;
}
unset( $_COOKIE[$name] );
return static::set($name, '', -86400, $path ?: ( $this->options['path'] ?? "" ), $domain ?: ( $this->options['domain'] ?? "" ), $this->options['secure'] ?? false, $this->options['httponly'] ?? false);
}
public function __set($key, $value)
{
return static::set($key, $value);
}
public function __get($key)
{
return static::get($key);
}
public function __isset($key)
{
return array_key_exists($key, $_SESSION);
}
public function __unset($key)
{
$this->delete($key);
}
}

98
src/Session.php Normal file
View File

@ -0,0 +1,98 @@
<?php
namespace Storage;
class Session
{
public static function get($key, $default = null)
{
return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
public static function set($key, $value)
{
return $_SESSION[$key] = $value;
}
public static function delete($key)
{
unset($_SESSION[$key]);
}
public static function clearAll()
{
$_SESSION = [];
}
public static function start(array $options, Cookie $cookie)
{
if ( session_status() === PHP_SESSION_ACTIVE ) {
return;
}
$params = session_get_cookie_params();
$params = [
'expires' => $options['lifetime'] ?? $params['lifetime'],
'path' => $options['path'] ?? $params['path'],
'domain' => $options['domain'] ?? $params['domain'],
'secure' => $options['secure'] ?? $params['secure'],
'httponly' => $options['httponly'] ?? $params['httponly'],
'samesite' => $options['samesite'] ?? $params['samesite'] ?? "",
];
if ( version_compare(PHP_VERSION, '7.3.0') >= 0 ) {
session_set_cookie_params($params);
}
else {
session_set_cookie_params( ...array_values(array_slice($params, 0, 5)) );
}
session_name($options['name']);
session_cache_limiter($options['cache_limiter'] ?? 'nocache');
session_start();
# Reset timeout after session started
$cookie->set(session_name(), session_id(), time() + $params['expires'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], $params['samesite']);
}
public static function regenerate()
{
if ( session_status() === PHP_SESSION_ACTIVE ) {
session_regenerate_id(true);
}
}
public static function destroy()
{
$this->clearAll();
if ( ini_get("session.use_cookies") ) {
$cookie->delete(session_name(), $params['path'] ?? "", $params['domain'] ?? "");
}
if ( session_status() === PHP_SESSION_ACTIVE ) {
session_destroy();
}
}
public function __set($key, $value)
{
return static::set($key, $value);
}
public function __get($key)
{
return static::get($key);
}
public function __isset($key)
{
return array_key_exists($key, $_SESSION);
}
public function __unset($key)
{
$this->delete($key);
}
}

49
src/SessionMiddleware.php Normal file
View File

@ -0,0 +1,49 @@
<?php
namespace Storage;
use Psr\Http\Message\RequestInterface,
Psr\Http\Message\ResponseInterface,
Psr\Http\Server\MiddlewareInterface,
Psr\Http\Message\ServerRequestInterface,
Psr\Http\Server\RequestHandlerInterface;
class SessionMiddleware implements MiddlewareInterface
{
protected array $options = [
'name' => '',
'path' => null,
'domain' => null,
'secure' => false,
'httponly' => true,
'lifetime' => 28800, # A day of work ~ 7 hours
'samesite' => "",
];
protected Cookie $cookie;
public function __construct(Cookie $cookie, array $options = [])
{
$this->cookie = $cookie;
if ( empty($options['name']) ) {
# unique directory-based named session
$options['name'] = md5(__FILE__);
}
$this->options = array_merge($this->options, $options);
}
/**
*
* @param RequestInterface $request PSR7 request object
* @param RequestHandlerInterface $response PSR7 handler object
*
* @return ResponseInterface PSR7 response object
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
Session::start($this->options, $this->cookie);
return $handler->handle($request);
}
}