MDL-20632 latest zend framework lib import

This commit is contained in:
Petr Skoda
2009-10-24 19:48:22 +00:00
parent c187722c1f
commit 2b271c7bc3
2298 changed files with 556400 additions and 2393 deletions
+1 -1
View File
@@ -256,7 +256,7 @@
<location>zend</location>
<name>Zend Framework</name>
<license>new BSD</license>
<version>1.7.3</version>
<version>1.9.4</version>
<licenseversion></licenseversion>
</library>
<library>
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Acl
*/
require_once 'Zend/Acl.php';
/**
* @see Zend_Acl_Role_Interface
*/
require_once 'Zend/Acl/Role/Interface.php';
/**
* @see Zend_Acl_Resource_Interface
*/
require_once 'Zend/Acl/Resource/Interface.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Acl_Assert_Interface
{
/**
* Returns true if and only if the assertion conditions are met
*
* This method is passed the ACL, Role, Resource, and privilege to which the authorization query applies. If the
* $role, $resource, or $privilege parameters are null, it means that the query applies to all Roles, Resources, or
* privileges, respectively.
*
* @param Zend_Acl $acl
* @param Zend_Acl_Role_Interface $role
* @param Zend_Acl_Resource_Interface $resource
* @param string $privilege
* @return boolean
*/
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null,
$privilege = null);
}
+36
View File
@@ -0,0 +1,36 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Exception
*/
require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Acl_Exception extends Zend_Exception
{}
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Acl_Resource_Interface
*/
require_once 'Zend/Acl/Resource/Interface.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Acl_Resource implements Zend_Acl_Resource_Interface
{
/**
* Unique id of Resource
*
* @var string
*/
protected $_resourceId;
/**
* Sets the Resource identifier
*
* @param string $resourceId
* @return void
*/
public function __construct($resourceId)
{
$this->_resourceId = (string) $resourceId;
}
/**
* Defined by Zend_Acl_Resource_Interface; returns the Resource identifier
*
* @return string
*/
public function getResourceId()
{
return $this->_resourceId;
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Acl_Resource_Interface
{
/**
* Returns the string identifier of the Resource
*
* @return string
*/
public function getResourceId();
}
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Acl_Role_Interface
*/
require_once 'Zend/Acl/Role/Interface.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Acl_Role implements Zend_Acl_Role_Interface
{
/**
* Unique id of Role
*
* @var string
*/
protected $_roleId;
/**
* Sets the Role identifier
*
* @param string $id
* @return void
*/
public function __construct($roleId)
{
$this->_roleId = (string) $roleId;
}
/**
* Defined by Zend_Acl_Role_Interface; returns the Role identifier
*
* @return string
*/
public function getRoleId()
{
return $this->_roleId;
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Acl_Role_Interface
{
/**
* Returns the string identifier of the Role
*
* @return string
*/
public function getRoleId();
}
+271
View File
@@ -0,0 +1,271 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Acl_Role_Interface
*/
require_once 'Zend/Acl/Role/Interface.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Acl_Role_Registry
{
/**
* Internal Role registry data storage
*
* @var array
*/
protected $_roles = array();
/**
* Adds a Role having an identifier unique to the registry
*
* The $parents parameter may be a reference to, or the string identifier for,
* a Role existing in the registry, or $parents may be passed as an array of
* these - mixing string identifiers and objects is ok - to indicate the Roles
* from which the newly added Role will directly inherit.
*
* In order to resolve potential ambiguities with conflicting rules inherited
* from different parents, the most recently added parent takes precedence over
* parents that were previously added. In other words, the first parent added
* will have the least priority, and the last parent added will have the
* highest priority.
*
* @param Zend_Acl_Role_Interface $role
* @param Zend_Acl_Role_Interface|string|array $parents
* @throws Zend_Acl_Role_Registry_Exception
* @return Zend_Acl_Role_Registry Provides a fluent interface
*/
public function add(Zend_Acl_Role_Interface $role, $parents = null)
{
$roleId = $role->getRoleId();
if ($this->has($roleId)) {
/**
* @see Zend_Acl_Role_Registry_Exception
*/
require_once 'Zend/Acl/Role/Registry/Exception.php';
throw new Zend_Acl_Role_Registry_Exception("Role id '$roleId' already exists in the registry");
}
$roleParents = array();
if (null !== $parents) {
if (!is_array($parents)) {
$parents = array($parents);
}
/**
* @see Zend_Acl_Role_Registry_Exception
*/
require_once 'Zend/Acl/Role/Registry/Exception.php';
foreach ($parents as $parent) {
try {
if ($parent instanceof Zend_Acl_Role_Interface) {
$roleParentId = $parent->getRoleId();
} else {
$roleParentId = $parent;
}
$roleParent = $this->get($roleParentId);
} catch (Zend_Acl_Role_Registry_Exception $e) {
throw new Zend_Acl_Role_Registry_Exception("Parent Role id '$roleParentId' does not exist");
}
$roleParents[$roleParentId] = $roleParent;
$this->_roles[$roleParentId]['children'][$roleId] = $role;
}
}
$this->_roles[$roleId] = array(
'instance' => $role,
'parents' => $roleParents,
'children' => array()
);
return $this;
}
/**
* Returns the identified Role
*
* The $role parameter can either be a Role or a Role identifier.
*
* @param Zend_Acl_Role_Interface|string $role
* @throws Zend_Acl_Role_Registry_Exception
* @return Zend_Acl_Role_Interface
*/
public function get($role)
{
if ($role instanceof Zend_Acl_Role_Interface) {
$roleId = $role->getRoleId();
} else {
$roleId = (string) $role;
}
if (!$this->has($role)) {
/**
* @see Zend_Acl_Role_Registry_Exception
*/
require_once 'Zend/Acl/Role/Registry/Exception.php';
throw new Zend_Acl_Role_Registry_Exception("Role '$roleId' not found");
}
return $this->_roles[$roleId]['instance'];
}
/**
* Returns true if and only if the Role exists in the registry
*
* The $role parameter can either be a Role or a Role identifier.
*
* @param Zend_Acl_Role_Interface|string $role
* @return boolean
*/
public function has($role)
{
if ($role instanceof Zend_Acl_Role_Interface) {
$roleId = $role->getRoleId();
} else {
$roleId = (string) $role;
}
return isset($this->_roles[$roleId]);
}
/**
* Returns an array of an existing Role's parents
*
* The array keys are the identifiers of the parent Roles, and the values are
* the parent Role instances. The parent Roles are ordered in this array by
* ascending priority. The highest priority parent Role, last in the array,
* corresponds with the parent Role most recently added.
*
* If the Role does not have any parents, then an empty array is returned.
*
* @param Zend_Acl_Role_Interface|string $role
* @uses Zend_Acl_Role_Registry::get()
* @return array
*/
public function getParents($role)
{
$roleId = $this->get($role)->getRoleId();
return $this->_roles[$roleId]['parents'];
}
/**
* Returns true if and only if $role inherits from $inherit
*
* Both parameters may be either a Role or a Role identifier. If
* $onlyParents is true, then $role must inherit directly from
* $inherit in order to return true. By default, this method looks
* through the entire inheritance DAG to determine whether $role
* inherits from $inherit through its ancestor Roles.
*
* @param Zend_Acl_Role_Interface|string $role
* @param Zend_Acl_Role_Interface|string $inherit
* @param boolean $onlyParents
* @throws Zend_Acl_Role_Registry_Exception
* @return boolean
*/
public function inherits($role, $inherit, $onlyParents = false)
{
/**
* @see Zend_Acl_Role_Registry_Exception
*/
require_once 'Zend/Acl/Role/Registry/Exception.php';
try {
$roleId = $this->get($role)->getRoleId();
$inheritId = $this->get($inherit)->getRoleId();
} catch (Zend_Acl_Role_Registry_Exception $e) {
throw $e;
}
$inherits = isset($this->_roles[$roleId]['parents'][$inheritId]);
if ($inherits || $onlyParents) {
return $inherits;
}
foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) {
if ($this->inherits($parentId, $inheritId)) {
return true;
}
}
return false;
}
/**
* Removes the Role from the registry
*
* The $role parameter can either be a Role or a Role identifier.
*
* @param Zend_Acl_Role_Interface|string $role
* @throws Zend_Acl_Role_Registry_Exception
* @return Zend_Acl_Role_Registry Provides a fluent interface
*/
public function remove($role)
{
/**
* @see Zend_Acl_Role_Registry_Exception
*/
require_once 'Zend/Acl/Role/Registry/Exception.php';
try {
$roleId = $this->get($role)->getRoleId();
} catch (Zend_Acl_Role_Registry_Exception $e) {
throw $e;
}
foreach ($this->_roles[$roleId]['children'] as $childId => $child) {
unset($this->_roles[$childId]['parents'][$roleId]);
}
foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) {
unset($this->_roles[$parentId]['children'][$roleId]);
}
unset($this->_roles[$roleId]);
return $this;
}
/**
* Removes all Roles from the registry
*
* @return Zend_Acl_Role_Registry Provides a fluent interface
*/
public function removeAll()
{
$this->_roles = array();
return $this;
}
public function getRoles()
{
return $this->_roles;
}
}
@@ -0,0 +1,36 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Acl_Exception
*/
require_once 'Zend/Acl/Exception.php';
/**
* @category Zend
* @package Zend_Acl
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Acl_Role_Registry_Exception extends Zend_Acl_Exception
{}
+133
View File
@@ -0,0 +1,133 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Auth_Abstract */
require_once 'Zend/Amf/Auth/Abstract.php';
/** Zend_Acl */
require_once 'Zend/Acl.php';
/** Zend_Auth_Result */
require_once 'Zend/Auth/Result.php';
/**
* This class implements authentication against XML file with roles for Flex Builder.
*
* @package Zend_Amf
* @subpackage Adobe
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Adobe_Auth extends Zend_Amf_Auth_Abstract
{
/**
* ACL for authorization
*
* @var Zend_Acl
*/
protected $_acl;
/**
* Username/password array
*
* @var array
*/
protected $_users = array();
/**
* Create auth adapter
*
* @param string $rolefile File containing XML with users and roles
*/
public function __construct($rolefile)
{
$this->_acl = new Zend_Acl();
$xml = simplexml_load_file($rolefile);
/*
Roles file format:
<roles>
<role id=”admin”>
<user name=”user1” password=”pwd”/>
</role>
<role id=”hr”>
<user name=”user2” password=”pwd2”/>
</role>
</roles>
*/
foreach($xml->role as $role) {
$this->_acl->addRole(new Zend_Acl_Role((string)$role["id"]));
foreach($role->user as $user) {
$this->_users[(string)$user["name"]] = array("password" => (string)$user["password"],
"role" => (string)$role["id"]);
}
}
}
/**
* Get ACL with roles from XML file
*
* @return Zend_Acl
*/
public function getAcl()
{
return $this->_acl;
}
/**
* Perform authentication
*
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result
* @see Zend_Auth_Adapter_Interface#authenticate()
*/
public function authenticate()
{
if (empty($this->_username) ||
empty($this->_password)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Username/password should be set');
}
if(!isset($this->_users[$this->_username])) {
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND,
null,
array('Username not found')
);
}
$user = $this->_users[$this->_username];
if($user["password"] != $this->_password) {
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID,
null,
array('Authentication failed')
);
}
$id = new stdClass();
$id->role = $user["role"];
$id->name = $this->_username;
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $id);
}
}
+103
View File
@@ -0,0 +1,103 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* This class implements authentication against XML file with roles for Flex Builder.
*
* @package Zend_Amf
* @subpackage Adobe
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Adobe_DbInspector
{
/**
* Connect to the database
*
* @param string $dbType Database adapter type for Zend_Db
* @param array|object $dbDescription Adapter-specific connection settings
* @return Zend_Db_Adapter_Abstract
* @see Zend_Db::factory()
*/
protected function _connect($dbType, $dbDescription)
{
if(is_object($dbDescription)) {
$dbDescription = get_object_vars($dbDescription);
}
return Zend_Db::factory($dbType, $dbDescription);
}
/**
* Describe database object.
*
* Usage example:
* $inspector->describeTable('Pdo_Mysql',
* array(
* 'host' => '127.0.0.1',
* 'username' => 'webuser',
* 'password' => 'xxxxxxxx',
* 'dbname' => 'test'
* ),
* 'mytable'
* );
*
* @param string $dbType Database adapter type for Zend_Db
* @param array|object $dbDescription Adapter-specific connection settings
* @param string $tableName Table name
* @return array Table description
* @see Zend_Db::describeTable()
* @see Zend_Db::factory()
*/
public function describeTable($dbType, $dbDescription, $tableName)
{
$db = $this->_connect($dbType, $dbDescription);
return $db->describeTable($tableName);
}
/**
* Test database connection
*
* @param string $dbType Database adapter type for Zend_Db
* @param array|object $dbDescription Adapter-specific connection settings
* @return bool
* @see Zend_Db::factory()
*/
public function connect($dbType, $dbDescription)
{
$db = $this->_connect($dbType, $dbDescription);
$db->listTables();
return true;
}
/**
* Get the list of database tables
*
* @param string $dbType Database adapter type for Zend_Db
* @param array|object $dbDescription Adapter-specific connection settings
* @return array List of the tables
*/
public function getTables($dbType, $dbDescription)
{
$db = $this->_connect($dbType, $dbDescription);
return $db->listTables();
}
}
+309
View File
@@ -0,0 +1,309 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_TypeLoader */
require_once 'Zend/Amf/Parse/TypeLoader.php';
/** Zend_Reflection_Class */
require_once 'Zend/Reflection/Class.php';
/** Zend_Server_Reflection */
require_once 'Zend/Server/Reflection.php';
/**
* This class implements a service for generating AMF service descriptions as XML.
*
* @package Zend_Amf
* @subpackage Adobe
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Adobe_Introspector
{
/**
* Options used:
* - server: instance of Zend_Amf_Server to use
* - directories: directories where class files may be looked up
*
* @var array Introspector options
*/
protected $_options;
/**
* @var DOMElement DOM element to store types
*/
protected $_types;
/**
* @var array Map of the known types
*/
protected $_typesMap = array();
/**
* @var DOMDocument XML document to store data
*/
protected $_xml;
/**
* Constructor
*
* @return void
*/
public function __construct()
{
$this->_xml = new DOMDocument('1.0', 'utf-8');
}
/**
* Create XML definition on an AMF service class
*
* @param string $serviceClass Service class name
* @param array $options invocation options
* @return string XML with service class introspection
*/
public function introspect($serviceClass, $options = array())
{
$this->_options = $options;
if (strpbrk($serviceClass, '\\/<>')) {
return $this->_returnError('Invalid service name');
}
// Transform com.foo.Bar into com_foo_Bar
$serviceClass = str_replace('.' , '_', $serviceClass);
// Introspect!
if (!class_exists($serviceClass)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($serviceClass, $this->_getServicePath());
}
$serv = $this->_xml->createElement('service-description');
$serv->setAttribute('xmlns', 'http://ns.adobe.com/flex/service-description/2008');
$this->_types = $this->_xml->createElement('types');
$this->_ops = $this->_xml->createElement('operations');
$r = Zend_Server_Reflection::reflectClass($serviceClass);
$this->_addService($r, $this->_ops);
$serv->appendChild($this->_types);
$serv->appendChild($this->_ops);
$this->_xml->appendChild($serv);
return $this->_xml->saveXML();
}
/**
* Authentication handler
*
* @param Zend_Acl $acl
* @return unknown_type
*/
public function initAcl(Zend_Acl $acl)
{
return false; // we do not need auth for this class
}
/**
* Generate map of public class attributes
*
* @param string $typename type name
* @param DOMElement $typexml target XML element
* @return void
*/
protected function _addClassAttributes($typename, DOMElement $typexml)
{
// Do not try to autoload here because _phpTypeToAS should
// have already attempted to load this class
if (!class_exists($typename, false)) {
return;
}
$rc = new Zend_Reflection_Class($typename);
foreach ($rc->getProperties() as $prop) {
if (!$prop->isPublic()) {
continue;
}
$propxml = $this->_xml->createElement('property');
$propxml->setAttribute('name', $prop->getName());
$type = $this->_registerType($this->_getPropertyType($prop));
$propxml->setAttribute('type', $type);
$typexml->appendChild($propxml);
}
}
/**
* Build XML service description from reflection class
*
* @param Zend_Server_Reflection_Class $refclass
* @param DOMElement $target target XML element
* @return void
*/
protected function _addService(Zend_Server_Reflection_Class $refclass, DOMElement $target)
{
foreach ($refclass->getMethods() as $method) {
if (!$method->isPublic()
|| $method->isConstructor()
|| ('__' == substr($method->name, 0, 2))
) {
continue;
}
foreach ($method->getPrototypes() as $proto) {
$op = $this->_xml->createElement('operation');
$op->setAttribute('name', $method->getName());
$rettype = $this->_registerType($proto->getReturnType());
$op->setAttribute('returnType', $rettype);
foreach ($proto->getParameters() as $param) {
$arg = $this->_xml->createElement('argument');
$arg->setAttribute('name', $param->getName());
$type = $param->getType();
if ($type == 'mixed' && ($pclass = $param->getClass())) {
$type = $pclass->getName();
}
$ptype = $this->_registerType($type);
$arg->setAttribute('type', $ptype);
$op->appendChild($arg);
}
$target->appendChild($op);
}
}
}
/**
* Extract type of the property from DocBlock
*
* @param Zend_Reflection_Property $prop reflection property object
* @return string Property type
*/
protected function _getPropertyType(Zend_Reflection_Property $prop)
{
$docBlock = $prop->getDocComment();
if (!$docBlock) {
return 'Unknown';
}
if (!$docBlock->hasTag('var')) {
return 'Unknown';
}
$tag = $docBlock->getTag('var');
return trim($tag->getDescription());
}
/**
* Get the array of service directories
*
* @return array Service class directories
*/
protected function _getServicePath()
{
if (isset($this->_options['server'])) {
return $this->_options['server']->getDirectory();
}
if (isset($this->_options['directories'])) {
return $this->_options['directories'];
}
return array();
}
/**
* Map from PHP type name to AS type name
*
* @param string $typename PHP type name
* @return string AS type name
*/
protected function _phpTypeToAS($typename)
{
if (class_exists($typename)) {
$vars = get_class_vars($typename);
if (isset($vars['_explicitType'])) {
return $vars['_explicitType'];
}
}
if (false !== ($asname = Zend_Amf_Parse_TypeLoader::getMappedClassName($typename))) {
return $asname;
}
return $typename;
}
/**
* Register new type on the system
*
* @param string $typename type name
* @return string New type name
*/
protected function _registerType($typename)
{
// Known type - return its AS name
if (isset($this->_typesMap[$typename])) {
return $this->_typesMap[$typename];
}
// Standard types
if (in_array($typename, array('void', 'null', 'mixed', 'unknown_type'))) {
return 'Unknown';
}
if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass', 'array'))) {
return $typename;
}
// Resolve and store AS name
$asTypeName = $this->_phpTypeToAS($typename);
$this->_typesMap[$typename] = $asTypeName;
// Create element for the name
$typeEl = $this->_xml->createElement('type');
$typeEl->setAttribute('name', $asTypeName);
$this->_addClassAttributes($typename, $typeEl);
$this->_types->appendChild($typeEl);
return $asTypeName;
}
/**
* Return error with error message
*
* @param string $msg Error message
* @return string
*/
protected function _returnError($msg)
{
return 'ERROR: $msg';
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Auth_Adapter_Interface */
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* Base abstract class for AMF authentication implementation
*
* @package Zend_Amf
* @subpackage Auth
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Auth_Abstract implements Zend_Auth_Adapter_Interface
{
protected $_username;
protected $_password;
public function setCredentials($username, $password) {
$this->_username = $username;
$this->_password = $password;
}
}
+10 -2
View File
@@ -14,8 +14,9 @@
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -23,7 +24,7 @@
* deserialization to detect the AMF marker and encoding types.
*
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
final class Zend_Amf_Constants
@@ -67,6 +68,8 @@ final class Zend_Amf_Constants
const ET_EXTERNAL = 0x01;
const ET_DYNAMIC = 0x02;
const ET_PROXY = 0x03;
const FMS_OBJECT_ENCODING = 0x01;
/**
* Special content length value that indicates "unknown" content length
@@ -76,4 +79,9 @@ final class Zend_Amf_Constants
const URL_APPEND_HEADER = 'AppendToGatewayUrl';
const RESULT_METHOD = '/onResult';
const STATUS_METHOD = '/onStatus';
const CREDENTIALS_HEADER = 'Credentials';
const PERSISTENT_HEADER = 'RequestPersistentHeader';
const DESCRIBE_HEADER = 'DescribeService';
const GUEST_ROLE = 'anonymous';
}
+3 -2
View File
@@ -14,8 +14,9 @@
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -25,7 +26,7 @@ require_once 'Zend/Exception.php';
/**
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Exception extends Zend_Exception
+11 -29
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf0
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_Deserializer */
@@ -29,7 +30,7 @@ require_once 'Zend/Amf/Parse/Deserializer.php';
* @todo Class could be implmented as Factory Class with each data type it's own class
* @package Zend_Amf
* @subpackage Parse_Amf0
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
@@ -47,13 +48,6 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
*/
protected $_objectEncoding = Zend_Amf_Constants::AMF0_OBJECT_ENCODING;
/**
* refrence to AMF3 deserializer
*
* @var Zend_Amf_Parse_Amf3_Deserializer
*/
protected $_deserializer = null;
/**
* Read AMF markers and dispatch for deserialization
*
@@ -63,12 +57,11 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
*
* @param integer $typeMarker
* @return mixed whatever the data type is of the marker in php
* @return mixed
* @throws Zend_Amf_Exception for invalid type
*/
public function readTypeMarker($typeMarker = null)
{
if (is_null($typeMarker)) {
if ($typeMarker === null) {
$typeMarker = $this->_stream->readByte();
}
@@ -152,7 +145,7 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
*/
public function readObject($object = null)
{
if (is_null($object)) {
if ($object === null) {
$object = array();
}
@@ -261,7 +254,7 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
* Commonly used for Value Objects on the server
*
* @todo implement Typed Class mapping
* @return object
* @return object|array
* @throws Zend_Amf_Exception if unable to load type
*/
public function readTypedObject()
@@ -277,7 +270,9 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
$returnObject->$key = $value;
}
}
if($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) {
$returnObject = get_object_vars($returnObject);
}
return $returnObject;
}
@@ -289,7 +284,8 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
*/
public function readAmf3TypeMarker()
{
$deserializer = $this->getDeserializer();
require_once 'Zend/Amf/Parse/Amf3/Deserializer.php';
$deserializer = new Zend_Amf_Parse_Amf3_Deserializer($this->_stream);
$this->_objectEncoding = Zend_Amf_Constants::AMF3_OBJECT_ENCODING;
return $deserializer->readTypeMarker();
}
@@ -304,18 +300,4 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
{
return $this->_objectEncoding;
}
/**
* Get deserializer
*
* @return Zend_Amf_Parse_Amf3_Deserializer
*/
public function getDeserializer()
{
if (null === $this->_deserializer) {
require_once 'Zend/Amf/Parse/Amf3/Deserializer.php';
$this->_deserializer = new Zend_Amf_Parse_Amf3_Deserializer($this->_stream);
}
return $this->_deserializer;
}
}
+106 -49
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf0
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_Serializer */
@@ -28,7 +29,7 @@ require_once 'Zend/Amf/Parse/Serializer.php';
* @uses Zend_Amf_Parse_Serializer
* @package Zend_Amf
* @subpackage Parse_Amf0
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
@@ -37,6 +38,12 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
* @var string Name of the class to be returned
*/
protected $_className = '';
/**
* An array of reference objects
* @var array
*/
protected $_referenceObjects = array();
/**
* Determine type and serialize accordingly
@@ -53,50 +60,60 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
public function writeTypeMarker($data, $markerType = null)
{
if (null !== $markerType) {
// Write the Type Marker to denote the following action script data type
$this->_stream->writeByte($markerType);
switch($markerType) {
case Zend_Amf_Constants::AMF0_NUMBER:
$this->_stream->writeDouble($data);
break;
case Zend_Amf_Constants::AMF0_BOOLEAN:
$this->_stream->writeByte($data);
break;
case Zend_Amf_Constants::AMF0_STRING:
$this->_stream->writeUTF($data);
break;
case Zend_Amf_Constants::AMF0_OBJECT:
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_NULL:
break;
case Zend_Amf_Constants::AMF0_MIXEDARRAY:
// Write length of numeric keys as zero.
$this->_stream->writeLong(0);
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_ARRAY:
$this->writeArray($data);
break;
case Zend_Amf_Constants::AMF0_DATE:
$this->writeDate($data);
break;
case Zend_Amf_Constants::AMF0_LONGSTRING:
$this->_stream->writeLongUTF($data);
break;
case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
$this->writeTypedObject($data);
break;
case Zend_Amf_Constants::AMF0_AMF3:
$this->writeAmf3TypeMarker($data);
break;
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
//try to refrence the given object
if( !$this->writeObjectReference($data, $markerType) ) {
// Write the Type Marker to denote the following action script data type
$this->_stream->writeByte($markerType);
switch($markerType) {
case Zend_Amf_Constants::AMF0_NUMBER:
$this->_stream->writeDouble($data);
break;
case Zend_Amf_Constants::AMF0_BOOLEAN:
$this->_stream->writeByte($data);
break;
case Zend_Amf_Constants::AMF0_STRING:
$this->_stream->writeUTF($data);
break;
case Zend_Amf_Constants::AMF0_OBJECT:
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_NULL:
break;
case Zend_Amf_Constants::AMF0_REFERENCE:
$this->_stream->writeInt($data);
break;
case Zend_Amf_Constants::AMF0_MIXEDARRAY:
// Write length of numeric keys as zero.
$this->_stream->writeLong(0);
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_ARRAY:
$this->writeArray($data);
break;
case Zend_Amf_Constants::AMF0_DATE:
$this->writeDate($data);
break;
case Zend_Amf_Constants::AMF0_LONGSTRING:
$this->_stream->writeLongUTF($data);
break;
case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
$this->writeTypedObject($data);
break;
case Zend_Amf_Constants::AMF0_AMF3:
$this->writeAmf3TypeMarker($data);
break;
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
}
}
} else {
if(is_resource($data)) {
$data = Zend_Amf_Parse_TypeLoader::handleResource($data);
}
switch (true) {
case (is_int($data) || is_float($data)):
case (is_int($data) || is_float($data)):
$markerType = Zend_Amf_Constants::AMF0_NUMBER;
break;
case (is_bool($data)):
@@ -128,12 +145,19 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
$markerType = Zend_Amf_Constants::AMF0_NULL;
break;
case (is_array($data)):
// check if it is a mixed typed array
// check if it is an associative array
$i = 0;
foreach (array_keys($data) as $key) {
if (!is_numeric($key)) {
$markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
break;
}
// check if it contains non-integer keys
if (!is_numeric($key) || intval($key) != $key) {
$markerType = Zend_Amf_Constants::AMF0_OBJECT;
break;
// check if it is a sparse indexed array
} else if ($key != $i) {
$markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
break;
}
$i++;
}
// Dealing with a standard numeric array
if(!$markerType){
@@ -150,6 +174,33 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
}
return $this;
}
/**
* Check if the given object is in the reference table, write the reference if it exists,
* otherwise add the object to the reference table
*
* @param mixed $object object to check for reference
* @param $markerType AMF type of the object to write
* @return Boolean true, if the reference was written, false otherwise
*/
protected function writeObjectReference($object, $markerType){
if( $markerType == Zend_Amf_Constants::AMF0_OBJECT ||
$markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY ||
$markerType == Zend_Amf_Constants::AMF0_ARRAY ||
$markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT ) {
$ref = array_search($object, $this->_referenceObjects,true);
//handle object reference
if($ref !== false){
$this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE);
return true;
}
$this->_referenceObjects[] = $object;
}
return false;
}
/**
* Write a php array with string or mixed keys.
@@ -161,6 +212,8 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
{
// Loop each element and write the name of the property.
foreach ($object as $key => $value) {
// skip variables starting with an _ provate transient
if( $key[0] == "_") continue;
$this->_stream->writeUTF($key);
$this->writeTypeMarker($value);
}
@@ -270,14 +323,18 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
// Check to see if the user has defined an explicit Action Script type.
case isset($object->_explicitType):
$className = $object->_explicitType;
unset($object->_explicitType);
break;
// Check if user has defined a method for accessing the Action Script type
case method_exists($object, 'getASClassName'):
$className = $object->getASClassName();
break;
// No return class name is set make it a generic object
case ($object instanceof stdClass):
$className = '';
break;
// By default, use object's class name
default:
$className = get_class($object);
break;
}
if(!$className == '') {
+421 -410
View File
@@ -1,410 +1,421 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/** Zend_Amf_Parse_Deserializer */
require_once 'Zend/Amf/Parse/Deserializer.php';
/** Zend_Amf_Parse_TypeLoader */
require_once 'Zend/Amf/Parse/TypeLoader.php';
/**
* Read an AMF3 input stream and convert it into PHP data types.
*
* @todo readObject to handle Typed Objects
* @todo readXMLStrimg to be implemented.
* @todo Class could be implmented as Factory Class with each data type it's own class.
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
{
/**
* Total number of objects in the referenceObject array
* @var int
*/
protected $_objectCount;
/**
* An array of reference objects per amf body
* @var array
*/
protected $_referenceObjects = array();
/**
* An array of reference strings per amf body
* @var array
*/
protected $_referenceStrings = array();
/**
* An array of reference class definitions per body
* @var array
*/
protected $_referenceDefinitions = array();
/**
* Read AMF markers and dispatch for deserialization
*
* Checks for AMF marker types and calls the appropriate methods
* for deserializing those marker types. markers are the data type of
* the following value.
*
* @param integer $typeMarker
* @return mixed Whatever the corresponding PHP data type is
* @throws Zend_Amf_Exception for unidentified marker type
*/
public function readTypeMarker($typeMarker = null)
{
if(null === $typeMarker) {
$typeMarker = $this->_stream->readByte();
}
switch($typeMarker) {
case Zend_Amf_Constants::AMF3_UNDEFINED:
return null;
case Zend_Amf_Constants::AMF3_NULL:
return null;
case Zend_Amf_Constants::AMF3_BOOLEAN_FALSE:
return false;
case Zend_Amf_Constants::AMF3_BOOLEAN_TRUE:
return true;
case Zend_Amf_Constants::AMF3_INTEGER:
return $this->readInteger();
case Zend_Amf_Constants::AMF3_NUMBER:
return $this->_stream->readDouble();
case Zend_Amf_Constants::AMF3_STRING:
return $this->readString();
case Zend_Amf_Constants::AMF3_DATE:
return $this->readDate();
case Zend_Amf_Constants::AMF3_ARRAY:
return $this->readArray();
case Zend_Amf_Constants::AMF3_OBJECT:
return $this->readObject();
case Zend_Amf_Constants::AMF3_XML:
case Zend_Amf_Constants::AMF3_XMLSTRING:
return $this->readXmlString();
case Zend_Amf_Constants::AMF3_BYTEARRAY:
return $this->readString();
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unsupported type marker: ' . $typeMarker);
}
}
/**
* Read and deserialize an integer
*
* AMF 3 represents smaller integers with fewer bytes using the most
* significant bit of each byte. The worst case uses 32-bits
* to represent a 29-bit number, which is what we would have
* done with no compression.
* - 0x00000000 - 0x0000007F : 0xxxxxxx
* - 0x00000080 - 0x00003FFF : 1xxxxxxx 0xxxxxxx
* - 0x00004000 - 0x001FFFFF : 1xxxxxxx 1xxxxxxx 0xxxxxxx
* - 0x00200000 - 0x3FFFFFFF : 1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx
* - 0x40000000 - 0xFFFFFFFF : throw range exception
*
*
* 0x04 -> integer type code, followed by up to 4 bytes of data.
*
* @see: Parsing integers on OSFlash {http://osflash.org/amf3/parsing_integers>} for the AMF3 integer data format.
* @return int|float
*/
public function readInteger()
{
$count = 1;
$intReference = $this->_stream->readByte();
$result = 0;
while ((($intReference & 0x80) != 0) && $count < 4) {
$result <<= 7;
$result |= ($intReference & 0x7f);
$intReference = $this->_stream->readByte();
$count++;
}
if ($count < 4) {
$result <<= 7;
$result |= $intReference;
} else {
// Use all 8 bits from the 4th byte
$result <<= 8;
$result |= $intReference;
// Check if the integer should be negative
if (($result & 0x10000000) != 0) {
//and extend the sign bit
$result |= 0xe0000000;
}
}
return $result;
}
/**
* Read and deserialize a string
*
* Strings can be sent as a reference to a previously
* occurring String by using an index to the implicit string reference table.
* Strings are encoding using UTF-8 - however the header may either
* describe a string literal or a string reference.
*
* - string = 0x06 string-data
* - string-data = integer-data [ modified-utf-8 ]
* - modified-utf-8 = *OCTET
*
* @return String
*/
public function readString()
{
$stringReference = $this->readInteger();
//Check if this is a reference string
if (($stringReference & 0x01) == 0) {
// reference string
$stringReference = $stringReference >> 1;
if ($stringReference >= count($this->_referenceStrings)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Undefined string reference: ' . $stringReference);
}
// reference string found
return $this->_referenceStrings[$stringReference];
}
$length = $stringReference >> 1;
if ($length) {
$string = $this->_stream->readBytes($length);
$this->_referenceStrings[] = $string;
} else {
$string = "";
}
return $string;
}
/**
* Read and deserialize a date
*
* Data is the number of milliseconds elapsed since the epoch
* of midnight, 1st Jan 1970 in the UTC time zone.
* Local time zone information is not sent to flash.
*
* - date = 0x08 integer-data [ number-data ]
*
* @return Zend_Date
*/
public function readDate()
{
$dateReference = $this->readInteger();
if (($dateReference & 0x01) == 0) {
$dateReference = $dateReference >> 1;
if ($dateReference>=count($this->_referenceObjects)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Undefined date reference: ' . $dateReference);
}
return $this->_referenceObjects[$dateReference];
}
$timestamp = floor($this->_stream->readDouble() / 1000);
require_once 'Zend/Date.php';
$dateTime = new Zend_Date((int) $timestamp);
$this->_referenceObjects[] = $dateTime;
return $dateTime;
}
/**
* Read amf array to PHP array
*
* - array = 0x09 integer-data ( [ 1OCTET *amf3-data ] | [OCTET *amf3-data 1] | [ OCTET *amf-data ] )
*
* @return array
*/
public function readArray()
{
$arrayReference = $this->readInteger();
if (($arrayReference & 0x01)==0){
$arrayReference = $arrayReference >> 1;
if ($arrayReference>=count($this->_referenceObjects)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknow array reference: ' . $arrayReference);
}
return $this->_referenceObjects[$arrayReference];
}
// Create a holder for the array in the reference list
$data = array();
$this->_referenceObjects[] &= $data;
$key = $this->readString();
// Iterating for string based keys.
while ($key != '') {
$data[$key] = $this->readTypeMarker();
$key = $this->readString();
}
$arrayReference = $arrayReference >>1;
//We have a dense array
for ($i=0; $i < $arrayReference; $i++) {
$data[] = $this->readTypeMarker();
}
return $data;
}
/**
* Read an object from the AMF stream and convert it into a PHP object
*
* @todo Rather than using an array of traitsInfo create Zend_Amf_Value_TraitsInfo
* @return object
*/
public function readObject()
{
$traitsInfo = $this->readInteger();
$storedObject = ($traitsInfo & 0x01)==0;
$traitsInfo = $traitsInfo >> 1;
// Check if the Object is in the stored Objects reference table
if ($storedObject) {
$ref = $traitsInfo;
if (!isset($this->_referenceObjects[$ref])) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknown Object reference: ' . $ref);
}
$returnObject = $this->_referenceObjects[$ref];
} else {
// Check if the Object is in the stored Definistions reference table
$storedClass = ($traitsInfo & 0x01) == 0;
$traitsInfo = $traitsInfo >> 1;
if ($storedClass) {
$ref = $traitsInfo;
if (!isset($this->_referenceDefinitions[$ref])) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknows Definition reference: '. $ref);
}
// Populate the reference attributes
$className = $this->_referenceDefinitions[$ref]['className'];
$encoding = $this->_referenceDefinitions[$ref]['encoding'];
$propertyNames = $this->_referenceDefinitions[$ref]['propertyNames'];
} else {
// The class was not in the reference tables. Start reading rawdata to build traits.
// Create a traits table. Zend_Amf_Value_TraitsInfo would be ideal
$className = $this->readString();
$encoding = $traitsInfo & 0x03;
$propertyNames = array();
$traitsInfo = $traitsInfo >> 2;
}
// We now have the object traits defined in variables. Time to go to work:
if (!$className) {
// No class name generic object
$returnObject = new stdClass();
} else {
// Defined object
// Typed object lookup agsinst registered classname maps
if ($loader = Zend_Amf_Parse_TypeLoader::loadType($className)) {
$returnObject = new $loader();
} else {
//user defined typed object
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Typed object not found: '. $className . ' ');
}
}
// Add the Object ot the reference table
$this->_referenceObjects[] = $returnObject;
// Check encoding types for additional processing.
switch ($encoding) {
case (Zend_Amf_Constants::ET_EXTERNAL):
// Externalizable object such as {ArrayCollection} and {ObjectProxy}
if (!$storedClass) {
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
$returnObject->externalizedData = $this->readTypeMarker();
break;
case (Zend_Amf_Constants::ET_DYNAMIC):
// used for Name-value encoding
if (!$storedClass) {
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
// not a refrence object read name value properties from byte stream
$properties = array(); // clear value
do {
$property = $this->readString();
if ($property != "") {
$propertyNames[] = $property;
$properties[$property] = $this->readTypeMarker();
}
} while ($property !="");
break;
default:
// basic property list object.
if (!$storedClass) {
$count = $traitsInfo; // Number of properties in the list
for($i=0; $i< $count; $i++) {
$propertyNames[] = $this->readString();
}
// Add a refrence to the class.
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
$properties = array(); // clear value
foreach ($propertyNames as $property) {
$properties[$property] = $this->readTypeMarker();
}
break;
}
// Add properties back to the return object.
foreach($properties as $key=>$value) {
if($key) {
$returnObject->$key = $value;
}
}
}
return $returnObject;
}
/**
* Convert XML to SimpleXml
* If user wants DomDocument they can use dom_import_simplexml
*
* @return SimpleXml Object
*/
public function readXmlString()
{
$xmlReference = $this->readInteger();
$length = $xmlReference >> 1;
$string = $this->_stream->readBytes($length);
return simplexml_load_string($string);
}
}
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_Deserializer */
require_once 'Zend/Amf/Parse/Deserializer.php';
/** Zend_Amf_Parse_TypeLoader */
require_once 'Zend/Amf/Parse/TypeLoader.php';
/**
* Read an AMF3 input stream and convert it into PHP data types.
*
* @todo readObject to handle Typed Objects
* @todo readXMLStrimg to be implemented.
* @todo Class could be implmented as Factory Class with each data type it's own class.
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
{
/**
* Total number of objects in the referenceObject array
* @var int
*/
protected $_objectCount;
/**
* An array of reference objects per amf body
* @var array
*/
protected $_referenceObjects = array();
/**
* An array of reference strings per amf body
* @var array
*/
protected $_referenceStrings = array();
/**
* An array of reference class definitions per body
* @var array
*/
protected $_referenceDefinitions = array();
/**
* Read AMF markers and dispatch for deserialization
*
* Checks for AMF marker types and calls the appropriate methods
* for deserializing those marker types. markers are the data type of
* the following value.
*
* @param integer $typeMarker
* @return mixed Whatever the corresponding PHP data type is
* @throws Zend_Amf_Exception for unidentified marker type
*/
public function readTypeMarker($typeMarker = null)
{
if(null === $typeMarker) {
$typeMarker = $this->_stream->readByte();
}
switch($typeMarker) {
case Zend_Amf_Constants::AMF3_UNDEFINED:
return null;
case Zend_Amf_Constants::AMF3_NULL:
return null;
case Zend_Amf_Constants::AMF3_BOOLEAN_FALSE:
return false;
case Zend_Amf_Constants::AMF3_BOOLEAN_TRUE:
return true;
case Zend_Amf_Constants::AMF3_INTEGER:
return $this->readInteger();
case Zend_Amf_Constants::AMF3_NUMBER:
return $this->_stream->readDouble();
case Zend_Amf_Constants::AMF3_STRING:
return $this->readString();
case Zend_Amf_Constants::AMF3_DATE:
return $this->readDate();
case Zend_Amf_Constants::AMF3_ARRAY:
return $this->readArray();
case Zend_Amf_Constants::AMF3_OBJECT:
return $this->readObject();
case Zend_Amf_Constants::AMF3_XML:
case Zend_Amf_Constants::AMF3_XMLSTRING:
return $this->readXmlString();
case Zend_Amf_Constants::AMF3_BYTEARRAY:
return $this->readString();
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unsupported type marker: ' . $typeMarker);
}
}
/**
* Read and deserialize an integer
*
* AMF 3 represents smaller integers with fewer bytes using the most
* significant bit of each byte. The worst case uses 32-bits
* to represent a 29-bit number, which is what we would have
* done with no compression.
* - 0x00000000 - 0x0000007F : 0xxxxxxx
* - 0x00000080 - 0x00003FFF : 1xxxxxxx 0xxxxxxx
* - 0x00004000 - 0x001FFFFF : 1xxxxxxx 1xxxxxxx 0xxxxxxx
* - 0x00200000 - 0x3FFFFFFF : 1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx
* - 0x40000000 - 0xFFFFFFFF : throw range exception
*
* 0x04 -> integer type code, followed by up to 4 bytes of data.
*
* Parsing integers on OSFlash for the AMF3 integer data format:
* @link http://osflash.org/amf3/parsing_integers
* @return int|float
*/
public function readInteger()
{
$count = 1;
$intReference = $this->_stream->readByte();
$result = 0;
while ((($intReference & 0x80) != 0) && $count < 4) {
$result <<= 7;
$result |= ($intReference & 0x7f);
$intReference = $this->_stream->readByte();
$count++;
}
if ($count < 4) {
$result <<= 7;
$result |= $intReference;
} else {
// Use all 8 bits from the 4th byte
$result <<= 8;
$result |= $intReference;
// Check if the integer should be negative
if (($result & 0x10000000) != 0) {
//and extend the sign bit
$result |= ~0xFFFFFFF;
}
}
return $result;
}
/**
* Read and deserialize a string
*
* Strings can be sent as a reference to a previously
* occurring String by using an index to the implicit string reference table.
* Strings are encoding using UTF-8 - however the header may either
* describe a string literal or a string reference.
*
* - string = 0x06 string-data
* - string-data = integer-data [ modified-utf-8 ]
* - modified-utf-8 = *OCTET
*
* @return String
*/
public function readString()
{
$stringReference = $this->readInteger();
//Check if this is a reference string
if (($stringReference & 0x01) == 0) {
// reference string
$stringReference = $stringReference >> 1;
if ($stringReference >= count($this->_referenceStrings)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Undefined string reference: ' . $stringReference);
}
// reference string found
return $this->_referenceStrings[$stringReference];
}
$length = $stringReference >> 1;
if ($length) {
$string = $this->_stream->readBytes($length);
$this->_referenceStrings[] = $string;
} else {
$string = "";
}
return $string;
}
/**
* Read and deserialize a date
*
* Data is the number of milliseconds elapsed since the epoch
* of midnight, 1st Jan 1970 in the UTC time zone.
* Local time zone information is not sent to flash.
*
* - date = 0x08 integer-data [ number-data ]
*
* @return Zend_Date
*/
public function readDate()
{
$dateReference = $this->readInteger();
if (($dateReference & 0x01) == 0) {
$dateReference = $dateReference >> 1;
if ($dateReference>=count($this->_referenceObjects)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Undefined date reference: ' . $dateReference);
}
return $this->_referenceObjects[$dateReference];
}
$timestamp = floor($this->_stream->readDouble() / 1000);
require_once 'Zend/Date.php';
$dateTime = new Zend_Date((int) $timestamp);
$this->_referenceObjects[] = $dateTime;
return $dateTime;
}
/**
* Read amf array to PHP array
*
* - array = 0x09 integer-data ( [ 1OCTET *amf3-data ] | [OCTET *amf3-data 1] | [ OCTET *amf-data ] )
*
* @return array
*/
public function readArray()
{
$arrayReference = $this->readInteger();
if (($arrayReference & 0x01)==0){
$arrayReference = $arrayReference >> 1;
if ($arrayReference>=count($this->_referenceObjects)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknow array reference: ' . $arrayReference);
}
return $this->_referenceObjects[$arrayReference];
}
// Create a holder for the array in the reference list
$data = array();
$this->_referenceObjects[] =& $data;
$key = $this->readString();
// Iterating for string based keys.
while ($key != '') {
$data[$key] = $this->readTypeMarker();
$key = $this->readString();
}
$arrayReference = $arrayReference >>1;
//We have a dense array
for ($i=0; $i < $arrayReference; $i++) {
$data[] = $this->readTypeMarker();
}
return $data;
}
/**
* Read an object from the AMF stream and convert it into a PHP object
*
* @todo Rather than using an array of traitsInfo create Zend_Amf_Value_TraitsInfo
* @return object|array
*/
public function readObject()
{
$traitsInfo = $this->readInteger();
$storedObject = ($traitsInfo & 0x01)==0;
$traitsInfo = $traitsInfo >> 1;
// Check if the Object is in the stored Objects reference table
if ($storedObject) {
$ref = $traitsInfo;
if (!isset($this->_referenceObjects[$ref])) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknown Object reference: ' . $ref);
}
$returnObject = $this->_referenceObjects[$ref];
} else {
// Check if the Object is in the stored Definistions reference table
$storedClass = ($traitsInfo & 0x01) == 0;
$traitsInfo = $traitsInfo >> 1;
if ($storedClass) {
$ref = $traitsInfo;
if (!isset($this->_referenceDefinitions[$ref])) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknows Definition reference: '. $ref);
}
// Populate the reference attributes
$className = $this->_referenceDefinitions[$ref]['className'];
$encoding = $this->_referenceDefinitions[$ref]['encoding'];
$propertyNames = $this->_referenceDefinitions[$ref]['propertyNames'];
} else {
// The class was not in the reference tables. Start reading rawdata to build traits.
// Create a traits table. Zend_Amf_Value_TraitsInfo would be ideal
$className = $this->readString();
$encoding = $traitsInfo & 0x03;
$propertyNames = array();
$traitsInfo = $traitsInfo >> 2;
}
// We now have the object traits defined in variables. Time to go to work:
if (!$className) {
// No class name generic object
$returnObject = new stdClass();
} else {
// Defined object
// Typed object lookup agsinst registered classname maps
if ($loader = Zend_Amf_Parse_TypeLoader::loadType($className)) {
$returnObject = new $loader();
} else {
//user defined typed object
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Typed object not found: '. $className . ' ');
}
}
// Add the Object ot the reference table
$this->_referenceObjects[] = $returnObject;
$properties = array(); // clear value
// Check encoding types for additional processing.
switch ($encoding) {
case (Zend_Amf_Constants::ET_EXTERNAL):
// Externalizable object such as {ArrayCollection} and {ObjectProxy}
if (!$storedClass) {
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
$returnObject->externalizedData = $this->readTypeMarker();
break;
case (Zend_Amf_Constants::ET_DYNAMIC):
// used for Name-value encoding
if (!$storedClass) {
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
// not a refrence object read name value properties from byte stream
do {
$property = $this->readString();
if ($property != "") {
$propertyNames[] = $property;
$properties[$property] = $this->readTypeMarker();
}
} while ($property !="");
break;
default:
// basic property list object.
if (!$storedClass) {
$count = $traitsInfo; // Number of properties in the list
for($i=0; $i< $count; $i++) {
$propertyNames[] = $this->readString();
}
// Add a refrence to the class.
$this->_referenceDefinitions[] = array(
'className' => $className,
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
}
foreach ($propertyNames as $property) {
$properties[$property] = $this->readTypeMarker();
}
break;
}
// Add properties back to the return object.
foreach($properties as $key=>$value) {
if($key) {
$returnObject->$key = $value;
}
}
}
if($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) {
if(isset($returnObject->externalizedData)) {
$returnObject = $returnObject->externalizedData;
} else {
$returnObject = get_object_vars($returnObject);
}
}
return $returnObject;
}
/**
* Convert XML to SimpleXml
* If user wants DomDocument they can use dom_import_simplexml
*
* @return SimpleXml Object
*/
public function readXmlString()
{
$xmlReference = $this->readInteger();
$length = $xmlReference >> 1;
$string = $this->_stream->readBytes($length);
return simplexml_load_string($string);
}
}
+217 -30
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_Serializer */
@@ -30,11 +31,29 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
*
* @package Zend_Amf
* @subpackage Parse_Amf3
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
{
/**
* An array of reference objects per amf body
* @var array
*/
protected $_referenceObjects = array();
/**
* An array of reference strings per amf body
* @var array
*/
protected $_referenceStrings = array();
/**
* An array of reference class definitions, indexed by classname
* @var array
*/
protected $_referenceDefinitions = array();
/**
* Serialize PHP types to AMF3 and write to stream
*
@@ -78,7 +97,10 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF3_BYTEARRAY:
$this->writeString($data);
$this->writeByteArray($data);
break;
case Zend_Amf_Constants::AMF3_XMLSTRING;
$this->writeXml($data);
break;
default:
require_once 'Zend/Amf/Exception.php';
@@ -86,8 +108,11 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
}
} else {
// Detect Type Marker
if(is_resource($data)) {
$data = Zend_Amf_Parse_TypeLoader::handleResource($data);
}
switch (true) {
case (null === $data):
case (null === $data):
$markerType = Zend_Amf_Constants::AMF3_NULL;
break;
case (is_bool($data)):
@@ -119,6 +144,8 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
$markerType = Zend_Amf_Constants::AMF3_DATE;
} else if ($data instanceof Zend_Amf_Value_ByteArray) {
$markerType = Zend_Amf_Constants::AMF3_BYTEARRAY;
} else if (($data instanceof DOMDocument) || ($data instanceof SimpleXMLElement)) {
$markerType = Zend_Amf_Constants::AMF3_XMLSTRING;
} else {
$markerType = Zend_Amf_Constants::AMF3_OBJECT;
}
@@ -163,6 +190,21 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
$this->_stream->writeByte($int & 0xff);
return $this;
}
/**
* Send string to output stream, without trying to reference it.
* The string is prepended with strlen($string) << 1 | 0x01
*
* @param string $string
* @return Zend_Amf_Parse_Amf3_Serializer
*/
protected function writeBinaryString($string){
$ref = strlen($string) << 1 | 0x01;
$this->writeInteger($ref);
$this->_stream->writeBytes($string);
return $this;
}
/**
* Send string to output stream
@@ -172,9 +214,74 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeString($string)
{
$ref = strlen($string) << 1 | 0x01;
$this->writeInteger($ref);
$this->_stream->writeBytes($string);
$len = strlen($string);
if(!$len){
$this->writeInteger(0x01);
return $this;
}
$ref = array_search($string, $this->_referenceStrings, true);
if($ref === false){
$this->_referenceStrings[] = $string;
$this->writeBinaryString($string);
} else {
$ref <<= 1;
$this->writeInteger($ref);
}
return $this;
}
/**
* Send ByteArray to output stream
*
* @param string|Zend_Amf_Value_ByteArray $data
* @return Zend_Amf_Parse_Amf3_Serializer
*/
public function writeByteArray($data){
if($this->writeObjectReference($data)){
return $this;
}
if(is_string($data)) {
//nothing to do
} else if ($data instanceof Zend_Amf_Value_ByteArray) {
$data = $data->getData();
} else {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Invalid ByteArray specified; must be a string or Zend_Amf_Value_ByteArray');
}
$this->writeBinaryString($data);
return $this;
}
/**
* Send xml to output stream
*
* @param DOMDocument|SimpleXMLElement $xml
* @return Zend_Amf_Parse_Amf3_Serializer
*/
public function writeXml($xml)
{
if($this->writeObjectReference($xml)){
return $this;
}
if(is_string($xml)) {
//nothing to do
} else if ($xml instanceof DOMDocument) {
$xml = $xml->saveXml();
} else if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
} else {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Invalid xml specified; must be a DOMDocument or SimpleXMLElement');
}
$this->writeBinaryString($xml);
return $this;
}
@@ -186,6 +293,10 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeDate($date)
{
if($this->writeObjectReference($date)){
return $this;
}
if ($date instanceof DateTime) {
$dateString = $date->format('U') * 1000;
} elseif ($date instanceof Zend_Date) {
@@ -209,6 +320,10 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeArray(array $array)
{
if($this->writeObjectReference($array)){
return $this;
}
// have to seperate mixed from numberic keys.
$numeric = array();
$string = array();
@@ -238,6 +353,25 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
}
return $this;
}
/**
* Check if the given object is in the reference table, write the reference if it exists,
* otherwise add the object to the reference table
*
* @param mixed $object object to check for reference
* @return Boolean true, if the reference was written, false otherwise
*/
protected function writeObjectReference($object){
$ref = array_search($object, $this->_referenceObjects,true);
//quickly handle object references
if($ref !== false){
$ref <<= 1;
$this->writeInteger($ref);
return true;
}
$this->_referenceObjects[] = $object;
return false;
}
/**
* Write object to ouput stream
@@ -247,7 +381,10 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeObject($object)
{
$encoding = Zend_Amf_Constants::ET_PROPLIST;
if($this->writeObjectReference($object)){
return $this;
}
$className = '';
//Check to see if the object is a typed object and we need to change
@@ -259,7 +396,6 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
// Check to see if the user has defined an explicit Action Script type.
case isset($object->_explicitType):
$className = $object->_explicitType;
unset($object->_explicitType);
break;
// Check if user has defined a method for accessing the Action Script type
@@ -268,36 +404,87 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
break;
// No return class name is set make it a generic object
case ($object instanceof stdClass):
$className = '';
break;
// By default, use object's class name
default:
$className = get_class($object);
break;
}
$traitsInfo = Zend_Amf_Constants::AMF3_OBJECT_ENCODING;
$traitsInfo |= $encoding << 2;
$writeTraits = true;
//check to see, if we have a corresponding definition
if(array_key_exists($className, $this->_referenceDefinitions)){
$traitsInfo = $this->_referenceDefinitions[$className]['id'];
$encoding = $this->_referenceDefinitions[$className]['encoding'];
$propertyNames = $this->_referenceDefinitions[$className]['propertyNames'];
$traitsInfo = ($traitsInfo << 2) | 0x01;
$writeTraits = false;
} else {
$propertyNames = array();
if($className == ''){
//if there is no className, we interpret the class as dynamic without any sealed members
$encoding = Zend_Amf_Constants::ET_DYNAMIC;
} else {
$encoding = Zend_Amf_Constants::ET_PROPLIST;
foreach($object as $key => $value) {
if( $key[0] != "_") {
$propertyNames[] = $key;
}
}
}
$this->_referenceDefinitions[$className] = array(
'id' => count($this->_referenceDefinitions),
'encoding' => $encoding,
'propertyNames' => $propertyNames,
);
$traitsInfo = Zend_Amf_Constants::AMF3_OBJECT_ENCODING;
$traitsInfo |= $encoding << 2;
$traitsInfo |= (count($propertyNames) << 4);
}
$this->writeInteger($traitsInfo);
if($writeTraits){
$this->writeString($className);
foreach ($propertyNames as $value) {
$this->writeString($value);
}
}
try {
switch($encoding) {
case Zend_Amf_Constants::ET_PROPLIST:
$count = 0;
foreach($object as $key => $value) {
$count++;
//Write the sealed values to the output stream.
foreach ($propertyNames as $key) {
$this->writeTypeMarker($object->$key);
}
$traitsInfo |= ($count << 4);
// Write the object ID
$this->writeInteger($traitsInfo);
// Write the classname
$this->writeString($className);
// Write the object Key's to the output stream
foreach ($object as $key => $value) {
$this->writeString($key);
break;
case Zend_Amf_Constants::ET_DYNAMIC:
//Write the sealed values to the output stream.
foreach ($propertyNames as $key) {
$this->writeTypeMarker($object->$key);
}
//Write the object values to the output stream.
foreach ($object as $key => $value) {
$this->writeTypeMarker($value);
//Write remaining properties
foreach($object as $key => $value){
if(!in_array($key,$propertyNames) && $key[0] != "_"){
$this->writeString($key);
$this->writeTypeMarker($value);
}
}
//Write an empty string to end the dynamic part
$this->writeString('');
break;
case Zend_Amf_Constants::ET_EXTERNAL:
require_once 'Zend/Amf/Exception.php';
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -29,7 +30,7 @@
* @see http://opensource.adobe.com/svn/opensource/blazeds/trunk/modules/core/src/java/flex/messaging/io/amf/
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Parse_Deserializer
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Util_BinaryStream */
@@ -30,7 +31,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
*
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_InputStream extends Zend_Amf_Util_BinaryStream
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Util_BinaryStream */
@@ -31,7 +32,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
* @uses Zend_Amf_Util_BinaryStream
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_OutputStream extends Zend_Amf_Util_BinaryStream
+70
View File
@@ -0,0 +1,70 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* This class will convert mysql result resource to array suitable for passing
* to the external entities.
*
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_MysqlResult
{
/**
* @var array List of Mysql types with PHP counterparts
*
* Key => Value is Mysql type (exact string) => PHP type
*/
static public $fieldTypes = array(
"int" => "int",
"timestamp" => "int",
"year" => "int",
"real" => "float",
);
/**
* Parse resource into array
*
* @param resource $resource
* @return array
*/
public function parse($resource) {
$result = array();
$fieldcnt = mysql_num_fields($resource);
$fields_transform = array();
for($i=0;$i<$fieldcnt;$i++) {
$type = mysql_field_type($resource, $i);
if(isset(self::$fieldTypes[$type])) {
$fields_transform[mysql_field_name($resource, $i)] = self::$fieldTypes[$type];
}
}
while($row = mysql_fetch_object($resource)) {
foreach($fields_transform as $fieldname => $fieldtype) {
settype($row->$fieldname, $fieldtype);
}
$result[] = $row;
}
return $result;
}
}
@@ -0,0 +1,128 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* This class will convert mysql result resource to array suitable for passing
* to the external entities.
*
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_MysqliResult
{
/**
* mapping taken from http://forums.mysql.com/read.php?52,255868,255895#msg-255895
*/
static public $mysqli_type = array(
0 => "MYSQLI_TYPE_DECIMAL",
1 => "MYSQLI_TYPE_TINYINT",
2 => "MYSQLI_TYPE_SMALLINT",
3 => "MYSQLI_TYPE_INTEGER",
4 => "MYSQLI_TYPE_FLOAT",
5 => "MYSQLI_TYPE_DOUBLE",
7 => "MYSQLI_TYPE_TIMESTAMP",
8 => "MYSQLI_TYPE_BIGINT",
9 => "MYSQLI_TYPE_MEDIUMINT",
10 => "MYSQLI_TYPE_DATE",
11 => "MYSQLI_TYPE_TIME",
12 => "MYSQLI_TYPE_DATETIME",
13 => "MYSQLI_TYPE_YEAR",
14 => "MYSQLI_TYPE_DATE",
16 => "MYSQLI_TYPE_BIT",
246 => "MYSQLI_TYPE_DECIMAL",
247 => "MYSQLI_TYPE_ENUM",
248 => "MYSQLI_TYPE_SET",
249 => "MYSQLI_TYPE_TINYBLOB",
250 => "MYSQLI_TYPE_MEDIUMBLOB",
251 => "MYSQLI_TYPE_LONGBLOB",
252 => "MYSQLI_TYPE_BLOB",
253 => "MYSQLI_TYPE_VARCHAR",
254 => "MYSQLI_TYPE_CHAR",
255 => "MYSQLI_TYPE_GEOMETRY",
);
// Build an associative array for a type look up
static $mysqli_to_php = array(
"MYSQLI_TYPE_DECIMAL" => 'float',
"MYSQLI_TYPE_NEWDECIMAL" => 'float',
"MYSQLI_TYPE_BIT" => 'integer',
"MYSQLI_TYPE_TINYINT" => 'integer',
"MYSQLI_TYPE_SMALLINT" => 'integer',
"MYSQLI_TYPE_MEDIUMINT" => 'integer',
"MYSQLI_TYPE_BIGINT" => 'integer',
"MYSQLI_TYPE_INTEGER" => 'integer',
"MYSQLI_TYPE_FLOAT" => 'float',
"MYSQLI_TYPE_DOUBLE" => 'float',
"MYSQLI_TYPE_NULL" => 'null',
"MYSQLI_TYPE_TIMESTAMP" => 'string',
"MYSQLI_TYPE_INT24" => 'integer',
"MYSQLI_TYPE_DATE" => 'string',
"MYSQLI_TYPE_TIME" => 'string',
"MYSQLI_TYPE_DATETIME" => 'string',
"MYSQLI_TYPE_YEAR" => 'string',
"MYSQLI_TYPE_NEWDATE" => 'string',
"MYSQLI_TYPE_ENUM" => 'string',
"MYSQLI_TYPE_SET" => 'string',
"MYSQLI_TYPE_TINYBLOB" => 'object',
"MYSQLI_TYPE_MEDIUMBLOB" => 'object',
"MYSQLI_TYPE_LONGBLOB" => 'object',
"MYSQLI_TYPE_BLOB" => 'object',
"MYSQLI_TYPE_CHAR" => 'string',
"MYSQLI_TYPE_VARCHAR" => 'string',
"MYSQLI_TYPE_GEOMETRY" => 'object',
"MYSQLI_TYPE_BIT" => 'integer',
);
/**
* Parse resource into array
*
* @param resource $resource
* @return array
*/
public function parse($resource) {
$result = array();
$fieldcnt = mysqli_num_fields($resource);
$fields_transform = array();
for($i=0;$i<$fieldcnt;$i++) {
$finfo = mysqli_fetch_field_direct($resource, $i);
if(isset(self::$mysqli_type[$finfo->type])) {
$fields_transform[$finfo->name] = self::$mysqli_to_php[self::$mysqli_type[$finfo->type]];
}
}
while($row = mysqli_fetch_assoc($resource)) {
foreach($fields_transform as $fieldname => $fieldtype) {
settype($row[$fieldname], $fieldtype);
}
$result[] = $row;
}
return $result;
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* This class will convert stream resource to string by just reading it
*
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_Stream
{
/**
* Parse resource into string
*
* @param resource $resource Stream resource
* @return array
*/
public function parse($resource) {
return stream_get_contents($resource);
}
}
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -24,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Parse_Serializer
+105 -7
View File
@@ -15,14 +15,30 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Amf_Value_Messaging_AcknowledgeMessage
*/
require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
/**
* @see Zend_Amf_Value_Messaging_AsyncMessage
*/
require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
/**
* @see Zend_Amf_Value_Messaging_CommandMessage
*/
require_once 'Zend/Amf/Value/Messaging/CommandMessage.php';
/**
* @see Zend_Amf_Value_Messaging_ErrorMessage
*/
require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
/**
* @see Zend_Amf_Value_Messaging_RemotingMessage
*/
require_once 'Zend/Amf/Value/Messaging/RemotingMessage.php';
/**
@@ -31,7 +47,7 @@ require_once 'Zend/Amf/Value/Messaging/RemotingMessage.php';
* @todo PHP 5.3 can drastically change this class w/ namespace and the new call_user_func w/ namespace
* @package Zend_Amf
* @subpackage Parse
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
final class Zend_Amf_Parse_TypeLoader
@@ -50,6 +66,7 @@ final class Zend_Amf_Parse_TypeLoader
'flex.messaging.messages.CommandMessage' => 'Zend_Amf_Value_Messaging_CommandMessage',
'flex.messaging.messages.ErrorMessage' => 'Zend_Amf_Value_Messaging_ErrorMessage',
'flex.messaging.messages.RemotingMessage' => 'Zend_Amf_Value_Messaging_RemotingMessage',
'flex.messaging.io.ArrayCollection' => 'Zend_Amf_Value_Messaging_ArrayCollection',
);
/**
@@ -61,7 +78,14 @@ final class Zend_Amf_Parse_TypeLoader
'flex.messaging.messages.CommandMessage' => 'Zend_Amf_Value_Messaging_CommandMessage',
'flex.messaging.messages.ErrorMessage' => 'Zend_Amf_Value_Messaging_ErrorMessage',
'flex.messaging.messages.RemotingMessage' => 'Zend_Amf_Value_Messaging_RemotingMessage',
'flex.messaging.io.ArrayCollection' => 'Zend_Amf_Value_Messaging_ArrayCollection',
);
/**
* @var Zend_Loader_PluginLoader_Interface
*/
protected static $_resourceLoader = null;
/**
* Load the mapped class type into a callback.
@@ -71,14 +95,13 @@ final class Zend_Amf_Parse_TypeLoader
*/
public static function loadType($className)
{
$class = false;
$callBack = false;
$class = self::getMappedClassName($className);
if(!$class) {
$class = str_replace('.', '_', $className);
}
if (!class_exists($class)) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception($className .' mapped class '. $class . ' is not defined');
return "stdClass";
}
return $class;
}
@@ -130,4 +153,79 @@ final class Zend_Amf_Parse_TypeLoader
{
self::$classMap = self::$_defaultClassMap;
}
/**
* Set loader for resource type handlers
*
* @param Zend_Loader_PluginLoader_Interface $loader
*/
public static function setResourceLoader(Zend_Loader_PluginLoader_Interface $loader)
{
self::$_resourceLoader = $loader;
}
/**
* Add directory to the list of places where to look for resource handlers
*
* @param string $prefix
* @param string $dir
*/
public static function addResourceDirectory($prefix, $dir)
{
if(self::$_resourceLoader) {
self::$_resourceLoader->addPrefixPath($prefix, $dir);
}
}
/**
* Get plugin class that handles this resource
*
* @param resource $resource Resource type
* @return string Class name
*/
public static function getResourceParser($resource)
{
if(self::$_resourceLoader) {
$type = preg_replace("/[^A-Za-z0-9_]/", " ", get_resource_type($resource));
$type = str_replace(" ","", ucwords($type));
return self::$_resourceLoader->load($type);
}
return false;
}
/**
* Convert resource to a serializable object
*
* @param resource $resource
* @return mixed
*/
public static function handleResource($resource)
{
if(!self::$_resourceLoader) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unable to handle resources - resource plugin loader not set');
}
try {
while(is_resource($resource)) {
$resclass = self::getResourceParser($resource);
if(!$resclass) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Can not serialize resource type: '. get_resource_type($resource));
}
$parser = new $resclass();
if(is_callable(array($parser, 'parse'))) {
$resource = $parser->parse($resource);
} else {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception("Could not call parse() method on class $resclass");
}
}
return $resource;
} catch(Zend_Amf_Exception $e) {
throw $e;
} catch(Exception $e) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Can not serialize resource type: '. get_resource_type($resource));
}
}
}
+6 -4
View File
@@ -14,8 +14,9 @@
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Parse_InputStream */
@@ -39,7 +40,7 @@ require_once 'Zend/Amf/Value/MessageBody.php';
*
* @todo Currently not checking if the object needs to be Type Mapped to a server object.
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Request
@@ -89,7 +90,7 @@ class Zend_Amf_Request
public function initialize($request)
{
$this->_inputStream = new Zend_Amf_Parse_InputStream($request);
$this->_deserializer = new Zend_Amf_Parse_AMF0_Deserializer($this->_inputStream);
$this->_deserializer = new Zend_Amf_Parse_Amf0_Deserializer($this->_inputStream);
$this->readMessage($this->_inputStream);
return $this;
}
@@ -105,6 +106,7 @@ class Zend_Amf_Request
$clientVersion = $stream->readUnsignedShort();
if (($clientVersion != Zend_Amf_Constants::AMF0_OBJECT_ENCODING)
&& ($clientVersion != Zend_Amf_Constants::AMF3_OBJECT_ENCODING)
&& ($clientVersion != Zend_Amf_Constants::FMS_OBJECT_ENCODING)
) {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unknown Player Version ' . $clientVersion);
@@ -181,7 +183,7 @@ class Zend_Amf_Request
* an AMF0 array called Content. The following code gets the object
* out of the content array and sets it as the message data.
*/
if(is_array($data) && is_object($data[0])){
if(is_array($data) && $data[0] instanceof Zend_Amf_Value_Messaging_AbstractMessage){
$data = $data[0];
}
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Request
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Request */
@@ -31,7 +32,7 @@ require_once 'Zend/Amf/Request.php';
*
* @package Zend_Amf
* @subpackage Request
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Request_Http extends Zend_Amf_Request
+3 -2
View File
@@ -14,8 +14,9 @@
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Constants */
@@ -31,7 +32,7 @@ require_once 'Zend/Amf/Parse/Amf0/Serializer.php';
* Handles converting the PHP object ready for response back into AMF
*
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Response
+5 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Response
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Response */
@@ -27,7 +28,7 @@ require_once 'Zend/Amf/Response.php';
*
* @package Zend_Amf
* @subpackage Response
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Response_Http extends Zend_Amf_Response
@@ -40,6 +41,8 @@ class Zend_Amf_Response_Http extends Zend_Amf_Response
public function getResponse()
{
if (!headers_sent()) {
header('Cache-Control: cache, must-revalidate');
header('Pragma: public');
header('Content-Type: application/x-amf');
}
return parent::getResponse();
+363 -57
View File
@@ -14,8 +14,9 @@
*
* @category Zend
* @package Zend_Amf
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Server_Interface */
@@ -30,17 +31,28 @@ require_once 'Zend/Amf/Constants.php';
/** Zend_Amf_Value_MessageBody */
require_once 'Zend/Amf/Value/MessageBody.php';
/** Zend_Amf_Value_MessageHeader */
require_once 'Zend/Amf/Value/MessageHeader.php';
/** Zend_Amf_Value_Messaging_CommandMessage */
require_once 'Zend/Amf/Value/Messaging/CommandMessage.php';
/** Zend_Loader_PluginLoader */
require_once 'Zend/Loader/PluginLoader.php';
/** Zend_Amf_Parse_TypeLoader */
require_once 'Zend/Amf/Parse/TypeLoader.php';
/** Zend_Auth */
require_once 'Zend/Auth.php';
/**
* An AMF gateway server implementation to allow the connection of the Adobe Flash Player to
* the Zend Framework
* Zend Framework
*
* @todo Make the relection methods cache and autoload.
* @package Zend_Amf
* @subpackage Server
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Server implements Zend_Server_Interface
@@ -50,12 +62,21 @@ class Zend_Amf_Server implements Zend_Server_Interface
* @var array
*/
protected $_methods = array();
/**
* Array of directories to search for loading classes dynamically
* Array of classes that can be called without being explicitly loaded
*
* Keys are class names.
*
* @var array
*/
protected $_directories = array();
protected $_classAllowed = array();
/**
* Loader for classes in added directories
* @var Zend_Loader_PluginLoader
*/
protected $_loader;
/**
* @var bool Production flag; whether or not to return exception messages
@@ -80,6 +101,86 @@ class Zend_Amf_Server implements Zend_Server_Interface
*/
protected $_table = array();
/**
*
* @var bool session flag; whether or not to add a session to each response.
*/
protected $_session = false;
/**
* Namespace allows all AMF calls to not clobber other php session variables
* @var Zend_Session_NameSpace default session namespace zend_amf
*/
protected $_sesionNamespace = 'zend_amf';
/**
* Set the default session.name if php_
* @var string
*/
protected $_sessionName = 'PHPSESSID';
/**
* Authentication handler object
*
* @var Zend_Amf_Auth_Abstract
*/
protected $_auth;
/**
* ACL handler object
*
* @var Zend_Acl
*/
protected $_acl;
/**
* The server constructor
*/
public function __construct()
{
Zend_Amf_Parse_TypeLoader::setResourceLoader(new Zend_Loader_PluginLoader(array("Zend_Amf_Parse_Resource" => "Zend/Amf/Parse/Resource")));
}
/**
* Set authentication adapter
*
* @param Zend_Amf_Auth_Abstract $auth
* @return Zend_Amf_Server
*/
public function setAuth(Zend_Amf_Auth_Abstract $auth)
{
$this->_auth = $auth;
return $this;
}
/**
* Get authentication adapter
*
* @return Zend_Amf_Auth_Abstract
*/
public function getAuth()
{
return $this->_auth;
}
/**
* Set ACL adapter
*
* @param Zend_Acl $acl
* @return Zend_Amf_Server
*/
public function setAcl(Zend_Acl $acl)
{
$this->_acl = $acl;
return $this;
}
/**
* Get ACL adapter
*
* @return Zend_Acl
*/
public function getAcl()
{
return $this->_acl;
}
/**
* Set production flag
*
@@ -102,7 +203,87 @@ class Zend_Amf_Server implements Zend_Server_Interface
return $this->_production;
}
/**
* @param namespace of all incoming sessions defaults to Zend_Amf
* @return Zend_Amf_Server
*/
public function setSession($namespace = 'Zend_Amf')
{
require_once 'Zend/Session.php';
$this->_session = true;
$this->_sesionNamespace = new Zend_Session_Namespace($namespace);
return $this;
}
/**
* Whether of not the server is using sessions
* @return bool
*/
public function isSession()
{
return $this->_session;
}
/**
* Check if the ACL allows accessing the function or method
*
* @param string|object $object Object or class being accessed
* @param string $function Function or method being acessed
* @return unknown_type
*/
protected function _checkAcl($object, $function)
{
if(!$this->_acl) {
return true;
}
if($object) {
$class = is_object($object)?get_class($object):$object;
if(!$this->_acl->has($class)) {
require_once 'Zend/Acl/Resource.php';
$this->_acl->add(new Zend_Acl_Resource($class));
}
$call = array($object, "initAcl");
if(is_callable($call) && !call_user_func($call, $this->_acl)) {
// if initAcl returns false, no ACL check
return true;
}
} else {
$class = null;
}
$auth = Zend_Auth::getInstance();
if($auth->hasIdentity()) {
$role = $auth->getIdentity()->role;
} else {
if($this->_acl->hasRole(Zend_Amf_Constants::GUEST_ROLE)) {
$role = Zend_Amf_Constants::GUEST_ROLE;
} else {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception("Unauthenticated access not allowed");
}
}
if($this->_acl->isAllowed($role, $class, $function)) {
return true;
} else {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception("Access not allowed");
}
}
/**
* Get PluginLoader for the Server
*
* @return Zend_Loader_PluginLoader
*/
protected function getLoader()
{
if(empty($this->_loader)) {
require_once 'Zend/Loader/PluginLoader.php';
$this->_loader = new Zend_Loader_PluginLoader();
}
return $this->_loader;
}
/**
* Loads a remote class or method and executes the function and returns
* the result
@@ -114,42 +295,45 @@ class Zend_Amf_Server implements Zend_Server_Interface
*/
protected function _dispatch($method, $params = null, $source = null)
{
if (!isset($this->_table[$method])) {
if($source) {
if(($mapped = Zend_Amf_Parse_TypeLoader::getMappedClassName($source)) !== false) {
$source = $mapped;
}
}
$qualifiedName = empty($source) ? $method : $source.".".$method;
if (!isset($this->_table[$qualifiedName])) {
// if source is null a method that was not defined was called.
if ($source) {
$classPath = array();
$path = explode('.', $source);
$className = array_pop($path);
$uriclasspath = implode('/', $path);
// Take the user supplied directories and add the unique service path to the end.
foreach ($this->_directories as $dir) {
$classPath[] = $dir . $uriclasspath;
}
require_once('Zend/Loader.php');
$className = str_replace(".", "_", $source);
if(class_exists($className, false) && !isset($this->_classAllowed[$className])) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()');
}
try {
Zend_Loader::loadClass($className, $classPath);
$this->getLoader()->load($className);
} catch (Exception $e) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist');
throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage());
}
// Add the new loaded class to the server.
$this->setClass($className);
$this->setClass($className, $source);
} else {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist');
}
}
$info = $this->_table[$method];
$info = $this->_table[$qualifiedName];
$argv = $info->getInvokeArguments();
if (0 < count($argv)) {
$params = array_merge($params, $argv);
}
if ($info instanceof Zend_Server_Reflection_Function) {
$func = $info->getName();
$this->_checkAcl(null, $func);
$return = call_user_func_array($func, $params);
} elseif ($info instanceof Zend_Server_Reflection_Method) {
// Get class
@@ -158,6 +342,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
// for some reason, invokeArgs() does not work the same as
// invoke(), and expects the first argument to be an object.
// So, using a callback if the method is static.
$this->_checkAcl($class, $info->getName());
$return = call_user_func_array(array($class, $info->getName()), $params);
} else {
// Object methods
@@ -165,8 +350,9 @@ class Zend_Amf_Server implements Zend_Server_Interface
$object = $info->getDeclaringClass()->newInstance();
} catch (Exception $e) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName(), 621);
throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName() . ': '.$e->getMessage(), 621);
}
$this->_checkAcl($object, $info->getName());
$return = $info->invokeArgs($object, $params);
}
} else {
@@ -188,9 +374,30 @@ class Zend_Amf_Server implements Zend_Server_Interface
*/
protected function _loadCommandMessage(Zend_Amf_Value_Messaging_CommandMessage $message)
{
require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
switch($message->operation) {
case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION :
require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
case Zend_Amf_Value_Messaging_CommandMessage::DISCONNECT_OPERATION :
case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION :
$return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
break;
case Zend_Amf_Value_Messaging_CommandMessage::LOGIN_OPERATION :
$data = explode(':', base64_decode($message->body));
$userid = $data[0];
$password = isset($data[1])?$data[1]:"";
if(empty($userid)) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Login failed: username not supplied');
}
if(!$this->_handleAuth($userid, $password)) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Authentication failed');
}
$return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
break;
case Zend_Amf_Value_Messaging_CommandMessage::LOGOUT_OPERATION :
if($this->_auth) {
Zend_Auth::getInstance()->clearIdentity();
}
$return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
break;
default :
@@ -201,11 +408,74 @@ class Zend_Amf_Server implements Zend_Server_Interface
return $return;
}
/**
* Create appropriate error message
*
* @param int $objectEncoding Current AMF encoding
* @param string $message Message that was being processed when error happened
* @param string $description Error description
* @param mixed $detail Detailed data about the error
* @param int $code Error code
* @param int $line Error line
* @return Zend_Amf_Value_Messaging_ErrorMessage|array
*/
protected function _errorMessage($objectEncoding, $message, $description, $detail, $code, $line)
{
$return = null;
switch ($objectEncoding) {
case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
return array (
'description' => ($this->isProduction ()) ? '' : $description,
'detail' => ($this->isProduction ()) ? '' : $detail,
'line' => ($this->isProduction ()) ? 0 : $line,
'code' => $code
);
case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
$return = new Zend_Amf_Value_Messaging_ErrorMessage ( $message );
$return->faultString = $this->isProduction () ? '' : $description;
$return->faultCode = $code;
$return->faultDetail = $this->isProduction () ? '' : $detail;
break;
}
return $return;
}
/**
* Handle AMF authenticaton
*
* @param string $userid
* @param string $password
* @return boolean
*/
protected function _handleAuth( $userid, $password)
{
if (!$this->_auth) {
return true;
}
$this->_auth->setCredentials($userid, $password);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($this->_auth);
if ($result->isValid()) {
if (!$this->isSession()) {
$this->setSession();
}
return true;
} else {
// authentication failed, good bye
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception(
"Authentication failed: " . join("\n",
$result->getMessages()), $result->getCode());
}
}
/**
* Takes the deserialized AMF request and performs any operations.
*
* @todo should implement and SPL observer pattern for custom AMF headers
* @todo implement AMF header authentication
* @todo DescribeService support
* @param Zend_Amf_Request $request
* @return Zend_Amf_Response
* @throws Zend_Amf_server_Exception|Exception
@@ -220,16 +490,42 @@ class Zend_Amf_Server implements Zend_Server_Interface
// set reponse encoding
$response->setObjectEncoding($objectEncoding);
$responseBody = $request->getAmfBodies();
$handleAuth = false;
if ($this->_auth) {
$headers = $request->getAmfHeaders();
if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) &&
isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
$handleAuth = true;
}
}
// Iterate through each of the service calls in the AMF request
foreach($responseBody as $body)
{
try {
if ($handleAuth) {
if ($this->_handleAuth(
$headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
$headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) {
// use RequestPersistentHeader to clear credentials
$response->addAmfHeader(
new Zend_Amf_Value_MessageHeader(
Zend_Amf_Constants::PERSISTENT_HEADER,
false,
new Zend_Amf_Value_MessageHeader(
Zend_Amf_Constants::CREDENTIALS_HEADER,
false, null)));
$handleAuth = false;
}
}
if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) {
// AMF0 Object Encoding
$targetURI = $body->getTargetURI();
$message = '';
// Split the target string into its values.
$source = substr($targetURI, 0, strrpos($targetURI, '.'));
@@ -262,7 +558,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
if ($source) {
// Break off method name from namespace into source
$method = substr(strrchr($targetURI, '.'), 1);
$return = $this->_dispatch($method, array($body->getData()), $source);
$return = $this->_dispatch($method, $body->getData(), $source);
} else {
// Just have a method name.
$return = $this->_dispatch($targetURI, $body->getData());
@@ -271,23 +567,8 @@ class Zend_Amf_Server implements Zend_Server_Interface
}
$responseType = Zend_AMF_Constants::RESULT_METHOD;
} catch (Exception $e) {
switch ($objectEncoding) {
case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
$return = array(
'description' => ($this->isProduction()) ? '' : $e->getMessage(),
'detail' => ($this->isProduction()) ? '' : $e->getTraceAsString(),
'line' => ($this->isProduction()) ? 0 : $e->getLine(),
'code' => $e->getCode(),
);
break;
case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
$return = new Zend_Amf_Value_Messaging_ErrorMessage($message);
$return->faultString = $this->isProduction() ? '' : $e->getMessage();
$return->faultCode = $e->getCode();
$return->faultDetail = $this->isProduction() ? '' : $e->getTraceAsString();
break;
}
$return = $this->_errorMessage($objectEncoding, $message,
$e->getMessage(), $e->getTraceAsString(),$e->getCode(), $e->getLine());
$responseType = Zend_AMF_Constants::STATUS_METHOD;
}
@@ -295,6 +576,23 @@ class Zend_Amf_Server implements Zend_Server_Interface
$newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $return);
$response->addAmfBody($newBody);
}
// Add a session header to the body if session is requested.
if($this->isSession()) {
$currentID = session_id();
$joint = "?";
if(isset($_SERVER['QUERY_STRING'])) {
if(!strpos($_SERVER['QUERY_STRING'], $currentID) !== FALSE) {
if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE) {
$joint = "&";
}
}
}
// create a new AMF message header with the session id as a variable.
$sessionValue = $joint . $this->_sessionName . "=" . $currentID;
$sessionHeader = new Zend_Amf_Value_MessageHeader(Zend_Amf_Constants::URL_APPEND_HEADER, false, $sessionValue);
$response->addAmfHeader($sessionHeader);
}
// serialize the response and return serialized body.
$response->finalize();
@@ -314,6 +612,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
} else {
$this->setRequest($request);
}
if ($this->isSession()) {
// Check if a session is being sent from the amf call
if (isset($_COOKIE[$this->_sessionName])) {
session_id($_COOKIE[$this->_sessionName]);
}
}
// Check for errors that may have happend in deserialization of Request.
try {
@@ -404,15 +708,6 @@ class Zend_Amf_Server implements Zend_Server_Interface
return $this->_response;
}
/**
* Add a file system path to a directory of services.
* @param string|array $path
*/
public function setClassPath($path)
{
}
/**
* Attach a class or object to the server
*
@@ -443,6 +738,14 @@ class Zend_Amf_Server implements Zend_Server_Interface
$argv = array_slice(func_get_args(), 2);
}
// Use the class name as the name space by default.
if ($namespace == '') {
$namespace = is_object($class) ? get_class($class) : $class;
}
$this->_classAllowed[is_object($class) ? get_class($class) : $class] = true;
$this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
$this->_buildDispatchTable();
@@ -489,12 +792,13 @@ class Zend_Amf_Server implements Zend_Server_Interface
/**
* Creates an array of directories in which services can reside.
*
* TODO: add support for prefixes?
*
* @param string $dir
*/
public function addDirectory($dir)
{
$this->_directories[] = $dir;
$this->getLoader()->addPrefixPath("", $dir);
}
/**
@@ -504,7 +808,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
*/
public function getDirectory()
{
return $_directory;
return $this->getLoader()->getPaths("");
}
/**
@@ -550,6 +854,8 @@ class Zend_Amf_Server implements Zend_Server_Interface
$this->_table = $table;
}
/**
* Raise a server fault
*
+11 -9
View File
@@ -4,18 +4,20 @@
*
* LICENSE
*
* This source file is subject to version 1.0 of the Zend Framework
* license, that is bundled with this package in the file LICENSE.txt, and
* is available through the world-wide-web at the following URL:
* http://framework.zend.com/license/new-bsd. If you did not receive
* a copy of the Zend Framework license and are unable to obtain it
* through the world-wide-web, please send a note to [email protected]
* so we can mail you a copy immediately.
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Server
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Exception */
@@ -27,7 +29,7 @@ require_once 'Zend/Amf/Exception.php';
* @category Zend
* @package Zend_Amf
* @subpackage Server
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Server_Exception extends Zend_Amf_Exception
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Util
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -24,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Util
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Util_BinaryStream
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -24,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_ByteArray
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -32,7 +33,7 @@
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_MessageBody
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -27,7 +28,7 @@
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_MessageHeader
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -25,7 +26,7 @@
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AbstractMessage
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Value_Messaging_AsyncMessage */
@@ -31,7 +32,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AcknowledgeMessage extends Zend_Amf_Value_Messaging_AsyncMessage
@@ -52,7 +53,7 @@ class Zend_Amf_Value_Messaging_AcknowledgeMessage extends Zend_Amf_Value_Messagi
$this->body = null;
// correleate the two messages
if ($message) {
if ($message && isset($message->messageId)) {
$this->correlationId = $message->messageId;
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Type encapsulating Flex ArrayCollection
*
* Corresponds to flex.messaging.io.ArrayCollection
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_ArrayCollection
{
}
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -29,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AsyncMessage extends Zend_Amf_Value_Messaging_AbstractMessage
@@ -15,10 +15,14 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Amf_Value_Messaging_AsyncMessage
*/
require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
/**
@@ -32,7 +36,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_CommandMessage extends Zend_Amf_Value_Messaging_AsyncMessage
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Value_Messaging_AcknowledgeMessage */
@@ -29,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_ErrorMessage extends Zend_Amf_Value_Messaging_AcknowledgeMessage
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Amf_Value_Messaging_AbstractMessage */
@@ -30,7 +31,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_RemotingMessage extends Zend_Amf_Value_Messaging_AbstractMessage
+3 -2
View File
@@ -15,8 +15,9 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
@@ -24,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Value
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_TraitsInfo
@@ -0,0 +1,79 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Concrete base class for bootstrap classes
*
* Registers and utilizes Zend_Controller_Front by default.
*
* @uses Zend_Application_Bootstrap_Bootstrap
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Bootstrap_Bootstrap
extends Zend_Application_Bootstrap_BootstrapAbstract
{
/**
* Constructor
*
* Ensure FrontController resource is registered
*
* @param Zend_Application|Zend_Application_Bootstrap_Bootstrapper $application
* @return void
*/
public function __construct($application)
{
parent::__construct($application);
if (!$this->hasPluginResource('FrontController')) {
$this->registerPluginResource('FrontController');
}
}
/**
* Run the application
*
* Checks to see that we have a default controller directory. If not, an
* exception is thrown.
*
* If so, it registers the bootstrap with the 'bootstrap' parameter of
* the front controller, and dispatches the front controller.
*
* @return void
* @throws Zend_Application_Bootstrap_Exception
*/
public function run()
{
$front = $this->getResource('FrontController');
$default = $front->getDefaultModule();
if (null === $front->getControllerDirectory($default)) {
throw new Zend_Application_Bootstrap_Exception(
'No default controller directory registered with front controller'
);
}
$front->setParam('bootstrap', $this);
$front->dispatch();
}
}
@@ -0,0 +1,764 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Abstract base class for bootstrap classes
*
* @uses Zend_Application_Bootstrap_Bootstrapper
* @uses Zend_Application_Bootstrap_ResourceBootstrapper
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Application_Bootstrap_BootstrapAbstract
implements Zend_Application_Bootstrap_Bootstrapper,
Zend_Application_Bootstrap_ResourceBootstrapper
{
/**
* @var Zend_Application|Zend_Application_Bootstrap_Bootstrapper
*/
protected $_application;
/**
* @var array Internal resource methods (resource/method pairs)
*/
protected $_classResources;
/**
* @var object Resource container
*/
protected $_container;
/**
* @var string
*/
protected $_environment;
/**
* Flattened (lowercase) option keys used for lookups
*
* @var array
*/
protected $_optionKeys = array();
/**
* @var array
*/
protected $_options = array();
/**
* @var Zend_Loader_PluginLoader_Interface
*/
protected $_pluginLoader;
/**
* @var array Class-based resource plugins
*/
protected $_pluginResources = array();
/**
* @var array Initializers that have been run
*/
protected $_run = array();
/**
* @var array Initializers that have been started but not yet completed (circular dependency detection)
*/
protected $_started = array();
/**
* Constructor
*
* Sets application object, initializes options, and prepares list of
* initializer methods.
*
* @param Zend_Application|Zend_Application_Bootstrap_Bootstrapper $application
* @return void
* @throws Zend_Application_Bootstrap_Exception When invalid applicaiton is provided
*/
public function __construct($application)
{
$this->setApplication($application);
$options = $application->getOptions();
$this->setOptions($options);
}
/**
* Set class state
*
* @param array $options
* @return Zend_Application_Bootstrap_BootstrapAbstract
*/
public function setOptions(array $options)
{
$this->_options = $this->mergeOptions($this->_options, $options);
$options = array_change_key_case($options, CASE_LOWER);
$this->_optionKeys = array_merge($this->_optionKeys, array_keys($options));
$methods = get_class_methods($this);
foreach ($methods as $key => $method) {
$methods[$key] = strtolower($method);
}
if (array_key_exists('pluginpaths', $options)) {
$pluginLoader = $this->getPluginLoader();
foreach ($options['pluginpaths'] as $prefix => $path) {
$pluginLoader->addPrefixPath($prefix, $path);
}
unset($options['pluginpaths']);
}
foreach ($options as $key => $value) {
$method = 'set' . strtolower($key);
if (in_array($method, $methods)) {
$this->$method($value);
} elseif ('resources' == $key) {
foreach ($value as $resource => $resourceOptions) {
$this->registerPluginResource($resource, $resourceOptions);
}
}
}
return $this;
}
/**
* Get current options from bootstrap
*
* @return array
*/
public function getOptions()
{
return $this->_options;
}
/**
* Is an option present?
*
* @param string $key
* @return bool
*/
public function hasOption($key)
{
return in_array($key, $this->_optionKeys);
}
/**
* Retrieve a single option
*
* @param string $key
* @return mixed
*/
public function getOption($key)
{
if ($this->hasOption($key)) {
$options = $this->getOptions();
$options = array_change_key_case($options, CASE_LOWER);
return $options[strtolower($key)];
}
return null;
}
/**
* Merge options recursively
*
* @param array $array1
* @param mixed $array2
* @return array
*/
public function mergeOptions(array $array1, $array2 = null)
{
if (is_array($array2)) {
foreach ($array2 as $key => $val) {
if (is_array($array2[$key])) {
$array1[$key] = (array_key_exists($key, $array1) && is_array($array1[$key]))
? $this->mergeOptions($array1[$key], $array2[$key])
: $array2[$key];
} else {
$array1[$key] = $val;
}
}
}
return $array1;
}
/**
* Get class resources (as resource/method pairs)
*
* Uses get_class_methods() by default, reflection on prior to 5.2.6,
* as a bug prevents the usage of get_class_methods() there.
*
* @return array
*/
public function getClassResources()
{
if (null === $this->_classResources) {
if (version_compare(PHP_VERSION, '5.2.6') === -1) {
$class = new ReflectionObject($this);
$classMethods = $class->getMethods();
$methodNames = array();
foreach ($classMethods as $method) {
$methodNames[] = $method->getName();
}
} else {
$methodNames = get_class_methods($this);
}
$this->_classResources = array();
foreach ($methodNames as $method) {
if (5 < strlen($method) && '_init' === substr($method, 0, 5)) {
$this->_classResources[strtolower(substr($method, 5))] = $method;
}
}
}
return $this->_classResources;
}
/**
* Get class resource names
*
* @return array
*/
public function getClassResourceNames()
{
$resources = $this->getClassResources();
return array_keys($resources);
}
/**
* Register a new resource plugin
*
* @param string|Zend_Application_Resource_Resource $resource
* @param mixed $options
* @return Zend_Application_Bootstrap_BootstrapAbstract
* @throws Zend_Application_Bootstrap_Exception When invalid resource is provided
*/
public function registerPluginResource($resource, $options = null)
{
if ($resource instanceof Zend_Application_Resource_Resource) {
$resource->setBootstrap($this);
$pluginName = $this->_resolvePluginResourceName($resource);
$this->_pluginResources[$pluginName] = $resource;
return $this;
}
if (!is_string($resource)) {
throw new Zend_Application_Bootstrap_Exception('Invalid resource provided to ' . __METHOD__);
}
$this->_pluginResources[$resource] = $options;
return $this;
}
/**
* Unregister a resource from the bootstrap
*
* @param string|Zend_Application_Resource_Resource $resource
* @return Zend_Application_Bootstrap_BootstrapAbstract
* @throws Zend_Application_Bootstrap_Exception When unknown resource type is provided
*/
public function unregisterPluginResource($resource)
{
if ($resource instanceof Zend_Application_Resource_Resource) {
if ($index = array_search($resource, $this->_pluginResources, true)) {
unset($this->_pluginResources[$index]);
}
return $this;
}
if (!is_string($resource)) {
throw new Zend_Application_Bootstrap_Exception('Unknown resource type provided to ' . __METHOD__);
}
$resource = strtolower($resource);
if (array_key_exists($resource, $this->_pluginResources)) {
unset($this->_pluginResources[$resource]);
}
return $this;
}
/**
* Is the requested plugin resource registered?
*
* @param string $resource
* @return bool
*/
public function hasPluginResource($resource)
{
return (null !== $this->getPluginResource($resource));
}
/**
* Get a registered plugin resource
*
* @param string $resourceName
* @return Zend_Application_Resource_Resource
*/
public function getPluginResource($resource)
{
if (array_key_exists(strtolower($resource), $this->_pluginResources)) {
$resource = strtolower($resource);
if (!$this->_pluginResources[$resource] instanceof Zend_Application_Resource_Resource) {
$resourceName = $this->_loadPluginResource($resource, $this->_pluginResources[$resource]);
if (!$resourceName) {
throw new Zend_Application_Bootstrap_Exception(sprintf('Unable to resolve plugin "%s"; no corresponding plugin with that name', $resource));
}
$resource = $resourceName;
}
return $this->_pluginResources[$resource];
}
foreach ($this->_pluginResources as $plugin => $spec) {
if ($spec instanceof Zend_Application_Resource_Resource) {
$pluginName = $this->_resolvePluginResourceName($spec);
if (0 === strcasecmp($resource, $pluginName)) {
unset($this->_pluginResources[$plugin]);
$this->_pluginResources[$pluginName] = $spec;
return $spec;
}
continue;
}
if (false !== $pluginName = $this->_loadPluginResource($plugin, $spec)) {
if (0 === strcasecmp($resource, $pluginName)) {
return $this->_pluginResources[$pluginName];
}
}
if (class_exists($plugin)) {
$spec = (array) $spec;
$spec['bootstrap'] = $this;
$instance = new $plugin($spec);
$pluginName = $this->_resolvePluginResourceName($instance);
unset($this->_pluginResources[$plugin]);
$this->_pluginResources[$pluginName] = $instance;
if (0 === strcasecmp($resource, $pluginName)) {
return $instance;
}
}
}
return null;
}
/**
* Retrieve all plugin resources
*
* @return array
*/
public function getPluginResources()
{
foreach (array_keys($this->_pluginResources) as $resource) {
$this->getPluginResource($resource);
}
return $this->_pluginResources;
}
/**
* Retrieve plugin resource names
*
* @return array
*/
public function getPluginResourceNames()
{
$this->getPluginResources();
return array_keys($this->_pluginResources);
}
/**
* Set plugin loader for loading resources
*
* @param Zend_Loader_PluginLoader_Interface $loader
* @return Zend_Application_Bootstrap_BootstrapAbstract
*/
public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader)
{
$this->_pluginLoader = $loader;
return $this;
}
/**
* Get the plugin loader for resources
*
* @return Zend_Loader_PluginLoader_Interface
*/
public function getPluginLoader()
{
if ($this->_pluginLoader === null) {
$options = array(
'Zend_Application_Resource' => 'Zend/Application/Resource'
);
$this->_pluginLoader = new Zend_Loader_PluginLoader($options);
}
return $this->_pluginLoader;
}
/**
* Set application/parent bootstrap
*
* @param Zend_Application|Zend_Application_Bootstrap_Bootstrapper $application
* @return Zend_Application_Bootstrap_BootstrapAbstract
*/
public function setApplication($application)
{
if (($application instanceof Zend_Application)
|| ($application instanceof Zend_Application_Bootstrap_Bootstrapper)
) {
$this->_application = $application;
} else {
throw new Zend_Application_Bootstrap_Exception('Invalid application provided to bootstrap constructor (received "' . get_class($application) . '" instance)');
}
return $this;
}
/**
* Retrieve parent application instance
*
* @return Zend_Application|Zend_Application_Bootstrap_Bootstrapper
*/
public function getApplication()
{
return $this->_application;
}
/**
* Retrieve application environment
*
* @return string
*/
public function getEnvironment()
{
if (null === $this->_environment) {
$this->_environment = $this->getApplication()->getEnvironment();
}
return $this->_environment;
}
/**
* Set resource container
*
* By default, if a resource callback has a non-null return value, this
* value will be stored in a container using the resource name as the
* key.
*
* Containers must be objects, and must allow setting public properties.
*
* @param object $container
* @return Zend_Application_Bootstrap_BootstrapAbstract
*/
public function setContainer($container)
{
if (!is_object($container)) {
throw new Zend_Application_Bootstrap_Exception('Resource containers must be objects');
}
$this->_container = $container;
return $this;
}
/**
* Retrieve resource container
*
* @return object
*/
public function getContainer()
{
if (null === $this->_container) {
$this->setContainer(new Zend_Registry());
}
return $this->_container;
}
/**
* Determine if a resource has been stored in the container
*
* During bootstrap resource initialization, you may return a value. If
* you do, it will be stored in the {@link setContainer() container}.
* You can use this method to determine if a value was stored.
*
* @param string $name
* @return bool
*/
public function hasResource($name)
{
$resource = strtolower($name);
$container = $this->getContainer();
return isset($container->{$resource});
}
/**
* Retrieve a resource from the container
*
* During bootstrap resource initialization, you may return a value. If
* you do, it will be stored in the {@link setContainer() container}.
* You can use this method to retrieve that value.
*
* If no value was returned, this will return a null value.
*
* @param string $name
* @return null|mixed
*/
public function getResource($name)
{
$resource = strtolower($name);
$container = $this->getContainer();
if ($this->hasResource($resource)) {
return $container->{$resource};
}
return null;
}
/**
* Implement PHP's magic to retrieve a ressource
* in the bootstrap
*
* @param string $prop
* @return null|mixed
*/
public function __get($prop)
{
return $this->getResource($prop);
}
/**
* Implement PHP's magic to ask for the
* existence of a ressource in the bootstrap
*
* @param string $prop
* @return bool
*/
public function __isset($prop)
{
return $this->hasResource($prop);
}
/**
* Bootstrap individual, all, or multiple resources
*
* Marked as final to prevent issues when subclassing and naming the
* child class 'Bootstrap' (in which case, overriding this method
* would result in it being treated as a constructor).
*
* If you need to override this functionality, override the
* {@link _bootstrap()} method.
*
* @param null|string|array $resource
* @return Zend_Application_Bootstrap_BootstrapAbstract
* @throws Zend_Application_Bootstrap_Exception When invalid argument was passed
*/
final public function bootstrap($resource = null)
{
$this->_bootstrap($resource);
return $this;
}
/**
* Overloading: intercept calls to bootstrap<resourcename>() methods
*
* @param string $method
* @param array $args
* @return void
* @throws Zend_Application_Bootstrap_Exception On invalid method name
*/
public function __call($method, $args)
{
if (9 < strlen($method) && 'bootstrap' === substr($method, 0, 9)) {
$resource = substr($method, 9);
return $this->bootstrap($resource);
}
throw new Zend_Application_Bootstrap_Exception('Invalid method "' . $method . '"');
}
/**
* Bootstrap implementation
*
* This method may be overridden to provide custom bootstrapping logic.
* It is the sole method called by {@link bootstrap()}.
*
* @param null|string|array $resource
* @return void
* @throws Zend_Application_Bootstrap_Exception When invalid argument was passed
*/
protected function _bootstrap($resource = null)
{
if (null === $resource) {
foreach ($this->getClassResourceNames() as $resource) {
$this->_executeResource($resource);
}
foreach ($this->getPluginResourceNames() as $resource) {
$this->_executeResource($resource);
}
} elseif (is_string($resource)) {
$this->_executeResource($resource);
} elseif (is_array($resource)) {
foreach ($resource as $r) {
$this->_executeResource($r);
}
} else {
throw new Zend_Application_Bootstrap_Exception('Invalid argument passed to ' . __METHOD__);
}
}
/**
* Execute a resource
*
* Checks to see if the resource has already been run. If not, it searches
* first to see if a local method matches the resource, and executes that.
* If not, it checks to see if a plugin resource matches, and executes that
* if found.
*
* Finally, if not found, it throws an exception.
*
* @param string $resource
* @return void
* @throws Zend_Application_Bootstrap_Exception When resource not found
*/
protected function _executeResource($resource)
{
$resourceName = strtolower($resource);
if (in_array($resourceName, $this->_run)) {
return;
}
if (isset($this->_started[$resourceName]) && $this->_started[$resourceName]) {
throw new Zend_Application_Bootstrap_Exception('Circular resource dependency detected');
}
$classResources = $this->getClassResources();
if (array_key_exists($resourceName, $classResources)) {
$this->_started[$resourceName] = true;
$method = $classResources[$resourceName];
$return = $this->$method();
unset($this->_started[$resourceName]);
$this->_markRun($resourceName);
if (null !== $return) {
$this->getContainer()->{$resourceName} = $return;
}
return;
}
if ($this->hasPluginResource($resource)) {
$this->_started[$resourceName] = true;
$plugin = $this->getPluginResource($resource);
$return = $plugin->init();
unset($this->_started[$resourceName]);
$this->_markRun($resourceName);
if (null !== $return) {
$this->getContainer()->{$resourceName} = $return;
}
return;
}
throw new Zend_Application_Bootstrap_Exception('Resource matching "' . $resource . '" not found');
}
/**
* Load a plugin resource
*
* @param string $resource
* @param array|object|null $options
* @return string|false
*/
protected function _loadPluginResource($resource, $options)
{
$options = (array) $options;
$options['bootstrap'] = $this;
$className = $this->getPluginLoader()->load(strtolower($resource), false);
if (!$className) {
return false;
}
$instance = new $className($options);
unset($this->_pluginResources[$resource]);
if (isset($instance->_explicitType)) {
$resource = $instance->_explicitType;
}
$resource = strtolower($resource);
$this->_pluginResources[$resource] = $instance;
return $resource;
}
/**
* Mark a resource as having run
*
* @param string $resource
* @return void
*/
protected function _markRun($resource)
{
if (!in_array($resource, $this->_run)) {
$this->_run[] = $resource;
}
}
/**
* Resolve a plugin resource name
*
* Uses, in order of preference
* - $_explicitType property of resource
* - Short name of resource (if a matching prefix path is found)
* - class name (if none of the above are true)
*
* The name is then cast to lowercase.
*
* @param Zend_Application_Resource_Resource $resource
* @return string
*/
protected function _resolvePluginResourceName($resource)
{
if (isset($resource->_explicitType)) {
$pluginName = $resource->_explicitType;
} else {
$className = get_class($resource);
$pluginName = $className;
$loader = $this->getPluginLoader();
foreach ($loader->getPaths() as $prefix => $paths) {
if (0 === strpos($className, $prefix)) {
$pluginName = substr($className, strlen($prefix));
$pluginName = trim($pluginName, '_');
}
}
}
$pluginName = strtolower($pluginName);
return $pluginName;
}
}
@@ -0,0 +1,94 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Interface for bootstrap classes
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Application_Bootstrap_Bootstrapper
{
/**
* Constructor
*
* @param Zend_Application $application
* @return void
*/
public function __construct($application);
/**
* Set bootstrap options
*
* @param array $options
* @return Zend_Application_Bootstrap_Bootstrapper
*/
public function setOptions(array $options);
/**
* Retrieve application object
*
* @return Zend_Application|Zend_Application_Bootstrap_Bootstrapper
*/
public function getApplication();
/**
* Retrieve application environment
*
* @return string
*/
public function getEnvironment();
/**
* Retrieve list of class resource initializers (_init* methods). Returns
* as resource/method pairs.
*
* @return array
*/
public function getClassResources();
/**
* Retrieve list of class resource initializer names (resource names only,
* no method names)
*
* @return array
*/
public function getClassResourceNames();
/**
* Bootstrap application or individual resource
*
* @param null|string $resource
* @return mixed
*/
public function bootstrap($resource = null);
/**
* Run the application
*
* @return void
*/
public function run();
}
@@ -0,0 +1,38 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Application_Exception
*/
require_once 'Zend/Application/Exception.php';
/**
* Exception class for Zend_Application
*
* @category Zend
* @package Zend_Application
* @uses Zend_Application_Exception
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Bootstrap_Exception extends Zend_Application_Exception
{
}
@@ -0,0 +1,95 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Interface for bootstrap classes that utilize resource plugins
*
* @category Zend
* @package Zend_Application
* @subpackage Bootstrap
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Application_Bootstrap_ResourceBootstrapper
{
/**
* Register a resource with the bootstrap
*
* @param string|Zend_Application_Resource_Resource $resource
* @param null|array|Zend_Config $options
* @return Zend_Application_Bootstrap_ResourceBootstrapper
*/
public function registerPluginResource($resource, $options = null);
/**
* Unregister a resource from the bootstrap
*
* @param string|Zend_Application_Resource_Resource $resource
* @return Zend_Application_Bootstrap_ResourceBootstrapper
*/
public function unregisterPluginResource($resource);
/**
* Is the requested resource registered?
*
* @param string $resource
* @return bool
*/
public function hasPluginResource($resource);
/**
* Retrieve resource
*
* @param string $resource
* @return Zend_Application_Resource_Resource
*/
public function getPluginResource($resource);
/**
* Get all resources
*
* @return array
*/
public function getPluginResources();
/**
* Get just resource names
*
* @return array
*/
public function getPluginResourceNames();
/**
* Set plugin loader to use to fetch resources
*
* @param Zend_Loader_PluginLoader_Interface Zend_Loader_PluginLoader
* @return Zend_Application_Bootstrap_ResourceBootstrapper
*/
public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
/**
* Retrieve plugin loader for resources
*
* @return Zend_Loader_PluginLoader
*/
public function getPluginLoader();
}
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Exception
*/
require_once 'Zend/Exception.php';
/**
* Exception class for Zend_Application
*
* @uses Zend_Exception
* @category Zend
* @package Zend_Application
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Exception extends Zend_Exception
{
}
@@ -0,0 +1,89 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Module
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @version $Id$
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/** Zend_Loader_Autoloader_Resource */
require_once 'Zend/Loader/Autoloader/Resource.php';
/**
* Resource loader for application module classes
*
* @uses Zend_Loader_Autoloader_Resource
* @package Zend_Application
* @subpackage Module
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Module_Autoloader extends Zend_Loader_Autoloader_Resource
{
/**
* Constructor
*
* @param array|Zend_Config $options
* @return void
*/
public function __construct($options)
{
parent::__construct($options);
$this->initDefaultResourceTypes();
}
/**
* Initialize default resource types for module resource classes
*
* @return void
*/
public function initDefaultResourceTypes()
{
$basePath = $this->getBasePath();
$this->addResourceTypes(array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
'model' => array(
'namespace' => 'Model',
'path' => 'models',
),
'plugin' => array(
'namespace' => 'Plugin',
'path' => 'plugins',
),
'service' => array(
'namespace' => 'Service',
'path' => 'services',
),
'viewhelper' => array(
'namespace' => 'View_Helper',
'path' => 'views/helpers',
),
'viewfilter' => array(
'namespace' => 'View_Filter',
'path' => 'views/filters',
),
));
$this->setDefaultResourceType('model');
}
}
@@ -0,0 +1,143 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Module
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @version $Id$
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Application_Bootstrap_Bootstrap
*/
require_once 'Zend/Application/Bootstrap/Bootstrap.php';
/**
* Base bootstrap class for modules
*
* @uses Zend_Loader_Autoloader_Resource
* @uses Zend_Application_Bootstrap_Bootstrap
* @package Zend_Application
* @subpackage Module
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Application_Module_Bootstrap
extends Zend_Application_Bootstrap_Bootstrap
{
/**
* @var Zend_Loader_Autoloader_Resource
*/
protected $_resourceLoader;
/**
* Constructor
*
* @param Zend_Application|Zend_Application_Bootstrap_Bootstrapper $application
* @return void
*/
public function __construct($application)
{
$this->setApplication($application);
// Use same plugin loader as parent bootstrap
if ($application instanceof Zend_Application_Bootstrap_ResourceBootstrapper) {
$this->setPluginLoader($application->getPluginLoader());
}
$key = strtolower($this->getModuleName());
if ($application->hasOption($key)) {
// Don't run via setOptions() to prevent duplicate initialization
$this->setOptions($application->getOption($key));
}
if ($application->hasOption('resourceloader')) {
$this->setOptions(array(
'resourceloader' => $application->getOption('resourceloader')
));
}
$this->initResourceLoader();
// ZF-6545: ensure front controller resource is loaded
if (!$this->hasPluginResource('FrontController')) {
$this->registerPluginResource('FrontController');
}
// ZF-6545: prevent recursive registration of modules
if ($this->hasPluginResource('modules')) {
$this->unregisterPluginResource('modules');
}
}
/**
* Set module resource loader
*
* @param Zend_Loader_Autoloader_Resource $loader
* @return Zend_Application_Module_Bootstrap
*/
public function setResourceLoader(Zend_Loader_Autoloader_Resource $loader)
{
$this->_resourceLoader = $loader;
return $this;
}
/**
* Retrieve module resource loader
*
* @return Zend_Loader_Autoloader_Resource
*/
public function getResourceLoader()
{
if (null === $this->_resourceLoader) {
$r = new ReflectionClass($this);
$path = $r->getFileName();
$this->setResourceLoader(new Zend_Application_Module_Autoloader(array(
'namespace' => $this->getModuleName(),
'basePath' => dirname($path),
)));
}
return $this->_resourceLoader;
}
/**
* Ensure resource loader is loaded
*
* @return void
*/
public function initResourceLoader()
{
$this->getResourceLoader();
}
/**
* Retrieve module name
*
* @return string
*/
public function getModuleName()
{
if (empty($this->_moduleName)) {
$class = get_class($this);
if (preg_match('/^([a-z][a-z0-9]*)_/i', $class, $matches)) {
$prefix = $matches[1];
} else {
$prefix = $class;
}
$this->_moduleName = $prefix;
}
return $this->_moduleName;
}
}
+156
View File
@@ -0,0 +1,156 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for creating database adapter
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Db extends Zend_Application_Resource_ResourceAbstract
{
/**
* Adapter to use
*
* @var string
*/
protected $_adapter = null;
/**
* @var Zend_Db_Adapter_Interface
*/
protected $_db;
/**
* Parameters to use
*
* @var array
*/
protected $_params = array();
/**
* Wether to register the created adapter as default table adapter
*
* @var boolean
*/
protected $_isDefaultTableAdapter = true;
/**
* Set the adapter
*
* @param $adapter string
* @return Zend_Application_Resource_Db
*/
public function setAdapter($adapter)
{
$this->_adapter = $adapter;
return $this;
}
/**
* Adapter type to use
*
* @return string
*/
public function getAdapter()
{
return $this->_adapter;
}
/**
* Set the adapter params
*
* @param $adapter string
* @return Zend_Application_Resource_Db
*/
public function setParams(array $params)
{
$this->_params = $params;
return $this;
}
/**
* Adapter parameters
*
* @return array
*/
public function getParams()
{
return $this->_params;
}
/**
* Set whether to use this as default table adapter
*
* @param boolean $defaultTableAdapter
* @return Zend_Application_Resource_Db
*/
public function setIsDefaultTableAdapter($isDefaultTableAdapter)
{
$this->_isDefaultTableAdapter = $isDefaultTableAdapter;
return $this;
}
/**
* Is this adapter the default table adapter?
*
* @return void
*/
public function isDefaultTableAdapter()
{
return $this->_isDefaultTableAdapter;
}
/**
* Retrieve initialized DB connection
*
* @return null|Zend_Db_Adapter_Interface
*/
public function getDbAdapter()
{
if ((null === $this->_db)
&& (null !== ($adapter = $this->getAdapter()))
) {
$this->_db = Zend_Db::factory($adapter, $this->getParams());
}
return $this->_db;
}
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Db_Adapter_Abstract|null
*/
public function init()
{
if (null !== ($db = $this->getDbAdapter())) {
if ($this->isDefaultTableAdapter()) {
Zend_Db_Table::setDefaultAdapter($db);
}
return $db;
}
}
}
@@ -0,0 +1,35 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Exception class for Zend_Application
*
* @uses Zend_Application_Exception
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Exception extends Zend_Application_Exception
{
}
@@ -0,0 +1,134 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Front Controller resource
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Frontcontroller extends Zend_Application_Resource_ResourceAbstract
{
/**
* @var Zend_Controller_Front
*/
protected $_front;
/**
* Initialize Front Controller
*
* @return Zend_Controller_Front
*/
public function init()
{
$front = $this->getFrontController();
foreach ($this->getOptions() as $key => $value) {
switch (strtolower($key)) {
case 'controllerdirectory':
if (is_string($value)) {
$front->setControllerDirectory($value);
} elseif (is_array($value)) {
foreach ($value as $module => $directory) {
$front->addControllerDirectory($directory, $module);
}
}
break;
case 'modulecontrollerdirectoryname':
$front->setModuleControllerDirectoryName($value);
break;
case 'moduledirectory':
$front->addModuleDirectory($value);
break;
case 'defaultcontrollername':
$front->setDefaultControllerName($value);
break;
case 'defaultaction':
$front->setDefaultAction($value);
break;
case 'defaultmodule':
$front->setDefaultModule($value);
break;
case 'baseurl':
if (!empty($value)) {
$front->setBaseUrl($value);
}
break;
case 'params':
$front->setParams($value);
break;
case 'plugins':
foreach ((array) $value as $pluginClass) {
$plugin = new $pluginClass();
$front->registerPlugin($plugin);
}
break;
case 'throwexceptions':
$front->throwExceptions((bool) $value);
break;
case 'actionhelperpaths':
if (is_array($value)) {
foreach ($value as $helperPrefix => $helperPath) {
Zend_Controller_Action_HelperBroker::addPath($helperPath, $helperPrefix);
}
}
break;
default:
$front->setParam($key, $value);
break;
}
}
if (null !== ($bootstrap = $this->getBootstrap())) {
$this->getBootstrap()->frontController = $front;
}
return $front;
}
/**
* Retrieve front controller instance
*
* @return Zend_Controller_Front
*/
public function getFrontController()
{
if (null === $this->_front) {
$this->_front = Zend_Controller_Front::getInstance();
}
return $this->_front;
}
}
@@ -0,0 +1,64 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for settings layout options
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Layout
extends Zend_Application_Resource_ResourceAbstract
{
/**
* @var Zend_Layout
*/
protected $_layout;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Layout
*/
public function init()
{
$this->getBootstrap()->bootstrap('FrontController');
return $this->getLayout();
}
/**
* Retrieve layout object
*
* @return Zend_Layout
*/
public function getLayout()
{
if (null === $this->_layout) {
$this->_layout = Zend_Layout::startMvc($this->getOptions());
}
return $this->_layout;
}
}
@@ -0,0 +1,77 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for initializing the locale
*
* @uses Zend_Application_Resource_Base
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Locale
extends Zend_Application_Resource_ResourceAbstract
{
const DEFAULT_REGISTRY_KEY = 'Zend_Locale';
/**
* @var Zend_Locale
*/
protected $_locale;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Locale
*/
public function init()
{
return $this->getLocale();
}
/**
* Retrieve locale object
*
* @return Zend_Locale
*/
public function getLocale()
{
if (null === $this->_locale) {
$options = $this->getOptions();
if (!isset($options['default'])) {
$this->_locale = new Zend_Locale();
} else {
Zend_Locale::setDefault($options['default']);
$this->_locale = new Zend_Locale($options['default']);
}
$key = (isset($options['registry_key']) && !is_numeric($options['registry_key']))
? $options['registry_key']
: self::DEFAULT_REGISTRY_KEY;
Zend_Registry::set($key, $this->_locale);
}
return $this->_locale;
}
}
@@ -0,0 +1,132 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Module bootstrapping resource
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Modules extends Zend_Application_Resource_ResourceAbstract
{
/**
* @var ArrayObject
*/
protected $_bootstraps;
/**
* Constructor
*
* @param mixed $options
* @return void
*/
public function __construct($options = null)
{
$this->_bootstraps = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
parent::__construct($options);
}
/**
* Initialize modules
*
* @return array
* @throws Zend_Application_Resource_Exception When bootstrap class was not found
*/
public function init()
{
$bootstrap = $this->getBootstrap();
$bootstrap->bootstrap('FrontController');
$front = $bootstrap->getResource('FrontController');
$modules = $front->getControllerDirectory();
$default = $front->getDefaultModule();
$curBootstrapClass = get_class($bootstrap);
foreach ($modules as $module => $moduleDirectory) {
$bootstrapClass = $this->_formatModuleName($module) . '_Bootstrap';
if (!class_exists($bootstrapClass, false)) {
$bootstrapPath = dirname($moduleDirectory) . '/Bootstrap.php';
if (file_exists($bootstrapPath)) {
$eMsgTpl = 'Bootstrap file found for module "%s" but bootstrap class "%s" not found';
include_once $bootstrapPath;
if (($default != $module)
&& !class_exists($bootstrapClass, false)
) {
throw new Zend_Application_Resource_Exception(sprintf(
$eMsgTpl, $module, $bootstrapClass
));
} elseif ($default == $module) {
if (!class_exists($bootstrapClass, false)) {
$bootstrapClass = 'Bootstrap';
if (!class_exists($bootstrapClass, false)) {
throw new Zend_Application_Resource_Exception(sprintf(
$eMsgTpl, $module, $bootstrapClass
));
}
}
}
} else {
continue;
}
}
if ($bootstrapClass == $curBootstrapClass) {
// If the found bootstrap class matches the one calling this
// resource, don't re-execute.
continue;
}
$moduleBootstrap = new $bootstrapClass($bootstrap);
$moduleBootstrap->bootstrap();
$this->_bootstraps[$module] = $moduleBootstrap;
}
return $this->_bootstraps;
}
/**
* Get bootstraps that have been run
*
* @return ArrayObject
*/
public function getExecutedBootstraps()
{
return $this->_bootstraps;
}
/**
* Format a module name to the module class prefix
*
* @param string $name
* @return string
*/
protected function _formatModuleName($name)
{
$name = strtolower($name);
$name = str_replace(array('-', '.'), ' ', $name);
$name = ucwords($name);
$name = str_replace(' ', '', $name);
return $name;
}
}
@@ -0,0 +1,118 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for setting navigation structure
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @author Dolf Schimmel
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Navigation
extends Zend_Application_Resource_ResourceAbstract
{
const DEFAULT_REGISTRY_KEY = 'Zend_Navigation';
/**
* @var Zend_Navigation
*/
protected $_container;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Navigation
*/
public function init()
{
if (!$this->_container) {
$options = $this->getOptions();
$pages = isset($options['pages']) ? $options['pages'] : array();
$this->_container = new Zend_Navigation($pages);
}
$this->store();
return $this->_container;
}
/**
* Stores navigation container in registry or Navigation view helper
*
* @return void
*/
public function store()
{
$options = $this->getOptions();
if (isset($options['storage']['registry']) &&
$options['storage']['registry'] == true) {
$this->_storeRegistry();
} else {
$this->_storeHelper();
}
}
/**
* Stores navigation container in the registry
*
* @return void
*/
protected function _storeRegistry()
{
$options = $this->getOptions();
if(isset($options['storage']) &&
isset($options['storage']['registry']) &&
isset($options['storage']['registry']['key']))
{
$key = $options['storage']['registry']['key'];
} else {
$key = self::DEFAULT_REGISTRY_KEY;
}
Zend_Registry::set($key,$this->getContainer());
}
/**
* Stores navigation container in the Navigation helper
*
* @return void
*/
protected function _storeHelper()
{
$this->getBootstrap()->bootstrap('view');
$view = $this->getBootstrap()->view;
$view->getHelper('navigation')->navigation($this->getContainer());
}
/**
* Returns navigation container
*
* @return Zend_Navigation
*/
public function getContainer()
{
return $this->_container;
}
}
@@ -0,0 +1,80 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Interface for bootstrap resources
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Application_Resource_Resource
{
/**
* Constructor
*
* Must take an optional single argument, $options.
*
* @param mixed $options
* @return void
*/
public function __construct($options = null);
/**
* Set the bootstrap to which the resource is attached
*
* @param Zend_Application_Bootstrap_Bootstrapper $bootstrap
* @return Zend_Application_Resource_Resource
*/
public function setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap);
/**
* Retrieve the bootstrap to which the resource is attached
*
* @return Zend_Application_Bootstrap_Bootstrapper
*/
public function getBootstrap();
/**
* Set resource options
*
* @param array $options
* @return Zend_Application_Resource_Resource
*/
public function setOptions(array $options);
/**
* Retrieve resource options
*
* @return array
*/
public function getOptions();
/**
* Strategy pattern: initialize resource
*
* @return mixed
*/
public function init();
}
@@ -0,0 +1,159 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Application_Resource_Resource
*/
require_once 'Zend/Application/Resource/Resource.php';
/**
* Abstract class for bootstrap resources
*
* @uses Zend_Application_Resource_Resource
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Application_Resource_ResourceAbstract implements Zend_Application_Resource_Resource
{
/**
* Parent bootstrap
*
* @var Zend_Application_Bootstrap_Bootstrapper
*/
protected $_bootstrap;
/**
* Options for the resource
*
* @var array
*/
protected $_options = array();
/**
* Option keys to skip when calling setOptions()
*
* @var array
*/
protected $_skipOptions = array(
'options',
'config',
);
/**
* Create a instance with options
*
* @param mixed $options
*/
public function __construct($options = null)
{
if (is_array($options)) {
$this->setOptions($options);
} else if ($options instanceof Zend_Config) {
$this->setOptions($options->toArray());
}
}
/**
* Set options from array
*
* @param array $options Configuration for resource
* @return Zend_Application_Resource_ResourceAbstract
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value) {
if (in_array(strtolower($key), $this->_skipOptions)) {
continue;
}
$method = 'set' . strtolower($key);
if (method_exists($this, $method)) {
$this->$method($value);
}
if ('bootstrap' == $key) {
unset($options[$key]);
}
}
$this->_options = $this->mergeOptions($this->_options, $options);
return $this;
}
/**
* Retrieve resource options
*
* @return array
*/
public function getOptions()
{
return $this->_options;
}
/**
* Merge options recursively
*
* @param array $array1
* @param mixed $array2
* @return array
*/
public function mergeOptions(array $array1, $array2 = null)
{
if (is_array($array2)) {
foreach ($array2 as $key => $val) {
if (is_array($array2[$key])) {
$array1[$key] = (array_key_exists($key, $array1) && is_array($array1[$key]))
? $this->mergeOptions($array1[$key], $array2[$key])
: $array2[$key];
} else {
$array1[$key] = $val;
}
}
}
return $array1;
}
/**
* Set the bootstrap to which the resource is attached
*
* @param Zend_Application_Bootstrap_Bootstrapper $bootstrap
* @return Zend_Application_Resource_Resource
*/
public function setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap)
{
$this->_bootstrap = $bootstrap;
return $this;
}
/**
* Retrieve the bootstrap to which the resource is attached
*
* @return null|Zend_Application_Bootstrap_Bootstrapper
*/
public function getBootstrap()
{
return $this->_bootstrap;
}
}
@@ -0,0 +1,78 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for initializing the locale
*
* @uses Zend_Application_Resource_Base
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Router
extends Zend_Application_Resource_ResourceAbstract
{
/**
* @var Zend_Controller_Router_Rewrite
*/
protected $_router;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Controller_Router_Rewrite
*/
public function init()
{
return $this->getRouter();
}
/**
* Retrieve router object
*
* @return Zend_Controller_Router_Rewrite
*/
public function getRouter()
{
if (null === $this->_router) {
$bootstrap = $this->getBootstrap();
$bootstrap->bootstrap('FrontController');
$this->_router = $bootstrap->getContainer()->frontcontroller->getRouter();
$options = $this->getOptions();
if (!isset($options['routes'])) {
$options['routes'] = array();
}
if (isset($options['chainNameSeparator'])) {
$this->_router->setChainNameSeparator($options['chainNameSeparator']);
}
$this->_router->addConfig(new Zend_Config($options['routes']));
}
return $this->_router;
}
}
@@ -0,0 +1,112 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for setting session options
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Session extends Zend_Application_Resource_ResourceAbstract
{
/**
* Save handler to use
*
* @var Zend_Session_SaveHandler_Interface
*/
protected $_saveHandler = null;
/**
* Set session save handler
*
* @param array|string|Zend_Session_SaveHandler_Interface $saveHandler
* @return Zend_Application_Resource_Session
* @throws Zend_Application_Resource_Exception When $saveHandler is no valid save handler
*/
public function setSaveHandler($saveHandler)
{
$this->_saveHandler = $saveHandler;
return $this;
}
/**
* Get session save handler
*
* @return Zend_Session_SaveHandler_Interface
*/
public function getSaveHandler()
{
if (!$this->_saveHandler instanceof Zend_Session_SaveHandler_Interface) {
if (is_array($this->_saveHandler)) {
if (!array_key_exists('class', $this->_saveHandler)) {
throw new Zend_Application_Resource_Exception('Session save handler class not provided in options');
}
$options = array();
if (array_key_exists('options', $this->_saveHandler)) {
$options = $this->_saveHandler['options'];
}
$this->_saveHandler = $this->_saveHandler['class'];
$this->_saveHandler = new $this->_saveHandler($options);
} elseif (is_string($this->_saveHandler)) {
$this->_saveHandler = new $this->_saveHandler();
}
if (!$this->_saveHandler instanceof Zend_Session_SaveHandler_Interface) {
throw new Zend_Application_Resource_Exception('Invalid session save handler');
}
}
return $this->_saveHandler;
}
/**
* @return bool
*/
protected function _hasSaveHandler()
{
return ($this->_saveHandler !== null);
}
/**
* Defined by Zend_Application_Resource_Resource
*
* @return void
*/
public function init()
{
$options = array_change_key_case($this->getOptions(), CASE_LOWER);
if (isset($options['savehandler'])) {
unset($options['savehandler']);
}
if (count($options) > 0) {
Zend_Session::setOptions($options);
}
if ($this->_hasSaveHandler()) {
Zend_Session::setSaveHandler($this->getSaveHandler());
}
}
}
@@ -0,0 +1,83 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for setting translation options
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_Translate extends Zend_Application_Resource_ResourceAbstract
{
const DEFAULT_REGISTRY_KEY = 'Zend_Translate';
/**
* @var Zend_Translate
*/
protected $_translate;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_Translate
*/
public function init()
{
return $this->getTranslate();
}
/**
* Retrieve translate object
*
* @return Zend_Translate
*/
public function getTranslate()
{
if (null === $this->_translate) {
$options = $this->getOptions();
if (!isset($options['data'])) {
throw new Zend_Application_Resource_Exception('No translation source data provided.');
}
$adapter = isset($options['adapter']) ? $options['adapter'] : Zend_Translate::AN_ARRAY;
$locale = isset($options['locale']) ? $options['locale'] : null;
$translateOptions = isset($options['options']) ? $options['options'] : array();
$this->_translate = new Zend_Translate(
$adapter, $options['data'], $locale, $translateOptions
);
$key = (isset($options['registry_key']) && !is_numeric($options['registry_key']))
? $options['registry_key']
: self::DEFAULT_REGISTRY_KEY;
Zend_Registry::set($key, $this->_translate);
}
return $this->_translate;
}
}
@@ -0,0 +1,67 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Resource for settings view options
*
* @uses Zend_Application_Resource_ResourceAbstract
* @category Zend
* @package Zend_Application
* @subpackage Resource
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Application_Resource_View extends Zend_Application_Resource_ResourceAbstract
{
/**
* @var Zend_View_Interface
*/
protected $_view;
/**
* Defined by Zend_Application_Resource_Resource
*
* @return Zend_View
*/
public function init()
{
$view = $this->getView();
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
return $view;
}
/**
* Retrieve view object
*
* @return Zend_View
*/
public function getView()
{
if (null === $this->_view) {
$this->_view = new Zend_View($this->getOptions());
}
return $this->_view;
}
}
+484
View File
@@ -0,0 +1,484 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_Db_Adapter_Abstract
*/
require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Auth_Result
*/
require_once 'Zend/Auth/Result.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
{
/**
* Database Connection
*
* @var Zend_Db_Adapter_Abstract
*/
protected $_zendDb = null;
/**
* @var Zend_Db_Select
*/
protected $_dbSelect = null;
/**
* $_tableName - the table name to check
*
* @var string
*/
protected $_tableName = null;
/**
* $_identityColumn - the column to use as the identity
*
* @var string
*/
protected $_identityColumn = null;
/**
* $_credentialColumns - columns to be used as the credentials
*
* @var string
*/
protected $_credentialColumn = null;
/**
* $_identity - Identity value
*
* @var string
*/
protected $_identity = null;
/**
* $_credential - Credential values
*
* @var string
*/
protected $_credential = null;
/**
* $_credentialTreatment - Treatment applied to the credential, such as MD5() or PASSWORD()
*
* @var string
*/
protected $_credentialTreatment = null;
/**
* $_authenticateResultInfo
*
* @var array
*/
protected $_authenticateResultInfo = null;
/**
* $_resultRow - Results of database authentication query
*
* @var array
*/
protected $_resultRow = null;
/**
* __construct() - Sets configuration options
*
* @param Zend_Db_Adapter_Abstract $zendDb
* @param string $tableName
* @param string $identityColumn
* @param string $credentialColumn
* @param string $credentialTreatment
* @return void
*/
public function __construct(Zend_Db_Adapter_Abstract $zendDb, $tableName = null, $identityColumn = null,
$credentialColumn = null, $credentialTreatment = null)
{
$this->_zendDb = $zendDb;
if (null !== $tableName) {
$this->setTableName($tableName);
}
if (null !== $identityColumn) {
$this->setIdentityColumn($identityColumn);
}
if (null !== $credentialColumn) {
$this->setCredentialColumn($credentialColumn);
}
if (null !== $credentialTreatment) {
$this->setCredentialTreatment($credentialTreatment);
}
}
/**
* setTableName() - set the table name to be used in the select query
*
* @param string $tableName
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setTableName($tableName)
{
$this->_tableName = $tableName;
return $this;
}
/**
* setIdentityColumn() - set the column name to be used as the identity column
*
* @param string $identityColumn
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setIdentityColumn($identityColumn)
{
$this->_identityColumn = $identityColumn;
return $this;
}
/**
* setCredentialColumn() - set the column name to be used as the credential column
*
* @param string $credentialColumn
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setCredentialColumn($credentialColumn)
{
$this->_credentialColumn = $credentialColumn;
return $this;
}
/**
* setCredentialTreatment() - allows the developer to pass a parameterized string that is
* used to transform or treat the input credential data
*
* In many cases, passwords and other sensitive data are encrypted, hashed, encoded,
* obscured, or otherwise treated through some function or algorithm. By specifying a
* parameterized treatment string with this method, a developer may apply arbitrary SQL
* upon input credential data.
*
* Examples:
*
* 'PASSWORD(?)'
* 'MD5(?)'
*
* @param string $treatment
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setCredentialTreatment($treatment)
{
$this->_credentialTreatment = $treatment;
return $this;
}
/**
* setIdentity() - set the value to be used as the identity
*
* @param string $value
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setIdentity($value)
{
$this->_identity = $value;
return $this;
}
/**
* setCredential() - set the credential value to be used, optionally can specify a treatment
* to be used, should be supplied in parameterized form, such as 'MD5(?)' or 'PASSWORD(?)'
*
* @param string $credential
* @return Zend_Auth_Adapter_DbTable Provides a fluent interface
*/
public function setCredential($credential)
{
$this->_credential = $credential;
return $this;
}
/**
* getDbSelect() - Return the preauthentication Db Select object for userland select query modification
*
* @return Zend_Db_Select
*/
public function getDbSelect()
{
if ($this->_dbSelect == null) {
$this->_dbSelect = $this->_zendDb->select();
}
return $this->_dbSelect;
}
/**
* getResultRowObject() - Returns the result row as a stdClass object
*
* @param string|array $returnColumns
* @param string|array $omitColumns
* @return stdClass|boolean
*/
public function getResultRowObject($returnColumns = null, $omitColumns = null)
{
if (!$this->_resultRow) {
return false;
}
$returnObject = new stdClass();
if (null !== $returnColumns) {
$availableColumns = array_keys($this->_resultRow);
foreach ( (array) $returnColumns as $returnColumn) {
if (in_array($returnColumn, $availableColumns)) {
$returnObject->{$returnColumn} = $this->_resultRow[$returnColumn];
}
}
return $returnObject;
} elseif (null !== $omitColumns) {
$omitColumns = (array) $omitColumns;
foreach ($this->_resultRow as $resultColumn => $resultValue) {
if (!in_array($resultColumn, $omitColumns)) {
$returnObject->{$resultColumn} = $resultValue;
}
}
return $returnObject;
} else {
foreach ($this->_resultRow as $resultColumn => $resultValue) {
$returnObject->{$resultColumn} = $resultValue;
}
return $returnObject;
}
}
/**
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to
* attempt an authenication. Previous to this call, this adapter would have already
* been configured with all nessissary information to successfully connect to a database
* table and attempt to find a record matching the provided identity.
*
* @throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible
* @return Zend_Auth_Result
*/
public function authenticate()
{
$this->_authenticateSetup();
$dbSelect = $this->_authenticateCreateSelect();
$resultIdentities = $this->_authenticateQuerySelect($dbSelect);
if ( ($authResult = $this->_authenticateValidateResultset($resultIdentities)) instanceof Zend_Auth_Result) {
return $authResult;
}
$authResult = $this->_authenticateValidateResult(array_shift($resultIdentities));
return $authResult;
}
/**
* _authenticateSetup() - This method abstracts the steps involved with making sure
* that this adapter was indeed setup properly with all required peices of information.
*
* @throws Zend_Auth_Adapter_Exception - in the event that setup was not done properly
* @return true
*/
protected function _authenticateSetup()
{
$exception = null;
if ($this->_tableName == '') {
$exception = 'A table must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.';
} elseif ($this->_identityColumn == '') {
$exception = 'An identity column must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.';
} elseif ($this->_credentialColumn == '') {
$exception = 'A credential column must be supplied for the Zend_Auth_Adapter_DbTable authentication adapter.';
} elseif ($this->_identity == '') {
$exception = 'A value for the identity was not provided prior to authentication with Zend_Auth_Adapter_DbTable.';
} elseif ($this->_credential === null) {
$exception = 'A credential value was not provided prior to authentication with Zend_Auth_Adapter_DbTable.';
}
if (null !== $exception) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception($exception);
}
$this->_authenticateResultInfo = array(
'code' => Zend_Auth_Result::FAILURE,
'identity' => $this->_identity,
'messages' => array()
);
return true;
}
/**
* _authenticateCreateSelect() - This method creates a Zend_Db_Select object that
* is completely configured to be queried against the database.
*
* @return Zend_Db_Select
*/
protected function _authenticateCreateSelect()
{
// build credential expression
if (empty($this->_credentialTreatment) || (strpos($this->_credentialTreatment, '?') === false)) {
$this->_credentialTreatment = '?';
}
$credentialExpression = new Zend_Db_Expr(
'(CASE WHEN ' .
$this->_zendDb->quoteInto(
$this->_zendDb->quoteIdentifier($this->_credentialColumn, true)
. ' = ' . $this->_credentialTreatment, $this->_credential
)
. ' THEN 1 ELSE 0 END) AS '
. $this->_zendDb->quoteIdentifier(
$this->_zendDb->foldCase('zend_auth_credential_match')
)
);
// get select
$dbSelect = clone $this->getDbSelect();
$dbSelect->from($this->_tableName, array('*', $credentialExpression))
->where($this->_zendDb->quoteIdentifier($this->_identityColumn, true) . ' = ?', $this->_identity);
return $dbSelect;
}
/**
* _authenticateQuerySelect() - This method accepts a Zend_Db_Select object and
* performs a query against the database with that object.
*
* @param Zend_Db_Select $dbSelect
* @throws Zend_Auth_Adapter_Exception - when a invalid select object is encoutered
* @return array
*/
protected function _authenticateQuerySelect(Zend_Db_Select $dbSelect)
{
try {
if ($this->_zendDb->getFetchMode() != Zend_DB::FETCH_ASSOC) {
$origDbFetchMode = $this->_zendDb->getFetchMode();
$this->_zendDb->setFetchMode(Zend_DB::FETCH_ASSOC);
}
$resultIdentities = $this->_zendDb->fetchAll($dbSelect->__toString());
if (isset($origDbFetchMode)) {
$this->_zendDb->setFetchMode($origDbFetchMode);
unset($origDbFetchMode);
}
} catch (Exception $e) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The supplied parameters to Zend_Auth_Adapter_DbTable failed to '
. 'produce a valid sql statement, please check table and column names '
. 'for validity.');
}
return $resultIdentities;
}
/**
* _authenticateValidateResultSet() - This method attempts to make certian that only one
* record was returned in the result set
*
* @param array $resultIdentities
* @return true|Zend_Auth_Result
*/
protected function _authenticateValidateResultSet(array $resultIdentities)
{
if (count($resultIdentities) < 1) {
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
$this->_authenticateResultInfo['messages'][] = 'A record with the supplied identity could not be found.';
return $this->_authenticateCreateAuthResult();
} elseif (count($resultIdentities) > 1) {
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS;
$this->_authenticateResultInfo['messages'][] = 'More than one record matches the supplied identity.';
return $this->_authenticateCreateAuthResult();
}
return true;
}
/**
* _authenticateValidateResult() - This method attempts to validate that the record in the
* result set is indeed a record that matched the identity provided to this adapter.
*
* @param array $resultIdentity
* @return Zend_Auth_Result
*/
protected function _authenticateValidateResult($resultIdentity)
{
$zendAuthCredentialMatchColumn = $this->_zendDb->foldCase('zend_auth_credential_match');
if ($resultIdentity[$zendAuthCredentialMatchColumn] != '1') {
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
return $this->_authenticateCreateAuthResult();
}
unset($resultIdentity[$zendAuthCredentialMatchColumn]);
$this->_resultRow = $resultIdentity;
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::SUCCESS;
$this->_authenticateResultInfo['messages'][] = 'Authentication successful.';
return $this->_authenticateCreateAuthResult();
}
/**
* _authenticateCreateAuthResult() - This method creates a Zend_Auth_Result object
* from the information that has been collected during the authenticate() attempt.
*
* @return Zend_Auth_Result
*/
protected function _authenticateCreateAuthResult()
{
return new Zend_Auth_Result(
$this->_authenticateResultInfo['code'],
$this->_authenticateResultInfo['identity'],
$this->_authenticateResultInfo['messages']
);
}
}
+230
View File
@@ -0,0 +1,230 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Digest implements Zend_Auth_Adapter_Interface
{
/**
* Filename against which authentication queries are performed
*
* @var string
*/
protected $_filename;
/**
* Digest authentication realm
*
* @var string
*/
protected $_realm;
/**
* Digest authentication user
*
* @var string
*/
protected $_username;
/**
* Password for the user of the realm
*
* @var string
*/
protected $_password;
/**
* Sets adapter options
*
* @param mixed $filename
* @param mixed $realm
* @param mixed $username
* @param mixed $password
* @return void
*/
public function __construct($filename = null, $realm = null, $username = null, $password = null)
{
$options = array('filename', 'realm', 'username', 'password');
foreach ($options as $option) {
if (null !== $$option) {
$methodName = 'set' . ucfirst($option);
$this->$methodName($$option);
}
}
}
/**
* Returns the filename option value or null if it has not yet been set
*
* @return string|null
*/
public function getFilename()
{
return $this->_filename;
}
/**
* Sets the filename option value
*
* @param mixed $filename
* @return Zend_Auth_Adapter_Digest Provides a fluent interface
*/
public function setFilename($filename)
{
$this->_filename = (string) $filename;
return $this;
}
/**
* Returns the realm option value or null if it has not yet been set
*
* @return string|null
*/
public function getRealm()
{
return $this->_realm;
}
/**
* Sets the realm option value
*
* @param mixed $realm
* @return Zend_Auth_Adapter_Digest Provides a fluent interface
*/
public function setRealm($realm)
{
$this->_realm = (string) $realm;
return $this;
}
/**
* Returns the username option value or null if it has not yet been set
*
* @return string|null
*/
public function getUsername()
{
return $this->_username;
}
/**
* Sets the username option value
*
* @param mixed $username
* @return Zend_Auth_Adapter_Digest Provides a fluent interface
*/
public function setUsername($username)
{
$this->_username = (string) $username;
return $this;
}
/**
* Returns the password option value or null if it has not yet been set
*
* @return string|null
*/
public function getPassword()
{
return $this->_password;
}
/**
* Sets the password option value
*
* @param mixed $password
* @return Zend_Auth_Adapter_Digest Provides a fluent interface
*/
public function setPassword($password)
{
$this->_password = (string) $password;
return $this;
}
/**
* Defined by Zend_Auth_Adapter_Interface
*
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result
*/
public function authenticate()
{
$optionsRequired = array('filename', 'realm', 'username', 'password');
foreach ($optionsRequired as $optionRequired) {
if (null === $this->{"_$optionRequired"}) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception("Option '$optionRequired' must be set before authentication");
}
}
if (false === ($fileHandle = @fopen($this->_filename, 'r'))) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception("Cannot open '$this->_filename' for reading");
}
$id = "$this->_username:$this->_realm";
$idLength = strlen($id);
$result = array(
'code' => Zend_Auth_Result::FAILURE,
'identity' => array(
'realm' => $this->_realm,
'username' => $this->_username,
),
'messages' => array()
);
while ($line = trim(fgets($fileHandle))) {
if (substr($line, 0, $idLength) === $id) {
if (substr($line, -32) === md5("$this->_username:$this->_realm:$this->_password")) {
$result['code'] = Zend_Auth_Result::SUCCESS;
} else {
$result['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$result['messages'][] = 'Password incorrect';
}
return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']);
}
}
$result['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
$result['messages'][] = "Username '$this->_username' and realm '$this->_realm' combination not found";
return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Zend_Auth_Exception
*/
require_once 'Zend/Auth/Exception.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Exception extends Zend_Auth_Exception
{}
+847
View File
@@ -0,0 +1,847 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* HTTP Authentication Adapter
*
* Implements a pretty good chunk of RFC 2617.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @todo Support auth-int
* @todo Track nonces, nonce-count, opaque for replay protection and stale support
* @todo Support Authentication-Info header
*/
class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
{
/**
* Reference to the HTTP Request object
*
* @var Zend_Controller_Request_Http
*/
protected $_request;
/**
* Reference to the HTTP Response object
*
* @var Zend_Controller_Response_Http
*/
protected $_response;
/**
* Object that looks up user credentials for the Basic scheme
*
* @var Zend_Auth_Adapter_Http_Resolver_Interface
*/
protected $_basicResolver;
/**
* Object that looks up user credentials for the Digest scheme
*
* @var Zend_Auth_Adapter_Http_Resolver_Interface
*/
protected $_digestResolver;
/**
* List of authentication schemes supported by this class
*
* @var array
*/
protected $_supportedSchemes = array('basic', 'digest');
/**
* List of schemes this class will accept from the client
*
* @var array
*/
protected $_acceptSchemes;
/**
* Space-delimited list of protected domains for Digest Auth
*
* @var string
*/
protected $_domains;
/**
* The protection realm to use
*
* @var string
*/
protected $_realm;
/**
* Nonce timeout period
*
* @var integer
*/
protected $_nonceTimeout;
/**
* Whether to send the opaque value in the header. True by default
*
* @var boolean
*/
protected $_useOpaque;
/**
* List of the supported digest algorithms. I want to support both MD5 and
* MD5-sess, but MD5-sess won't make it into the first version.
*
* @var array
*/
protected $_supportedAlgos = array('MD5');
/**
* The actual algorithm to use. Defaults to MD5
*
* @var string
*/
protected $_algo;
/**
* List of supported qop options. My intetion is to support both 'auth' and
* 'auth-int', but 'auth-int' won't make it into the first version.
*
* @var array
*/
protected $_supportedQops = array('auth');
/**
* Whether or not to do Proxy Authentication instead of origin server
* authentication (send 407's instead of 401's). Off by default.
*
* @var boolean
*/
protected $_imaProxy;
/**
* Flag indicating the client is IE and didn't bother to return the opaque string
*
* @var boolean
*/
protected $_ieNoOpaque;
/**
* Constructor
*
* @param array $config Configuration settings:
* 'accept_schemes' => 'basic'|'digest'|'basic digest'
* 'realm' => <string>
* 'digest_domains' => <string> Space-delimited list of URIs
* 'nonce_timeout' => <int>
* 'use_opaque' => <bool> Whether to send the opaque value in the header
* 'alogrithm' => <string> See $_supportedAlgos. Default: MD5
* 'proxy_auth' => <bool> Whether to do authentication as a Proxy
* @throws Zend_Auth_Adapter_Exception
* @return void
*/
public function __construct(array $config)
{
if (!extension_loaded('hash')) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception(__CLASS__ . ' requires the \'hash\' extension');
}
$this->_request = null;
$this->_response = null;
$this->_ieNoOpaque = false;
if (empty($config['accept_schemes'])) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'accept_schemes\' is required');
}
$schemes = explode(' ', $config['accept_schemes']);
$this->_acceptSchemes = array_intersect($schemes, $this->_supportedSchemes);
if (empty($this->_acceptSchemes)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('No supported schemes given in \'accept_schemes\'. Valid values: '
. implode(', ', $this->_supportedSchemes));
}
// Double-quotes are used to delimit the realm string in the HTTP header,
// and colons are field delimiters in the password file.
if (empty($config['realm']) ||
!ctype_print($config['realm']) ||
strpos($config['realm'], ':') !== false ||
strpos($config['realm'], '"') !== false) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'realm\' is required, and must contain only printable '
. 'characters, excluding quotation marks and colons');
} else {
$this->_realm = $config['realm'];
}
if (in_array('digest', $this->_acceptSchemes)) {
if (empty($config['digest_domains']) ||
!ctype_print($config['digest_domains']) ||
strpos($config['digest_domains'], '"') !== false) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'digest_domains\' is required, and must contain '
. 'only printable characters, excluding quotation marks');
} else {
$this->_domains = $config['digest_domains'];
}
if (empty($config['nonce_timeout']) ||
!is_numeric($config['nonce_timeout'])) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'nonce_timeout\' is required, and must be an '
. 'integer');
} else {
$this->_nonceTimeout = (int) $config['nonce_timeout'];
}
// We use the opaque value unless explicitly told not to
if (isset($config['use_opaque']) && false == (bool) $config['use_opaque']) {
$this->_useOpaque = false;
} else {
$this->_useOpaque = true;
}
if (isset($config['algorithm']) && in_array($config['algorithm'], $this->_supportedAlgos)) {
$this->_algo = $config['algorithm'];
} else {
$this->_algo = 'MD5';
}
}
// Don't be a proxy unless explicitly told to do so
if (isset($config['proxy_auth']) && true == (bool) $config['proxy_auth']) {
$this->_imaProxy = true; // I'm a Proxy
} else {
$this->_imaProxy = false;
}
}
/**
* Setter for the _basicResolver property
*
* @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver
* @return Zend_Auth_Adapter_Http Provides a fluent interface
*/
public function setBasicResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver)
{
$this->_basicResolver = $resolver;
return $this;
}
/**
* Getter for the _basicResolver property
*
* @return Zend_Auth_Adapter_Http_Resolver_Interface
*/
public function getBasicResolver()
{
return $this->_basicResolver;
}
/**
* Setter for the _digestResolver property
*
* @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver
* @return Zend_Auth_Adapter_Http Provides a fluent interface
*/
public function setDigestResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver)
{
$this->_digestResolver = $resolver;
return $this;
}
/**
* Getter for the _digestResolver property
*
* @return Zend_Auth_Adapter_Http_Resolver_Interface
*/
public function getDigestResolver()
{
return $this->_digestResolver;
}
/**
* Setter for the Request object
*
* @param Zend_Controller_Request_Http $request
* @return Zend_Auth_Adapter_Http Provides a fluent interface
*/
public function setRequest(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
return $this;
}
/**
* Getter for the Request object
*
* @return Zend_Controller_Request_Http
*/
public function getRequest()
{
return $this->_request;
}
/**
* Setter for the Response object
*
* @param Zend_Controller_Response_Http $response
* @return Zend_Auth_Adapter_Http Provides a fluent interface
*/
public function setResponse(Zend_Controller_Response_Http $response)
{
$this->_response = $response;
return $this;
}
/**
* Getter for the Response object
*
* @return Zend_Controller_Response_Http
*/
public function getResponse()
{
return $this->_response;
}
/**
* Authenticate
*
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result
*/
public function authenticate()
{
if (empty($this->_request) ||
empty($this->_response)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Request and Response objects must be set before calling '
. 'authenticate()');
}
if ($this->_imaProxy) {
$getHeader = 'Proxy-Authorization';
} else {
$getHeader = 'Authorization';
}
$authHeader = $this->_request->getHeader($getHeader);
if (!$authHeader) {
return $this->_challengeClient();
}
list($clientScheme) = explode(' ', $authHeader);
$clientScheme = strtolower($clientScheme);
// The server can issue multiple challenges, but the client should
// answer with only the selected auth scheme.
if (!in_array($clientScheme, $this->_supportedSchemes)) {
$this->_response->setHttpResponseCode(400);
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE_UNCATEGORIZED,
array(),
array('Client requested an incorrect or unsupported authentication scheme')
);
}
// client sent a scheme that is not the one required
if (!in_array($clientScheme, $this->_acceptSchemes)) {
// challenge again the client
return $this->_challengeClient();
}
switch ($clientScheme) {
case 'basic':
$result = $this->_basicAuth($authHeader);
break;
case 'digest':
$result = $this->_digestAuth($authHeader);
break;
default:
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Unsupported authentication scheme');
}
return $result;
}
/**
* Challenge Client
*
* Sets a 401 or 407 Unauthorized response code, and creates the
* appropriate Authenticate header(s) to prompt for credentials.
*
* @return Zend_Auth_Result Always returns a non-identity Auth result
*/
protected function _challengeClient()
{
if ($this->_imaProxy) {
$statusCode = 407;
$headerName = 'Proxy-Authenticate';
} else {
$statusCode = 401;
$headerName = 'WWW-Authenticate';
}
$this->_response->setHttpResponseCode($statusCode);
// Send a challenge in each acceptable authentication scheme
if (in_array('basic', $this->_acceptSchemes)) {
$this->_response->setHeader($headerName, $this->_basicHeader());
}
if (in_array('digest', $this->_acceptSchemes)) {
$this->_response->setHeader($headerName, $this->_digestHeader());
}
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID,
array(),
array('Invalid or absent credentials; challenging client')
);
}
/**
* Basic Header
*
* Generates a Proxy- or WWW-Authenticate header value in the Basic
* authentication scheme.
*
* @return string Authenticate header value
*/
protected function _basicHeader()
{
return 'Basic realm="' . $this->_realm . '"';
}
/**
* Digest Header
*
* Generates a Proxy- or WWW-Authenticate header value in the Digest
* authentication scheme.
*
* @return string Authenticate header value
*/
protected function _digestHeader()
{
$wwwauth = 'Digest realm="' . $this->_realm . '", '
. 'domain="' . $this->_domains . '", '
. 'nonce="' . $this->_calcNonce() . '", '
. ($this->_useOpaque ? 'opaque="' . $this->_calcOpaque() . '", ' : '')
. 'algorithm="' . $this->_algo . '", '
. 'qop="' . implode(',', $this->_supportedQops) . '"';
return $wwwauth;
}
/**
* Basic Authentication
*
* @param string $header Client's Authorization header
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result
*/
protected function _basicAuth($header)
{
if (empty($header)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
}
if (empty($this->_basicResolver)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('A basicResolver object must be set before doing Basic '
. 'authentication');
}
// Decode the Authorization header
$auth = substr($header, strlen('Basic '));
$auth = base64_decode($auth);
if (!$auth) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Unable to base64_decode Authorization header value');
}
// See ZF-1253. Validate the credentials the same way the digest
// implementation does. If invalid credentials are detected,
// re-challenge the client.
if (!ctype_print($auth)) {
return $this->_challengeClient();
}
// Fix for ZF-1515: Now re-challenges on empty username or password
$creds = array_filter(explode(':', $auth));
if (count($creds) != 2) {
return $this->_challengeClient();
}
$password = $this->_basicResolver->resolve($creds[0], $this->_realm);
if ($password && $password == $creds[1]) {
$identity = array('username'=>$creds[0], 'realm'=>$this->_realm);
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
} else {
return $this->_challengeClient();
}
}
/**
* Digest Authentication
*
* @param string $header Client's Authorization header
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result Valid auth result only on successful auth
*/
protected function _digestAuth($header)
{
if (empty($header)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
}
if (empty($this->_digestResolver)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('A digestResolver object must be set before doing Digest authentication');
}
$data = $this->_parseDigestAuth($header);
if ($data === false) {
$this->_response->setHttpResponseCode(400);
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE_UNCATEGORIZED,
array(),
array('Invalid Authorization header format')
);
}
// See ZF-1052. This code was a bit too unforgiving of invalid
// usernames. Now, if the username is bad, we re-challenge the client.
if ('::invalid::' == $data['username']) {
return $this->_challengeClient();
}
// Verify that the client sent back the same nonce
if ($this->_calcNonce() != $data['nonce']) {
return $this->_challengeClient();
}
// The opaque value is also required to match, but of course IE doesn't
// play ball.
if (!$this->_ieNoOpaque && $this->_calcOpaque() != $data['opaque']) {
return $this->_challengeClient();
}
// Look up the user's password hash. If not found, deny access.
// This makes no assumptions about how the password hash was
// constructed beyond that it must have been built in such a way as
// to be recreatable with the current settings of this object.
$ha1 = $this->_digestResolver->resolve($data['username'], $data['realm']);
if ($ha1 === false) {
return $this->_challengeClient();
}
// If MD5-sess is used, a1 value is made of the user's password
// hash with the server and client nonce appended, separated by
// colons.
if ($this->_algo == 'MD5-sess') {
$ha1 = hash('md5', $ha1 . ':' . $data['nonce'] . ':' . $data['cnonce']);
}
// Calculate h(a2). The value of this hash depends on the qop
// option selected by the client and the supported hash functions
switch ($data['qop']) {
case 'auth':
$a2 = $this->_request->getMethod() . ':' . $data['uri'];
break;
case 'auth-int':
// Should be REQUEST_METHOD . ':' . uri . ':' . hash(entity-body),
// but this isn't supported yet, so fall through to default case
default:
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Client requested an unsupported qop option');
}
// Using hash() should make parameterizing the hash algorithm
// easier
$ha2 = hash('md5', $a2);
// Calculate the server's version of the request-digest. This must
// match $data['response']. See RFC 2617, section 3.2.2.1
$message = $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $ha2;
$digest = hash('md5', $ha1 . ':' . $message);
// If our digest matches the client's let them in, otherwise return
// a 401 code and exit to prevent access to the protected resource.
if ($digest == $data['response']) {
$identity = array('username'=>$data['username'], 'realm'=>$data['realm']);
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
} else {
return $this->_challengeClient();
}
}
/**
* Calculate Nonce
*
* @return string The nonce value
*/
protected function _calcNonce()
{
// Once subtle consequence of this timeout calculation is that it
// actually divides all of time into _nonceTimeout-sized sections, such
// that the value of timeout is the point in time of the next
// approaching "boundary" of a section. This allows the server to
// consistently generate the same timeout (and hence the same nonce
// value) across requests, but only as long as one of those
// "boundaries" is not crossed between requests. If that happens, the
// nonce will change on its own, and effectively log the user out. This
// would be surprising if the user just logged in.
$timeout = ceil(time() / $this->_nonceTimeout) * $this->_nonceTimeout;
$nonce = hash('md5', $timeout . ':' . $this->_request->getServer('HTTP_USER_AGENT') . ':' . __CLASS__);
return $nonce;
}
/**
* Calculate Opaque
*
* The opaque string can be anything; the client must return it exactly as
* it was sent. It may be useful to store data in this string in some
* applications. Ideally, a new value for this would be generated each time
* a WWW-Authenticate header is sent (in order to reduce predictability),
* but we would have to be able to create the same exact value across at
* least two separate requests from the same client.
*
* @return string The opaque value
*/
protected function _calcOpaque()
{
return hash('md5', 'Opaque Data:' . __CLASS__);
}
/**
* Parse Digest Authorization header
*
* @param string $header Client's Authorization: HTTP header
* @return array|false Data elements from header, or false if any part of
* the header is invalid
*/
protected function _parseDigestAuth($header)
{
$temp = null;
$data = array();
// See ZF-1052. Detect invalid usernames instead of just returning a
// 400 code.
$ret = preg_match('/username="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])
|| !ctype_print($temp[1])
|| strpos($temp[1], ':') !== false) {
$data['username'] = '::invalid::';
} else {
$data['username'] = $temp[1];
}
$temp = null;
$ret = preg_match('/realm="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (!ctype_print($temp[1]) || strpos($temp[1], ':') !== false) {
return false;
} else {
$data['realm'] = $temp[1];
}
$temp = null;
$ret = preg_match('/nonce="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (!ctype_xdigit($temp[1])) {
return false;
} else {
$data['nonce'] = $temp[1];
}
$temp = null;
$ret = preg_match('/uri="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
// Section 3.2.2.5 in RFC 2617 says the authenticating server must
// verify that the URI field in the Authorization header is for the
// same resource requested in the Request Line.
$rUri = @parse_url($this->_request->getRequestUri());
$cUri = @parse_url($temp[1]);
if (false === $rUri || false === $cUri) {
return false;
} else {
// Make sure the path portion of both URIs is the same
if ($rUri['path'] != $cUri['path']) {
return false;
}
// Section 3.2.2.5 seems to suggest that the value of the URI
// Authorization field should be made into an absolute URI if the
// Request URI is absolute, but it's vague, and that's a bunch of
// code I don't want to write right now.
$data['uri'] = $temp[1];
}
$temp = null;
$ret = preg_match('/response="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (32 != strlen($temp[1]) || !ctype_xdigit($temp[1])) {
return false;
} else {
$data['response'] = $temp[1];
}
$temp = null;
// The spec says this should default to MD5 if omitted. OK, so how does
// that square with the algo we send out in the WWW-Authenticate header,
// if it can easily be overridden by the client?
$ret = preg_match('/algorithm="?(' . $this->_algo . ')"?/', $header, $temp);
if ($ret && !empty($temp[1])
&& in_array($temp[1], $this->_supportedAlgos)) {
$data['algorithm'] = $temp[1];
} else {
$data['algorithm'] = 'MD5'; // = $this->_algo; ?
}
$temp = null;
// Not optional in this implementation
$ret = preg_match('/cnonce="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (!ctype_print($temp[1])) {
return false;
} else {
$data['cnonce'] = $temp[1];
}
$temp = null;
// If the server sent an opaque value, the client must send it back
if ($this->_useOpaque) {
$ret = preg_match('/opaque="([^"]+)"/', $header, $temp);
if (!$ret || empty($temp[1])) {
// Big surprise: IE isn't RFC 2617-compliant.
if (false !== strpos($this->_request->getHeader('User-Agent'), 'MSIE')) {
$temp[1] = '';
$this->_ieNoOpaque = true;
} else {
return false;
}
}
// This implementation only sends MD5 hex strings in the opaque value
if (!$this->_ieNoOpaque &&
(32 != strlen($temp[1]) || !ctype_xdigit($temp[1]))) {
return false;
} else {
$data['opaque'] = $temp[1];
}
$temp = null;
}
// Not optional in this implementation, but must be one of the supported
// qop types
$ret = preg_match('/qop="?(' . implode('|', $this->_supportedQops) . ')"?/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (!in_array($temp[1], $this->_supportedQops)) {
return false;
} else {
$data['qop'] = $temp[1];
}
$temp = null;
// Not optional in this implementation. The spec says this value
// shouldn't be a quoted string, but apparently some implementations
// quote it anyway. See ZF-1544.
$ret = preg_match('/nc="?([0-9A-Fa-f]{8})"?/', $header, $temp);
if (!$ret || empty($temp[1])) {
return false;
}
if (8 != strlen($temp[1]) || !ctype_xdigit($temp[1])) {
return false;
} else {
$data['nc'] = $temp[1];
}
$temp = null;
return $data;
}
}
@@ -0,0 +1,40 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Exception
*/
require_once 'Zend/Auth/Exception.php';
/**
* HTTP Auth Resolver Exception
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Http_Resolver_Exception extends Zend_Auth_Exception
{}
@@ -0,0 +1,167 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Http_Resolver_Interface
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Interface.php';
/**
* HTTP Authentication File Resolver
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Resolver_Interface
{
/**
* Path to credentials file
*
* @var string
*/
protected $_file;
/**
* Constructor
*
* @param string $path Complete filename where the credentials are stored
* @return void
*/
public function __construct($path = '')
{
if (!empty($path)) {
$this->setFile($path);
}
}
/**
* Set the path to the credentials file
*
* @param string $path
* @throws Zend_Auth_Adapter_Http_Resolver_Exception
* @return Zend_Auth_Adapter_Http_Resolver_File Provides a fluent interface
*/
public function setFile($path)
{
if (empty($path) || !is_readable($path)) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Path not readable: ' . $path);
}
$this->_file = $path;
return $this;
}
/**
* Returns the path to the credentials file
*
* @return string
*/
public function getFile()
{
return $this->_file;
}
/**
* Resolve credentials
*
* Only the first matching username/realm combination in the file is
* returned. If the file contains credentials for Digest authentication,
* the returned string is the password hash, or h(a1) from RFC 2617. The
* returned string is the plain-text password for Basic authentication.
*
* The expected format of the file is:
* username:realm:sharedSecret
*
* That is, each line consists of the user's username, the applicable
* authentication realm, and the password or hash, each delimited by
* colons.
*
* @param string $username Username
* @param string $realm Authentication Realm
* @throws Zend_Auth_Adapter_Http_Resolver_Exception
* @return string|false User's shared secret, if the user is found in the
* realm, false otherwise.
*/
public function resolve($username, $realm)
{
if (empty($username)) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username is required');
} else if (!ctype_print($username) || strpos($username, ':') !== false) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username must consist only of printable characters, '
. 'excluding the colon');
}
if (empty($realm)) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm is required');
} else if (!ctype_print($realm) || strpos($realm, ':') !== false) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm must consist only of printable characters, '
. 'excluding the colon.');
}
// Open file, read through looking for matching credentials
$fp = @fopen($this->_file, 'r');
if (!$fp) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Unable to open password file: ' . $this->_file);
}
// No real validation is done on the contents of the password file. The
// assumption is that we trust the administrators to keep it secure.
while (($line = fgetcsv($fp, 512, ':')) !== false) {
if ($line[0] == $username && $line[1] == $realm) {
$password = $line[2];
fclose($fp);
return $password;
}
}
fclose($fp);
return false;
}
}
@@ -0,0 +1,47 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* Auth HTTP Resolver Interface
*
* Defines an interace to resolve a username/realm combination into a shared
* secret usable by HTTP Authentication.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Adapter_Http_Resolver_Interface
{
/**
* Resolve username/realm to password/hash/etc.
*
* @param string $username Username
* @param string $realm Authentication Realm
* @return string|false User's shared secret, if the user is found in the
* realm, false otherwise.
*/
public function resolve($username, $realm);
}
+261
View File
@@ -0,0 +1,261 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_Auth_Result
*/
require_once 'Zend/Auth/Result.php';
/**
* @see Zend_InfoCard
*/
require_once 'Zend/InfoCard.php';
/**
* A Zend_Auth Authentication Adapter allowing the use of Information Cards as an
* authentication mechanism
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_InfoCard implements Zend_Auth_Adapter_Interface
{
/**
* The XML Token being authenticated
*
* @var string
*/
protected $_xmlToken;
/**
* The instance of Zend_InfoCard
*
* @var Zend_InfoCard
*/
protected $_infoCard;
/**
* Constructor
*
* @param string $strXmlDocument The XML Token provided by the client
* @return void
*/
public function __construct($strXmlDocument)
{
$this->_xmlToken = $strXmlDocument;
$this->_infoCard = new Zend_InfoCard();
}
/**
* Sets the InfoCard component Adapter to use
*
* @param Zend_InfoCard_Adapter_Interface $a
* @return Zend_Auth_Adapter_InfoCard Provides a fluent interface
*/
public function setAdapter(Zend_InfoCard_Adapter_Interface $a)
{
$this->_infoCard->setAdapter($a);
return $this;
}
/**
* Retrieves the InfoCard component adapter being used
*
* @return Zend_InfoCard_Adapter_Interface
*/
public function getAdapter()
{
return $this->_infoCard->getAdapter();
}
/**
* Retrieves the InfoCard public key cipher object being used
*
* @return Zend_InfoCard_Cipher_PKI_Interface
*/
public function getPKCipherObject()
{
return $this->_infoCard->getPKCipherObject();
}
/**
* Sets the InfoCard public key cipher object to use
*
* @param Zend_InfoCard_Cipher_PKI_Interface $cipherObj
* @return Zend_Auth_Adapter_InfoCard Provides a fluent interface
*/
public function setPKICipherObject(Zend_InfoCard_Cipher_PKI_Interface $cipherObj)
{
$this->_infoCard->setPKICipherObject($cipherObj);
return $this;
}
/**
* Retrieves the Symmetric cipher object being used
*
* @return Zend_InfoCard_Cipher_Symmetric_Interface
*/
public function getSymCipherObject()
{
return $this->_infoCard->getSymCipherObject();
}
/**
* Sets the InfoCard symmetric cipher object to use
*
* @param Zend_InfoCard_Cipher_Symmetric_Interface $cipherObj
* @return Zend_Auth_Adapter_InfoCard Provides a fluent interface
*/
public function setSymCipherObject(Zend_InfoCard_Cipher_Symmetric_Interface $cipherObj)
{
$this->_infoCard->setSymCipherObject($cipherObj);
return $this;
}
/**
* Remove a Certificate Pair by Key ID from the search list
*
* @param string $key_id The Certificate Key ID returned from adding the certificate pair
* @throws Zend_InfoCard_Exception
* @return Zend_Auth_Adapter_InfoCard Provides a fluent interface
*/
public function removeCertificatePair($key_id)
{
$this->_infoCard->removeCertificatePair($key_id);
return $this;
}
/**
* Add a Certificate Pair to the list of certificates searched by the component
*
* @param string $private_key_file The path to the private key file for the pair
* @param string $public_key_file The path to the certificate / public key for the pair
* @param string $type (optional) The URI for the type of key pair this is (default RSA with OAEP padding)
* @param string $password (optional) The password for the private key file if necessary
* @throws Zend_InfoCard_Exception
* @return string A key ID representing this key pair in the component
*/
public function addCertificatePair($private_key_file, $public_key_file, $type = Zend_InfoCard_Cipher::ENC_RSA_OAEP_MGF1P, $password = null)
{
return $this->_infoCard->addCertificatePair($private_key_file, $public_key_file, $type, $password);
}
/**
* Return a Certificate Pair from a key ID
*
* @param string $key_id The Key ID of the certificate pair in the component
* @throws Zend_InfoCard_Exception
* @return array An array containing the path to the private/public key files,
* the type URI and the password if provided
*/
public function getCertificatePair($key_id)
{
return $this->_infoCard->getCertificatePair($key_id);
}
/**
* Set the XML Token to be processed
*
* @param string $strXmlToken The XML token to process
* @return Zend_Auth_Adapter_InfoCard Provides a fluent interface
*/
public function setXmlToken($strXmlToken)
{
$this->_xmlToken = $strXmlToken;
return $this;
}
/**
* Get the XML Token being processed
*
* @return string The XML token to be processed
*/
public function getXmlToken()
{
return $this->_xmlToken;
}
/**
* Authenticates the XML token
*
* @return Zend_Auth_Result The result of the authentication
*/
public function authenticate()
{
try {
$claims = $this->_infoCard->process($this->getXmlToken());
} catch(Exception $e) {
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE , null, array('Exception Thrown',
$e->getMessage(),
$e->getTraceAsString(),
serialize($e)));
}
if(!$claims->isValid()) {
switch($claims->getCode()) {
case Zend_infoCard_Claims::RESULT_PROCESSING_FAILURE:
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$claims,
array(
'Processing Failure',
$claims->getErrorMsg()
)
);
break;
case Zend_InfoCard_Claims::RESULT_VALIDATION_FAILURE:
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID,
$claims,
array(
'Validation Failure',
$claims->getErrorMsg()
)
);
break;
default:
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$claims,
array(
'Unknown Failure',
$claims->getErrorMsg()
)
);
break;
}
}
return new Zend_Auth_Result(
Zend_Auth_Result::SUCCESS,
$claims
);
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Result
*/
require_once 'Zend/Auth/Result.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Adapter_Interface
{
/**
* Performs an authentication attempt
*
* @throws Zend_Auth_Adapter_Exception If authentication cannot be performed
* @return Zend_Auth_Result
*/
public function authenticate();
}
+512
View File
@@ -0,0 +1,512 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
{
/**
* The Zend_Ldap context.
*
* @var Zend_Ldap
*/
protected $_ldap = null;
/**
* The array of arrays of Zend_Ldap options passed to the constructor.
*
* @var array
*/
protected $_options = null;
/**
* The username of the account being authenticated.
*
* @var string
*/
protected $_username = null;
/**
* The password of the account being authenticated.
*
* @var string
*/
protected $_password = null;
/**
* The DN of the authenticated account. Used to retrieve the account entry on request.
*
* @var string
*/
protected $_authenticatedDn = null;
/**
* Constructor
*
* @param array $options An array of arrays of Zend_Ldap options
* @param string $username The username of the account being authenticated
* @param string $password The password of the account being authenticated
* @return void
*/
public function __construct(array $options = array(), $username = null, $password = null)
{
$this->setOptions($options);
if ($username !== null) {
$this->setUsername($username);
}
if ($password !== null) {
$this->setPassword($password);
}
}
/**
* Returns the array of arrays of Zend_Ldap options of this adapter.
*
* @return array|null
*/
public function getOptions()
{
return $this->_options;
}
/**
* Sets the array of arrays of Zend_Ldap options to be used by
* this adapter.
*
* @param array $options The array of arrays of Zend_Ldap options
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setOptions($options)
{
$this->_options = is_array($options) ? $options : array();
return $this;
}
/**
* Returns the username of the account being authenticated, or
* NULL if none is set.
*
* @return string|null
*/
public function getUsername()
{
return $this->_username;
}
/**
* Sets the username for binding
*
* @param string $username The username for binding
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setUsername($username)
{
$this->_username = (string) $username;
return $this;
}
/**
* Returns the password of the account being authenticated, or
* NULL if none is set.
*
* @return string|null
*/
public function getPassword()
{
return $this->_password;
}
/**
* Sets the passwort for the account
*
* @param string $password The password of the account being authenticated
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setPassword($password)
{
$this->_password = (string) $password;
return $this;
}
/**
* setIdentity() - set the identity (username) to be used
*
* Proxies to {@see setPassword()}
*
* Closes ZF-6813
*
* @param string $identity
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setIdentity($identity)
{
return $this->setUsername($identity);
}
/**
* setCredential() - set the credential (password) value to be used
*
* Proxies to {@see setPassword()}
*
* Closes ZF-6813
*
* @param string $credential
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setCredential($credential)
{
return $this->setPassword($credential);
}
/**
* Returns the LDAP Object
*
* @return Zend_Ldap The Zend_Ldap object used to authenticate the credentials
*/
public function getLdap()
{
if ($this->_ldap === null) {
/**
* @see Zend_Ldap
*/
require_once 'Zend/Ldap.php';
$this->_ldap = new Zend_Ldap();
}
return $this->_ldap;
}
/**
* Set an Ldap connection
*
* @param Zend_Ldap $ldap An existing Ldap object
* @return Zend_Auth_Adapter_Ldap Provides a fluent interface
*/
public function setLdap(Zend_Ldap $ldap)
{
$this->_ldap = $ldap;
$this->setOptions(array($ldap->getOptions()));
return $this;
}
/**
* Returns a domain name for the current LDAP options. This is used
* for skipping redundant operations (e.g. authentications).
*
* @return string
*/
protected function _getAuthorityName()
{
$options = $this->getLdap()->getOptions();
$name = $options['accountDomainName'];
if (!$name)
$name = $options['accountDomainNameShort'];
return $name ? $name : '';
}
/**
* Authenticate the user
*
* @throws Zend_Auth_Adapter_Exception
* @return Zend_Auth_Result
*/
public function authenticate()
{
/**
* @see Zend_Ldap_Exception
*/
require_once 'Zend/Ldap/Exception.php';
$messages = array();
$messages[0] = ''; // reserved
$messages[1] = ''; // reserved
$username = $this->_username;
$password = $this->_password;
if (!$username) {
$code = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
$messages[0] = 'A username is required';
return new Zend_Auth_Result($code, '', $messages);
}
if (!$password) {
/* A password is required because some servers will
* treat an empty password as an anonymous bind.
*/
$code = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$messages[0] = 'A password is required';
return new Zend_Auth_Result($code, '', $messages);
}
$ldap = $this->getLdap();
$code = Zend_Auth_Result::FAILURE;
$messages[0] = "Authority not found: $username";
$failedAuthorities = array();
/* Iterate through each server and try to authenticate the supplied
* credentials against it.
*/
foreach ($this->_options as $name => $options) {
if (!is_array($options)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Adapter options array not in array');
}
$adapterOptions = $this->_prepareOptions($ldap, $options);
$dname = '';
try {
if ($messages[1])
$messages[] = $messages[1];
$messages[1] = '';
$messages[] = $this->_optionsToString($options);
$dname = $this->_getAuthorityName();
if (isset($failedAuthorities[$dname])) {
/* If multiple sets of server options for the same domain
* are supplied, we want to skip redundant authentications
* where the identity or credentials where found to be
* invalid with another server for the same domain. The
* $failedAuthorities array tracks this condition (and also
* serves to supply the original error message).
* This fixes issue ZF-4093.
*/
$messages[1] = $failedAuthorities[$dname];
$messages[] = "Skipping previously failed authority: $dname";
continue;
}
$canonicalName = $ldap->getCanonicalAccountName($username);
$ldap->bind($canonicalName, $password);
$dn = $ldap->getCanonicalAccountName($canonicalName, Zend_Ldap::ACCTNAME_FORM_DN);
$groupResult = $this->_checkGroupMembership($ldap, $canonicalName, $dn, $adapterOptions);
if ($groupResult === true) {
$this->_authenticatedDn = $dn;
$messages[0] = '';
$messages[1] = '';
$messages[] = "$canonicalName authentication successful";
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $canonicalName, $messages);
} else {
$messages[0] = 'Account is not a member of the specified group';
$messages[1] = $groupResult;
$failedAuthorities[$dname] = $groupResult;
}
} catch (Zend_Ldap_Exception $zle) {
/* LDAP based authentication is notoriously difficult to diagnose. Therefore
* we bend over backwards to capture and record every possible bit of
* information when something goes wrong.
*/
$err = $zle->getCode();
if ($err == Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) {
/* This error indicates that the domain supplied in the
* username did not match the domains in the server options
* and therefore we should just skip to the next set of
* server options.
*/
continue;
} else if ($err == Zend_Ldap_Exception::LDAP_NO_SUCH_OBJECT) {
$code = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
$messages[0] = "Account not found: $username";
$failedAuthorities[$dname] = $zle->getMessage();
} else if ($err == Zend_Ldap_Exception::LDAP_INVALID_CREDENTIALS) {
$code = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$messages[0] = 'Invalid credentials';
$failedAuthorities[$dname] = $zle->getMessage();
} else {
$line = $zle->getLine();
$messages[] = $zle->getFile() . "($line): " . $zle->getMessage();
$messages[] = str_replace($password, '*****', $zle->getTraceAsString());
$messages[0] = 'An unexpected failure occurred';
}
$messages[1] = $zle->getMessage();
}
}
$msg = isset($messages[1]) ? $messages[1] : $messages[0];
$messages[] = "$username authentication failed: $msg";
return new Zend_Auth_Result($code, $username, $messages);
}
/**
* Sets the LDAP specific options on the Zend_Ldap instance
*
* @param Zend_Ldap $ldap
* @param array $options
* @return array of auth-adapter specific options
*/
protected function _prepareOptions(Zend_Ldap $ldap, array $options)
{
$adapterOptions = array(
'group' => null,
'groupDn' => $ldap->getBaseDn(),
'groupScope' => Zend_Ldap::SEARCH_SCOPE_SUB,
'groupAttr' => 'cn',
'groupFilter' => 'objectClass=groupOfUniqueNames',
'memberAttr' => 'uniqueMember',
'memberIsDn' => true
);
foreach ($adapterOptions as $key => $value) {
if (array_key_exists($key, $options)) {
$value = $options[$key];
unset($options[$key]);
switch ($key) {
case 'groupScope':
$value = (int)$value;
if (in_array($value, array(Zend_Ldap::SEARCH_SCOPE_BASE,
Zend_Ldap::SEARCH_SCOPE_ONE, Zend_Ldap::SEARCH_SCOPE_SUB), true)) {
$adapterOptions[$key] = $value;
}
break;
case 'memberIsDn':
$adapterOptions[$key] = ($value === true ||
$value === '1' || strcasecmp($value, 'true') == 0);
break;
default:
$adapterOptions[$key] = trim($value);
break;
}
}
}
$ldap->setOptions($options);
return $adapterOptions;
}
/**
* Checks the group membership of the bound user
*
* @param Zend_Ldap $ldap
* @param string $canonicalName
* @param string $dn
* @param array $adapterOptions
* @return string|true
*/
protected function _checkGroupMembership(Zend_Ldap $ldap, $canonicalName, $dn, array $adapterOptions)
{
if ($adapterOptions['group'] === null) {
return true;
}
if ($adapterOptions['memberIsDn'] === false) {
$user = $canonicalName;
} else {
$user = $dn;
}
/**
* @see Zend_Ldap_Filter
*/
require_once 'Zend/Ldap/Filter.php';
$groupName = Zend_Ldap_Filter::equals($adapterOptions['groupAttr'], $adapterOptions['group']);
$membership = Zend_Ldap_Filter::equals($adapterOptions['memberAttr'], $user);
$group = Zend_Ldap_Filter::andFilter($groupName, $membership);
$groupFilter = $adapterOptions['groupFilter'];
if (!empty($groupFilter)) {
$group = $group->addAnd($groupFilter);
}
/*
* Fixes problem when authenticated user is not allowed to retrieve
* group-membership information.
* This requires that the user specified with "username" and "password"
* in the Zend_Ldap options is able to retrieve the required information.
*/
$ldap->bind();
$result = $ldap->count($group, $adapterOptions['groupDn'], $adapterOptions['groupScope']);
if ($result === 1) {
return true;
} else {
return 'Failed to verify group membership with ' . $group->toString();
}
}
/**
* getAccountObject() - Returns the result entry as a stdClass object
*
* This ressembles the feature {@see Zend_Auth_Adapter_DbTable::getResultRowObject()}.
* Closes ZF-6813
*
* @param array $returnAttribs
* @return stdClass|boolean
*/
public function getAccountObject(array $returnAttribs = array())
{
if (!$this->_authenticatedDn) {
return false;
}
$returnObject = new stdClass();
$entry = $this->getLdap()->getEntry($this->_authenticatedDn, $returnAttribs, true);
foreach ($entry as $attr => $value) {
if (is_array($value)) {
$returnObject->$attr = (count($value) > 1) ? $value : $value[0];
} else {
$returnObject->$attr = $value;
}
}
return $returnObject;
}
/**
* Converts options to string
*
* @param array $options
* @return string
*/
private function _optionsToString(array $options)
{
$str = '';
foreach ($options as $key => $val) {
if ($key === 'password')
$val = '*****';
if ($str)
$str .= ',';
$str .= $key . '=' . $val;
}
return $str;
}
}
+284
View File
@@ -0,0 +1,284 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_OpenId_Consumer
*/
require_once 'Zend/OpenId/Consumer.php';
/**
* A Zend_Auth Authentication Adapter allowing the use of OpenID protocol as an
* authentication mechanism
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_OpenId implements Zend_Auth_Adapter_Interface
{
/**
* The identity value being authenticated
*
* @var string
*/
private $_id = null;
/**
* Reference to an implementation of a storage object
*
* @var Zend_OpenId_Consumer_Storage
*/
private $_storage = null;
/**
* The URL to redirect response from server to
*
* @var string
*/
private $_returnTo = null;
/**
* The HTTP URL to identify consumer on server
*
* @var string
*/
private $_root = null;
/**
* Extension object or array of extensions objects
*
* @var string
*/
private $_extensions = null;
/**
* The response object to perform HTTP or HTML form redirection
*
* @var Zend_Controller_Response_Abstract
*/
private $_response = null;
/**
* Enables or disables interaction with user during authentication on
* OpenID provider.
*
* @var bool
*/
private $_check_immediate = false;
/**
* HTTP client to make HTTP requests
*
* @var Zend_Http_Client $_httpClient
*/
private $_httpClient = null;
/**
* Constructor
*
* @param string $id the identity value
* @param Zend_OpenId_Consumer_Storage $storage an optional implementation
* of a storage object
* @param string $returnTo HTTP URL to redirect response from server to
* @param string $root HTTP URL to identify consumer on server
* @param mixed $extensions extension object or array of extensions objects
* @param Zend_Controller_Response_Abstract $response an optional response
* object to perform HTTP or HTML form redirection
* @return void
*/
public function __construct($id = null,
Zend_OpenId_Consumer_Storage $storage = null,
$returnTo = null,
$root = null,
$extensions = null,
Zend_Controller_Response_Abstract $response = null) {
$this->_id = $id;
$this->_storage = $storage;
$this->_returnTo = $returnTo;
$this->_root = $root;
$this->_extensions = $extensions;
$this->_response = $response;
}
/**
* Sets the value to be used as the identity
*
* @param string $id the identity value
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setIdentity($id)
{
$this->_id = $id;
return $this;
}
/**
* Sets the storage implementation which will be use by OpenId
*
* @param Zend_OpenId_Consumer_Storage $storage
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setStorage(Zend_OpenId_Consumer_Storage $storage)
{
$this->_storage = $storage;
return $this;
}
/**
* Sets the HTTP URL to redirect response from server to
*
* @param string $returnTo
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setReturnTo($returnTo)
{
$this->_returnTo = $returnTo;
return $this;
}
/**
* Sets HTTP URL to identify consumer on server
*
* @param string $root
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setRoot($root)
{
$this->_root = $root;
return $this;
}
/**
* Sets OpenID extension(s)
*
* @param mixed $extensions
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setExtensions($extensions)
{
$this->_extensions = $extensions;
return $this;
}
/**
* Sets an optional response object to perform HTTP or HTML form redirection
*
* @param string $root
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setResponse($response)
{
$this->_response = $response;
return $this;
}
/**
* Enables or disables interaction with user during authentication on
* OpenID provider.
*
* @param bool $check_immediate
* @return Zend_Auth_Adapter_OpenId Provides a fluent interface
*/
public function setCheckImmediate($check_immediate)
{
$this->_check_immediate = $check_immediate;
return $this;
}
/**
* Sets HTTP client object to make HTTP requests
*
* @param Zend_Http_Client $client HTTP client object to be used
*/
public function setHttpClient($client) {
$this->_httpClient = $client;
}
/**
* Authenticates the given OpenId identity.
* Defined by Zend_Auth_Adapter_Interface.
*
* @throws Zend_Auth_Adapter_Exception If answering the authentication query is impossible
* @return Zend_Auth_Result
*/
public function authenticate() {
$id = $this->_id;
if (!empty($id)) {
$consumer = new Zend_OpenId_Consumer($this->_storage);
$consumer->setHttpClient($this->_httpClient);
/* login() is never returns on success */
if (!$this->_check_immediate) {
if (!$consumer->login($id,
$this->_returnTo,
$this->_root,
$this->_extensions,
$this->_response)) {
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$id,
array("Authentication failed", $consumer->getError()));
}
} else {
if (!$consumer->check($id,
$this->_returnTo,
$this->_root,
$this->_extensions,
$this->_response)) {
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$id,
array("Authentication failed", $consumer->getError()));
}
}
} else {
$params = (isset($_SERVER['REQUEST_METHOD']) &&
$_SERVER['REQUEST_METHOD']=='POST') ? $_POST: $_GET;
$consumer = new Zend_OpenId_Consumer($this->_storage);
$consumer->setHttpClient($this->_httpClient);
if ($consumer->verify(
$params,
$id,
$this->_extensions)) {
return new Zend_Auth_Result(
Zend_Auth_Result::SUCCESS,
$id,
array("Authentication successful"));
} else {
return new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$id,
array("Authentication failed", $consumer->getError()));
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Exception
*/
require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Auth
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Exception extends Zend_Exception
{}
+148
View File
@@ -0,0 +1,148 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @category Zend
* @package Zend_Auth
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Result
{
/**
* General Failure
*/
const FAILURE = 0;
/**
* Failure due to identity not being found.
*/
const FAILURE_IDENTITY_NOT_FOUND = -1;
/**
* Failure due to identity being ambiguous.
*/
const FAILURE_IDENTITY_AMBIGUOUS = -2;
/**
* Failure due to invalid credential being supplied.
*/
const FAILURE_CREDENTIAL_INVALID = -3;
/**
* Failure due to uncategorized reasons.
*/
const FAILURE_UNCATEGORIZED = -4;
/**
* Authentication success.
*/
const SUCCESS = 1;
/**
* Authentication result code
*
* @var int
*/
protected $_code;
/**
* The identity used in the authentication attempt
*
* @var mixed
*/
protected $_identity;
/**
* An array of string reasons why the authentication attempt was unsuccessful
*
* If authentication was successful, this should be an empty array.
*
* @var array
*/
protected $_messages;
/**
* Sets the result code, identity, and failure messages
*
* @param int $code
* @param mixed $identity
* @param array $messages
* @return void
*/
public function __construct($code, $identity, array $messages = array())
{
$code = (int) $code;
if ($code < self::FAILURE_UNCATEGORIZED) {
$code = self::FAILURE;
} elseif ($code > self::SUCCESS ) {
$code = 1;
}
$this->_code = $code;
$this->_identity = $identity;
$this->_messages = $messages;
}
/**
* Returns whether the result represents a successful authentication attempt
*
* @return boolean
*/
public function isValid()
{
return ($this->_code > 0) ? true : false;
}
/**
* getCode() - Get the result code for this authentication attempt
*
* @return int
*/
public function getCode()
{
return $this->_code;
}
/**
* Returns the identity used in the authentication attempt
*
* @return mixed
*/
public function getIdentity()
{
return $this->_identity;
}
/**
* Returns an array of string reasons why the authentication attempt was unsuccessful
*
* If authentication was successful, this method returns an empty array.
*
* @return array
*/
public function getMessages()
{
return $this->_messages;
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Exception
*/
require_once 'Zend/Auth/Exception.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_Exception extends Zend_Auth_Exception
{}
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Storage_Interface
{
/**
* Returns true if and only if storage is empty
*
* @throws Zend_Auth_Storage_Exception If it is impossible to determine whether storage is empty
* @return boolean
*/
public function isEmpty();
/**
* Returns the contents of storage
*
* Behavior is undefined when storage is empty.
*
* @throws Zend_Auth_Storage_Exception If reading contents from storage is impossible
* @return mixed
*/
public function read();
/**
* Writes $contents to storage
*
* @param mixed $contents
* @throws Zend_Auth_Storage_Exception If writing $contents to storage is impossible
* @return void
*/
public function write($contents);
/**
* Clears contents from storage
*
* @throws Zend_Auth_Storage_Exception If clearing contents from storage is impossible
* @return void
*/
public function clear();
}
@@ -0,0 +1,96 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Storage_Interface
*/
require_once 'Zend/Auth/Storage/Interface.php';
/**
* Non-Persistent Auth Storage
*
* Since HTTP Authentication happens again on each request, this will always be
* re-populated. So there's no need to use sessions, this simple value class
* will hold the data for rest of the current request.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_NonPersistent implements Zend_Auth_Storage_Interface
{
/**
* Holds the actual auth data
*/
protected $_data;
/**
* Returns true if and only if storage is empty
*
* @throws Zend_Auth_Storage_Exception If it is impossible to determine whether storage is empty
* @return boolean
*/
public function isEmpty()
{
return empty($this->_data);
}
/**
* Returns the contents of storage
* Behavior is undefined when storage is empty.
*
* @throws Zend_Auth_Storage_Exception If reading contents from storage is impossible
* @return mixed
*/
public function read()
{
return $this->_data;
}
/**
* Writes $contents to storage
*
* @param mixed $contents
* @throws Zend_Auth_Storage_Exception If writing $contents to storage is impossible
* @return void
*/
public function write($contents)
{
$this->_data = $contents;
}
/**
* Clears contents from storage
*
* @throws Zend_Auth_Storage_Exception If clearing contents from storage is impossible
* @return void
*/
public function clear()
{
$this->_data = null;
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Auth_Storage_Interface
*/
require_once 'Zend/Auth/Storage/Interface.php';
/**
* @see Zend_Session
*/
require_once 'Zend/Session.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Storage
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_Session implements Zend_Auth_Storage_Interface
{
/**
* Default session namespace
*/
const NAMESPACE_DEFAULT = 'Zend_Auth';
/**
* Default session object member name
*/
const MEMBER_DEFAULT = 'storage';
/**
* Object to proxy $_SESSION storage
*
* @var Zend_Session_Namespace
*/
protected $_session;
/**
* Session namespace
*
* @var mixed
*/
protected $_namespace;
/**
* Session object member
*
* @var mixed
*/
protected $_member;
/**
* Sets session storage options and initializes session namespace object
*
* @param mixed $namespace
* @param mixed $member
* @return void
*/
public function __construct($namespace = self::NAMESPACE_DEFAULT, $member = self::MEMBER_DEFAULT)
{
$this->_namespace = $namespace;
$this->_member = $member;
$this->_session = new Zend_Session_Namespace($this->_namespace);
}
/**
* Returns the session namespace
*
* @return string
*/
public function getNamespace()
{
return $this->_namespace;
}
/**
* Returns the name of the session object member
*
* @return string
*/
public function getMember()
{
return $this->_member;
}
/**
* Defined by Zend_Auth_Storage_Interface
*
* @return boolean
*/
public function isEmpty()
{
return !isset($this->_session->{$this->_member});
}
/**
* Defined by Zend_Auth_Storage_Interface
*
* @return mixed
*/
public function read()
{
return $this->_session->{$this->_member};
}
/**
* Defined by Zend_Auth_Storage_Interface
*
* @param mixed $contents
* @return void
*/
public function write($contents)
{
$this->_session->{$this->_member} = $contents;
}
/**
* Defined by Zend_Auth_Storage_Interface
*
* @return void
*/
public function clear()
{
unset($this->_session->{$this->_member});
}
}
+272
View File
@@ -0,0 +1,272 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend
{
/**
* Frontend or Core directives
*
* =====> (int) lifetime :
* - Cache lifetime (in seconds)
* - If null, the cache is valid forever
*
* =====> (int) logging :
* - if set to true, a logging is activated throw Zend_Log
*
* @var array directives
*/
protected $_directives = array(
'lifetime' => 3600,
'logging' => false,
'logger' => null
);
/**
* Available options
*
* @var array available options
*/
protected $_options = array();
/**
* Constructor
*
* @param array $options Associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
while (list($name, $value) = each($options)) {
$this->setOption($name, $value);
}
}
/**
* Set the frontend directives
*
* @param array $directives Assoc of directives
* @throws Zend_Cache_Exception
* @return void
*/
public function setDirectives($directives)
{
if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');
while (list($name, $value) = each($directives)) {
if (!is_string($name)) {
Zend_Cache::throwException("Incorrect option name : $name");
}
$name = strtolower($name);
if (array_key_exists($name, $this->_directives)) {
$this->_directives[$name] = $value;
}
}
$this->_loggerSanity();
}
/**
* Set an option
*
* @param string $name
* @param mixed $value
* @throws Zend_Cache_Exception
* @return void
*/
public function setOption($name, $value)
{
if (!is_string($name)) {
Zend_Cache::throwException("Incorrect option name : $name");
}
$name = strtolower($name);
if (array_key_exists($name, $this->_options)) {
$this->_options[$name] = $value;
}
}
/**
* Get the life time
*
* if $specificLifetime is not false, the given specific life time is used
* else, the global lifetime is used
*
* @param int $specificLifetime
* @return int Cache life time
*/
public function getLifetime($specificLifetime)
{
if ($specificLifetime === false) {
return $this->_directives['lifetime'];
}
return $specificLifetime;
}
/**
* Return true if the automatic cleaning is available for the backend
*
* DEPRECATED : use getCapabilities() instead
*
* @deprecated
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return true;
}
/**
* Determine system TMP directory and detect if we have read access
*
* inspired from Zend_File_Transfer_Adapter_Abstract
*
* @return string
* @throws Zend_Cache_Exception if unable to determine directory
*/
public function getTmpDir()
{
$tmpdir = array();
foreach (array($_ENV, $_SERVER) as $tab) {
foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
if (isset($tab[$key])) {
if (($key == 'windir') or ($key == 'SystemRoot')) {
$dir = realpath($tab[$key] . '\\temp');
} else {
$dir = realpath($tab[$key]);
}
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
}
}
$upload = ini_get('upload_tmp_dir');
if ($upload) {
$dir = realpath($upload);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if (function_exists('sys_get_temp_dir')) {
$dir = sys_get_temp_dir();
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
// Attemp to detect by creating a temporary file
$tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
if ($tempFile) {
$dir = realpath(dirname($tempFile));
unlink($tempFile);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if ($this->_isGoodTmpDir('/tmp')) {
return '/tmp';
}
if ($this->_isGoodTmpDir('\\temp')) {
return '\\temp';
}
Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
}
/**
* Verify if the given temporary directory is readable and writable
*
* @param $dir temporary directory
* @return boolean true if the directory is ok
*/
protected function _isGoodTmpDir($dir)
{
if (is_readable($dir)) {
if (is_writable($dir)) {
return true;
}
}
return false;
}
/**
* Make sure if we enable logging that the Zend_Log class
* is available.
* Create a default log object if none is set.
*
* @throws Zend_Cache_Exception
* @return void
*/
protected function _loggerSanity()
{
if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
return;
}
try {
/**
* @see Zend_Log
*/
require_once 'Zend/Log.php';
} catch (Zend_Exception $e) {
Zend_Cache::throwException('Logging feature is enabled but the Zend_Log class is not available');
}
if (isset($this->_directives['logger'])) {
if ($this->_directives['logger'] instanceof Zend_Log) {
return;
} else {
Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
}
}
// Create a default logger to the standard output stream
require_once 'Zend/Log/Writer/Stream.php';
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
$this->_directives['logger'] = $logger;
}
/**
* Log a message at the WARN (4) priority.
*
* @param string $message
* @throws Zend_Cache_Exception
* @return void
*/
protected function _log($message, $priority = 4)
{
if (!$this->_directives['logging']) {
return;
}
if (!isset($this->_directives['logger'])) {
Zend_Cache::throwException('Logging is enabled but logger is not set.');
}
$logger = $this->_directives['logger'];
if (!$logger instanceof Zend_Log) {
Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
}
$logger->log($message, $priority);
}
}
+355
View File
@@ -0,0 +1,355 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Log message
*/
const TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::clean() : tags are unsupported by the Apc backend';
const TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND = 'Zend_Cache_Backend_Apc::save() : tags are unsupported by the Apc backend';
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
if (!extension_loaded('apc')) {
Zend_Cache::throwException('The apc extension must be loaded for using this backend !');
}
parent::__construct($options);
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* WARNING $doNotTestCacheValidity=true is unsupported by the Apc backend
*
* @param string $id cache id
* @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
* @return string cached datas (or false)
*/
public function load($id, $doNotTestCacheValidity = false)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
return $tmp[0];
}
return false;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
return $tmp[1];
}
return false;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data datas to cache
* @param string $id cache id
* @param array $tags array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$lifetime = $this->getLifetime($specificLifetime);
$result = apc_store($id, array($data, time(), $lifetime), $lifetime);
if (count($tags) > 0) {
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
}
return $result;
}
/**
* Remove a cache record
*
* @param string $id cache id
* @return boolean true if no problem
*/
public function remove($id)
{
return apc_delete($id);
}
/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => unsupported
* 'matchingTag' => unsupported
* 'notMatchingTag' => unsupported
* 'matchingAnyTag' => unsupported
*
* @param string $mode clean mode
* @param array $tags array of tags
* @throws Zend_Cache_Exception
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
return apc_clear_cache('user');
break;
case Zend_Cache::CLEANING_MODE_OLD:
$this->_log("Zend_Cache_Backend_Apc::clean() : CLEANING_MODE_OLD is unsupported by the Apc backend");
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_APC_BACKEND);
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
/**
* Return true if the automatic cleaning is available for the backend
*
* DEPRECATED : use getCapabilities() instead
*
* @deprecated
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return false;
}
/**
* Return the filling percentage of the backend storage
*
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
$mem = apc_sma_info(true);
$memSize = $mem['num_seg'] * $mem['seg_size'];
$memAvailable= $mem['avail_mem'];
$memUsed = $memSize - $memAvailable;
if ($memSize == 0) {
Zend_Cache::throwException('can\'t get apc memory size');
}
if ($memUsed > $memSize) {
return 100;
}
return ((int) (100. * ($memUsed / $memSize)));
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
return array();
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
$res = array();
$array = apc_cache_info('user', false);
$records = $array['cache_list'];
foreach ($records as $record) {
$res[] = $record['info'];
}
return $res;
}
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
$data = $tmp[0];
$mtime = $tmp[1];
if (!isset($tmp[2])) {
// because this record is only with 1.7 release
// if old cache records are still there...
return false;
}
$lifetime = $tmp[2];
return array(
'expire' => $mtime + $lifetime,
'tags' => array(),
'mtime' => $mtime
);
}
return false;
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
$data = $tmp[0];
$mtime = $tmp[1];
if (!isset($tmp[2])) {
// because this record is only with 1.7 release
// if old cache records are still there...
return false;
}
$lifetime = $tmp[2];
$newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
if ($newLifetime <=0) {
return false;
}
apc_store($id, array($data, time(), $newLifetime), $newLifetime);
return true;
}
return false;
}
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities()
{
return array(
'automatic_cleaning' => false,
'tags' => false,
'expired_read' => false,
'priority' => false,
'infinite_lifetime' => false,
'get_list' => true
);
}
}
@@ -0,0 +1,126 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/Interface.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interface
{
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds();
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags();
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array());
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array());
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array());
/**
* Return the filling percentage of the backend storage
*
* @return int integer between 0 and 100
*/
public function getFillingPercentage();
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id);
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime);
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities();
}
+999
View File
@@ -0,0 +1,999 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Available options
*
* =====> (string) cache_dir :
* - Directory where to put the cache files
*
* =====> (boolean) file_locking :
* - Enable / disable file_locking
* - Can avoid cache corruption under bad circumstances but it doesn't work on multithread
* webservers and on NFS filesystems for example
*
* =====> (boolean) read_control :
* - Enable / disable read control
* - If enabled, a control key is embeded in cache file and this key is compared with the one
* calculated after the reading.
*
* =====> (string) read_control_type :
* - Type of read control (only if read control is enabled). Available values are :
* 'md5' for a md5 hash control (best but slowest)
* 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
* 'adler32' for an adler32 hash control (excellent choice too, faster than crc32)
* 'strlen' for a length only test (fastest)
*
* =====> (int) hashed_directory_level :
* - Hashed directory level
* - Set the hashed directory structure level. 0 means "no hashed directory
* structure", 1 means "one level of directory", 2 means "two levels"...
* This option can speed up the cache only when you have many thousands of
* cache file. Only specific benchs can help you to choose the perfect value
* for you. Maybe, 1 or 2 is a good start.
*
* =====> (int) hashed_directory_umask :
* - Umask for hashed directory structure
*
* =====> (string) file_name_prefix :
* - prefix for cache files
* - be really carefull with this option because a too generic value in a system cache dir
* (like /tmp) can cause disasters when cleaning the cache
*
* =====> (int) cache_file_umask :
* - Umask for cache files
*
* =====> (int) metatadatas_array_max_size :
* - max size for the metadatas array (don't change this value unless you
* know what you are doing)
*
* @var array available options
*/
protected $_options = array(
'cache_dir' => null,
'file_locking' => true,
'read_control' => true,
'read_control_type' => 'crc32',
'hashed_directory_level' => 0,
'hashed_directory_umask' => 0700,
'file_name_prefix' => 'zend_cache',
'cache_file_umask' => 0600,
'metadatas_array_max_size' => 100
);
/**
* Array of metadatas (each item is an associative array)
*
* @var array
*/
protected $_metadatasArray = array();
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
parent::__construct($options);
if ($this->_options['cache_dir'] !== null) { // particular case for this option
$this->setCacheDir($this->_options['cache_dir']);
} else {
$this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false);
}
if (isset($this->_options['file_name_prefix'])) { // particular case for this option
if (!preg_match('~^[\w]+$~', $this->_options['file_name_prefix'])) {
Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-A0-9_]');
}
}
if ($this->_options['metadatas_array_max_size'] < 10) {
Zend_Cache::throwException('Invalid metadatas_array_max_size, must be > 10');
}
if (isset($options['hashed_directory_umask']) && is_string($options['hashed_directory_umask'])) {
// See #ZF-4422
$this->_options['hashed_directory_umask'] = octdec($this->_options['hashed_directory_umask']);
}
if (isset($options['cache_file_umask']) && is_string($options['cache_file_umask'])) {
// See #ZF-4422
$this->_options['cache_file_umask'] = octdec($this->_options['cache_file_umask']);
}
}
/**
* Set the cache_dir (particular case of setOption() method)
*
* @param string $value
* @param boolean $trailingSeparator If true, add a trailing separator is necessary
* @throws Zend_Cache_Exception
* @return void
*/
public function setCacheDir($value, $trailingSeparator = true)
{
if (!is_dir($value)) {
Zend_Cache::throwException('cache_dir must be a directory');
}
if (!is_writable($value)) {
Zend_Cache::throwException('cache_dir is not writable');
}
if ($trailingSeparator) {
// add a trailing DIRECTORY_SEPARATOR if necessary
$value = rtrim(realpath($value), '\\/') . DIRECTORY_SEPARATOR;
}
$this->_options['cache_dir'] = $value;
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id cache id
* @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
* @return string|false cached datas
*/
public function load($id, $doNotTestCacheValidity = false)
{
if (!($this->_test($id, $doNotTestCacheValidity))) {
// The cache is not hit !
return false;
}
$metadatas = $this->_getMetadatas($id);
$file = $this->_file($id);
$data = $this->_fileGetContents($file);
if ($this->_options['read_control']) {
$hashData = $this->_hash($data, $this->_options['read_control_type']);
$hashControl = $metadatas['hash'];
if ($hashData != $hashControl) {
// Problem detected by the read control !
$this->_log('Zend_Cache_Backend_File::load() / read_control : stored hash and computed hash do not match');
$this->remove($id);
return false;
}
}
return $data;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
clearstatcache();
return $this->_test($id, false);
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
clearstatcache();
$file = $this->_file($id);
$path = $this->_path($id);
if ($this->_options['hashed_directory_level'] > 0) {
if (!is_writable($path)) {
// maybe, we just have to build the directory structure
$this->_recursiveMkdirAndChmod($id);
}
if (!is_writable($path)) {
return false;
}
}
if ($this->_options['read_control']) {
$hash = $this->_hash($data, $this->_options['read_control_type']);
} else {
$hash = '';
}
$metadatas = array(
'hash' => $hash,
'mtime' => time(),
'expire' => $this->_expireTime($this->getLifetime($specificLifetime)),
'tags' => $tags
);
$res = $this->_setMetadatas($id, $metadatas);
if (!$res) {
$this->_log('Zend_Cache_Backend_File::save() / error on saving metadata');
return false;
}
$res = $this->_filePutContents($file, $data);
return $res;
}
/**
* Remove a cache record
*
* @param string $id cache id
* @return boolean true if no problem
*/
public function remove($id)
{
$file = $this->_file($id);
$boolRemove = $this->_remove($file);
$boolMetadata = $this->_delMetadatas($id);
return $boolMetadata && $boolRemove;
}
/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => remove too old cache entries ($tags is not used)
* 'matchingTag' => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* 'notMatchingTag' => remove cache entries not matching one of the given tags
* ($tags can be an array of strings or a single string)
* 'matchingAnyTag' => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode clean mode
* @param tags array $tags array of tags
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
// We use this protected method to hide the recursive stuff
clearstatcache();
return $this->_clean($this->_options['cache_dir'], $mode, $tags);
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
return $this->_get($this->_options['cache_dir'], 'ids', array());
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
return $this->_get($this->_options['cache_dir'], 'tags', array());
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'matching', $tags);
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'notMatching', $tags);
}
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags);
}
/**
* Return the filling percentage of the backend storage
*
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
$free = disk_free_space($this->_options['cache_dir']);
$total = disk_total_space($this->_options['cache_dir']);
if ($total == 0) {
Zend_Cache::throwException('can\'t get disk_total_space');
} else {
if ($free >= $total) {
return 100;
}
return ((int) (100. * ($total - $free) / $total));
}
}
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
$metadatas = $this->_getMetadatas($id);
if (!$metadatas) {
return false;
}
if (time() > $metadatas['expire']) {
return false;
}
return array(
'expire' => $metadatas['expire'],
'tags' => $metadatas['tags'],
'mtime' => $metadatas['mtime']
);
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
$metadatas = $this->_getMetadatas($id);
if (!$metadatas) {
return false;
}
if (time() > $metadatas['expire']) {
return false;
}
$newMetadatas = array(
'hash' => $metadatas['hash'],
'mtime' => time(),
'expire' => $metadatas['expire'] + $extraLifetime,
'tags' => $metadatas['tags']
);
$res = $this->_setMetadatas($id, $newMetadatas);
if (!$res) {
return false;
}
return true;
}
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities()
{
return array(
'automatic_cleaning' => true,
'tags' => true,
'expired_read' => true,
'priority' => false,
'infinite_lifetime' => true,
'get_list' => true
);
}
/**
* PUBLIC METHOD FOR UNIT TESTING ONLY !
*
* Force a cache record to expire
*
* @param string $id cache id
*/
public function ___expire($id)
{
$metadatas = $this->_getMetadatas($id);
if ($metadatas) {
$metadatas['expire'] = 1;
$this->_setMetadatas($id, $metadatas);
}
}
/**
* Get a metadatas record
*
* @param string $id Cache id
* @return array|false Associative array of metadatas
*/
protected function _getMetadatas($id)
{
if (isset($this->_metadatasArray[$id])) {
return $this->_metadatasArray[$id];
} else {
$metadatas = $this->_loadMetadatas($id);
if (!$metadatas) {
return false;
}
$this->_setMetadatas($id, $metadatas, false);
return $metadatas;
}
}
/**
* Set a metadatas record
*
* @param string $id Cache id
* @param array $metadatas Associative array of metadatas
* @param boolean $save optional pass false to disable saving to file
* @return boolean True if no problem
*/
protected function _setMetadatas($id, $metadatas, $save = true)
{
if (count($this->_metadatasArray) >= $this->_options['metadatas_array_max_size']) {
$n = (int) ($this->_options['metadatas_array_max_size'] / 10);
$this->_metadatasArray = array_slice($this->_metadatasArray, $n);
}
if ($save) {
$result = $this->_saveMetadatas($id, $metadatas);
if (!$result) {
return false;
}
}
$this->_metadatasArray[$id] = $metadatas;
return true;
}
/**
* Drop a metadata record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
protected function _delMetadatas($id)
{
if (isset($this->_metadatasArray[$id])) {
unset($this->_metadatasArray[$id]);
}
$file = $this->_metadatasFile($id);
return $this->_remove($file);
}
/**
* Clear the metadatas array
*
* @return void
*/
protected function _cleanMetadatas()
{
$this->_metadatasArray = array();
}
/**
* Load metadatas from disk
*
* @param string $id Cache id
* @return array|false Metadatas associative array
*/
protected function _loadMetadatas($id)
{
$file = $this->_metadatasFile($id);
$result = $this->_fileGetContents($file);
if (!$result) {
return false;
}
$tmp = @unserialize($result);
return $tmp;
}
/**
* Save metadatas to disk
*
* @param string $id Cache id
* @param array $metadatas Associative array
* @return boolean True if no problem
*/
protected function _saveMetadatas($id, $metadatas)
{
$file = $this->_metadatasFile($id);
$result = $this->_filePutContents($file, serialize($metadatas));
if (!$result) {
return false;
}
return true;
}
/**
* Make and return a file name (with path) for metadatas
*
* @param string $id Cache id
* @return string Metadatas file name (with path)
*/
protected function _metadatasFile($id)
{
$path = $this->_path($id);
$fileName = $this->_idToFileName('internal-metadatas---' . $id);
return $path . $fileName;
}
/**
* Check if the given filename is a metadatas one
*
* @param string $fileName File name
* @return boolean True if it's a metadatas one
*/
protected function _isMetadatasFile($fileName)
{
$id = $this->_fileNameToId($fileName);
if (substr($id, 0, 21) == 'internal-metadatas---') {
return true;
} else {
return false;
}
}
/**
* Remove a file
*
* If we can't remove the file (because of locks or any problem), we will touch
* the file to invalidate it
*
* @param string $file Complete file path
* @return boolean True if ok
*/
protected function _remove($file)
{
if (!is_file($file)) {
return false;
}
if (!@unlink($file)) {
# we can't remove the file (because of locks or any problem)
$this->_log("Zend_Cache_Backend_File::_remove() : we can't remove $file");
return false;
}
return true;
}
/**
* Clean some cache records (protected method used for recursive stuff)
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $dir Directory to clean
* @param string $mode Clean mode
* @param array $tags Array of tags
* @throws Zend_Cache_Exception
* @return boolean True if no problem
*/
protected function _clean($dir, $mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
if (!is_dir($dir)) {
return false;
}
$result = true;
$prefix = $this->_options['file_name_prefix'];
$glob = @glob($dir . $prefix . '--*');
if ($glob === false) {
return true;
}
foreach ($glob as $file) {
if (is_file($file)) {
$fileName = basename($file);
if ($this->_isMetadatasFile($fileName)) {
// in CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files
if ($mode != Zend_Cache::CLEANING_MODE_ALL) {
continue;
}
}
$id = $this->_fileNameToId($fileName);
$metadatas = $this->_getMetadatas($id);
if ($metadatas === FALSE) {
$metadatas = array('expire' => 1, 'tags' => array());
}
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
$res = $this->remove($id);
if (!$res) {
// in this case only, we accept a problem with the metadatas file drop
$res = $this->_remove($file);
}
$result = $result && $res;
break;
case Zend_Cache::CLEANING_MODE_OLD:
if (time() > $metadatas['expire']) {
$result = $this->remove($id) && $result;
}
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
$matching = true;
foreach ($tags as $tag) {
if (!in_array($tag, $metadatas['tags'])) {
$matching = false;
break;
}
}
if ($matching) {
$result = $this->remove($id) && $result;
}
break;
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
$matching = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
break;
}
}
if (!$matching) {
$result = $this->remove($id) && $result;
}
break;
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$matching = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
break;
}
}
if ($matching) {
$result = $this->remove($id) && $result;
}
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
// Recursive call
$result = $this->_clean($file . DIRECTORY_SEPARATOR, $mode, $tags) && $result;
if ($mode=='all') {
// if mode=='all', we try to drop the structure too
@rmdir($file);
}
}
}
return $result;
}
protected function _get($dir, $mode, $tags = array())
{
if (!is_dir($dir)) {
return false;
}
$result = array();
$prefix = $this->_options['file_name_prefix'];
$glob = @glob($dir . $prefix . '--*');
if ($glob === false) {
return true;
}
foreach ($glob as $file) {
if (is_file($file)) {
$fileName = basename($file);
$id = $this->_fileNameToId($fileName);
$metadatas = $this->_getMetadatas($id);
if ($metadatas === FALSE) {
continue;
}
if (time() > $metadatas['expire']) {
continue;
}
switch ($mode) {
case 'ids':
$result[] = $id;
break;
case 'tags':
$result = array_unique(array_merge($result, $metadatas['tags']));
break;
case 'matching':
$matching = true;
foreach ($tags as $tag) {
if (!in_array($tag, $metadatas['tags'])) {
$matching = false;
break;
}
}
if ($matching) {
$result[] = $id;
}
break;
case 'notMatching':
$matching = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
break;
}
}
if (!$matching) {
$result[] = $id;
}
break;
case 'matchingAny':
$matching = false;
foreach ($tags as $tag) {
if (in_array($tag, $metadatas['tags'])) {
$matching = true;
break;
}
}
if ($matching) {
$result[] = $id;
}
break;
default:
Zend_Cache::throwException('Invalid mode for _get() method');
break;
}
}
if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
// Recursive call
$result = array_unique(array_merge($result, $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags)));
}
}
return array_unique($result);
}
/**
* Compute & return the expire time
*
* @return int expire time (unix timestamp)
*/
protected function _expireTime($lifetime)
{
if ($lifetime === null) {
return 9999999999;
}
return time() + $lifetime;
}
/**
* Make a control key with the string containing datas
*
* @param string $data Data
* @param string $controlType Type of control 'md5', 'crc32' or 'strlen'
* @throws Zend_Cache_Exception
* @return string Control key
*/
protected function _hash($data, $controlType)
{
switch ($controlType) {
case 'md5':
return md5($data);
case 'crc32':
return crc32($data);
case 'strlen':
return strlen($data);
case 'adler32':
return hash('adler32', $data);
default:
Zend_Cache::throwException("Incorrect hash function : $controlType");
}
}
/**
* Transform a cache id into a file name and return it
*
* @param string $id Cache id
* @return string File name
*/
protected function _idToFileName($id)
{
$prefix = $this->_options['file_name_prefix'];
$result = $prefix . '---' . $id;
return $result;
}
/**
* Make and return a file name (with path)
*
* @param string $id Cache id
* @return string File name (with path)
*/
protected function _file($id)
{
$path = $this->_path($id);
$fileName = $this->_idToFileName($id);
return $path . $fileName;
}
/**
* Return the complete directory path of a filename (including hashedDirectoryStructure)
*
* @param string $id Cache id
* @param boolean $parts if true, returns array of directory parts instead of single string
* @return string Complete directory path
*/
protected function _path($id, $parts = false)
{
$partsArray = array();
$root = $this->_options['cache_dir'];
$prefix = $this->_options['file_name_prefix'];
if ($this->_options['hashed_directory_level']>0) {
$hash = hash('adler32', $id);
for ($i=0 ; $i < $this->_options['hashed_directory_level'] ; $i++) {
$root = $root . $prefix . '--' . substr($hash, 0, $i + 1) . DIRECTORY_SEPARATOR;
$partsArray[] = $root;
}
}
if ($parts) {
return $partsArray;
} else {
return $root;
}
}
/**
* Make the directory strucuture for the given id
*
* @param string $id cache id
* @return boolean true
*/
protected function _recursiveMkdirAndChmod($id)
{
if ($this->_options['hashed_directory_level'] <=0) {
return true;
}
$partsArray = $this->_path($id, true);
foreach ($partsArray as $part) {
if (!is_dir($part)) {
@mkdir($part, $this->_options['hashed_directory_umask']);
@chmod($part, $this->_options['hashed_directory_umask']); // see #ZF-320 (this line is required in some configurations)
}
}
return true;
}
/**
* Test if the given cache id is available (and still valid as a cache record)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
protected function _test($id, $doNotTestCacheValidity)
{
$metadatas = $this->_getMetadatas($id);
if (!$metadatas) {
return false;
}
if ($doNotTestCacheValidity || (time() <= $metadatas['expire'])) {
return $metadatas['mtime'];
}
return false;
}
/**
* Return the file content of the given file
*
* @param string $file File complete path
* @return string File content (or false if problem)
*/
protected function _fileGetContents($file)
{
$result = false;
if (!is_file($file)) {
return false;
}
$f = @fopen($file, 'rb');
if ($f) {
if ($this->_options['file_locking']) @flock($f, LOCK_SH);
$result = stream_get_contents($f);
if ($this->_options['file_locking']) @flock($f, LOCK_UN);
@fclose($f);
}
return $result;
}
/**
* Put the given string into the given file
*
* @param string $file File complete path
* @param string $string String to put in file
* @return boolean true if no problem
*/
protected function _filePutContents($file, $string)
{
$result = false;
$f = @fopen($file, 'ab+');
if ($f) {
if ($this->_options['file_locking']) @flock($f, LOCK_EX);
fseek($f, 0);
ftruncate($f, 0);
$tmp = @fwrite($f, $string);
if (!($tmp === FALSE)) {
$result = true;
}
@fclose($f);
}
@chmod($file, $this->_options['cache_file_umask']);
return $result;
}
/**
* Transform a file name into cache id and return it
*
* @param string $fileName File name
* @return string Cache id
*/
protected function _fileNameToId($fileName)
{
$prefix = $this->_options['file_name_prefix'];
return preg_replace('~^' . $prefix . '---(.*)$~', '$1', $fileName);
}
}
+99
View File
@@ -0,0 +1,99 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Cache_Backend_Interface
{
/**
* Set the frontend directives
*
* @param array $directives assoc of directives
*/
public function setDirectives($directives);
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string|false cached datas
*/
public function load($id, $doNotTestCacheValidity = false);
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id);
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false);
/**
* Remove a cache record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id);
/**
* Clean some cache records
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array());
}
+502
View File
@@ -0,0 +1,502 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Default Values
*/
const DEFAULT_HOST = '127.0.0.1';
const DEFAULT_PORT = 11211;
const DEFAULT_PERSISTENT = true;
const DEFAULT_WEIGHT = 1;
const DEFAULT_TIMEOUT = 1;
const DEFAULT_RETRY_INTERVAL = 15;
const DEFAULT_STATUS = true;
const DEFAULT_FAILURE_CALLBACK = null;
/**
* Log message
*/
const TAGS_UNSUPPORTED_BY_CLEAN_OF_MEMCACHED_BACKEND = 'Zend_Cache_Backend_Memcached::clean() : tags are unsupported by the Memcached backend';
const TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND = 'Zend_Cache_Backend_Memcached::save() : tags are unsupported by the Memcached backend';
/**
* Available options
*
* =====> (array) servers :
* an array of memcached server ; each memcached server is described by an associative array :
* 'host' => (string) : the name of the memcached server
* 'port' => (int) : the port of the memcached server
* 'persistent' => (bool) : use or not persistent connections to this memcached server
* 'weight' => (int) : number of buckets to create for this server which in turn control its
* probability of it being selected. The probability is relative to the total
* weight of all servers.
* 'timeout' => (int) : value in seconds which will be used for connecting to the daemon. Think twice
* before changing the default value of 1 second - you can lose all the
* advantages of caching if your connection is too slow.
* 'retry_interval' => (int) : controls how often a failed server will be retried, the default value
* is 15 seconds. Setting this parameter to -1 disables automatic retry.
* 'status' => (bool) : controls if the server should be flagged as online.
* 'failure_callback' => (callback) : Allows the user to specify a callback function to run upon
* encountering an error. The callback is run before failover
* is attempted. The function takes two parameters, the hostname
* and port of the failed server.
*
* =====> (boolean) compression :
* true if you want to use on-the-fly compression
*
* =====> (boolean) compatibility :
* true if you use old memcache server or extension
*
* @var array available options
*/
protected $_options = array(
'servers' => array(array(
'host' => self::DEFAULT_HOST,
'port' => self::DEFAULT_PORT,
'persistent' => self::DEFAULT_PERSISTENT,
'weight' => self::DEFAULT_WEIGHT,
'timeout' => self::DEFAULT_TIMEOUT,
'retry_interval' => self::DEFAULT_RETRY_INTERVAL,
'status' => self::DEFAULT_STATUS,
'failure_callback' => self::DEFAULT_FAILURE_CALLBACK
)),
'compression' => false,
'compatibility' => false,
);
/**
* Memcache object
*
* @var mixed memcache object
*/
protected $_memcache = null;
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
if (!extension_loaded('memcache')) {
Zend_Cache::throwException('The memcache extension must be loaded for using this backend !');
}
parent::__construct($options);
if (isset($this->_options['servers'])) {
$value= $this->_options['servers'];
if (isset($value['host'])) {
// in this case, $value seems to be a simple associative array (one server only)
$value = array(0 => $value); // let's transform it into a classical array of associative arrays
}
$this->setOption('servers', $value);
}
$this->_memcache = new Memcache;
foreach ($this->_options['servers'] as $server) {
if (!array_key_exists('port', $server)) {
$server['port'] = self::DEFAULT_PORT;
}
if (!array_key_exists('persistent', $server)) {
$server['persistent'] = self::DEFAULT_PERSISTENT;
}
if (!array_key_exists('weight', $server)) {
$server['weight'] = self::DEFAULT_WEIGHT;
}
if (!array_key_exists('timeout', $server)) {
$server['timeout'] = self::DEFAULT_TIMEOUT;
}
if (!array_key_exists('retry_interval', $server)) {
$server['retry_interval'] = self::DEFAULT_RETRY_INTERVAL;
}
if (!array_key_exists('status', $server)) {
$server['status'] = self::DEFAULT_STATUS;
}
if (!array_key_exists('failure_callback', $server)) {
$server['failure_callback'] = self::DEFAULT_FAILURE_CALLBACK;
}
if ($this->_options['compatibility']) {
// No status for compatibility mode (#ZF-5887)
$this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
$server['weight'], $server['timeout'],
$server['retry_interval']);
} else {
$this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
$server['weight'], $server['timeout'],
$server['retry_interval'],
$server['status'], $server['failure_callback']);
}
}
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string|false cached datas
*/
public function load($id, $doNotTestCacheValidity = false)
{
$tmp = $this->_memcache->get($id);
if (is_array($tmp)) {
return $tmp[0];
}
return false;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id Cache id
* @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$tmp = $this->_memcache->get($id);
if (is_array($tmp)) {
return $tmp[1];
}
return false;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean True if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$lifetime = $this->getLifetime($specificLifetime);
if ($this->_options['compression']) {
$flag = MEMCACHE_COMPRESSED;
} else {
$flag = 0;
}
// #ZF-5702 : we try add() first becase set() seems to be slower
if (!($result = $this->_memcache->add($id, array($data, time(), $lifetime), $flag, $lifetime))) {
$result = $this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
}
if (count($tags) > 0) {
$this->_log("Zend_Cache_Backend_Memcached::save() : tags are unsupported by the Memcached backend");
}
return $result;
}
/**
* Remove a cache record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id)
{
return $this->_memcache->delete($id);
}
/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => unsupported
* 'matchingTag' => unsupported
* 'notMatchingTag' => unsupported
* 'matchingAnyTag' => unsupported
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @throws Zend_Cache_Exception
* @return boolean True if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
return $this->_memcache->flush();
break;
case Zend_Cache::CLEANING_MODE_OLD:
$this->_log("Zend_Cache_Backend_Memcached::clean() : CLEANING_MODE_OLD is unsupported by the Memcached backend");
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_MEMCACHED_BACKEND);
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
/**
* Return true if the automatic cleaning is available for the backend
*
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return false;
}
/**
* Set the frontend directives
*
* @param array $directives Assoc of directives
* @throws Zend_Cache_Exception
* @return void
*/
public function setDirectives($directives)
{
parent::setDirectives($directives);
$lifetime = $this->getLifetime(false);
if ($lifetime > 2592000) {
// #ZF-3490 : For the memcached backend, there is a lifetime limit of 30 days (2592000 seconds)
$this->_log('memcached backend has a limit of 30 days (2592000 seconds) for the lifetime');
}
if ($lifetime === null) {
// #ZF-4614 : we tranform null to zero to get the maximal lifetime
parent::setDirectives(array('lifetime' => 0));
}
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
$this->_log("Zend_Cache_Backend_Memcached::save() : getting the list of cache ids is unsupported by the Memcache backend");
return array();
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
return array();
}
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
return array();
}
/**
* Return the filling percentage of the backend storage
*
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
$mems = $this->_memcache->getExtendedStats();
$memSize = 0;
$memUsed = 0;
foreach ($mems as $key => $mem) {
if ($mem === false) {
Zend_Cache::throwException('can\'t get stat from ' . $key);
} else {
$eachSize = $mem['limit_maxbytes'];
if ($eachSize == 0) {
Zend_Cache::throwException('can\'t get memory size from ' . $key);
}
$eachUsed = $mem['bytes'];
if ($eachUsed > $eachSize) {
$eachUsed = $eachSize;
}
$memSize += $eachSize;
$memUsed += $eachUsed;
}
}
return ((int) (100. * ($memUsed / $memSize)));
}
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
$tmp = $this->_memcache->get($id);
if (is_array($tmp)) {
$data = $tmp[0];
$mtime = $tmp[1];
if (!isset($tmp[2])) {
// because this record is only with 1.7 release
// if old cache records are still there...
return false;
}
$lifetime = $tmp[2];
return array(
'expire' => $mtime + $lifetime,
'tags' => array(),
'mtime' => $mtime
);
}
return false;
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
if ($this->_options['compression']) {
$flag = MEMCACHE_COMPRESSED;
} else {
$flag = 0;
}
$tmp = $this->_memcache->get($id);
if (is_array($tmp)) {
$data = $tmp[0];
$mtime = $tmp[1];
if (!isset($tmp[2])) {
// because this record is only with 1.7 release
// if old cache records are still there...
return false;
}
$lifetime = $tmp[2];
$newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
if ($newLifetime <=0) {
return false;
}
// #ZF-5702 : we try replace() first becase set() seems to be slower
if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $flag, $newLifetime))) {
$result = $this->_memcache->set($id, array($data, time(), $newLifetime), $flag, $newLifetime);
}
return $result;
}
return false;
}
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities()
{
return array(
'automatic_cleaning' => false,
'tags' => false,
'expired_read' => false,
'priority' => false,
'infinite_lifetime' => false,
'get_list' => false
);
}
}
+679
View File
@@ -0,0 +1,679 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Sqlite extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Available options
*
* =====> (string) cache_db_complete_path :
* - the complete path (filename included) of the SQLITE database
*
* ====> (int) automatic_vacuum_factor :
* - Disable / Tune the automatic vacuum process
* - The automatic vacuum process defragment the database file (and make it smaller)
* when a clean() or delete() is called
* 0 => no automatic vacuum
* 1 => systematic vacuum (when delete() or clean() methods are called)
* x (integer) > 1 => automatic vacuum randomly 1 times on x clean() or delete()
*
* @var array Available options
*/
protected $_options = array(
'cache_db_complete_path' => null,
'automatic_vacuum_factor' => 10
);
/**
* DB ressource
*
* @var mixed $_db
*/
private $_db = null;
/**
* Boolean to store if the structure has benn checked or not
*
* @var boolean $_structureChecked
*/
private $_structureChecked = false;
/**
* Constructor
*
* @param array $options Associative array of options
* @throws Zend_cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
parent::__construct($options);
if ($this->_options['cache_db_complete_path'] === null) {
Zend_Cache::throwException('cache_db_complete_path option has to set');
}
if (!extension_loaded('sqlite')) {
Zend_Cache::throwException("Cannot use SQLite storage because the 'sqlite' extension is not loaded in the current PHP environment");
}
$this->_getConnection();
}
/**
* Destructor
*
* @return void
*/
public function __destruct()
{
@sqlite_close($this->_getConnection());
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string|false Cached datas
*/
public function load($id, $doNotTestCacheValidity = false)
{
$this->_checkAndBuildStructure();
$sql = "SELECT content FROM cache WHERE id='$id'";
if (!$doNotTestCacheValidity) {
$sql = $sql . " AND (expire=0 OR expire>" . time() . ')';
}
$result = $this->_query($sql);
$row = @sqlite_fetch_array($result);
if ($row) {
return $row['content'];
}
return false;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id Cache id
* @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$this->_checkAndBuildStructure();
$sql = "SELECT lastModified FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')';
$result = $this->_query($sql);
$row = @sqlite_fetch_array($result);
if ($row) {
return ((int) $row['lastModified']);
}
return false;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @throws Zend_Cache_Exception
* @return boolean True if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$this->_checkAndBuildStructure();
$lifetime = $this->getLifetime($specificLifetime);
$data = @sqlite_escape_string($data);
$mktime = time();
if ($lifetime === null) {
$expire = 0;
} else {
$expire = $mktime + $lifetime;
}
$this->_query("DELETE FROM cache WHERE id='$id'");
$sql = "INSERT INTO cache (id, content, lastModified, expire) VALUES ('$id', '$data', $mktime, $expire)";
$res = $this->_query($sql);
if (!$res) {
$this->_log("Zend_Cache_Backend_Sqlite::save() : impossible to store the cache id=$id");
return false;
}
$res = true;
foreach ($tags as $tag) {
$res = $this->_registerTag($id, $tag) && $res;
}
return $res;
}
/**
* Remove a cache record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id)
{
$this->_checkAndBuildStructure();
$res = $this->_query("SELECT COUNT(*) AS nbr FROM cache WHERE id='$id'");
$result1 = @sqlite_fetch_single($res);
$result2 = $this->_query("DELETE FROM cache WHERE id='$id'");
$result3 = $this->_query("DELETE FROM tag WHERE id='$id'");
$this->_automaticVacuum();
return ($result1 && $result2 && $result3);
}
/**
* Clean some cache records
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @return boolean True if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
$this->_checkAndBuildStructure();
$return = $this->_clean($mode, $tags);
$this->_automaticVacuum();
return $return;
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
$this->_checkAndBuildStructure();
$res = $this->_query("SELECT id FROM cache WHERE (expire=0 OR expire>" . time() . ")");
$result = array();
while ($id = @sqlite_fetch_single($res)) {
$result[] = $id;
}
return $result;
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
$this->_checkAndBuildStructure();
$res = $this->_query("SELECT DISTINCT(name) AS name FROM tag");
$result = array();
while ($id = @sqlite_fetch_single($res)) {
$result[] = $id;
}
return $result;
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
$first = true;
$ids = array();
foreach ($tags as $tag) {
$res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'");
if (!$res) {
return array();
}
$rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
$ids2 = array();
foreach ($rows as $row) {
$ids2[] = $row['id'];
}
if ($first) {
$ids = $ids2;
$first = false;
} else {
$ids = array_intersect($ids, $ids2);
}
}
$result = array();
foreach ($ids as $id) {
$result[] = $id;
}
return $result;
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
$res = $this->_query("SELECT id FROM cache");
$rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
$result = array();
foreach ($rows as $row) {
$id = $row['id'];
$matching = false;
foreach ($tags as $tag) {
$res = $this->_query("SELECT COUNT(*) AS nbr FROM tag WHERE name='$tag' AND id='$id'");
if (!$res) {
return array();
}
$nbr = (int) @sqlite_fetch_single($res);
if ($nbr > 0) {
$matching = true;
}
}
if (!$matching) {
$result[] = $id;
}
}
return $result;
}
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
$first = true;
$ids = array();
foreach ($tags as $tag) {
$res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'");
if (!$res) {
return array();
}
$rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
$ids2 = array();
foreach ($rows as $row) {
$ids2[] = $row['id'];
}
if ($first) {
$ids = $ids2;
$first = false;
} else {
$ids = array_merge($ids, $ids2);
}
}
$result = array();
foreach ($ids as $id) {
$result[] = $id;
}
return $result;
}
/**
* Return the filling percentage of the backend storage
*
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
$dir = dirname($this->_options['cache_db_complete_path']);
$free = disk_free_space($dir);
$total = disk_total_space($dir);
if ($total == 0) {
Zend_Cache::throwException('can\'t get disk_total_space');
} else {
if ($free >= $total) {
return 100;
}
return ((int) (100. * ($total - $free) / $total));
}
}
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
$tags = array();
$res = $this->_query("SELECT name FROM tag WHERE id='$id'");
if ($res) {
$rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
foreach ($rows as $row) {
$tags[] = $row['name'];
}
}
$this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)');
$res = $this->_query("SELECT lastModified,expire FROM cache WHERE id='$id'");
if (!$res) {
return false;
}
$row = @sqlite_fetch_array($res, SQLITE_ASSOC);
return array(
'tags' => $tags,
'mtime' => $row['lastModified'],
'expire' => $row['expire']
);
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
$sql = "SELECT expire FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')';
$res = $this->_query($sql);
if (!$res) {
return false;
}
$expire = @sqlite_fetch_single($res);
$newExpire = $expire + $extraLifetime;
$res = $this->_query("UPDATE cache SET lastModified=" . time() . ", expire=$newExpire WHERE id='$id'");
if ($res) {
return true;
} else {
return false;
}
}
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities()
{
return array(
'automatic_cleaning' => true,
'tags' => true,
'expired_read' => true,
'priority' => false,
'infinite_lifetime' => true,
'get_list' => true
);
}
/**
* PUBLIC METHOD FOR UNIT TESTING ONLY !
*
* Force a cache record to expire
*
* @param string $id Cache id
*/
public function ___expire($id)
{
$time = time() - 1;
$this->_query("UPDATE cache SET lastModified=$time, expire=$time WHERE id='$id'");
}
/**
* Return the connection resource
*
* If we are not connected, the connection is made
*
* @throws Zend_Cache_Exception
* @return resource Connection resource
*/
private function _getConnection()
{
if (is_resource($this->_db)) {
return $this->_db;
} else {
$this->_db = @sqlite_open($this->_options['cache_db_complete_path']);
if (!(is_resource($this->_db))) {
Zend_Cache::throwException("Impossible to open " . $this->_options['cache_db_complete_path'] . " cache DB file");
}
return $this->_db;
}
}
/**
* Execute an SQL query silently
*
* @param string $query SQL query
* @return mixed|false query results
*/
private function _query($query)
{
$db = $this->_getConnection();
if (is_resource($db)) {
$res = @sqlite_query($db, $query);
if ($res === false) {
return false;
} else {
return $res;
}
}
return false;
}
/**
* Deal with the automatic vacuum process
*
* @return void
*/
private function _automaticVacuum()
{
if ($this->_options['automatic_vacuum_factor'] > 0) {
$rand = rand(1, $this->_options['automatic_vacuum_factor']);
if ($rand == 1) {
$this->_query('VACUUM');
@sqlite_close($this->_getConnection());
}
}
}
/**
* Register a cache id with the given tag
*
* @param string $id Cache id
* @param string $tag Tag
* @return boolean True if no problem
*/
private function _registerTag($id, $tag) {
$res = $this->_query("DELETE FROM TAG WHERE name='$tag' AND id='$id'");
$res = $this->_query("INSERT INTO tag (name, id) VALUES ('$tag', '$id')");
if (!$res) {
$this->_log("Zend_Cache_Backend_Sqlite::_registerTag() : impossible to register tag=$tag on id=$id");
return false;
}
return true;
}
/**
* Build the database structure
*
* @return false
*/
private function _buildStructure()
{
$this->_query('DROP INDEX tag_id_index');
$this->_query('DROP INDEX tag_name_index');
$this->_query('DROP INDEX cache_id_expire_index');
$this->_query('DROP TABLE version');
$this->_query('DROP TABLE cache');
$this->_query('DROP TABLE tag');
$this->_query('CREATE TABLE version (num INTEGER PRIMARY KEY)');
$this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)');
$this->_query('CREATE TABLE tag (name TEXT, id TEXT)');
$this->_query('CREATE INDEX tag_id_index ON tag(id)');
$this->_query('CREATE INDEX tag_name_index ON tag(name)');
$this->_query('CREATE INDEX cache_id_expire_index ON cache(id, expire)');
$this->_query('INSERT INTO version (num) VALUES (1)');
}
/**
* Check if the database structure is ok (with the good version)
*
* @return boolean True if ok
*/
private function _checkStructureVersion()
{
$result = $this->_query("SELECT num FROM version");
if (!$result) return false;
$row = @sqlite_fetch_array($result);
if (!$row) {
return false;
}
if (((int) $row['num']) != 1) {
// old cache structure
$this->_log('Zend_Cache_Backend_Sqlite::_checkStructureVersion() : old cache structure version detected => the cache is going to be dropped');
return false;
}
return true;
}
/**
* Clean some cache records
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @return boolean True if no problem
*/
private function _clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
$res1 = $this->_query('DELETE FROM cache');
$res2 = $this->_query('DELETE FROM tag');
return $res1 && $res2;
break;
case Zend_Cache::CLEANING_MODE_OLD:
$mktime = time();
$res1 = $this->_query("DELETE FROM tag WHERE id IN (SELECT id FROM cache WHERE expire>0 AND expire<=$mktime)");
$res2 = $this->_query("DELETE FROM cache WHERE expire>0 AND expire<=$mktime");
return $res1 && $res2;
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
$ids = $this->getIdsMatchingTags($tags);
$result = true;
foreach ($ids as $id) {
$result = $this->remove($id) && $result;
}
return $result;
break;
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
$ids = $this->getIdsNotMatchingTags($tags);
$result = true;
foreach ($ids as $id) {
$result = $this->remove($id) && $result;
}
return $result;
break;
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$ids = $this->getIdsMatchingAnyTags($tags);
$result = true;
foreach ($ids as $id) {
$result = $this->remove($id) && $result;
}
return $result;
break;
default:
break;
}
return false;
}
/**
* Check if the database structure is ok (with the good version), if no : build it
*
* @throws Zend_Cache_Exception
* @return boolean True if ok
*/
private function _checkAndBuildStructure()
{
if (!($this->_structureChecked)) {
if (!$this->_checkStructureVersion()) {
$this->_buildStructure();
if (!$this->_checkStructureVersion()) {
Zend_Cache::throwException("Impossible to build cache structure in " . $this->_options['cache_db_complete_path']);
}
}
$this->_structureChecked = true;
}
return true;
}
}
+270
View File
@@ -0,0 +1,270 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/Interface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
{
/**
* Available options
*
* @var array available options
*/
protected $_options = array();
/**
* Frontend or Core directives
*
* @var array directives
*/
protected $_directives = array();
/**
* Array to log actions
*
* @var array $_log
*/
private $_log = array();
/**
* Current index for log array
*
* @var int $_index
*/
private $_index = 0;
/**
* Constructor
*
* @param array $options associative array of options
* @return void
*/
public function __construct($options = array())
{
$this->_addLog('construct', array($options));
}
/**
* Set the frontend directives
*
* @param array $directives assoc of directives
* @return void
*/
public function setDirectives($directives)
{
$this->_addLog('setDirectives', array($directives));
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* For this test backend only, if $id == 'false', then the method will return false
* if $id == 'serialized', the method will return a serialized array
* ('foo' else)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string Cached datas (or false)
*/
public function load($id, $doNotTestCacheValidity = false)
{
$this->_addLog('get', array($id, $doNotTestCacheValidity));
if ($id=='false') {
return false;
}
if ($id=='serialized') {
return serialize(array('foo'));
}
if ($id=='serialized2') {
return serialize(array('headers' => array(), 'data' => 'foo'));
}
if (($id=='71769f39054f75894288e397df04e445') or ($id=='615d222619fb20b527168340cebd0578')) {
return serialize(array('foo', 'bar'));
}
if (($id=='8a02d218a5165c467e7a5747cc6bd4b6') or ($id=='648aca1366211d17cbf48e65dc570bee')) {
return serialize(array('foo', 'bar'));
}
return 'foo';
}
/**
* Test if a cache is available or not (for the given id)
*
* For this test backend only, if $id == 'false', then the method will return false
* (123456 else)
*
* @param string $id Cache id
* @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$this->_addLog('test', array($id));
if ($id=='false') {
return false;
}
if (($id=='d8523b3ee441006261eeffa5c3d3a0a7') or ($id=='3c439c922209e2cb0b54d6deffccd75a')) {
return false;
}
if (($id=='40f649b94977c0a6e76902e2a0b43587') or ($id=='e83249ea22178277d5befc2c5e2e9ace')) {
return false;
}
return 123456;
}
/**
* Save some string datas into a cache record
*
* For this test backend only, if $id == 'false', then the method will return false
* (true else)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean True if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$this->_addLog('save', array($data, $id, $tags));
if ($id=='false') {
return false;
}
return true;
}
/**
* Remove a cache record
*
* For this test backend only, if $id == 'false', then the method will return false
* (true else)
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id)
{
$this->_addLog('remove', array($id));
if ($id=='false') {
return false;
}
return true;
}
/**
* Clean some cache records
*
* For this test backend only, if $mode == 'false', then the method will return false
* (true else)
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @return boolean True if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
$this->_addLog('clean', array($mode, $tags));
if ($mode=='false') {
return false;
}
return true;
}
/**
* Get the last log
*
* @return string The last log
*/
public function getLastLog()
{
return $this->_log[$this->_index - 1];
}
/**
* Get the log index
*
* @return int Log index
*/
public function getLogIndex()
{
return $this->_index;
}
/**
* Get the complete log array
*
* @return array Complete log array
*/
public function getAllLogs()
{
return $this->_log;
}
/**
* Return true if the automatic cleaning is available for the backend
*
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return true;
}
/**
* Add an event to the log array
*
* @param string $methodName MethodName
* @param array $args Arguments
* @return void
*/
private function _addLog($methodName, $args)
{
$this->_log[$this->_index] = array(
'methodName' => $methodName,
'args' => $args
);
$this->_index = $this->_index + 1;
}
}
+506
View File
@@ -0,0 +1,506 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_ExtendedInterface
*/
require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_TwoLevels extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Available options
*
* =====> (string) slow_backend :
* - Slow backend name
* - Must implement the Zend_Cache_Backend_ExtendedInterface
* - Should provide a big storage
*
* =====> (string) fast_backend :
* - Flow backend name
* - Must implement the Zend_Cache_Backend_ExtendedInterface
* - Must be much faster than slow_backend
*
* =====> (array) slow_backend_options :
* - Slow backend options (see corresponding backend)
*
* =====> (array) fast_backend_options :
* - Fast backend options (see corresponding backend)
*
* =====> (int) stats_update_factor :
* - Disable / Tune the computation of the fast backend filling percentage
* - When saving a record into cache :
* 1 => systematic computation of the fast backend filling percentage
* x (integer) > 1 => computation of the fast backend filling percentage randomly 1 times on x cache write
*
* =====> (boolean) slow_backend_custom_naming :
* =====> (boolean) fast_backend_custom_naming :
* =====> (boolean) slow_backend_autoload :
* =====> (boolean) fast_backend_autoload :
* - See Zend_Cache::factory() method
*
* =====> (boolean) auto_refresh_fast_cache
* - If true, auto refresh the fast cache when a cache record is hit
*
* @var array available options
*/
protected $_options = array(
'slow_backend' => 'File',
'fast_backend' => 'Apc',
'slow_backend_options' => array(),
'fast_backend_options' => array(),
'stats_update_factor' => 10,
'slow_backend_custom_naming' => false,
'fast_backend_custom_naming' => false,
'slow_backend_autoload' => false,
'fast_backend_autoload' => false,
'auto_refresh_fast_cache' => true
);
/**
* Slow Backend
*
* @var Zend_Cache_Backend
*/
private $_slowBackend;
/**
* Fast Backend
*
* @var Zend_Cache_Backend
*/
private $_fastBackend;
/**
* Cache for the fast backend filling percentage
*
* @var int
*/
private $_fastBackendFillingPercentage = null;
/**
* Constructor
*
* @param array $options Associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
parent::__construct($options);
if ($this->_options['slow_backend'] === null) {
Zend_Cache::throwException('slow_backend option has to set');
}
if ($this->_options['fast_backend'] === null) {
Zend_Cache::throwException('fast_backend option has to set');
}
$this->_slowBackend = Zend_Cache::_makeBackend($this->_options['slow_backend'], $this->_options['slow_backend_options'], $this->_options['slow_backend_custom_naming'], $this->_options['slow_backend_autoload']);
$this->_fastBackend = Zend_Cache::_makeBackend($this->_options['fast_backend'], $this->_options['fast_backend_options'], $this->_options['fast_backend_custom_naming'], $this->_options['fast_backend_autoload']);
if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) {
Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
}
if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) {
Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
}
$this->_slowBackend->setDirectives($this->_directives);
$this->_fastBackend->setDirectives($this->_directives);
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$fastTest = $this->_fastBackend->test($id);
if ($fastTest) {
return $fastTest;
} else {
return $this->_slowBackend->test($id);
}
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Datas to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false, $priority = 8)
{
$usage = $this->_getFastFillingPercentage('saving');
$boolFast = true;
$lifetime = $this->getLifetime($specificLifetime);
$preparedData = $this->_prepareData($data, $lifetime, $priority);
if (($priority > 0) && (10 * $priority >= $usage)) {
$fastLifetime = $this->_getFastLifetime($lifetime, $priority);
$boolFast = $this->_fastBackend->save($preparedData, $id, array(), $fastLifetime);
}
$boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
return ($boolFast && $boolSlow);
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string|false cached datas
*/
public function load($id, $doNotTestCacheValidity = false)
{
$res = $this->_fastBackend->load($id, $doNotTestCacheValidity);
if ($res === false) {
$res = $this->_slowBackend->load($id, $doNotTestCacheValidity);
if ($res === false) {
// there is no cache at all for this id
return false;
}
}
$array = unserialize($res);
// maybe, we have to refresh the fast cache ?
if ($this->_options['auto_refresh_fast_cache']) {
if ($array['priority'] == 10) {
// no need to refresh the fast cache with priority = 10
return $array['data'];
}
$newFastLifetime = $this->_getFastLifetime($array['lifetime'], $array['priority'], time() - $array['expire']);
// we have the time to refresh the fast cache
$usage = $this->_getFastFillingPercentage('loading');
if (($array['priority'] > 0) && (10 * $array['priority'] >= $usage)) {
// we can refresh the fast cache
$preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
$this->_fastBackend->save($preparedData, $id, array(), $newFastLifetime);
}
}
return $array['data'];
}
/**
* Remove a cache record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id)
{
$boolFast = $this->_fastBackend->remove($id);
$boolSlow = $this->_slowBackend->remove($id);
return $boolFast && $boolSlow;
}
/**
* Clean some cache records
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @throws Zend_Cache_Exception
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
$boolFast = $this->_fastBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
$boolSlow = $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
return $boolFast && $boolSlow;
break;
case Zend_Cache::CLEANING_MODE_OLD:
return $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_OLD);
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
$ids = $this->_slowBackend->getIdsMatchingTags($tags);
$res = true;
foreach ($ids as $id) {
$bool = $this->remove($id);
$res = $res && $bool;
}
return $res;
break;
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
$ids = $this->_slowBackend->getIdsNotMatchingTags($tags);
$res = true;
foreach ($ids as $id) {
$bool = $this->remove($id);
$res = $res && $bool;
}
return $res;
break;
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$ids = $this->_slowBackend->getIdsMatchingAnyTags($tags);
$res = true;
foreach ($ids as $id) {
$bool = $this->remove($id);
$res = $res && $bool;
}
return $res;
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
return $this->_slowBackend->getIds();
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
return $this->_slowBackend->getTags();
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
return $this->_slowBackend->getIdsMatchingTags($tags);
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
return $this->_slowBackend->getIdsNotMatchingTags($tags);
}
/**
* Return an array of stored cache ids which match any given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array())
{
return $this->_slowBackend->getIdsMatchingAnyTags($tags);
}
/**
* Return the filling percentage of the backend storage
*
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
return $this->_slowBackend->getFillingPercentage();
}
/**
* Return an array of metadatas for the given cache id
*
* The array must include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
return $this->_slowBackend->getMetadatas($id);
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
return $this->_slowBackend->touch($id, $extraLifetime);
}
/**
* Return an associative array of capabilities (booleans) of the backend
*
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
* - expired_read (is it possible to read expired cache records
* (for doNotTestCacheValidity option for example))
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
*
* @return array associative of with capabilities
*/
public function getCapabilities()
{
$slowBackendCapabilities = $this->_slowBackend->getCapabilities();
return array(
'automatic_cleaning' => $slowBackendCapabilities['automatic_cleaning'],
'tags' => $slowBackendCapabilities['tags'],
'expired_read' => $slowBackendCapabilities['expired_read'],
'priority' => $slowBackendCapabilities['priority'],
'infinite_lifetime' => $slowBackendCapabilities['infinite_lifetime'],
'get_list' => $slowBackendCapabilities['get_list']
);
}
/**
* Prepare a serialized array to store datas and metadatas informations
*
* @param string $data data to store
* @param int $lifetime original lifetime
* @param int $priority priority
* @return string serialize array to store into cache
*/
private function _prepareData($data, $lifetime, $priority)
{
$lt = $lifetime;
if ($lt === null) {
$lt = 9999999999;
}
return serialize(array(
'data' => $data,
'lifetime' => $lifetime,
'expire' => time() + $lt,
'priority' => $priority
));
}
/**
* Compute and return the lifetime for the fast backend
*
* @param int $lifetime original lifetime
* @param int $priority priority
* @param int $maxLifetime maximum lifetime
* @return int lifetime for the fast backend
*/
private function _getFastLifetime($lifetime, $priority, $maxLifetime = null)
{
if ($lifetime === null) {
// if lifetime is null, we have an infinite lifetime
// we need to use arbitrary lifetimes
$fastLifetime = (int) (2592000 / (11 - $priority));
} else {
$fastLifetime = (int) ($lifetime / (11 - $priority));
}
if (($maxLifetime !== null) && ($maxLifetime >= 0)) {
if ($fastLifetime > $maxLifetime) {
return $maxLifetime;
}
}
return $fastLifetime;
}
/**
* PUBLIC METHOD FOR UNIT TESTING ONLY !
*
* Force a cache record to expire
*
* @param string $id cache id
*/
public function ___expire($id)
{
$this->_fastBackend->remove($id);
$this->_slowBackend->___expire($id);
}
private function _getFastFillingPercentage($mode)
{
if ($mode == 'saving') {
// mode saving
if ($this->_fastBackendFillingPercentage === null) {
$this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
} else {
$rand = rand(1, $this->_options['stats_update_factor']);
if ($rand == 1) {
// we force a refresh
$this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
}
}
} else {
// mode loading
// we compute the percentage only if it's not available in cache
if ($this->_fastBackendFillingPercentage === null) {
$this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
}
}
return $this->_fastBackendFillingPercentage;
}
}
+216
View File
@@ -0,0 +1,216 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/Interface.php';
/**
* @see Zend_Cache_Backend
*/
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Xcache extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
{
/**
* Log message
*/
const TAGS_UNSUPPORTED_BY_CLEAN_OF_XCACHE_BACKEND = 'Zend_Cache_Backend_Xcache::clean() : tags are unsupported by the Xcache backend';
const TAGS_UNSUPPORTED_BY_SAVE_OF_XCACHE_BACKEND = 'Zend_Cache_Backend_Xcache::save() : tags are unsupported by the Xcache backend';
/**
* Available options
*
* =====> (string) user :
* xcache.admin.user (necessary for the clean() method)
*
* =====> (string) password :
* xcache.admin.pass (clear, not MD5) (necessary for the clean() method)
*
* @var array available options
*/
protected $_options = array(
'user' => null,
'password' => null
);
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
if (!extension_loaded('xcache')) {
Zend_Cache::throwException('The xcache extension must be loaded for using this backend !');
}
parent::__construct($options);
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* WARNING $doNotTestCacheValidity=true is unsupported by the Xcache backend
*
* @param string $id cache id
* @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
* @return string cached datas (or false)
*/
public function load($id, $doNotTestCacheValidity = false)
{
if ($doNotTestCacheValidity) {
$this->_log("Zend_Cache_Backend_Xcache::load() : \$doNotTestCacheValidity=true is unsupported by the Xcache backend");
}
$tmp = xcache_get($id);
if (is_array($tmp)) {
return $tmp[0];
}
return false;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
if (xcache_isset($id)) {
$tmp = xcache_get($id);
if (is_array($tmp)) {
return $tmp[1];
}
}
return false;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data datas to cache
* @param string $id cache id
* @param array $tags array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$lifetime = $this->getLifetime($specificLifetime);
$result = xcache_set($id, array($data, time()), $lifetime);
if (count($tags) > 0) {
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_XCACHE_BACKEND);
}
return $result;
}
/**
* Remove a cache record
*
* @param string $id cache id
* @return boolean true if no problem
*/
public function remove($id)
{
return xcache_unset($id);
}
/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => unsupported
* 'matchingTag' => unsupported
* 'notMatchingTag' => unsupported
* 'matchingAnyTag' => unsupported
*
* @param string $mode clean mode
* @param array $tags array of tags
* @throws Zend_Cache_Exception
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
// Necessary because xcache_clear_cache() need basic authentification
$backup = array();
if (isset($_SERVER['PHP_AUTH_USER'])) {
$backup['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];
}
if (isset($_SERVER['PHP_AUTH_PW'])) {
$backup['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'];
}
if ($this->_options['user']) {
$_SERVER['PHP_AUTH_USER'] = $this->_options['user'];
}
if ($this->_options['password']) {
$_SERVER['PHP_AUTH_PW'] = $this->_options['password'];
}
xcache_clear_cache(XC_TYPE_VAR, 0);
if (isset($backup['PHP_AUTH_USER'])) {
$_SERVER['PHP_AUTH_USER'] = $backup['PHP_AUTH_USER'];
$_SERVER['PHP_AUTH_PW'] = $backup['PHP_AUTH_PW'];
}
return true;
break;
case Zend_Cache::CLEANING_MODE_OLD:
$this->_log("Zend_Cache_Backend_Xcache::clean() : CLEANING_MODE_OLD is unsupported by the Xcache backend");
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_XCACHE_BACKEND);
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
/**
* Return true if the automatic cleaning is available for the backend
*
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return false;
}
}
@@ -0,0 +1,317 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend.php';
/**
* @see Zend_Cache_Backend_Interface
*/
require_once 'Zend/Cache/Backend/Interface.php';
/**
* Impementation of Zend Cache Backend using the Zend Platform (Output Content Caching)
*
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendPlatform extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
{
/**
* internal ZP prefix
*/
const TAGS_PREFIX = "internal_ZPtag:";
/**
* Constructor
* Validate that the Zend Platform is loaded and licensed
*
* @param array $options Associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
if (!function_exists('accelerator_license_info')) {
Zend_Cache::throwException('The Zend Platform extension must be loaded for using this backend !');
}
if (!function_exists('accelerator_get_configuration')) {
$licenseInfo = accelerator_license_info();
Zend_Cache::throwException('The Zend Platform extension is not loaded correctly: '.$licenseInfo['failure_reason']);
}
$accConf = accelerator_get_configuration();
if (@!$accConf['output_cache_licensed']) {
Zend_Cache::throwException('The Zend Platform extension does not have the proper license to use content caching features');
}
if (@!$accConf['output_cache_enabled']) {
Zend_Cache::throwException('The Zend Platform content caching feature must be enabled for using this backend, set the \'zend_accelerator.output_cache_enabled\' directive to On !');
}
if (!is_writable($accConf['output_cache_dir'])) {
Zend_Cache::throwException('The cache copies directory \''. ini_get('zend_accelerator.output_cache_dir') .'\' must be writable !');
}
parent:: __construct($options);
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @return string Cached data (or false)
*/
public function load($id, $doNotTestCacheValidity = false)
{
// doNotTestCacheValidity implemented by giving zero lifetime to the cache
if ($doNotTestCacheValidity) {
$lifetime = 0;
} else {
$lifetime = $this->_directives['lifetime'];
}
$res = output_cache_get($id, $lifetime);
if($res) {
return $res[0];
} else {
return false;
}
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id Cache id
* @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record
*/
public function test($id)
{
$result = output_cache_get($id, $this->_directives['lifetime']);
if ($result) {
return $result[1];
}
return false;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data Data to cache
* @param string $id Cache id
* @param array $tags Array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
if (!($specificLifetime === false)) {
$this->_log("Zend_Cache_Backend_ZendPlatform::save() : non false specifc lifetime is unsuported for this backend");
}
$lifetime = $this->_directives['lifetime'];
$result1 = output_cache_put($id, array($data, time()));
$result2 = (count($tags) == 0);
foreach ($tags as $tag) {
$tagid = self::TAGS_PREFIX.$tag;
$old_tags = output_cache_get($tagid, $lifetime);
if ($old_tags === false) {
$old_tags = array();
}
$old_tags[$id] = $id;
output_cache_remove_key($tagid);
$result2 = output_cache_put($tagid, $old_tags);
}
return $result1 && $result2;
}
/**
* Remove a cache record
*
* @param string $id Cache id
* @return boolean True if no problem
*/
public function remove($id)
{
return output_cache_remove_key($id);
}
/**
* Clean some cache records
*
* Available modes are :
* Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
* Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
* This mode is not supported in this backend
* Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => unsupported
* Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode Clean mode
* @param array $tags Array of tags
* @throws Zend_Cache_Exception
* @return boolean True if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
case Zend_Cache::CLEANING_MODE_OLD:
$cache_dir = ini_get('zend_accelerator.output_cache_dir');
if (!$cache_dir) {
return false;
}
$cache_dir .= '/.php_cache_api/';
return $this->_clean($cache_dir, $mode);
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
$idlist = null;
foreach ($tags as $tag) {
$next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']);
if ($idlist) {
$idlist = array_intersect_assoc($idlist, $next_idlist);
} else {
$idlist = $next_idlist;
}
if (count($idlist) == 0) {
// if ID list is already empty - we may skip checking other IDs
$idlist = null;
break;
}
}
if ($idlist) {
foreach ($idlist as $id) {
output_cache_remove_key($id);
}
}
return true;
break;
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
$this->_log("Zend_Cache_Backend_ZendPlatform::clean() : CLEANING_MODE_NOT_MATCHING_TAG is not supported by the Zend Platform backend");
return false;
break;
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$idlist = null;
foreach ($tags as $tag) {
$next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']);
if ($idlist) {
$idlist = array_merge_recursive($idlist, $next_idlist);
} else {
$idlist = $next_idlist;
}
if (count($idlist) == 0) {
// if ID list is already empty - we may skip checking other IDs
$idlist = null;
break;
}
}
if ($idlist) {
foreach ($idlist as $id) {
output_cache_remove_key($id);
}
}
return true;
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
/**
* Clean a directory and recursivly go over it's subdirectories
*
* Remove all the cached files that need to be cleaned (according to mode and files mtime)
*
* @param string $dir Path of directory ot clean
* @param string $mode The same parameter as in Zend_Cache_Backend_ZendPlatform::clean()
* @return boolean True if ok
*/
private function _clean($dir, $mode)
{
$d = @dir($dir);
if (!$d) {
return false;
}
$result = true;
while (false !== ($file = $d->read())) {
if ($file == '.' || $file == '..') {
continue;
}
$file = $d->path . $file;
if (is_dir($file)) {
$result = ($this->_clean($file .'/', $mode)) && ($result);
} else {
if ($mode == Zend_Cache::CLEANING_MODE_ALL) {
$result = ($this->_remove($file)) && ($result);
} else if ($mode == Zend_Cache::CLEANING_MODE_OLD) {
// Files older than lifetime get deleted from cache
if ($this->_directives['lifetime'] !== null) {
if ((time() - @filemtime($file)) > $this->_directives['lifetime']) {
$result = ($this->_remove($file)) && ($result);
}
}
}
}
}
$d->close();
return $result;
}
/**
* Remove a file
*
* If we can't remove the file (because of locks or any problem), we will touch
* the file to invalidate it
*
* @param string $file Complete file path
* @return boolean True if ok
*/
private function _remove($file)
{
if (!@unlink($file)) {
# If we can't remove the file (because of locks or any problem), we will touch
# the file to invalidate it
$this->_log("Zend_Cache_Backend_ZendPlatform::_remove() : we can't remove $file => we are going to try to invalidate it");
if ($this->_directives['lifetime'] === null) {
return false;
}
if (!file_exists($file)) {
return false;
}
return @touch($file, time() - 2*abs($this->_directives['lifetime']));
}
return true;
}
}
+207
View File
@@ -0,0 +1,207 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** @see Zend_Cache_Backend_Interface */
require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend */
require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Cache_Backend_ZendServer extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
{
/**
* Available options
*
* =====> (string) namespace :
* Namespace to be used for chaching operations
*
* @var array available options
*/
protected $_options = array(
'namespace' => 'zendframework'
);
/**
* Store data
*
* @param mixed $data Object to store
* @param string $id Cache id
* @param int $timeToLive Time to live in seconds
* @throws Zend_Cache_Exception
*/
abstract protected function _store($data, $id, $timeToLive);
/**
* Fetch data
*
* @param string $id Cache id
* @throws Zend_Cache_Exception
*/
abstract protected function _fetch($id);
/**
* Unset data
*
* @param string $id Cache id
*/
abstract protected function _unset($id);
/**
* Clear cache
*/
abstract protected function _clear();
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id cache id
* @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
* @return string cached datas (or false)
*/
public function load($id, $doNotTestCacheValidity = false)
{
$tmp = $this->_fetch($id);
if ($tmp !== null) {
return $tmp;
}
return false;
}
/**
* Test if a cache is available or not (for the given id)
*
* @param string $id cache id
* @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
* @throws Zend_Cache_Exception
*/
public function test($id)
{
$tmp = $this->_fetch('internal-metadatas---' . $id);
if ($tmp !== false) {
if (!is_array($tmp) || !isset($tmp['mtime'])) {
Zend_Cache::throwException('Cache metadata for \'' . $id . '\' id is corrupted' );
}
return $tmp['mtime'];
}
return false;
}
/**
* Compute & return the expire time
*
* @return int expire time (unix timestamp)
*/
private function _expireTime($lifetime)
{
if ($lifetime === null) {
return 9999999999;
}
return time() + $lifetime;
}
/**
* Save some string datas into a cache record
*
* Note : $data is always "string" (serialization is done by the
* core not by the backend)
*
* @param string $data datas to cache
* @param string $id cache id
* @param array $tags array of strings, the cache record will be tagged by each string entry
* @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @return boolean true if no problem
*/
public function save($data, $id, $tags = array(), $specificLifetime = false)
{
$lifetime = $this->getLifetime($specificLifetime);
$metadatas = array(
'mtime' => time(),
'expire' => $this->_expireTime($lifetime),
);
if (count($tags) > 0) {
$this->_log('Zend_Cache_Backend_ZendServer::save() : tags are unsupported by the ZendServer backends');
}
return $this->_store($data, $id, $lifetime) &&
$this->_store($metadatas, 'internal-metadatas---' . $id, $lifetime);
}
/**
* Remove a cache record
*
* @param string $id cache id
* @return boolean true if no problem
*/
public function remove($id)
{
$result1 = $this->_unset($id);
$result2 = $this->_unset('internal-metadatas---' . $id);
return $result1 && $result2;
}
/**
* Clean some cache records
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => unsupported
* 'matchingTag' => unsupported
* 'notMatchingTag' => unsupported
* 'matchingAnyTag' => unsupported
*
* @param string $mode clean mode
* @param array $tags array of tags
* @throws Zend_Cache_Exception
* @return boolean true if no problem
*/
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
{
switch ($mode) {
case Zend_Cache::CLEANING_MODE_ALL:
$this->_clear();
return true;
break;
case Zend_Cache::CLEANING_MODE_OLD:
$this->_log("Zend_Cache_Backend_ZendServer::clean() : CLEANING_MODE_OLD is unsupported by the Zend Server backends.");
break;
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
$this->_clear();
$this->_log('Zend_Cache_Backend_ZendServer::clean() : tags are unsupported by the Zend Server backends.');
break;
default:
Zend_Cache::throwException('Invalid mode for clean() method');
break;
}
}
}
+100
View File
@@ -0,0 +1,100 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** @see Zend_Cache_Backend_Interface */
require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend_ZendServer */
require_once 'Zend/Cache/Backend/ZendServer.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer implements Zend_Cache_Backend_Interface
{
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
*/
public function __construct(array $options = array())
{
if (!function_exists('zend_disk_cache_store')) {
Zend_Cache::throwException('Zend_Cache_ZendServer_Disk backend has to be used within Zend Server environment.');
}
parent::__construct($options);
}
/**
* Store data
*
* @param mixed $data Object to store
* @param string $id Cache id
* @param int $timeToLive Time to live in seconds
* @return boolean true if no problem
*/
protected function _store($data, $id, $timeToLive)
{
if (zend_disk_cache_store($this->_options['namespace'] . '::' . $id,
$data,
$timeToLive) === false) {
$this->_log('Store operation failed.');
return false;
}
return true;
}
/**
* Fetch data
*
* @param string $id Cache id
*/
protected function _fetch($id)
{
return zend_disk_cache_fetch($this->_options['namespace'] . '::' . $id);
}
/**
* Unset data
*
* @param string $id Cache id
* @return boolean true if no problem
*/
protected function _unset($id)
{
return zend_disk_cache_delete($this->_options['namespace'] . '::' . $id);
}
/**
* Clear cache
*/
protected function _clear()
{
zend_disk_cache_clear($this->_options['namespace']);
}
}
+100
View File
@@ -0,0 +1,100 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** @see Zend_Cache_Backend_Interface */
require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend_ZendServer */
require_once 'Zend/Cache/Backend/ZendServer.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendServer_ShMem extends Zend_Cache_Backend_ZendServer implements Zend_Cache_Backend_Interface
{
/**
* Constructor
*
* @param array $options associative array of options
* @throws Zend_Cache_Exception
*/
public function __construct(array $options = array())
{
if (!function_exists('zend_shm_cache_store')) {
Zend_Cache::throwException('Zend_Cache_ZendServer_ShMem backend has to be used within Zend Server environment.');
}
parent::__construct($options);
}
/**
* Store data
*
* @param mixed $data Object to store
* @param string $id Cache id
* @param int $timeToLive Time to live in seconds
*
*/
protected function _store($data, $id, $timeToLive)
{
if (zend_shm_cache_store($this->_options['namespace'] . '::' . $id,
$data,
$timeToLive) === false) {
$this->_log('Store operation failed.');
return false;
}
return true;
}
/**
* Fetch data
*
* @param string $id Cache id
*/
protected function _fetch($id)
{
return zend_shm_cache_fetch($this->_options['namespace'] . '::' . $id);
}
/**
* Unset data
*
* @param string $id Cache id
* @return boolean true if no problem
*/
protected function _unset($id)
{
return zend_shm_cache_delete($this->_options['namespace'] . '::' . $id);
}
/**
* Clear cache
*/
protected function _clear()
{
zend_shm_cache_clear($this->_options['namespace']);
}
}
+683
View File
@@ -0,0 +1,683 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @package Zend_Cache
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Core
{
/**
* Backend Object
*
* @var object $_backend
*/
protected $_backend = null;
/**
* Available options
*
* ====> (boolean) write_control :
* - Enable / disable write control (the cache is read just after writing to detect corrupt entries)
* - Enable write control will lightly slow the cache writing but not the cache reading
* Write control can detect some corrupt cache files but maybe it's not a perfect control
*
* ====> (boolean) caching :
* - Enable / disable caching
* (can be very useful for the debug of cached scripts)
*
* =====> (string) cache_id_prefix :
* - prefix for cache ids (namespace)
*
* ====> (boolean) automatic_serialization :
* - Enable / disable automatic serialization
* - It can be used to save directly datas which aren't strings (but it's slower)
*
* ====> (int) automatic_cleaning_factor :
* - Disable / Tune the automatic cleaning process
* - The automatic cleaning process destroy too old (for the given life time)
* cache files when a new cache file is written :
* 0 => no automatic cache cleaning
* 1 => systematic cache cleaning
* x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
*
* ====> (int) lifetime :
* - Cache lifetime (in seconds)
* - If null, the cache is valid forever.
*
* ====> (boolean) logging :
* - If set to true, logging is activated (but the system is slower)
*
* ====> (boolean) ignore_user_abort
* - If set to true, the core will set the ignore_user_abort PHP flag inside the
* save() method to avoid cache corruptions in some cases (default false)
*
* @var array $_options available options
*/
protected $_options = array(
'write_control' => true,
'caching' => true,
'cache_id_prefix' => null,
'automatic_serialization' => false,
'automatic_cleaning_factor' => 10,
'lifetime' => 3600,
'logging' => false,
'logger' => null,
'ignore_user_abort' => false
);
/**
* Array of options which have to be transfered to backend
*
* @var array $_directivesList
*/
protected static $_directivesList = array('lifetime', 'logging', 'logger');
/**
* Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends)
*
* @var array $_specificOptions
*/
protected $_specificOptions = array();
/**
* Last used cache id
*
* @var string $_lastId
*/
private $_lastId = null;
/**
* True if the backend implements Zend_Cache_Backend_ExtendedInterface
*
* @var boolean $_extendedBackend
*/
protected $_extendedBackend = false;
/**
* Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface)
*
* @var array
*/
protected $_backendCapabilities = array();
/**
* Constructor
*
* @param array|Zend_Config $options Associative array of options or Zend_Config instance
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct($options = array())
{
if ($options instanceof Zend_Config) {
$options = $options->toArray();
}
if (!is_array($options)) {
Zend_Cache::throwException("Options passed were not an array"
. " or Zend_Config instance.");
}
while (list($name, $value) = each($options)) {
$this->setOption($name, $value);
}
$this->_loggerSanity();
}
/**
* Set options using an instance of type Zend_Config
*
* @param Zend_Config $config
* @return Zend_Cache_Core
*/
public function setConfig(Zend_Config $config)
{
$options = $config->toArray();
while (list($name, $value) = each($options)) {
$this->setOption($name, $value);
}
return $this;
}
/**
* Set the backend
*
* @param object $backendObject
* @throws Zend_Cache_Exception
* @return void
*/
public function setBackend(Zend_Cache_Backend $backendObject)
{
$this->_backend= $backendObject;
// some options (listed in $_directivesList) have to be given
// to the backend too (even if they are not "backend specific")
$directives = array();
foreach (Zend_Cache_Core::$_directivesList as $directive) {
$directives[$directive] = $this->_options[$directive];
}
$this->_backend->setDirectives($directives);
if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) {
$this->_extendedBackend = true;
$this->_backendCapabilities = $this->_backend->getCapabilities();
}
}
/**
* Returns the backend
*
* @return object backend object
*/
public function getBackend()
{
return $this->_backend;
}
/**
* Public frontend to set an option
*
* There is an additional validation (relatively to the protected _setOption method)
*
* @param string $name Name of the option
* @param mixed $value Value of the option
* @throws Zend_Cache_Exception
* @return void
*/
public function setOption($name, $value)
{
if (!is_string($name)) {
Zend_Cache::throwException("Incorrect option name : $name");
}
$name = strtolower($name);
if (array_key_exists($name, $this->_options)) {
// This is a Core option
$this->_setOption($name, $value);
return;
}
if (array_key_exists($name, $this->_specificOptions)) {
// This a specic option of this frontend
$this->_specificOptions[$name] = $value;
return;
}
}
/**
* Public frontend to get an option value
*
* @param string $name Name of the option
* @throws Zend_Cache_Exception
* @return mixed option value
*/
public function getOption($name)
{
if (is_string($name)) {
$name = strtolower($name);
if (array_key_exists($name, $this->_options)) {
// This is a Core option
return $this->_options[$name];
}
if (array_key_exists($name, $this->_specificOptions)) {
// This a specic option of this frontend
return $this->_specificOptions[$name];
}
}
Zend_Cache::throwException("Incorrect option name : $name");
}
/**
* Set an option
*
* @param string $name Name of the option
* @param mixed $value Value of the option
* @throws Zend_Cache_Exception
* @return void
*/
private function _setOption($name, $value)
{
if (!is_string($name) || !array_key_exists($name, $this->_options)) {
Zend_Cache::throwException("Incorrect option name : $name");
}
$this->_options[$name] = $value;
}
/**
* Force a new lifetime
*
* The new value is set for the core/frontend but for the backend too (directive)
*
* @param int $newLifetime New lifetime (in seconds)
* @return void
*/
public function setLifetime($newLifetime)
{
$this->_options['lifetime'] = $newLifetime;
$this->_backend->setDirectives(array(
'lifetime' => $newLifetime
));
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* @param string $id Cache id
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
* @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use
* @return mixed|false Cached datas
*/
public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)
{
if (!$this->_options['caching']) {
return false;
}
$id = $this->_id($id); // cache id may need prefix
$this->_lastId = $id;
self::_validateIdOrTag($id);
$data = $this->_backend->load($id, $doNotTestCacheValidity);
if ($data===false) {
// no cache available
return false;
}
if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) {
// we need to unserialize before sending the result
return unserialize($data);
}
return $data;
}
/**
* Test if a cache is available for the given id
*
* @param string $id Cache id
* @return boolean True is a cache is available, false else
*/
public function test($id)
{
if (!$this->_options['caching']) {
return false;
}
$id = $this->_id($id); // cache id may need prefix
self::_validateIdOrTag($id);
$this->_lastId = $id;
return $this->_backend->test($id);
}
/**
* Save some data in a cache
*
* @param mixed $data Data to put in cache (can be another type than string if automatic_serialization is on)
* @param string $id Cache id (if not set, the last cache id will be used)
* @param array $tags Cache tags
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
* @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
* @throws Zend_Cache_Exception
* @return boolean True if no problem
*/
public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8)
{
if (!$this->_options['caching']) {
return true;
}
if ($id === null) {
$id = $this->_lastId;
} else {
$id = $this->_id($id);
}
self::_validateIdOrTag($id);
self::_validateTagsArray($tags);
if ($this->_options['automatic_serialization']) {
// we need to serialize datas before storing them
$data = serialize($data);
} else {
if (!is_string($data)) {
Zend_Cache::throwException("Datas must be string or set automatic_serialization = true");
}
}
// automatic cleaning
if ($this->_options['automatic_cleaning_factor'] > 0) {
$rand = rand(1, $this->_options['automatic_cleaning_factor']);
if ($rand==1) {
if ($this->_extendedBackend) {
// New way
if ($this->_backendCapabilities['automatic_cleaning']) {
$this->clean(Zend_Cache::CLEANING_MODE_OLD);
} else {
$this->_log('Zend_Cache_Core::save() / automatic cleaning is not available/necessary with this backend');
}
} else {
// Deprecated way (will be removed in next major version)
if (method_exists($this->_backend, 'isAutomaticCleaningAvailable') && ($this->_backend->isAutomaticCleaningAvailable())) {
$this->clean(Zend_Cache::CLEANING_MODE_OLD);
} else {
$this->_log('Zend_Cache_Core::save() / automatic cleaning is not available/necessary with this backend');
}
}
}
}
if ($this->_options['ignore_user_abort']) {
$abort = ignore_user_abort(true);
}
if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) {
$result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority);
} else {
$result = $this->_backend->save($data, $id, $tags, $specificLifetime);
}
if ($this->_options['ignore_user_abort']) {
ignore_user_abort($abort);
}
if (!$result) {
// maybe the cache is corrupted, so we remove it !
if ($this->_options['logging']) {
$this->_log("Zend_Cache_Core::save() : impossible to save cache (id=$id)");
}
$this->remove($id);
return false;
}
if ($this->_options['write_control']) {
$data2 = $this->_backend->load($id, true);
if ($data!=$data2) {
$this->_log('Zend_Cache_Core::save() / write_control : written and read data do not match');
$this->_backend->remove($id);
return false;
}
}
return true;
}
/**
* Remove a cache
*
* @param string $id Cache id to remove
* @return boolean True if ok
*/
public function remove($id)
{
if (!$this->_options['caching']) {
return true;
}
$id = $this->_id($id); // cache id may need prefix
self::_validateIdOrTag($id);
return $this->_backend->remove($id);
}
/**
* Clean cache entries
*
* Available modes are :
* 'all' (default) => remove all cache entries ($tags is not used)
* 'old' => remove too old cache entries ($tags is not used)
* 'matchingTag' => remove cache entries matching all given tags
* ($tags can be an array of strings or a single string)
* 'notMatchingTag' => remove cache entries not matching one of the given tags
* ($tags can be an array of strings or a single string)
* 'matchingAnyTag' => remove cache entries matching any given tags
* ($tags can be an array of strings or a single string)
*
* @param string $mode
* @param array|string $tags
* @throws Zend_Cache_Exception
* @return boolean True if ok
*/
public function clean($mode = 'all', $tags = array())
{
if (!$this->_options['caching']) {
return true;
}
if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL,
Zend_Cache::CLEANING_MODE_OLD,
Zend_Cache::CLEANING_MODE_MATCHING_TAG,
Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG,
Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) {
Zend_Cache::throwException('Invalid cleaning mode');
}
self::_validateTagsArray($tags);
return $this->_backend->clean($mode, $tags);
}
/**
* Return an array of stored cache ids which match given tags
*
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of matching cache ids (string)
*/
public function getIdsMatchingTags($tags = array())
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
if (!($this->_backendCapabilities['tags'])) {
Zend_Cache::throwException('tags are not supported by the current backend');
}
return $this->_backend->getIdsMatchingTags($tags);
}
/**
* Return an array of stored cache ids which don't match given tags
*
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
*/
public function getIdsNotMatchingTags($tags = array())
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
if (!($this->_backendCapabilities['tags'])) {
Zend_Cache::throwException('tags are not supported by the current backend');
}
return $this->_backend->getIdsNotMatchingTags($tags);
}
/**
* Return an array of stored cache ids
*
* @return array array of stored cache ids (string)
*/
public function getIds()
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
$array = $this->_backend->getIds();
if ((!isset($this->_options['cache_id_prefix'])) || ($this->_options['cache_id_prefix'] == '')) return $array;
// we need to remove cache_id_prefix from ids (see #ZF-6178)
$res = array();
while (list(,$id) = each($array)) {
if (strpos($id, $this->_options['cache_id_prefix']) === 0) {
$res[] = preg_replace("~^{$this->_options['cache_id_prefix']}~", '', $id);
} else {
$res[] = $id;
}
}
return $res;
}
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
if (!($this->_backendCapabilities['tags'])) {
Zend_Cache::throwException('tags are not supported by the current backend');
}
return $this->_backend->getTags();
}
/**
* Return the filling percentage of the backend storage
*
* @return int integer between 0 and 100
*/
public function getFillingPercentage()
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
return $this->_backend->getFillingPercentage();
}
/**
* Return an array of metadatas for the given cache id
*
* The array will include these keys :
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
*
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id)
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
$id = $this->_id($id); // cache id may need prefix
return $this->_backend->getMetadatas($id);
}
/**
* Give (if possible) an extra lifetime to the given cache id
*
* @param string $id cache id
* @param int $extraLifetime
* @return boolean true if ok
*/
public function touch($id, $extraLifetime)
{
if (!$this->_extendedBackend) {
Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
}
$id = $this->_id($id); // cache id may need prefix
return $this->_backend->touch($id, $extraLifetime);
}
/**
* Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
*
* Throw an exception if a problem is found
*
* @param string $string Cache id or tag
* @throws Zend_Cache_Exception
* @return void
*/
protected static function _validateIdOrTag($string)
{
if (!is_string($string)) {
Zend_Cache::throwException('Invalid id or tag : must be a string');
}
if (substr($string, 0, 9) == 'internal-') {
Zend_Cache::throwException('"internal-*" ids or tags are reserved');
}
if (!preg_match('~^[\w]+$~D', $string)) {
Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]");
}
}
/**
* Validate a tags array (security, reliable filenames, reserved prefixes...)
*
* Throw an exception if a problem is found
*
* @param array $tags Array of tags
* @throws Zend_Cache_Exception
* @return void
*/
protected static function _validateTagsArray($tags)
{
if (!is_array($tags)) {
Zend_Cache::throwException('Invalid tags array : must be an array');
}
foreach($tags as $tag) {
self::_validateIdOrTag($tag);
}
reset($tags);
}
/**
* Make sure if we enable logging that the Zend_Log class
* is available.
* Create a default log object if none is set.
*
* @throws Zend_Cache_Exception
* @return void
*/
protected function _loggerSanity()
{
if (!isset($this->_options['logging']) || !$this->_options['logging']) {
return;
}
if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) {
return;
}
// Create a default logger to the standard output stream
require_once 'Zend/Log/Writer/Stream.php';
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
$this->_options['logger'] = $logger;
}
/**
* Log a message at the WARN (4) priority.
*
* @param string $message
* @throws Zend_Cache_Exception
* @return void
*/
protected function _log($message, $priority = 4)
{
if (!$this->_options['logging']) {
return;
}
if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) {
Zend_Cache::throwException('Logging is enabled but logger is not set');
}
$logger = $this->_options['logger'];
$logger->log($message, $priority);
}
/**
* Make and return a cache id
*
* Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null
*
* @param string $id Cache id
* @return string Cache id (with or without prefix)
*/
protected function _id($id)
{
if (($id !== null) && isset($this->_options['cache_id_prefix'])) {
return $this->_options['cache_id_prefix'] . $id; // return with prefix
}
return $id; // no prefix, just return the $id passed
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Exception
*/
require_once 'Zend/Exception.php';
/**
* @package Zend_Cache
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Exception extends Zend_Exception {}
+243
View File
@@ -0,0 +1,243 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* @see Zend_Cache_Core
*/
require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_Class extends Zend_Cache_Core
{
/**
* Available options
*
* ====> (mixed) cached_entity :
* - if set to a class name, we will cache an abstract class and will use only static calls
* - if set to an object, we will cache this object methods
*
* ====> (boolean) cache_by_default :
* - if true, method calls will be cached by default
*
* ====> (array) cached_methods :
* - an array of method names which will be cached (even if cache_by_default = false)
*
* ====> (array) non_cached_methods :
* - an array of method names which won't be cached (even if cache_by_default = true)
*
* @var array available options
*/
protected $_specificOptions = array(
'cached_entity' => null,
'cache_by_default' => true,
'cached_methods' => array(),
'non_cached_methods' => array()
);
/**
* Tags array
*
* @var array
*/
private $_tags = array();
/**
* SpecificLifetime value
*
* false => no specific life time
*
* @var int
*/
private $_specificLifetime = false;
/**
* The cached object or the name of the cached abstract class
*
* @var mixed
*/
private $_cachedEntity = null;
/**
* The class name of the cached object or cached abstract class
*
* Used to differentiate between different classes with the same method calls.
*
* @var string
*/
private $_cachedEntityLabel = '';
/**
* Priority (used by some particular backends)
*
* @var int
*/
private $_priority = 8;
/**
* Constructor
*
* @param array $options Associative array of options
* @throws Zend_Cache_Exception
* @return void
*/
public function __construct(array $options = array())
{
while (list($name, $value) = each($options)) {
$this->setOption($name, $value);
}
if ($this->_specificOptions['cached_entity'] === null) {
Zend_Cache::throwException('cached_entity must be set !');
}
$this->setCachedEntity($this->_specificOptions['cached_entity']);
$this->setOption('automatic_serialization', true);
}
/**
* Set a specific life time
*
* @param int $specificLifetime
* @return void
*/
public function setSpecificLifetime($specificLifetime = false)
{
$this->_specificLifetime = $specificLifetime;
}
/**
* Set the priority (used by some particular backends)
*
* @param int $priority integer between 0 (very low priority) and 10 (maximum priority)
*/
public function setPriority($priority)
{
$this->_priority = $priority;
}
/**
* Public frontend to set an option
*
* Just a wrapper to get a specific behaviour for cached_entity
*
* @param string $name Name of the option
* @param mixed $value Value of the option
* @throws Zend_Cache_Exception
* @return void
*/
public function setOption($name, $value)
{
if ($name == 'cached_entity') {
$this->setCachedEntity($value);
} else {
parent::setOption($name, $value);
}
}
/**
* Specific method to set the cachedEntity
*
* if set to a class name, we will cache an abstract class and will use only static calls
* if set to an object, we will cache this object methods
*
* @param mixed $cachedEntity
*/
public function setCachedEntity($cachedEntity)
{
if (!is_string($cachedEntity) && !is_object($cachedEntity)) {
Zend_Cache::throwException('cached_entity must be an object or a class name');
}
$this->_cachedEntity = $cachedEntity;
$this->_specificOptions['cached_entity'] = $cachedEntity;
if (is_string($this->_cachedEntity)){
$this->_cachedEntityLabel = $this->_cachedEntity;
} else {
$ro = new ReflectionObject($this->_cachedEntity);
$this->_cachedEntityLabel = $ro->getName();
}
}
/**
* Set the cache array
*
* @param array $tags
* @return void
*/
public function setTagsArray($tags = array())
{
$this->_tags = $tags;
}
/**
* Main method : call the specified method or get the result from cache
*
* @param string $name Method name
* @param array $parameters Method parameters
* @return mixed Result
*/
public function __call($name, $parameters)
{
$cacheBool1 = $this->_specificOptions['cache_by_default'];
$cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']);
$cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']);
$cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
if (!$cache) {
// We do not have not cache
return call_user_func_array(array($this->_cachedEntity, $name), $parameters);
}
$id = $this->_makeId($name, $parameters);
if ($this->test($id)) {
// A cache is available
$result = $this->load($id);
$output = $result[0];
$return = $result[1];
} else {
// A cache is not available
ob_start();
ob_implicit_flush(false);
$return = call_user_func_array(array($this->_cachedEntity, $name), $parameters);
$output = ob_get_contents();
ob_end_clean();
$data = array($output, $return);
$this->save($data, $id, $this->_tags, $this->_specificLifetime, $this->_priority);
}
echo $output;
return $return;
}
/**
* Make a cache id from the method name and parameters
*
* @param string $name Method name
* @param array $parameters Method parameters
* @return string Cache id
*/
private function _makeId($name, $parameters)
{
return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($parameters));
}
}

Some files were not shown because too many files have changed in this diff Show More