From: Michael M Slusarz Date: Wed, 3 Nov 2010 06:46:56 +0000 (-0600) Subject: New Horde_Session API. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=0fb327595ad09dd71138e059df8e124f79daacb4;p=horde.git New Horde_Session API. --- diff --git a/framework/Core/lib/Horde/Session.php b/framework/Core/lib/Horde/Session.php index be7aff6f3..74233b1d4 100644 --- a/framework/Core/lib/Horde/Session.php +++ b/framework/Core/lib/Horde/Session.php @@ -13,7 +13,7 @@ * @license http://www.fsf.org/copyleft/lgpl.html LGPL * @package Core */ -class Horde_Session implements ArrayAccess +class Horde_Session { /* Class constants. */ const DATA = '_d'; @@ -21,6 +21,9 @@ class Horde_Session implements ArrayAccess const PRUNE = '_p'; const SERIALIZED = '_s'; + const TYPE_ARRAY = 1; + const TYPE_OBJECT = 2; + /** * Maximum size of the pruneable data store. * @@ -167,133 +170,54 @@ class Horde_Session implements ArrayAccess $this->_cleansession = true; } - /** - * Return the list of subkeys for a master key. - * - * @param object $ob See _parseOffset(). - * - * @return array Subkeyname (keys) and session variable name (values). - */ - private function _subkeys($ob) - { - $ret = array(); - - if (isset($_SESSION[$ob->app]) && - ($ob->name[strlen($ob->name) - 1] == '/')) { - foreach (array_keys($_SESSION[$ob->app]) as $k) { - if (strpos($k, $ob->name) === 0) { - $ret[substr($k, strlen($ob->name))] = $k; - } - } - } - - return $ret; - } - - /* Session object storage. */ + /* Session variable access. */ /** - * Store an arbitrary piece of data in the session. - * Equivalent to: $this[self::DATA . ':' . $id] = $value; + * Does the session variable exist? * - * @param mixed $data Data to save. - * @param boolean $prune Is data pruneable? - * @param string $id ID to use (otherwise, is autogenerated). + * @param string $app Application name. + * @param string $name Session variable name. * - * @return string The session storage id (used to get session data). + * @return boolean True if session variable exists. */ - public function store($data, $prune = true, $id = null) + public function exists($app, $name) { - if (is_null($id)) { - $id = strval(new Horde_Support_Randomid()); - } else { - $offset = $this->_parseOffset($id); - $id = $offset->name; - } - - $full_id = self::DATA . ':' . $id; - $this->_offsetSet($this->_parseOffset($full_id), $data); - - if ($prune) { - $ptr = &$_SESSION[self::PRUNE]; - unset($ptr[$id]); - $ptr[$id] = 1; - if (count($ptr) > $this->maxStore) { - array_shift($ptr); - } - } - - return $full_id; + return isset($_SESSION[$app][$name]); } /** - * Retrieve data from the session data store (created via store()). - * Equivalent to: $value = $this[self::DATA . ':' . $id]; - * - * @param string $id The session data ID. + * Get the value of a session variable. * - * @return mixed The session data value. - */ - public function retrieve($id) - { - $id = trim($id); - - if (strpos($id, self::DATA) !== 0) { - $id = self::DATA . ':' . $id; - } - - return $this[$id]; - } - - /** - * Purge data from the session data store (created via store()). - * Equivalent to: unset($this[self::DATA . ':' . $id]); + * @param string $app Application name. + * @param string $name Session variable name. + * @param integer $mask One of: + *
+     * self::TYPE_ARRAY - Return an array value.
+     * self::TYPE_OBJECT - Return an object value.
+     * 
* - * @param string $id The session data ID. - */ - public function purge($id) - { - $id = trim($id); - - if (strpos($id, self::DATA) !== 0) { - $id = self::DATA . ':' . $id; - } - - unset($this[$id]); - } - - /* ArrayAccess methods. */ - - /** - */ - public function offsetExists($offset) - { - $ob = $this->_parseOffset($offset); - - return isset($_SESSION[$ob->app][$ob->name]); - } - - /** + * @return mixed The value or null if the value doesn't exist. */ - public function offsetGet($offset) + public function get($app, $name, $mask = 0) { - $ob = $this->_parseOffset($offset); - - if (!isset($_SESSION[$ob->app][$ob->name])) { - $subkeys = $this->_subkeys($ob); - if (!empty($subkeys)) { + if (!$this->exists($app, $name)) { + if ($subkeys = $this->_subkeys($app, $name)) { $ret = array(); foreach ($subkeys as $k => $v) { - $ret[$k] = $this[$v]; + $ret[$k] = $this->get($app, $v, $mask); } return $ret; } - switch ($ob->type) { - case 'array': + if (strpos($name, self::DATA) === 0) { + return $this->retrieve($name); + } + + switch ($mask) { + case self::TYPE_ARRAY: return array(); - case 'object': + case self::TYPE_OBJECT: return new stdClass; default: @@ -301,137 +225,200 @@ class Horde_Session implements ArrayAccess } } - $data = $_SESSION[$ob->app][$ob->name]; + $data = $_SESSION[$app][$name]; + $key = $this->_getKey($app, $name); - if (!isset($_SESSION[self::SERIALIZED][$ob->key])) { + if (!isset($_SESSION[self::SERIALIZED][$key])) { return $data; } if ($this->_lzf && (($data = @lzf_decompress($data)) === false)) { - unset($this[$offset]); - return $this[$offset]; + $this->remove($app, $name); + return $this->get($app, $name); } - return ($_SESSION[self::SERIALIZED][$ob->key] == 's') + return ($_SESSION[self::SERIALIZED][$key] == 's') ? @unserialize($data) : json_decode($data, true); } /** + * Sets the value of a session variable. + * + * @param string $app Application name. + * @param string $name Session variable name. + * @param mixed $value Session variable value. + *
+     * self::TYPE_ARRAY - Force save as an array value.
+     * self::TYPE_OBJECT - Force save as an object value.
+     * 
*/ - public function offsetSet($offset, $value) + public function set($app, $name, $value, $mask = 0) { - $ob = $this->_parseOffset($offset); - - if ($ob->app == self::DATA) { - $this->store($value, false, $ob->name); - } else { - $this->_offsetSet($ob, $value); - } - } + $key = $this->_getKey($app, $name); - /** - * TODO - */ - private function _offsetSet($ob, $value) - { /* Each particular piece of session data is generally not used on any * given page load. Thus, for arrays and objects, it is beneficial to * always convert to string representations so that the object/array * does not need to be rebuilt every time the session is reloaded. */ - if (is_object($value) || ($ob->type == 'object')) { + if (is_object($value) || ($mask & self::TYPE_OBJECT)) { $value = serialize($value); if ($this->_lzf) { $value = lzf_compress($value); } - $_SESSION[self::SERIALIZED][$ob->key] = 's'; - } elseif (is_array($value) || ($ob->type == 'array')) { + $_SESSION[self::SERIALIZED][$key] = 's'; + } elseif (is_array($value) || ($mask & self::TYPE_ARRAY)) { $value = json_encode($value); if ($this->_lzf) { $value = lzf_compress($value); } - $_SESSION[self::SERIALIZED][$ob->key] = 'j'; + $_SESSION[self::SERIALIZED][$key] = 'j'; } else { - unset($_SESSION[self::SERIALIZED][$ob->key]); + unset($_SESSION[self::SERIALIZED][$key]); } - $_SESSION[$ob->app][$ob->name] = $value; + $_SESSION[$app][$name] = $value; $this->sessionHandler->changed = true; } /** + * Remove session key(s). + * + * @param string $app Application name. + * @param string $name Session variable name. */ - public function offsetUnset($offset) + public function remove($app, $name = null) { - $ob = $this->_parseOffset($offset); + if (!isset($_SESSION[$app])) { + return; + } - if (isset($_SESSION[$ob->app])) { - if (!strlen($ob->name)) { - foreach (array_keys($_SESSION[$ob->app]) as $key) { - unset($_SESSION[self::SERIALIZED][$key]); - } - unset($_SESSION[$ob->app]); - } elseif (isset($_SESSION[$ob->app][$ob->name])) { - unset( - $_SESSION[$ob->app][$ob->name], - $_SESSION[self::PRUNE][$ob->key], - $_SESSION[self::SERIALIZED][$ob->key] - ); - } else { - foreach ($this->_subkeys($ob) as $val) { - unset($this[$val]); + if (is_null($name)) { + foreach (array_keys($_SESSION[$app]) as $key) { + unset($_SESSION[self::SERIALIZED][$key]); + } + unset($_SESSION[$app]); + } elseif (isset($_SESSION[$app][$name])) { + $key = $this->_getKey($app, $name); + unset( + $_SESSION[$app][$name], + $_SESSION[self::PRUNE][$key], + $_SESSION[self::SERIALIZED][$key] + ); + } else { + foreach ($this->_subkeys($app, $name) as $val) { + $this->remove($app, $val); + } + } + } + + /** + * Generates the unique storage key. + * + * @param string $app Application name. + * @param string $name Session variable name. + * + * @return string The unique storage key. + */ + private function _getKey($app, $name) + { + return $app . ':' . $name; + } + + /** + * Return the list of subkeys for a master key. + * + * @param string $app Application name. + * @param string $name Session variable name. + * + * @return array Subkeyname (keys) and session variable name (values). + */ + private function _subkeys($app, $name) + { + $ret = array(); + + if (isset($_SESSION[$app]) && + ($name[strlen($name) - 1] == '/')) { + foreach (array_keys($_SESSION[$app]) as $k) { + if (strpos($k, $name) === 0) { + $ret[substr($k, strlen($name))] = $k; } } } + + return $ret; } - /* ArrayAccess helper methods. */ + /* Session object storage. */ /** - * Parses a session variable identifier. - * Format: - *
-     * [app:]name[/subkey][;default]
+     * Store an arbitrary piece of data in the session.
      *
-     * app - Application name.
-     *       DEFAULT: horde
-     * default - Default value type to return if value doesn't exist.
-     *           Valid types: array, object
-     *           DEFAULT: none
-     * subkey - Indicate that this entry is a subkey of the master name key.
-     *          Requesting a session key with a trailing '/' will retrieve all
-     *          subkeys of the given master key.
-     * 
+ * @param mixed $data Data to save. + * @param boolean $prune Is data pruneable? + * @param string $id ID to use (otherwise, is autogenerated). * - * @return object Object with the following properties: - *
-     * app - Application name.
-     * key - Offset key.
-     * name - Variable name.
-     * type - Variable type.
-     * 
+ * @return string The session storage id (used to retrieve session data). */ - private function _parseOffset($offset) + public function store($data, $prune = true, $id = null) { - $ob = new stdClass; + $id = is_null($id) + ? strval(new Horde_Support_Randomid()) + : $this->_getStoreId($id); - $parts = explode(':', $offset); - if (isset($parts[1])) { - $ob->app = $parts[0]; - $type = explode(';', $parts[1]); - } else { - $ob->app = 'horde'; - $type = explode(';', $parts[0]); + $this->set(self::DATA, $id, $data); + + if ($prune) { + $ptr = &$_SESSION[self::PRUNE]; + unset($ptr[$id]); + $ptr[$id] = 1; + if (count($ptr) > $this->maxStore) { + array_shift($ptr); + } } - $ob->name = $type[0]; - $ob->key = $ob->app . ':' . $ob->name; - $ob->type = isset($type[1]) - ? $type[1] - : 'scalar'; + return $this->_getKey(self::DATA, $id); + } + + /** + * Retrieve data from the session data store (created via store()). + * + * @param string $id The session data ID. + * + * @return mixed The session data value. + */ + public function retrieve($id) + { + return $this->get(self::DATA, $this->_getStoreId($id)); + } + + /** + * Purge data from the session data store (created via store()). + * + * @param string $id The session data ID. + */ + public function purge($id) + { + $this->remove(self::DATA, $this->_getStoreId($id)); + } + + /** + * Returns the base storage ID. + * + * @param string $id The session data ID. + * + * @return string The base storage ID (without prefix). + */ + private function _getStoreId($id) + { + $id = trim($id); + + if (strpos($id, self::DATA) === 0) { + $id = substr($id, strlen(self::DATA) + 1); + } - return $ob; + return $id; } }