MDL-20632 latest zend framework lib import
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
{}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
{}
|
||||
Executable
+133
@@ -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);
|
||||
}
|
||||
}
|
||||
Executable
+103
@@ -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();
|
||||
}
|
||||
}
|
||||
Executable
+309
@@ -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';
|
||||
}
|
||||
}
|
||||
Executable
+42
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 == '') {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
Executable
+42
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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']
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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']);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
{}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+207
@@ -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
@@ -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
@@ -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']);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {}
|
||||
@@ -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
Reference in New Issue
Block a user