mirror of
https://github.com/torrentpier/torrentpier-lts.git
synced 2025-03-01 15:21:02 +03:00
487 lines
10 KiB
PHP
487 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* Zend Framework (http://framework.zend.com/)
|
|
*
|
|
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
|
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
|
*/
|
|
|
|
namespace Zend\Session\Storage;
|
|
|
|
use ArrayIterator;
|
|
use IteratorAggregate;
|
|
use Zend\Session\Exception;
|
|
|
|
/**
|
|
* Session storage in $_SESSION
|
|
*
|
|
* Replaces the $_SESSION superglobal with an ArrayObject that allows for
|
|
* property access, metadata storage, locking, and immutability.
|
|
*/
|
|
abstract class AbstractSessionArrayStorage implements
|
|
IteratorAggregate,
|
|
StorageInterface,
|
|
StorageInitializationInterface
|
|
{
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param array|null $input
|
|
*/
|
|
public function __construct($input = null)
|
|
{
|
|
// this is here for B.C.
|
|
$this->init($input);
|
|
}
|
|
|
|
/**
|
|
* Initialize Storage
|
|
*
|
|
* @param array $input
|
|
* @return void
|
|
*/
|
|
public function init($input = null)
|
|
{
|
|
if ((null === $input) && isset($_SESSION)) {
|
|
$input = $_SESSION;
|
|
if (is_object($input) && !$_SESSION instanceof \ArrayObject) {
|
|
$input = (array) $input;
|
|
}
|
|
} elseif (null === $input) {
|
|
$input = array();
|
|
}
|
|
$_SESSION = $input;
|
|
$this->setRequestAccessTime(microtime(true));
|
|
}
|
|
|
|
/**
|
|
* Get Offset
|
|
*
|
|
* @param mixed $key
|
|
* @return mixed
|
|
*/
|
|
public function __get($key)
|
|
{
|
|
return $this->offsetGet($key);
|
|
}
|
|
|
|
/**
|
|
* Set Offset
|
|
*
|
|
* @param mixed $key
|
|
* @param mixed $value
|
|
* @return void
|
|
*/
|
|
public function __set($key, $value)
|
|
{
|
|
return $this->offsetSet($key, $value);
|
|
}
|
|
|
|
/**
|
|
* Isset Offset
|
|
*
|
|
* @param mixed $key
|
|
* @return bool
|
|
*/
|
|
public function __isset($key)
|
|
{
|
|
return $this->offsetExists($key);
|
|
}
|
|
|
|
/**
|
|
* Unset Offset
|
|
*
|
|
* @param mixed $key
|
|
* @return void
|
|
*/
|
|
public function __unset($key)
|
|
{
|
|
return $this->offsetUnset($key);
|
|
}
|
|
|
|
/**
|
|
* Destructor
|
|
*
|
|
* @return void
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
* Offset Exists
|
|
*
|
|
* @param mixed $key
|
|
* @return bool
|
|
*/
|
|
public function offsetExists($key)
|
|
{
|
|
return isset($_SESSION[$key]);
|
|
}
|
|
|
|
/**
|
|
* Offset Get
|
|
*
|
|
* @param mixed $key
|
|
* @return mixed
|
|
*/
|
|
public function offsetGet($key)
|
|
{
|
|
if (isset($_SESSION[$key])) {
|
|
return $_SESSION[$key];
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Offset Set
|
|
*
|
|
* @param mixed $key
|
|
* @param mixed $value
|
|
* @return void
|
|
*/
|
|
public function offsetSet($key, $value)
|
|
{
|
|
$_SESSION[$key] = $value;
|
|
}
|
|
|
|
/**
|
|
* Offset Unset
|
|
*
|
|
* @param mixed $key
|
|
* @return void
|
|
*/
|
|
public function offsetUnset($key)
|
|
{
|
|
unset($_SESSION[$key]);
|
|
}
|
|
|
|
/**
|
|
* Count
|
|
*
|
|
* @return int
|
|
*/
|
|
public function count()
|
|
{
|
|
return count($_SESSION);
|
|
}
|
|
|
|
/**
|
|
* Seralize
|
|
*
|
|
* @return string
|
|
*/
|
|
public function serialize()
|
|
{
|
|
return serialize($_SESSION);
|
|
}
|
|
|
|
/**
|
|
* Unserialize
|
|
*
|
|
* @param string $session
|
|
* @return mixed
|
|
*/
|
|
public function unserialize($session)
|
|
{
|
|
return unserialize($session);
|
|
}
|
|
|
|
/**
|
|
* Get Iterator
|
|
*
|
|
* @return ArrayIterator
|
|
*/
|
|
public function getIterator()
|
|
{
|
|
return new ArrayIterator($_SESSION);
|
|
}
|
|
|
|
/**
|
|
* Load session object from an existing array
|
|
*
|
|
* Ensures $_SESSION is set to an instance of the object when complete.
|
|
*
|
|
* @param array $array
|
|
* @return SessionStorage
|
|
*/
|
|
public function fromArray(array $array)
|
|
{
|
|
$ts = $this->getRequestAccessTime();
|
|
$_SESSION = $array;
|
|
$this->setRequestAccessTime($ts);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Mark object as isImmutable
|
|
*
|
|
* @return SessionStorage
|
|
*/
|
|
public function markImmutable()
|
|
{
|
|
$_SESSION['_IMMUTABLE'] = true;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Determine if this object is isImmutable
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isImmutable()
|
|
{
|
|
return (isset($_SESSION['_IMMUTABLE']) && $_SESSION['_IMMUTABLE']);
|
|
}
|
|
|
|
/**
|
|
* Lock this storage instance, or a key within it
|
|
*
|
|
* @param null|int|string $key
|
|
* @return ArrayStorage
|
|
*/
|
|
public function lock($key = null)
|
|
{
|
|
if (null === $key) {
|
|
$this->setMetadata('_READONLY', true);
|
|
|
|
return $this;
|
|
}
|
|
if (isset($_SESSION[$key])) {
|
|
$this->setMetadata('_LOCKS', array($key => true));
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Is the object or key marked as locked?
|
|
*
|
|
* @param null|int|string $key
|
|
* @return bool
|
|
*/
|
|
public function isLocked($key = null)
|
|
{
|
|
if ($this->isImmutable()) {
|
|
// isImmutable trumps all
|
|
return true;
|
|
}
|
|
|
|
if (null === $key) {
|
|
// testing for global lock
|
|
return $this->getMetadata('_READONLY');
|
|
}
|
|
|
|
$locks = $this->getMetadata('_LOCKS');
|
|
$readOnly = $this->getMetadata('_READONLY');
|
|
|
|
if ($readOnly && !$locks) {
|
|
// global lock in play; all keys are locked
|
|
return true;
|
|
}
|
|
if ($readOnly && $locks) {
|
|
return array_key_exists($key, $locks);
|
|
}
|
|
|
|
// test for individual locks
|
|
if (!$locks) {
|
|
return false;
|
|
}
|
|
|
|
return array_key_exists($key, $locks);
|
|
}
|
|
|
|
/**
|
|
* Unlock an object or key marked as locked
|
|
*
|
|
* @param null|int|string $key
|
|
* @return ArrayStorage
|
|
*/
|
|
public function unlock($key = null)
|
|
{
|
|
if (null === $key) {
|
|
// Unlock everything
|
|
$this->setMetadata('_READONLY', false);
|
|
$this->setMetadata('_LOCKS', false);
|
|
|
|
return $this;
|
|
}
|
|
|
|
$locks = $this->getMetadata('_LOCKS');
|
|
if (!$locks) {
|
|
if (!$this->getMetadata('_READONLY')) {
|
|
return $this;
|
|
}
|
|
$array = $this->toArray();
|
|
$keys = array_keys($array);
|
|
$locks = array_flip($keys);
|
|
unset($array, $keys);
|
|
}
|
|
|
|
if (array_key_exists($key, $locks)) {
|
|
unset($locks[$key]);
|
|
$this->setMetadata('_LOCKS', $locks, true);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set storage metadata
|
|
*
|
|
* Metadata is used to store information about the data being stored in the
|
|
* object. Some example use cases include:
|
|
* - Setting expiry data
|
|
* - Maintaining access counts
|
|
* - localizing session storage
|
|
* - etc.
|
|
*
|
|
* @param string $key
|
|
* @param mixed $value
|
|
* @param bool $overwriteArray Whether to overwrite or merge array values; by default, merges
|
|
* @return ArrayStorage
|
|
* @throws Exception\RuntimeException
|
|
*/
|
|
public function setMetadata($key, $value, $overwriteArray = false)
|
|
{
|
|
if ($this->isImmutable()) {
|
|
throw new Exception\RuntimeException(
|
|
sprintf('Cannot set key "%s" as storage is marked isImmutable', $key)
|
|
);
|
|
}
|
|
|
|
if (!isset($_SESSION['__ZF'])) {
|
|
$_SESSION['__ZF'] = array();
|
|
}
|
|
if (isset($_SESSION['__ZF'][$key]) && is_array($value)) {
|
|
if ($overwriteArray) {
|
|
$_SESSION['__ZF'][$key] = $value;
|
|
} else {
|
|
$_SESSION['__ZF'][$key] = array_replace_recursive($_SESSION['__ZF'][$key], $value);
|
|
}
|
|
} else {
|
|
if ((null === $value) && isset($_SESSION['__ZF'][$key])) {
|
|
$array = $_SESSION['__ZF'];
|
|
unset($array[$key]);
|
|
$_SESSION['__ZF'] = $array;
|
|
unset($array);
|
|
} elseif (null !== $value) {
|
|
$_SESSION['__ZF'][$key] = $value;
|
|
}
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Retrieve metadata for the storage object or a specific metadata key
|
|
*
|
|
* Returns false if no metadata stored, or no metadata exists for the given
|
|
* key.
|
|
*
|
|
* @param null|int|string $key
|
|
* @return mixed
|
|
*/
|
|
public function getMetadata($key = null)
|
|
{
|
|
if (!isset($_SESSION['__ZF'])) {
|
|
return false;
|
|
}
|
|
|
|
if (null === $key) {
|
|
return $_SESSION['__ZF'];
|
|
}
|
|
|
|
if (!array_key_exists($key, $_SESSION['__ZF'])) {
|
|
return false;
|
|
}
|
|
|
|
return $_SESSION['__ZF'][$key];
|
|
}
|
|
|
|
/**
|
|
* Clear the storage object or a subkey of the object
|
|
*
|
|
* @param null|int|string $key
|
|
* @return ArrayStorage
|
|
* @throws Exception\RuntimeException
|
|
*/
|
|
public function clear($key = null)
|
|
{
|
|
if ($this->isImmutable()) {
|
|
throw new Exception\RuntimeException('Cannot clear storage as it is marked immutable');
|
|
}
|
|
if (null === $key) {
|
|
$this->fromArray(array());
|
|
|
|
return $this;
|
|
}
|
|
|
|
if (!isset($_SESSION[$key])) {
|
|
return $this;
|
|
}
|
|
|
|
// Clear key data
|
|
unset($_SESSION[$key]);
|
|
|
|
// Clear key metadata
|
|
$this->setMetadata($key, null)
|
|
->unlock($key);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the request access time
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getRequestAccessTime()
|
|
{
|
|
return $this->getMetadata('_REQUEST_ACCESS_TIME');
|
|
}
|
|
|
|
/**
|
|
* Set the request access time
|
|
*
|
|
* @param float $time
|
|
* @return ArrayStorage
|
|
*/
|
|
protected function setRequestAccessTime($time)
|
|
{
|
|
$this->setMetadata('_REQUEST_ACCESS_TIME', $time);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Cast the object to an array
|
|
*
|
|
* @param bool $metaData Whether to include metadata
|
|
* @return array
|
|
*/
|
|
public function toArray($metaData = false)
|
|
{
|
|
if (isset($_SESSION)) {
|
|
$values = $_SESSION;
|
|
} else {
|
|
$values = array();
|
|
}
|
|
|
|
if ($metaData) {
|
|
return $values;
|
|
}
|
|
|
|
if (isset($values['__ZF'])) {
|
|
unset($values['__ZF']);
|
|
}
|
|
|
|
return $values;
|
|
}
|
|
}
|