MDL-51536 libraries: Upgrade zend to 1.12.16
This commit is contained in:
@@ -200,7 +200,7 @@
|
||||
<location>zend</location>
|
||||
<name>Zend Framework</name>
|
||||
<license>BSD</license>
|
||||
<version>1.10.6</version>
|
||||
<version>1.12.16</version>
|
||||
<licenseversion></licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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-2015 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-2015 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-2015 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-2015 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
|
||||
{}
|
||||
+26
-29
@@ -13,65 +13,62 @@
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @package Zend_Acl
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Zend_Service_DeveloperGarden_Response_BaseType
|
||||
* @see Zend_Acl_Resource_Interface
|
||||
*/
|
||||
require_once 'Zend/Service/DeveloperGarden/Response/BaseType.php';
|
||||
require_once 'Zend/Acl/Resource/Interface.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @author Marco Kaiser
|
||||
* @package Zend_Acl
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Service_DeveloperGarden_Response_IpLocation_CityType
|
||||
extends Zend_Service_DeveloperGarden_Response_BaseType
|
||||
class Zend_Acl_Resource implements Zend_Acl_Resource_Interface
|
||||
{
|
||||
/**
|
||||
* Unique id of Resource
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $countryCode = null;
|
||||
protected $_resourceId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* Sets the Resource identifier
|
||||
*
|
||||
* @param string $resourceId
|
||||
*/
|
||||
public $cityCode = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $cityName = null;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCountryCode()
|
||||
public function __construct($resourceId)
|
||||
{
|
||||
return $this->countryCode;
|
||||
$this->_resourceId = (string) $resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Zend_Acl_Resource_Interface; returns the Resource identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCityCode()
|
||||
public function getResourceId()
|
||||
{
|
||||
return $this->cityCode;
|
||||
return $this->_resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Zend_Acl_Resource_Interface; returns the Resource identifier
|
||||
* Proxies to getResourceId()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCityName()
|
||||
public function __toString()
|
||||
{
|
||||
return $this->cityName;
|
||||
return $this->getResourceId();
|
||||
}
|
||||
}
|
||||
@@ -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-2015 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-2015 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();
|
||||
}
|
||||
+34
-20
@@ -13,48 +13,62 @@
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @package Zend_Acl
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
|
||||
* @see Zend_Acl_Role_Interface
|
||||
*/
|
||||
require_once 'Zend/Service/DeveloperGarden/Response/VoiceButler/VoiceButlerAbstract.php';
|
||||
require_once 'Zend/Acl/Role/Interface.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @author Marco Kaiser
|
||||
* @package Zend_Acl
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Service_DeveloperGarden_Response_VoiceButler_NewCallResponse
|
||||
extends Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
|
||||
class Zend_Acl_Role implements Zend_Acl_Role_Interface
|
||||
{
|
||||
/**
|
||||
* returns the session id
|
||||
* @return string
|
||||
* Unique id of Role
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public function getSessionId()
|
||||
protected $_roleId;
|
||||
|
||||
/**
|
||||
* Sets the Role identifier
|
||||
*
|
||||
* @param string $roleId
|
||||
*/
|
||||
public function __construct($roleId)
|
||||
{
|
||||
if (isset($this->return->sessionId)) {
|
||||
return $this->return->sessionId;
|
||||
}
|
||||
return null;
|
||||
$this->_roleId = (string) $roleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* prints the session on casting to string
|
||||
* Defined by Zend_Acl_Role_Interface; returns the Role identifier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRoleId()
|
||||
{
|
||||
return $this->_roleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Zend_Acl_Role_Interface; returns the Role identifier
|
||||
* Proxies to getRoleId()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getSessionId();
|
||||
return $this->getRoleId();
|
||||
}
|
||||
}
|
||||
@@ -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-2015 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-2015 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-2015 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-2015 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", 0, $e);
|
||||
}
|
||||
$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 new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $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 new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $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-2015 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-2015 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
|
||||
{}
|
||||
Regular → Executable
+6
-3
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -28,12 +28,15 @@ require_once 'Zend/Acl.php';
|
||||
/** @see Zend_Auth_Result */
|
||||
require_once 'Zend/Auth/Result.php';
|
||||
|
||||
/** @see Zend_Xml_Security */
|
||||
require_once 'Zend/Xml/Security.php';
|
||||
|
||||
/**
|
||||
* This class implements authentication against XML file with roles for Flex Builder.
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Adobe
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -61,7 +64,7 @@ class Zend_Amf_Adobe_Auth extends Zend_Amf_Auth_Abstract
|
||||
public function __construct($rolefile)
|
||||
{
|
||||
$this->_acl = new Zend_Acl();
|
||||
$xml = simplexml_load_file($rolefile);
|
||||
$xml = Zend_Xml_Security::scanFile($rolefile);
|
||||
/*
|
||||
Roles file format:
|
||||
<roles>
|
||||
|
||||
Regular → Executable
+2
-2
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Adobe
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Adobe_DbInspector
|
||||
|
||||
Regular → Executable
+8
-3
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ require_once 'Zend/Server/Reflection.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Adobe
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Adobe_Introspector
|
||||
@@ -283,7 +283,12 @@ class Zend_Amf_Adobe_Introspector
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass', 'array'))) {
|
||||
// Arrays
|
||||
if ('array' == $typename) {
|
||||
return 'Unknown[]';
|
||||
}
|
||||
|
||||
if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass'))) {
|
||||
return $typename;
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+2
-2
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -27,7 +27,7 @@ require_once 'Zend/Auth/Adapter/Interface.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Auth
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -24,7 +24,7 @@
|
||||
* deserialization to detect the AMF marker and encoding types.
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
final class Zend_Amf_Constants
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ require_once 'Zend/Exception.php';
|
||||
|
||||
/**
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf0
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -23,6 +23,9 @@
|
||||
/** Zend_Amf_Constants */
|
||||
require_once 'Zend/Amf/Constants.php';
|
||||
|
||||
/** Zend_Xml_Security */
|
||||
require_once 'Zend/Xml/Security.php';
|
||||
|
||||
/** @see Zend_Amf_Parse_Deserializer */
|
||||
require_once 'Zend/Amf/Parse/Deserializer.php';
|
||||
|
||||
@@ -33,7 +36,7 @@ require_once 'Zend/Amf/Parse/Deserializer.php';
|
||||
* @todo Class could be implemented as Factory Class with each data type it's own class
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf0
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -248,7 +251,7 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
|
||||
public function readXmlString()
|
||||
{
|
||||
$string = $this->_stream->readLongUTF();
|
||||
return simplexml_load_string($string);
|
||||
return Zend_Xml_Security::scan($string); //simplexml_load_string($string);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf0
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Parse/Serializer.php';
|
||||
* @uses Zend_Amf_Parse_Serializer
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf0
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -63,8 +63,8 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
|
||||
*/
|
||||
public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
|
||||
{
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// variables should be passed by reference"
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// variables should be passed by reference"
|
||||
if ((null === $data) && ($dataByVal !== false)) {
|
||||
$data = &$dataByVal;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
|
||||
case (is_bool($data)):
|
||||
$markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
|
||||
break;
|
||||
case (is_string($data) && (strlen($data) > 65536)):
|
||||
case (is_string($data) && (($this->_mbStringFunctionsOverloaded ? mb_strlen($data, '8bit') : strlen($data)) > 65536)):
|
||||
$markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
|
||||
break;
|
||||
case (is_string($data)):
|
||||
@@ -187,23 +187,23 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
|
||||
* 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 reference to check for reference
|
||||
* @param $markerType AMF type of the object to write
|
||||
* @param mixed $objectByVal object to check for reference
|
||||
* @param mixed $object object reference to check for reference
|
||||
* @param string $markerType AMF type of the object to write
|
||||
* @param mixed $objectByVal object to check for reference
|
||||
* @return Boolean true, if the reference was written, false otherwise
|
||||
*/
|
||||
protected function writeObjectReference(&$object, $markerType, $objectByVal = false)
|
||||
protected function writeObjectReference(&$object, $markerType, $objectByVal = false)
|
||||
{
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// variables should be passed by reference"
|
||||
if ((null === $object) && ($objectByVal !== false)) {
|
||||
$object = &$objectByVal;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf3
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -23,6 +23,9 @@
|
||||
/** Zend_Amf_Parse_Deserializer */
|
||||
require_once 'Zend/Amf/Parse/Deserializer.php';
|
||||
|
||||
/** Zend_Xml_Security */
|
||||
require_once 'Zend/Xml/Security.php';
|
||||
|
||||
/** Zend_Amf_Parse_TypeLoader */
|
||||
require_once 'Zend/Amf/Parse/TypeLoader.php';
|
||||
|
||||
@@ -34,7 +37,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
|
||||
* @todo Class could be implemented as Factory Class with each data type it's own class.
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf3
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -225,7 +228,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
|
||||
$timestamp = floor($this->_stream->readDouble() / 1000);
|
||||
|
||||
require_once 'Zend/Date.php';
|
||||
$dateTime = new Zend_Date((int) $timestamp);
|
||||
$dateTime = new Zend_Date($timestamp);
|
||||
$this->_referenceObjects[] = $dateTime;
|
||||
return $dateTime;
|
||||
}
|
||||
@@ -385,6 +388,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
|
||||
}
|
||||
|
||||
// Add properties back to the return object.
|
||||
if (!is_array($properties)) $properties = array();
|
||||
foreach($properties as $key=>$value) {
|
||||
if($key) {
|
||||
$returnObject->$key = $value;
|
||||
@@ -416,6 +420,6 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
|
||||
$xmlReference = $this->readInteger();
|
||||
$length = $xmlReference >> 1;
|
||||
$string = $this->_stream->readBytes($length);
|
||||
return simplexml_load_string($string);
|
||||
return Zend_Xml_Security::scan($string);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf3
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -35,7 +35,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse_Amf3
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -45,7 +45,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
* @var string
|
||||
*/
|
||||
protected $_strEmpty = '';
|
||||
|
||||
|
||||
/**
|
||||
* An array of reference objects per amf body
|
||||
* @var array
|
||||
@@ -78,7 +78,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
*/
|
||||
public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
|
||||
{
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// variables should be passed by reference"
|
||||
if ((null === $data) && ($dataByVal !== false)) {
|
||||
$data = &$dataByVal;
|
||||
@@ -215,7 +215,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
* @return Zend_Amf_Parse_Amf3_Serializer
|
||||
*/
|
||||
protected function writeBinaryString(&$string){
|
||||
$ref = strlen($string) << 1 | 0x01;
|
||||
$ref = ($this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string)) << 1 | 0x01;
|
||||
$this->writeInteger($ref);
|
||||
$this->_stream->writeBytes($string);
|
||||
|
||||
@@ -230,15 +230,17 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
*/
|
||||
public function writeString(&$string)
|
||||
{
|
||||
$len = strlen($string);
|
||||
$len = $this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string);
|
||||
if(!$len){
|
||||
$this->writeInteger(0x01);
|
||||
return $this;
|
||||
}
|
||||
|
||||
$ref = array_search($string, $this->_referenceStrings, true);
|
||||
if($ref === false){
|
||||
$this->_referenceStrings[] = $string;
|
||||
$ref = array_key_exists($string, $this->_referenceStrings)
|
||||
? $this->_referenceStrings[$string]
|
||||
: false;
|
||||
if ($ref === false){
|
||||
$this->_referenceStrings[$string] = count($this->_referenceStrings);
|
||||
$this->writeBinaryString($string);
|
||||
} else {
|
||||
$ref <<= 1;
|
||||
@@ -380,13 +382,16 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
*/
|
||||
protected function writeObjectReference(&$object, $objectByVal = false)
|
||||
{
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about "Only
|
||||
// variables should be passed by reference"
|
||||
if ((null === $object) && ($objectByVal !== false)) {
|
||||
$object = &$objectByVal;
|
||||
}
|
||||
|
||||
$ref = array_search($object, $this->_referenceObjects,true);
|
||||
$hash = spl_object_hash($object);
|
||||
$ref = array_key_exists($hash, $this->_referenceObjects)
|
||||
? $this->_referenceObjects[$hash]
|
||||
: false;
|
||||
|
||||
// quickly handle object references
|
||||
if ($ref !== false){
|
||||
@@ -394,7 +399,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
|
||||
$this->writeInteger($ref);
|
||||
return true;
|
||||
}
|
||||
$this->_referenceObjects[] = $object;
|
||||
$this->_referenceObjects[$hash] = count($this->_referenceObjects);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -30,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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -31,7 +31,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
|
||||
* @uses Zend_Amf_Util_BinaryStream
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
Regular → Executable
+2
-2
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -26,7 +26,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -26,7 +26,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
Regular → Executable
+2
-2
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -37,6 +37,13 @@ abstract class Zend_Amf_Parse_Serializer
|
||||
*/
|
||||
protected $_stream;
|
||||
|
||||
/**
|
||||
* str* functions overloaded using mbstring.func_overload
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mbStringFunctionsOverloaded;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -46,6 +53,7 @@ abstract class Zend_Amf_Parse_Serializer
|
||||
public function __construct(Zend_Amf_Parse_OutputStream $stream)
|
||||
{
|
||||
$this->_stream = $stream;
|
||||
$this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Parse
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -47,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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -40,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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Request
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Request
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Request.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Request
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -32,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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Response
|
||||
@@ -95,7 +95,7 @@ class Zend_Amf_Response
|
||||
$stream->writeByte($header->mustRead);
|
||||
$stream->writeLong(Zend_Amf_Constants::UNKNOWN_CONTENT_LENGTH);
|
||||
if (is_object($header->data)) {
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about
|
||||
// "Only variables should be passed by reference"
|
||||
$placeholder = null;
|
||||
$serializer->writeTypeMarker($placeholder, null, $header->data);
|
||||
@@ -115,7 +115,7 @@ class Zend_Amf_Response
|
||||
$bodyData = $body->getData();
|
||||
$markerType = ($this->_objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) ? null : Zend_Amf_Constants::AMF0_AMF3;
|
||||
if (is_object($bodyData)) {
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about
|
||||
// Workaround for PHP5 with E_STRICT enabled complaining about
|
||||
// "Only variables should be passed by reference"
|
||||
$placeholder = null;
|
||||
$serializer->writeTypeMarker($placeholder, $markerType, $bodyData);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Response
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -28,7 +28,7 @@ require_once 'Zend/Amf/Response.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Response
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -41,10 +41,33 @@ class Zend_Amf_Response_Http extends Zend_Amf_Response
|
||||
public function getResponse()
|
||||
{
|
||||
if (!headers_sent()) {
|
||||
header('Cache-Control: cache, must-revalidate');
|
||||
header('Pragma: public');
|
||||
if ($this->isIeOverSsl()) {
|
||||
header('Cache-Control: cache, must-revalidate');
|
||||
header('Pragma: public');
|
||||
} else {
|
||||
header('Cache-Control: no-cache, must-revalidate');
|
||||
header('Pragma: no-cache');
|
||||
}
|
||||
header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
|
||||
header('Content-Type: application/x-amf');
|
||||
}
|
||||
return parent::getResponse();
|
||||
}
|
||||
|
||||
protected function isIeOverSsl()
|
||||
{
|
||||
$ssl = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : false;
|
||||
if (!$ssl || ($ssl == 'off')) {
|
||||
// IIS reports "off", whereas other browsers simply don't populate
|
||||
return false;
|
||||
}
|
||||
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||
if (!preg_match('/; MSIE \d+\.\d+;/', $ua)) {
|
||||
// Not MicroSoft Internet Explorer
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+179
-64
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -52,7 +52,7 @@ require_once 'Zend/Auth.php';
|
||||
* @todo Make the reflection methods cache and autoload.
|
||||
* @package Zend_Amf
|
||||
* @subpackage Server
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
@@ -108,7 +108,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
protected $_session = false;
|
||||
|
||||
/**
|
||||
* Namespace allows all AMF calls to not clobber other php session variables
|
||||
* 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';
|
||||
@@ -142,12 +142,18 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
/**
|
||||
* Set authentication adapter
|
||||
*
|
||||
* If the authentication adapter implements a "getAcl()" method, populate
|
||||
* the ACL of this instance with it (if none exists already).
|
||||
*
|
||||
* @param Zend_Amf_Auth_Abstract $auth
|
||||
* @return Zend_Amf_Server
|
||||
*/
|
||||
public function setAuth(Zend_Amf_Auth_Abstract $auth)
|
||||
{
|
||||
$this->_auth = $auth;
|
||||
if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) {
|
||||
$this->setAcl($auth->getAcl());
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
@@ -300,12 +306,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
$source = $mapped;
|
||||
}
|
||||
}
|
||||
$qualifiedName = empty($source) ? $method : $source.".".$method;
|
||||
$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) {
|
||||
$className = str_replace(".", "_", $source);
|
||||
$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()');
|
||||
@@ -317,8 +323,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
|
||||
}
|
||||
// Add the new loaded class to the server.
|
||||
require_once 'Zend/Amf/Server/Exception.php';
|
||||
$this->setClass($className, $source);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!isset($this->_table[$qualifiedName])) {
|
||||
// Source is null or doesn't contain specified method
|
||||
require_once 'Zend/Amf/Server/Exception.php';
|
||||
throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist');
|
||||
}
|
||||
@@ -331,6 +341,8 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
$params = array_merge($params, $argv);
|
||||
}
|
||||
|
||||
$params = $this->_castParameters($info, $params);
|
||||
|
||||
if ($info instanceof Zend_Server_Reflection_Function) {
|
||||
$func = $info->getName();
|
||||
$this->_checkAcl(null, $func);
|
||||
@@ -491,66 +503,60 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
// set response 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;
|
||||
// Authenticate, if we have credential headers
|
||||
$error = false;
|
||||
$headers = $request->getAmfHeaders();
|
||||
if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER])
|
||||
&& isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)
|
||||
&& isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)
|
||||
) {
|
||||
try {
|
||||
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
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Error during authentication; report it
|
||||
$error = $this->_errorMessage(
|
||||
$objectEncoding,
|
||||
'',
|
||||
$e->getMessage(),
|
||||
$e->getTraceAsString(),
|
||||
$e->getCode(),
|
||||
$e->getLine()
|
||||
);
|
||||
$responseType = Zend_AMF_Constants::STATUS_METHOD;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through each of the service calls in the AMF request
|
||||
foreach($responseBody as $body)
|
||||
foreach($request->getAmfBodies() as $body)
|
||||
{
|
||||
if ($error) {
|
||||
// Error during authentication; just report it and be done
|
||||
$responseURI = $body->getResponseURI() . $responseType;
|
||||
$newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error);
|
||||
$response->addAmfBody($newBody);
|
||||
continue;
|
||||
}
|
||||
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, '.'));
|
||||
|
||||
if ($source) {
|
||||
// Break off method name from namespace into source
|
||||
$method = substr(strrchr($targetURI, '.'), 1);
|
||||
$return = $this->_dispatch($method, $body->getData(), $source);
|
||||
} else {
|
||||
// Just have a method name.
|
||||
$return = $this->_dispatch($targetURI, $body->getData());
|
||||
}
|
||||
} else {
|
||||
// AMF3 read message type
|
||||
$message = $body->getData();
|
||||
if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
|
||||
// async call with command message
|
||||
$return = $this->_loadCommandMessage($message);
|
||||
} elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
|
||||
require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
|
||||
$return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
|
||||
$return->body = $this->_dispatch($message->operation, $message->body, $message->source);
|
||||
} else {
|
||||
// Amf3 message sent with netConnection
|
||||
switch ($objectEncoding) {
|
||||
case 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, '.'));
|
||||
@@ -563,7 +569,35 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
// Just have a method name.
|
||||
$return = $this->_dispatch($targetURI, $body->getData());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Zend_Amf_Constants::AMF3_OBJECT_ENCODING:
|
||||
default:
|
||||
// AMF3 read message type
|
||||
$message = $body->getData();
|
||||
if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
|
||||
// async call with command message
|
||||
$return = $this->_loadCommandMessage($message);
|
||||
} elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
|
||||
require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
|
||||
$return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
|
||||
$return->body = $this->_dispatch($message->operation, $message->body, $message->source);
|
||||
} else {
|
||||
// Amf3 message sent with netConnection
|
||||
$targetURI = $body->getTargetURI();
|
||||
|
||||
// Split the target string into its values.
|
||||
$source = substr($targetURI, 0, strrpos($targetURI, '.'));
|
||||
|
||||
if ($source) {
|
||||
// Break off method name from namespace into source
|
||||
$method = substr(strrchr($targetURI, '.'), 1);
|
||||
$return = $this->_dispatch($method, $body->getData(), $source);
|
||||
} else {
|
||||
// Just have a method name.
|
||||
$return = $this->_dispatch($targetURI, $body->getData());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
$responseType = Zend_AMF_Constants::RESULT_METHOD;
|
||||
} catch (Exception $e) {
|
||||
@@ -607,7 +641,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
public function handle($request = null)
|
||||
{
|
||||
// Check if request was passed otherwise get it from the server
|
||||
if (is_null($request) || !$request instanceof Zend_Amf_Request) {
|
||||
if ($request === null || !$request instanceof Zend_Amf_Request) {
|
||||
$request = $this->getRequest();
|
||||
} else {
|
||||
$this->setRequest($request);
|
||||
@@ -733,9 +767,9 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object');
|
||||
}
|
||||
|
||||
$argv = null;
|
||||
$args = null;
|
||||
if (2 < func_num_args()) {
|
||||
$argv = array_slice(func_get_args(), 2);
|
||||
$args = array_slice(func_get_args(), 2);
|
||||
}
|
||||
|
||||
// Use the class name as the name space by default.
|
||||
@@ -746,7 +780,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
|
||||
$this->_classAllowed[is_object($class) ? get_class($class) : $class] = true;
|
||||
|
||||
$this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
|
||||
$this->_methods[] = Zend_Server_Reflection::reflectClass($class, $args, $namespace);
|
||||
$this->_buildDispatchTable();
|
||||
|
||||
return $this;
|
||||
@@ -930,4 +964,85 @@ class Zend_Amf_Server implements Zend_Server_Interface
|
||||
{
|
||||
return array_keys($this->_table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast parameters
|
||||
*
|
||||
* Takes the provided parameters from the request, and attempts to cast them
|
||||
* to objects, if the prototype defines any as explicit object types
|
||||
*
|
||||
* @param Reflection $reflectionMethod
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
protected function _castParameters($reflectionMethod, array $params)
|
||||
{
|
||||
$prototypes = $reflectionMethod->getPrototypes();
|
||||
$nonObjectTypes = array(
|
||||
'null',
|
||||
'mixed',
|
||||
'void',
|
||||
'unknown',
|
||||
'bool',
|
||||
'boolean',
|
||||
'number',
|
||||
'int',
|
||||
'integer',
|
||||
'double',
|
||||
'float',
|
||||
'string',
|
||||
'array',
|
||||
'object',
|
||||
'stdclass',
|
||||
);
|
||||
$types = array();
|
||||
foreach ($prototypes as $prototype) {
|
||||
foreach ($prototype->getParameters() as $parameter) {
|
||||
$type = $parameter->getType();
|
||||
if (in_array(strtolower($type), $nonObjectTypes)) {
|
||||
continue;
|
||||
}
|
||||
$position = $parameter->getPosition();
|
||||
$types[$position] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($types)) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
foreach ($params as $position => $value) {
|
||||
if (!isset($types[$position])) {
|
||||
// No specific type to cast to? done
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = $types[$position];
|
||||
|
||||
if (!class_exists($type)) {
|
||||
// Not a class, apparently. done
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value instanceof $type) {
|
||||
// Already of the right type? done
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_array($value) && !is_object($value)) {
|
||||
// Can't cast scalars to objects easily; done
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create instance, and loop through value to set
|
||||
$object = new $type;
|
||||
foreach ($value as $property => $defined) {
|
||||
$object->{$property} = $defined;
|
||||
}
|
||||
|
||||
$params[$position] = $object;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Server
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -29,7 +29,7 @@ require_once 'Zend/Amf/Exception.php';
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Server
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Util
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Util
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Util_BinaryStream
|
||||
@@ -50,6 +50,11 @@ class Zend_Amf_Util_BinaryStream
|
||||
*/
|
||||
protected $_needle;
|
||||
|
||||
/**
|
||||
* @var bool str* functions overloaded using mbstring.func_overload?
|
||||
*/
|
||||
protected $_mbStringFunctionsOverloaded;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -69,7 +74,8 @@ class Zend_Amf_Util_BinaryStream
|
||||
|
||||
$this->_stream = $stream;
|
||||
$this->_needle = 0;
|
||||
$this->_streamLength = strlen($stream);
|
||||
$this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2);
|
||||
$this->_streamLength = $this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream);
|
||||
$this->_bigEndian = (pack('l', 1) === "\x00\x00\x00\x01");
|
||||
}
|
||||
|
||||
@@ -97,7 +103,7 @@ class Zend_Amf_Util_BinaryStream
|
||||
require_once 'Zend/Amf/Exception.php';
|
||||
throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length);
|
||||
}
|
||||
$bytes = substr($this->_stream, $this->_needle, $length);
|
||||
$bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, $length, '8bit') : substr($this->_stream, $this->_needle, $length);
|
||||
$this->_needle+= $length;
|
||||
return $bytes;
|
||||
}
|
||||
@@ -120,12 +126,18 @@ class Zend_Amf_Util_BinaryStream
|
||||
* Reads a signed byte
|
||||
*
|
||||
* @return int Value is in the range of -128 to 127.
|
||||
* @throws Zend_Amf_Exception
|
||||
*/
|
||||
public function readByte()
|
||||
{
|
||||
if (($this->_needle + 1) > $this->_streamLength) {
|
||||
require_once 'Zend/Amf/Exception.php';
|
||||
throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length);
|
||||
throw new Zend_Amf_Exception(
|
||||
'Buffer underrun at needle position: '
|
||||
. $this->_needle
|
||||
. ' while requesting length: '
|
||||
. $this->_streamLength
|
||||
);
|
||||
}
|
||||
|
||||
return ord($this->_stream{$this->_needle++});
|
||||
@@ -184,7 +196,7 @@ class Zend_Amf_Util_BinaryStream
|
||||
*/
|
||||
public function writeUtf($stream)
|
||||
{
|
||||
$this->writeInt(strlen($stream));
|
||||
$this->writeInt($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream));
|
||||
$this->_stream.= $stream;
|
||||
return $this;
|
||||
}
|
||||
@@ -209,7 +221,7 @@ class Zend_Amf_Util_BinaryStream
|
||||
*/
|
||||
public function writeLongUtf($stream)
|
||||
{
|
||||
$this->writeLong(strlen($stream));
|
||||
$this->writeLong($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream));
|
||||
$this->_stream.= $stream;
|
||||
}
|
||||
|
||||
@@ -255,7 +267,7 @@ class Zend_Amf_Util_BinaryStream
|
||||
*/
|
||||
public function readDouble()
|
||||
{
|
||||
$bytes = substr($this->_stream, $this->_needle, 8);
|
||||
$bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, 8, '8bit') : substr($this->_stream, $this->_needle, 8);
|
||||
$this->_needle+= 8;
|
||||
|
||||
if (!$this->_bigEndian) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -33,7 +33,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -28,7 +28,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -26,7 +26,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
|
||||
Regular → Executable
+3
-3
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -27,9 +27,9 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
class Zend_Amf_Value_Messaging_ArrayCollection extends ArrayObject
|
||||
{
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -36,7 +36,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -31,7 +31,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 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,7 +15,7 @@
|
||||
* @category Zend
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
* @package Zend_Amf
|
||||
* @subpackage Value
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Amf_Value_TraitsInfo
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Auth
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
@@ -23,7 +23,7 @@
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Auth
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Auth
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
<?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 Adapter
|
||||
* @copyright Copyright (c) 2005-2015 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 Adapter
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
*/
|
||||
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 ($this->_secureStringCompare(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']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Securely compare two strings for equality while avoided C level memcmp()
|
||||
* optimisations capable of leaking timing information useful to an attacker
|
||||
* attempting to iteratively guess the unknown string (e.g. password) being
|
||||
* compared against.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return bool
|
||||
*/
|
||||
protected function _secureStringCompare($a, $b)
|
||||
{
|
||||
if (strlen($a) !== strlen($b)) {
|
||||
return false;
|
||||
}
|
||||
$result = 0;
|
||||
for ($i = 0; $i < strlen($a); $i++) {
|
||||
$result |= ord($a[$i]) ^ ord($b[$i]);
|
||||
}
|
||||
return $result == 0;
|
||||
}
|
||||
}
|
||||
@@ -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 Adapter
|
||||
* @copyright Copyright (c) 2005-2015 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 Adapter
|
||||
* @copyright Copyright (c) 2005-2015 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,868 @@
|
||||
<?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-2015 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-2015 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
|
||||
*/
|
||||
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 && $this->_secureStringCompare($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 ($this->_secureStringCompare($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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Securely compare two strings for equality while avoided C level memcmp()
|
||||
* optimisations capable of leaking timing information useful to an attacker
|
||||
* attempting to iteratively guess the unknown string (e.g. password) being
|
||||
* compared against.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return bool
|
||||
*/
|
||||
protected function _secureStringCompare($a, $b)
|
||||
{
|
||||
if (strlen($a) !== strlen($b)) {
|
||||
return false;
|
||||
}
|
||||
$result = 0;
|
||||
for ($i = 0; $i < strlen($a); $i++) {
|
||||
$result |= ord($a[$i]) ^ ord($b[$i]);
|
||||
}
|
||||
return $result == 0;
|
||||
}
|
||||
}
|
||||
@@ -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-2015 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-2015 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,166 @@
|
||||
<?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-2015 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-2015 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
|
||||
*/
|
||||
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-2015 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-2015 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,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-2015 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-2015 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,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-2015 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-2015 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,147 @@
|
||||
<?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-2015 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-2015 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
|
||||
*/
|
||||
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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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,66 @@
|
||||
<?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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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,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_Auth
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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,149 @@
|
||||
<?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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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 Storage
|
||||
* @copyright Copyright (c) 2005-2015 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
|
||||
*/
|
||||
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,250 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Cache
|
||||
{
|
||||
|
||||
/**
|
||||
* Standard frontends
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $standardFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');
|
||||
|
||||
/**
|
||||
* Standard backends
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform',
|
||||
'Xcache', 'TwoLevels', 'WinCache', 'ZendServer_Disk', 'ZendServer_ShMem');
|
||||
|
||||
/**
|
||||
* Standard backends which implement the ExtendedInterface
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $standardExtendedBackends = array('File', 'Apc', 'TwoLevels', 'Memcached', 'Libmemcached', 'Sqlite', 'WinCache');
|
||||
|
||||
/**
|
||||
* Only for backward compatibility (may be removed in next major release)
|
||||
*
|
||||
* @var array
|
||||
* @deprecated
|
||||
*/
|
||||
public static $availableFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');
|
||||
|
||||
/**
|
||||
* Only for backward compatibility (may be removed in next major release)
|
||||
*
|
||||
* @var array
|
||||
* @deprecated
|
||||
*/
|
||||
public static $availableBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform', 'Xcache', 'WinCache', 'TwoLevels');
|
||||
|
||||
/**
|
||||
* Consts for clean() method
|
||||
*/
|
||||
const CLEANING_MODE_ALL = 'all';
|
||||
const CLEANING_MODE_OLD = 'old';
|
||||
const CLEANING_MODE_MATCHING_TAG = 'matchingTag';
|
||||
const CLEANING_MODE_NOT_MATCHING_TAG = 'notMatchingTag';
|
||||
const CLEANING_MODE_MATCHING_ANY_TAG = 'matchingAnyTag';
|
||||
|
||||
/**
|
||||
* Factory
|
||||
*
|
||||
* @param mixed $frontend frontend name (string) or Zend_Cache_Frontend_ object
|
||||
* @param mixed $backend backend name (string) or Zend_Cache_Backend_ object
|
||||
* @param array $frontendOptions associative array of options for the corresponding frontend constructor
|
||||
* @param array $backendOptions associative array of options for the corresponding backend constructor
|
||||
* @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of "Zend_Cache_Frontend_[...]" class name
|
||||
* @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of "Zend_Cache_Backend_[...]" class name
|
||||
* @param boolean $autoload if true, there will no require_once for backend and frontend (useful only for custom backends/frontends)
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return Zend_Cache_Core|Zend_Cache_Frontend
|
||||
*/
|
||||
public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false)
|
||||
{
|
||||
if (is_string($backend)) {
|
||||
$backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload);
|
||||
} else {
|
||||
if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) {
|
||||
$backendObject = $backend;
|
||||
} else {
|
||||
self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface');
|
||||
}
|
||||
}
|
||||
if (is_string($frontend)) {
|
||||
$frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload);
|
||||
} else {
|
||||
if (is_object($frontend)) {
|
||||
$frontendObject = $frontend;
|
||||
} else {
|
||||
self::throwException('frontend must be a frontend name (string) or an object');
|
||||
}
|
||||
}
|
||||
$frontendObject->setBackend($backendObject);
|
||||
return $frontendObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend Constructor
|
||||
*
|
||||
* @param string $backend
|
||||
* @param array $backendOptions
|
||||
* @param boolean $customBackendNaming
|
||||
* @param boolean $autoload
|
||||
* @return Zend_Cache_Backend
|
||||
*/
|
||||
public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)
|
||||
{
|
||||
if (!$customBackendNaming) {
|
||||
$backend = self::_normalizeName($backend);
|
||||
}
|
||||
if (in_array($backend, Zend_Cache::$standardBackends)) {
|
||||
// we use a standard backend
|
||||
$backendClass = 'Zend_Cache_Backend_' . $backend;
|
||||
// security controls are explicit
|
||||
require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
|
||||
} else {
|
||||
// we use a custom backend
|
||||
if (!preg_match('~^[\w\\\\]+$~D', $backend)) {
|
||||
Zend_Cache::throwException("Invalid backend name [$backend]");
|
||||
}
|
||||
if (!$customBackendNaming) {
|
||||
// we use this boolean to avoid an API break
|
||||
$backendClass = 'Zend_Cache_Backend_' . $backend;
|
||||
} else {
|
||||
$backendClass = $backend;
|
||||
}
|
||||
if (!$autoload) {
|
||||
$file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
|
||||
if (!(self::_isReadable($file))) {
|
||||
self::throwException("file $file not found in include_path");
|
||||
}
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
return new $backendClass($backendOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frontend Constructor
|
||||
*
|
||||
* @param string $frontend
|
||||
* @param array $frontendOptions
|
||||
* @param boolean $customFrontendNaming
|
||||
* @param boolean $autoload
|
||||
* @return Zend_Cache_Core|Zend_Cache_Frontend
|
||||
*/
|
||||
public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false)
|
||||
{
|
||||
if (!$customFrontendNaming) {
|
||||
$frontend = self::_normalizeName($frontend);
|
||||
}
|
||||
if (in_array($frontend, self::$standardFrontends)) {
|
||||
// we use a standard frontend
|
||||
// For perfs reasons, with frontend == 'Core', we can interact with the Core itself
|
||||
$frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend;
|
||||
// security controls are explicit
|
||||
require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
|
||||
} else {
|
||||
// we use a custom frontend
|
||||
if (!preg_match('~^[\w\\\\]+$~D', $frontend)) {
|
||||
Zend_Cache::throwException("Invalid frontend name [$frontend]");
|
||||
}
|
||||
if (!$customFrontendNaming) {
|
||||
// we use this boolean to avoid an API break
|
||||
$frontendClass = 'Zend_Cache_Frontend_' . $frontend;
|
||||
} else {
|
||||
$frontendClass = $frontend;
|
||||
}
|
||||
if (!$autoload) {
|
||||
$file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
|
||||
if (!(self::_isReadable($file))) {
|
||||
self::throwException("file $file not found in include_path");
|
||||
}
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
return new $frontendClass($frontendOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception
|
||||
*
|
||||
* Note : for perf reasons, the "load" of Zend/Cache/Exception is dynamic
|
||||
* @param string $msg Message for the exception
|
||||
* @throws Zend_Cache_Exception
|
||||
*/
|
||||
public static function throwException($msg, Exception $e = null)
|
||||
{
|
||||
// For perfs reasons, we use this dynamic inclusion
|
||||
require_once 'Zend/Cache/Exception.php';
|
||||
throw new Zend_Cache_Exception($msg, 0, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize frontend and backend names to allow multiple words TitleCased
|
||||
*
|
||||
* @param string $name Name to normalize
|
||||
* @return string
|
||||
*/
|
||||
protected static function _normalizeName($name)
|
||||
{
|
||||
$name = ucfirst(strtolower($name));
|
||||
$name = str_replace(array('-', '_', '.'), ' ', $name);
|
||||
$name = ucwords($name);
|
||||
$name = str_replace(' ', '', $name);
|
||||
if (stripos($name, 'ZendServer') === 0) {
|
||||
$name = 'ZendServer_' . substr($name, strlen('ZendServer'));
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the $filename is readable, or FALSE otherwise.
|
||||
* This function uses the PHP include_path, where PHP's is_readable()
|
||||
* does not.
|
||||
*
|
||||
* Note : this method comes from Zend_Loader (see #ZF-2891 for details)
|
||||
*
|
||||
* @param string $filename
|
||||
* @return boolean
|
||||
*/
|
||||
private static function _isReadable($filename)
|
||||
{
|
||||
if (!$fh = @fopen($filename, 'r', true)) {
|
||||
return false;
|
||||
}
|
||||
@fclose($fh);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
<?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-2015 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-2015 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
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an option
|
||||
*
|
||||
* @param string $name Optional, the options name to return
|
||||
* @throws Zend_Cache_Exceptions
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOption($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (array_key_exists($name, $this->_options)) {
|
||||
return $this->_options[$name];
|
||||
}
|
||||
|
||||
if (array_key_exists($name, $this->_directives)) {
|
||||
return $this->_directives[$name];
|
||||
}
|
||||
|
||||
Zend_Cache::throwException("Incorrect option name : {$name}");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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]) && is_string($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 string $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;
|
||||
}
|
||||
|
||||
if (isset($this->_directives['logger'])) {
|
||||
if ($this->_directives['logger'] instanceof Zend_Log) {
|
||||
return;
|
||||
}
|
||||
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.php';
|
||||
require_once 'Zend/Log/Writer/Stream.php';
|
||||
require_once 'Zend/Log/Filter/Priority.php';
|
||||
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
|
||||
$logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
|
||||
$this->_directives['logger'] = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message at the WARN (4) priority.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $priority
|
||||
* @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-2015 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-2015 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()
|
||||
{
|
||||
$ids = array();
|
||||
$iterator = new APCIterator('user', null, APC_ITER_KEY);
|
||||
foreach ($iterator as $item) {
|
||||
$ids[] = $item['key'];
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,250 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Backend_BlackHole
|
||||
extends Zend_Cache_Backend
|
||||
implements Zend_Cache_Backend_ExtendedInterface
|
||||
{
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache record
|
||||
*
|
||||
* @param string $id cache id
|
||||
* @return boolean true if no problem
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored cache ids
|
||||
*
|
||||
* @return array array of stored cache ids (string)
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored tags
|
||||
*
|
||||
* @return array array of stored tags (string)
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
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())
|
||||
{
|
||||
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())
|
||||
{
|
||||
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())
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filling percentage of the backend storage
|
||||
*
|
||||
* @return int integer between 0 and 100
|
||||
* @throws Zend_Cache_Exception
|
||||
*/
|
||||
public function getFillingPercentage()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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)
|
||||
{
|
||||
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' => true,
|
||||
'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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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-2015 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-2015 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();
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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-2015 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-2015 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,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_Cache
|
||||
* @subpackage Zend_Cache_Backend
|
||||
* @copyright Copyright (c) 2005-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Backend_Libmemcached extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
|
||||
{
|
||||
/**
|
||||
* Default Server Values
|
||||
*/
|
||||
const DEFAULT_HOST = '127.0.0.1';
|
||||
const DEFAULT_PORT = 11211;
|
||||
const DEFAULT_WEIGHT = 1;
|
||||
|
||||
/**
|
||||
* Log message
|
||||
*/
|
||||
const TAGS_UNSUPPORTED_BY_CLEAN_OF_LIBMEMCACHED_BACKEND = 'Zend_Cache_Backend_Libmemcached::clean() : tags are unsupported by the Libmemcached backend';
|
||||
const TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND = 'Zend_Cache_Backend_Libmemcached::save() : tags are unsupported by the Libmemcached 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
|
||||
* '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.
|
||||
* =====> (array) client :
|
||||
* an array of memcached client options ; the memcached client is described by an associative array :
|
||||
* @see http://php.net/manual/memcached.constants.php
|
||||
* - The option name can be the name of the constant without the prefix 'OPT_'
|
||||
* or the integer value of this option constant
|
||||
*
|
||||
* @var array available options
|
||||
*/
|
||||
protected $_options = array(
|
||||
'servers' => array(array(
|
||||
'host' => self::DEFAULT_HOST,
|
||||
'port' => self::DEFAULT_PORT,
|
||||
'weight' => self::DEFAULT_WEIGHT,
|
||||
)),
|
||||
'client' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
* Memcached object
|
||||
*
|
||||
* @var mixed memcached 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('memcached')) {
|
||||
Zend_Cache::throwException('The memcached extension must be loaded for using this backend !');
|
||||
}
|
||||
|
||||
// override default client options
|
||||
$this->_options['client'] = array(
|
||||
Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT,
|
||||
Memcached::OPT_HASH => Memcached::HASH_MD5,
|
||||
Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
|
||||
);
|
||||
|
||||
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 Memcached;
|
||||
|
||||
// setup memcached client options
|
||||
foreach ($this->_options['client'] as $name => $value) {
|
||||
$optId = null;
|
||||
if (is_int($name)) {
|
||||
$optId = $name;
|
||||
} else {
|
||||
$optConst = 'Memcached::OPT_' . strtoupper($name);
|
||||
if (defined($optConst)) {
|
||||
$optId = constant($optConst);
|
||||
} else {
|
||||
$this->_log("Unknown memcached client option '{$name}' ({$optConst})");
|
||||
}
|
||||
}
|
||||
if (null !== $optId) {
|
||||
if (!$this->_memcache->setOption($optId, $value)) {
|
||||
$this->_log("Setting memcached client option '{$optId}' failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup memcached servers
|
||||
$servers = array();
|
||||
foreach ($this->_options['servers'] as $server) {
|
||||
if (!array_key_exists('port', $server)) {
|
||||
$server['port'] = self::DEFAULT_PORT;
|
||||
}
|
||||
if (!array_key_exists('weight', $server)) {
|
||||
$server['weight'] = self::DEFAULT_WEIGHT;
|
||||
}
|
||||
|
||||
$servers[] = array($server['host'], $server['port'], $server['weight']);
|
||||
}
|
||||
$this->_memcache->addServers($servers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (isset($tmp[0])) {
|
||||
return $tmp[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a cache is available or not (for the given id)
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @return int|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 (isset($tmp[0], $tmp[1])) {
|
||||
return (int)$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);
|
||||
|
||||
// ZF-8856: using set because add needs a second request if item already exists
|
||||
$result = @$this->_memcache->set($id, array($data, time(), $lifetime), $lifetime);
|
||||
if ($result === false) {
|
||||
$rsCode = $this->_memcache->getResultCode();
|
||||
$rsMsg = $this->_memcache->getResultMessage();
|
||||
$this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}");
|
||||
}
|
||||
|
||||
if (count($tags) > 0) {
|
||||
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_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_Libmemcached::clean() : CLEANING_MODE_OLD is unsupported by the Libmemcached 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_LIBMEMCACHED_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_Libmemcached::save() : getting the list of cache ids is unsupported by the Libmemcached 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_LIBMEMCACHED_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_LIBMEMCACHED_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_LIBMEMCACHED_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_LIBMEMCACHED_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->getStats();
|
||||
if ($mems === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$memSize = null;
|
||||
$memUsed = null;
|
||||
foreach ($mems as $key => $mem) {
|
||||
if ($mem === false) {
|
||||
$this->_log('can\'t get stat from ' . $key);
|
||||
continue;
|
||||
}
|
||||
|
||||
$eachSize = $mem['limit_maxbytes'];
|
||||
$eachUsed = $mem['bytes'];
|
||||
if ($eachUsed > $eachSize) {
|
||||
$eachUsed = $eachSize;
|
||||
}
|
||||
|
||||
$memSize += $eachSize;
|
||||
$memUsed += $eachUsed;
|
||||
}
|
||||
|
||||
if ($memSize === null || $memUsed === null) {
|
||||
Zend_Cache::throwException('Can\'t get filling percentage');
|
||||
}
|
||||
|
||||
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 (isset($tmp[0], $tmp[1], $tmp[2])) {
|
||||
$data = $tmp[0];
|
||||
$mtime = $tmp[1];
|
||||
$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 = $this->_memcache->get($id);
|
||||
if (isset($tmp[0], $tmp[1], $tmp[2])) {
|
||||
$data = $tmp[0];
|
||||
$mtime = $tmp[1];
|
||||
$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), $newLifetime))) {
|
||||
$result = $this->_memcache->set($id, array($data, time(), $newLifetime), $newLifetime);
|
||||
if ($result === false) {
|
||||
$rsCode = $this->_memcache->getResultCode();
|
||||
$rsMsg = $this->_memcache->getResultMessage();
|
||||
$this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}");
|
||||
}
|
||||
}
|
||||
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,509 @@
|
||||
<?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-2015 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-2015 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) && isset($tmp[0])) {
|
||||
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-8856: using set because add needs a second request if item already exists
|
||||
$result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
|
||||
|
||||
if (count($tags) > 0) {
|
||||
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_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, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = null;
|
||||
$memUsed = null;
|
||||
foreach ($mems as $key => $mem) {
|
||||
if ($mem === false) {
|
||||
$this->_log('can\'t get stat from ' . $key);
|
||||
continue;
|
||||
}
|
||||
|
||||
$eachSize = $mem['limit_maxbytes'];
|
||||
|
||||
/**
|
||||
* Couchbase 1.x uses 'mem_used' instead of 'bytes'
|
||||
* @see https://www.couchbase.com/issues/browse/MB-3466
|
||||
*/
|
||||
$eachUsed = isset($mem['bytes']) ? $mem['bytes'] : $mem['mem_used'];
|
||||
if ($eachUsed > $eachSize) {
|
||||
$eachUsed = $eachSize;
|
||||
}
|
||||
|
||||
$memSize += $eachSize;
|
||||
$memUsed += $eachUsed;
|
||||
}
|
||||
|
||||
if ($memSize === null || $memUsed === null) {
|
||||
Zend_Cache::throwException('Can\'t get filling percentage');
|
||||
}
|
||||
|
||||
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,678 @@
|
||||
<?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-2015 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-2015 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,579 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Backend_Static
|
||||
extends Zend_Cache_Backend
|
||||
implements Zend_Cache_Backend_Interface
|
||||
{
|
||||
const INNER_CACHE_NAME = 'zend_cache_backend_static_tagcache';
|
||||
|
||||
/**
|
||||
* Static backend options
|
||||
* @var array
|
||||
*/
|
||||
protected $_options = array(
|
||||
'public_dir' => null,
|
||||
'sub_dir' => 'html',
|
||||
'file_extension' => '.html',
|
||||
'index_filename' => 'index',
|
||||
'file_locking' => true,
|
||||
'cache_file_perm' => 0600,
|
||||
'cache_directory_perm' => 0700,
|
||||
'debug_header' => false,
|
||||
'tag_cache' => null,
|
||||
'disable_caching' => false
|
||||
);
|
||||
|
||||
/**
|
||||
* Cache for handling tags
|
||||
* @var Zend_Cache_Core
|
||||
*/
|
||||
protected $_tagCache = null;
|
||||
|
||||
/**
|
||||
* Tagged items
|
||||
* @var array
|
||||
*/
|
||||
protected $_tagged = null;
|
||||
|
||||
/**
|
||||
* Interceptor child method to handle the case where an Inner
|
||||
* Cache object is being set since it's not supported by the
|
||||
* standard backend interface
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return Zend_Cache_Backend_Static
|
||||
*/
|
||||
public function setOption($name, $value)
|
||||
{
|
||||
if ($name == 'tag_cache') {
|
||||
$this->setInnerCache($value);
|
||||
} else {
|
||||
// See #ZF-12047 and #GH-91
|
||||
if ($name == 'cache_file_umask') {
|
||||
trigger_error(
|
||||
"'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead",
|
||||
E_USER_NOTICE
|
||||
);
|
||||
|
||||
$name = 'cache_file_perm';
|
||||
}
|
||||
if ($name == 'cache_directory_umask') {
|
||||
trigger_error(
|
||||
"'cache_directory_umask' is deprecated -> please use 'cache_directory_perm' instead",
|
||||
E_USER_NOTICE
|
||||
);
|
||||
|
||||
$name = 'cache_directory_perm';
|
||||
}
|
||||
|
||||
parent::setOption($name, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve any option via interception of the parent's statically held
|
||||
* options including the local option for a tag cache.
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOption($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if ($name == 'tag_cache') {
|
||||
return $this->getInnerCache();
|
||||
}
|
||||
|
||||
return parent::getOption($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (($id = (string)$id) === '') {
|
||||
$id = $this->_detectId();
|
||||
} else {
|
||||
$id = $this->_decodeId($id);
|
||||
}
|
||||
if (!$this->_verifyPath($id)) {
|
||||
Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
|
||||
}
|
||||
if ($doNotTestCacheValidity) {
|
||||
$this->_log("Zend_Cache_Backend_Static::load() : \$doNotTestCacheValidity=true is unsupported by the Static backend");
|
||||
}
|
||||
|
||||
$fileName = basename($id);
|
||||
if ($fileName === '') {
|
||||
$fileName = $this->_options['index_filename'];
|
||||
}
|
||||
$pathName = $this->_options['public_dir'] . dirname($id);
|
||||
$file = rtrim($pathName, '/') . '/' . $fileName . $this->_options['file_extension'];
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
return $content;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a cache is available or not (for the given id)
|
||||
*
|
||||
* @param string $id cache id
|
||||
* @return bool
|
||||
*/
|
||||
public function test($id)
|
||||
{
|
||||
$id = $this->_decodeId($id);
|
||||
if (!$this->_verifyPath($id)) {
|
||||
Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
|
||||
}
|
||||
|
||||
$fileName = basename($id);
|
||||
if ($fileName === '') {
|
||||
$fileName = $this->_options['index_filename'];
|
||||
}
|
||||
if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
|
||||
$this->_tagged = $tagged;
|
||||
} elseif (!$this->_tagged) {
|
||||
return false;
|
||||
}
|
||||
$pathName = $this->_options['public_dir'] . dirname($id);
|
||||
|
||||
// Switch extension if needed
|
||||
if (isset($this->_tagged[$id])) {
|
||||
$extension = $this->_tagged[$id]['extension'];
|
||||
} else {
|
||||
$extension = $this->_options['file_extension'];
|
||||
}
|
||||
$file = $pathName . '/' . $fileName . $extension;
|
||||
if (file_exists($file)) {
|
||||
return true;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if ($this->_options['disable_caching']) {
|
||||
return true;
|
||||
}
|
||||
$extension = null;
|
||||
if ($this->_isSerialized($data)) {
|
||||
$data = unserialize($data);
|
||||
$extension = '.' . ltrim($data[1], '.');
|
||||
$data = $data[0];
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
if (($id = (string)$id) === '') {
|
||||
$id = $this->_detectId();
|
||||
} else {
|
||||
$id = $this->_decodeId($id);
|
||||
}
|
||||
|
||||
$fileName = basename($id);
|
||||
if ($fileName === '') {
|
||||
$fileName = $this->_options['index_filename'];
|
||||
}
|
||||
|
||||
$pathName = realpath($this->_options['public_dir']) . dirname($id);
|
||||
$this->_createDirectoriesFor($pathName);
|
||||
|
||||
if ($id === null || strlen($id) == 0) {
|
||||
$dataUnserialized = unserialize($data);
|
||||
$data = $dataUnserialized['data'];
|
||||
}
|
||||
$ext = $this->_options['file_extension'];
|
||||
if ($extension) $ext = $extension;
|
||||
$file = rtrim($pathName, '/') . '/' . $fileName . $ext;
|
||||
if ($this->_options['file_locking']) {
|
||||
$result = file_put_contents($file, $data, LOCK_EX);
|
||||
} else {
|
||||
$result = file_put_contents($file, $data);
|
||||
}
|
||||
@chmod($file, $this->_octdec($this->_options['cache_file_perm']));
|
||||
|
||||
if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
|
||||
$this->_tagged = $tagged;
|
||||
} elseif ($this->_tagged === null) {
|
||||
$this->_tagged = array();
|
||||
}
|
||||
if (!isset($this->_tagged[$id])) {
|
||||
$this->_tagged[$id] = array();
|
||||
}
|
||||
if (!isset($this->_tagged[$id]['tags'])) {
|
||||
$this->_tagged[$id]['tags'] = array();
|
||||
}
|
||||
$this->_tagged[$id]['tags'] = array_unique(array_merge($this->_tagged[$id]['tags'], $tags));
|
||||
$this->_tagged[$id]['extension'] = $ext;
|
||||
$this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively create the directories needed to write the static file
|
||||
*/
|
||||
protected function _createDirectoriesFor($path)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
$oldUmask = umask(0);
|
||||
if ( !@mkdir($path, $this->_octdec($this->_options['cache_directory_perm']), true)) {
|
||||
$lastErr = error_get_last();
|
||||
umask($oldUmask);
|
||||
Zend_Cache::throwException("Can't create directory: {$lastErr['message']}");
|
||||
}
|
||||
umask($oldUmask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect serialization of data (cannot predict since this is the only way
|
||||
* to obey the interface yet pass in another parameter).
|
||||
*
|
||||
* In future, ZF 2.0, check if we can just avoid the interface restraints.
|
||||
*
|
||||
* This format is the only valid one possible for the class, so it's simple
|
||||
* to just run a regular expression for the starting serialized format.
|
||||
*/
|
||||
protected function _isSerialized($data)
|
||||
{
|
||||
return preg_match("/a:2:\{i:0;s:\d+:\"/", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache record
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @return boolean True if no problem
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
if (!$this->_verifyPath($id)) {
|
||||
Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
|
||||
}
|
||||
$fileName = basename($id);
|
||||
if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
|
||||
$this->_tagged = $tagged;
|
||||
} elseif (!$this->_tagged) {
|
||||
return false;
|
||||
}
|
||||
if (isset($this->_tagged[$id])) {
|
||||
$extension = $this->_tagged[$id]['extension'];
|
||||
} else {
|
||||
$extension = $this->_options['file_extension'];
|
||||
}
|
||||
if ($fileName === '') {
|
||||
$fileName = $this->_options['index_filename'];
|
||||
}
|
||||
$pathName = $this->_options['public_dir'] . dirname($id);
|
||||
$file = realpath($pathName) . '/' . $fileName . $extension;
|
||||
if (!file_exists($file)) {
|
||||
return false;
|
||||
}
|
||||
return unlink($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache record recursively for the given directory matching a
|
||||
* REQUEST_URI based relative path (deletes the actual file matching this
|
||||
* in addition to the matching directory)
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @return boolean True if no problem
|
||||
*/
|
||||
public function removeRecursively($id)
|
||||
{
|
||||
if (!$this->_verifyPath($id)) {
|
||||
Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
|
||||
}
|
||||
$fileName = basename($id);
|
||||
if ($fileName === '') {
|
||||
$fileName = $this->_options['index_filename'];
|
||||
}
|
||||
$pathName = $this->_options['public_dir'] . dirname($id);
|
||||
$file = $pathName . '/' . $fileName . $this->_options['file_extension'];
|
||||
$directory = $pathName . '/' . $fileName;
|
||||
if (file_exists($directory)) {
|
||||
if (!is_writable($directory)) {
|
||||
return false;
|
||||
}
|
||||
if (is_dir($directory)) {
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
if (true === $file->isFile()) {
|
||||
if (false === unlink($file->getPathName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rmdir($directory);
|
||||
}
|
||||
if (file_exists($file)) {
|
||||
if (!is_writable($file)) {
|
||||
return false;
|
||||
}
|
||||
return unlink($file);
|
||||
}
|
||||
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
|
||||
* @throws Zend_Exception
|
||||
*/
|
||||
public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
|
||||
{
|
||||
$result = false;
|
||||
switch ($mode) {
|
||||
case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
|
||||
case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
|
||||
if (empty($tags)) {
|
||||
throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
|
||||
}
|
||||
if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
|
||||
$this->_tagged = $tagged;
|
||||
} elseif (!$this->_tagged) {
|
||||
return true;
|
||||
}
|
||||
foreach ($tags as $tag) {
|
||||
$urls = array_keys($this->_tagged);
|
||||
foreach ($urls as $url) {
|
||||
if (isset($this->_tagged[$url]['tags']) && in_array($tag, $this->_tagged[$url]['tags'])) {
|
||||
$this->remove($url);
|
||||
unset($this->_tagged[$url]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
|
||||
$result = true;
|
||||
break;
|
||||
case Zend_Cache::CLEANING_MODE_ALL:
|
||||
if ($this->_tagged === null) {
|
||||
$tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
|
||||
$this->_tagged = $tagged;
|
||||
}
|
||||
if ($this->_tagged === null || empty($this->_tagged)) {
|
||||
return true;
|
||||
}
|
||||
$urls = array_keys($this->_tagged);
|
||||
foreach ($urls as $url) {
|
||||
$this->remove($url);
|
||||
unset($this->_tagged[$url]);
|
||||
}
|
||||
$this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
|
||||
$result = true;
|
||||
break;
|
||||
case Zend_Cache::CLEANING_MODE_OLD:
|
||||
$this->_log("Zend_Cache_Backend_Static : Selected Cleaning Mode Currently Unsupported By This Backend");
|
||||
break;
|
||||
case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
|
||||
if (empty($tags)) {
|
||||
throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
|
||||
}
|
||||
if ($this->_tagged === null) {
|
||||
$tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
|
||||
$this->_tagged = $tagged;
|
||||
}
|
||||
if ($this->_tagged === null || empty($this->_tagged)) {
|
||||
return true;
|
||||
}
|
||||
$urls = array_keys($this->_tagged);
|
||||
foreach ($urls as $url) {
|
||||
$difference = array_diff($tags, $this->_tagged[$url]['tags']);
|
||||
if (count($tags) == count($difference)) {
|
||||
$this->remove($url);
|
||||
unset($this->_tagged[$url]);
|
||||
}
|
||||
}
|
||||
$this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
|
||||
$result = true;
|
||||
break;
|
||||
default:
|
||||
Zend_Cache::throwException('Invalid mode for clean() method');
|
||||
break;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an Inner Cache, used here primarily to store Tags associated
|
||||
* with caches created by this backend. Note: If Tags are lost, the cache
|
||||
* should be completely cleaned as the mapping of tags to caches will
|
||||
* have been irrevocably lost.
|
||||
*
|
||||
* @param Zend_Cache_Core
|
||||
* @return void
|
||||
*/
|
||||
public function setInnerCache(Zend_Cache_Core $cache)
|
||||
{
|
||||
$this->_tagCache = $cache;
|
||||
$this->_options['tag_cache'] = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Inner Cache if set
|
||||
*
|
||||
* @return Zend_Cache_Core
|
||||
*/
|
||||
public function getInnerCache()
|
||||
{
|
||||
if ($this->_tagCache === null) {
|
||||
Zend_Cache::throwException('An Inner Cache has not been set; use setInnerCache()');
|
||||
}
|
||||
return $this->_tagCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify path exists and is non-empty
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
protected function _verifyPath($path)
|
||||
{
|
||||
$path = realpath($path);
|
||||
$base = realpath($this->_options['public_dir']);
|
||||
return strncmp($path, $base, strlen($base)) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the page to save from the request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _detectId()
|
||||
{
|
||||
return $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @deprecated Not usable until perhaps ZF 2.0
|
||||
*/
|
||||
protected static function _validateIdOrTag($string)
|
||||
{
|
||||
if (!is_string($string)) {
|
||||
Zend_Cache::throwException('Invalid id or tag : must be a string');
|
||||
}
|
||||
|
||||
// Internal only checked in Frontend - not here!
|
||||
if (substr($string, 0, 9) == 'internal-') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation assumes no query string, fragments or scheme included - only the path
|
||||
if (!preg_match(
|
||||
'/^(?:\/(?:(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*\'()\[\]:@&=+$,;])*)?)+$/',
|
||||
$string
|
||||
)
|
||||
) {
|
||||
Zend_Cache::throwException("Invalid id or tag '$string' : must be a valid URL path");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect an octal string and return its octal value for file permission ops
|
||||
* otherwise return the non-string (assumed octal or decimal int already)
|
||||
*
|
||||
* @param string $val The potential octal in need of conversion
|
||||
* @return int
|
||||
*/
|
||||
protected function _octdec($val)
|
||||
{
|
||||
if (is_string($val) && decoct(octdec($val)) == $val) {
|
||||
return octdec($val);
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a request URI from the provided ID
|
||||
*
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
protected function _decodeId($id)
|
||||
{
|
||||
return pack('H*', $id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
<?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-2015 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-2015 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_ExtendedInterface
|
||||
{
|
||||
/**
|
||||
* 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'
|
||||
|| $id == 'd8523b3ee441006261eeffa5c3d3a0a7'
|
||||
|| $id == 'e83249ea22178277d5befc2c5e2e9ace'
|
||||
|| $id == '40f649b94977c0a6e76902e2a0b43587'
|
||||
|| $id == '88161989b73a4cbfd0b701c446115a99'
|
||||
|| $id == '205fc79cba24f0f0018eb92c7c8b3ba4'
|
||||
|| $id == '170720e35f38150b811f68a937fb042d')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ($id=='serialized') {
|
||||
return serialize(array('foo'));
|
||||
}
|
||||
if ($id=='serialized2') {
|
||||
return serialize(array('headers' => array(), 'data' => 'foo'));
|
||||
}
|
||||
if ( $id == '71769f39054f75894288e397df04e445' || $id == '615d222619fb20b527168340cebd0578'
|
||||
|| $id == '8a02d218a5165c467e7a5747cc6bd4b6' || $id == '648aca1366211d17cbf48e65dc570bee'
|
||||
|| $id == '4a923ef02d7f997ca14d56dfeae25ea7') {
|
||||
return serialize(array('foo', 'bar'));
|
||||
}
|
||||
if ( $id == 'f53c7d912cc523d9a65834c8286eceb9') {
|
||||
return serialize(array('foobar'));
|
||||
}
|
||||
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=='3c439c922209e2cb0b54d6deffccd75a')) {
|
||||
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 (substr($id,-5)=='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 (substr($id,-5)=='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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored cache ids
|
||||
*
|
||||
* @return array array of stored cache ids (string)
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
return array(
|
||||
'prefix_id1', 'prefix_id2'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored tags
|
||||
*
|
||||
* @return array array of stored tags (string)
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
return array(
|
||||
'tag1', 'tag2'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ($tags == array('tag1', 'tag2')) {
|
||||
return array('prefix_id1', 'prefix_id2');
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
if ($tags == array('tag3', 'tag4')) {
|
||||
return array('prefix_id3', 'prefix_id4');
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
if ($tags == array('tag5', 'tag6')) {
|
||||
return array('prefix_id5', 'prefix_id6');
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filling percentage of the backend storage
|
||||
*
|
||||
* @return int integer between 0 and 100
|
||||
*/
|
||||
public function getFillingPercentage()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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)
|
||||
{
|
||||
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' => false,
|
||||
'priority' => true,
|
||||
'infinite_lifetime' => true,
|
||||
'get_list' => 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,548 @@
|
||||
<?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-2015 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-2015 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_fill_fast_cache
|
||||
* - If true, automatically fill the fast cache when a cache record was not found in fast cache, but did
|
||||
* exist in slow cache. This can be usefull when a non-persistent cache like APC or Memcached got
|
||||
* purged for whatever reason.
|
||||
*
|
||||
* =====> (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_fill_fast_cache' => true,
|
||||
'auto_refresh_fast_cache' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Slow Backend
|
||||
*
|
||||
* @var Zend_Cache_Backend_ExtendedInterface
|
||||
*/
|
||||
protected $_slowBackend;
|
||||
|
||||
/**
|
||||
* Fast Backend
|
||||
*
|
||||
* @var Zend_Cache_Backend_ExtendedInterface
|
||||
*/
|
||||
protected $_fastBackend;
|
||||
|
||||
/**
|
||||
* Cache for the fast backend filling percentage
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_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');
|
||||
} elseif ($this->_options['slow_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
|
||||
$this->_slowBackend = $this->_options['slow_backend'];
|
||||
} else {
|
||||
$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']
|
||||
);
|
||||
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 ($this->_options['fast_backend'] === null) {
|
||||
Zend_Cache::throwException('fast_backend option has to set');
|
||||
} elseif ($this->_options['fast_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
|
||||
$this->_fastBackend = $this->_options['fast_backend'];
|
||||
} else {
|
||||
$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->_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);
|
||||
} else {
|
||||
$boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
|
||||
if ($boolSlow === true) {
|
||||
$boolFast = $this->_fastBackend->remove($id);
|
||||
if (!$boolFast && !$this->_fastBackend->test($id)) {
|
||||
// some backends return false on remove() even if the key never existed. (and it won't if fast is full)
|
||||
// all we care about is that the key doesn't exist now
|
||||
$boolFast = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
$resultFast = $this->_fastBackend->load($id, $doNotTestCacheValidity);
|
||||
if ($resultFast === false) {
|
||||
$resultSlow = $this->_slowBackend->load($id, $doNotTestCacheValidity);
|
||||
if ($resultSlow === false) {
|
||||
// there is no cache at all for this id
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$array = $resultFast !== false ? unserialize($resultFast) : unserialize($resultSlow);
|
||||
|
||||
//In case no cache entry was found in the FastCache and auto-filling is enabled, copy data to FastCache
|
||||
if ($resultFast === false && $this->_options['auto_fill_fast_cache']) {
|
||||
$preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
|
||||
$this->_fastBackend->save($preparedData, $id, array(), $array['lifetime']);
|
||||
}
|
||||
// maybe, we have to refresh the fast cache ?
|
||||
elseif ($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 <= 0) {
|
||||
// if no lifetime, we have an infinite lifetime
|
||||
// we need to use arbitrary lifetimes
|
||||
$fastLifetime = (int) (2592000 / (11 - $priority));
|
||||
} else {
|
||||
// prevent computed infinite lifetime (0) by ceil
|
||||
$fastLifetime = (int) ceil($lifetime / (11 - $priority));
|
||||
}
|
||||
|
||||
if ($maxLifetime >= 0 && $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,349 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Backend_WinCache extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
|
||||
{
|
||||
/**
|
||||
* Log message
|
||||
*/
|
||||
const TAGS_UNSUPPORTED_BY_CLEAN_OF_WINCACHE_BACKEND = 'Zend_Cache_Backend_WinCache::clean() : tags are unsupported by the WinCache backend';
|
||||
const TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND = 'Zend_Cache_Backend_WinCache::save() : tags are unsupported by the WinCache backend';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options associative array of options
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
if (!extension_loaded('wincache')) {
|
||||
Zend_Cache::throwException('The wincache 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 WinCache 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 = wincache_ucache_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 = wincache_ucache_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 = wincache_ucache_set($id, array($data, time(), $lifetime), $lifetime);
|
||||
if (count($tags) > 0) {
|
||||
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cache record
|
||||
*
|
||||
* @param string $id cache id
|
||||
* @return boolean true if no problem
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
return wincache_ucache_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 wincache_ucache_clear();
|
||||
break;
|
||||
case Zend_Cache::CLEANING_MODE_OLD:
|
||||
$this->_log("Zend_Cache_Backend_WinCache::clean() : CLEANING_MODE_OLD is unsupported by the WinCache 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_WINCACHE_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 = wincache_ucache_meminfo();
|
||||
$memSize = $mem['memory_total'];
|
||||
$memUsed = $memSize - $mem['memory_free'];
|
||||
if ($memSize == 0) {
|
||||
Zend_Cache::throwException('can\'t get WinCache 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_WINCACHE_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_WINCACHE_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_WINCACHE_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_WINCACHE_BACKEND);
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored cache ids
|
||||
*
|
||||
* @return array array of stored cache ids (string)
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
$res = array();
|
||||
$array = wincache_ucache_info();
|
||||
$records = $array['ucache_entries'];
|
||||
foreach ($records as $record) {
|
||||
$res[] = $record['key_name'];
|
||||
}
|
||||
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 = wincache_ucache_get($id);
|
||||
if (is_array($tmp)) {
|
||||
$data = $tmp[0];
|
||||
$mtime = $tmp[1];
|
||||
if (!isset($tmp[2])) {
|
||||
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 = wincache_ucache_get($id);
|
||||
if (is_array($tmp)) {
|
||||
$data = $tmp[0];
|
||||
$mtime = $tmp[1];
|
||||
if (!isset($tmp[2])) {
|
||||
return false;
|
||||
}
|
||||
$lifetime = $tmp[2];
|
||||
$newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
|
||||
if ($newLifetime <=0) {
|
||||
return false;
|
||||
}
|
||||
return wincache_ucache_set($id, array($data, time(), $newLifetime), $newLifetime);
|
||||
}
|
||||
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,221 @@
|
||||
<?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-2015 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-2015 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'];
|
||||
}
|
||||
|
||||
$cnt = xcache_count(XC_TYPE_VAR);
|
||||
for ($i=0; $i < $cnt; $i++) {
|
||||
xcache_clear_cache(XC_TYPE_VAR, $i);
|
||||
}
|
||||
|
||||
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-2015 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-2015 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-2015 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-2015 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
<?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-2015 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-2015 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
|
||||
* @return mixed|null
|
||||
*/
|
||||
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']);
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
<?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-2015 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-2015 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
|
||||
* @return bool
|
||||
*/
|
||||
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
|
||||
* @return mixed|null
|
||||
*/
|
||||
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,765 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Core
|
||||
{
|
||||
/**
|
||||
* Messages
|
||||
*/
|
||||
const BACKEND_NOT_SUPPORTS_TAG = 'tags are not supported by the current backend';
|
||||
const BACKEND_NOT_IMPLEMENTS_EXTENDED_IF = 'Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available';
|
||||
|
||||
/**
|
||||
* Backend Object
|
||||
*
|
||||
* @var Zend_Cache_Backend_Interface $_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.");
|
||||
}
|
||||
foreach ($options as $name => $value) {
|
||||
$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();
|
||||
foreach ($options as $name => $value) {
|
||||
$this->setOption($name, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the backend
|
||||
*
|
||||
* @param Zend_Cache_Backend $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 Zend_Cache_Backend 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 = 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)
|
||||
{
|
||||
$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");
|
||||
}
|
||||
if ($name == 'lifetime' && empty($value)) {
|
||||
$value = null;
|
||||
}
|
||||
$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;
|
||||
$this->_validateIdOrTag($id);
|
||||
|
||||
$this->_log("Zend_Cache_Core: load item '{$id}'", 7);
|
||||
$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 int|false Last modified time of cache entry if it is available, false otherwise
|
||||
*/
|
||||
public function test($id)
|
||||
{
|
||||
if (!$this->_options['caching']) {
|
||||
return false;
|
||||
}
|
||||
$id = $this->_id($id); // cache id may need prefix
|
||||
$this->_validateIdOrTag($id);
|
||||
$this->_lastId = $id;
|
||||
|
||||
$this->_log("Zend_Cache_Core: test item '{$id}'", 7);
|
||||
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);
|
||||
}
|
||||
$this->_validateIdOrTag($id);
|
||||
$this->_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) {
|
||||
// new way || deprecated way
|
||||
if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) {
|
||||
$this->_log("Zend_Cache_Core::save(): automatic cleaning running", 7);
|
||||
$this->clean(Zend_Cache::CLEANING_MODE_OLD);
|
||||
} else {
|
||||
$this->_log("Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_log("Zend_Cache_Core: save item '{$id}'", 7);
|
||||
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 !
|
||||
$this->_log("Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it", 4);
|
||||
$this->_backend->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 of item '{$id}' failed -> removing it", 4);
|
||||
$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
|
||||
$this->_validateIdOrTag($id);
|
||||
|
||||
$this->_log("Zend_Cache_Core: remove item '{$id}'", 7);
|
||||
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');
|
||||
}
|
||||
$this->_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(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
if (!($this->_backendCapabilities['tags'])) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
|
||||
}
|
||||
|
||||
$ids = $this->_backend->getIdsMatchingTags($tags);
|
||||
|
||||
// we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
|
||||
if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
|
||||
$prefix = & $this->_options['cache_id_prefix'];
|
||||
$prefixLen = strlen($prefix);
|
||||
foreach ($ids as &$id) {
|
||||
if (strpos($id, $prefix) === 0) {
|
||||
$id = substr($id, $prefixLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
if (!($this->_backendCapabilities['tags'])) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
|
||||
}
|
||||
|
||||
$ids = $this->_backend->getIdsNotMatchingTags($tags);
|
||||
|
||||
// we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
|
||||
if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
|
||||
$prefix = & $this->_options['cache_id_prefix'];
|
||||
$prefixLen = strlen($prefix);
|
||||
foreach ($ids as &$id) {
|
||||
if (strpos($id, $prefix) === 0) {
|
||||
$id = substr($id, $prefixLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored cache ids which match any given tags
|
||||
*
|
||||
* In case of multiple tags, a logical OR is made between tags
|
||||
*
|
||||
* @param array $tags array of tags
|
||||
* @return array array of matching any cache ids (string)
|
||||
*/
|
||||
public function getIdsMatchingAnyTags($tags = array())
|
||||
{
|
||||
if (!$this->_extendedBackend) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
if (!($this->_backendCapabilities['tags'])) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
|
||||
}
|
||||
|
||||
$ids = $this->_backend->getIdsMatchingAnyTags($tags);
|
||||
|
||||
// we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
|
||||
if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
|
||||
$prefix = & $this->_options['cache_id_prefix'];
|
||||
$prefixLen = strlen($prefix);
|
||||
foreach ($ids as &$id) {
|
||||
if (strpos($id, $prefix) === 0) {
|
||||
$id = substr($id, $prefixLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored cache ids
|
||||
*
|
||||
* @return array array of stored cache ids (string)
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
if (!$this->_extendedBackend) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
|
||||
$ids = $this->_backend->getIds();
|
||||
|
||||
// we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
|
||||
if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
|
||||
$prefix = & $this->_options['cache_id_prefix'];
|
||||
$prefixLen = strlen($prefix);
|
||||
foreach ($ids as &$id) {
|
||||
if (strpos($id, $prefix) === 0) {
|
||||
$id = substr($id, $prefixLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of stored tags
|
||||
*
|
||||
* @return array array of stored tags (string)
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
if (!$this->_extendedBackend) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
if (!($this->_backendCapabilities['tags'])) {
|
||||
Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
|
||||
}
|
||||
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(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
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(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
$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(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
|
||||
}
|
||||
$id = $this->_id($id); // cache id may need prefix
|
||||
|
||||
$this->_log("Zend_Cache_Core: touch item '{$id}'", 7);
|
||||
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 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('~^[a-zA-Z0-9_]+$~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 function _validateTagsArray($tags)
|
||||
{
|
||||
if (!is_array($tags)) {
|
||||
Zend_Cache::throwException('Invalid tags array : must be an array');
|
||||
}
|
||||
foreach($tags as $tag) {
|
||||
$this->_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.php';
|
||||
require_once 'Zend/Log/Writer/Stream.php';
|
||||
require_once 'Zend/Log/Filter/Priority.php';
|
||||
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
|
||||
$logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
|
||||
$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-2015 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-2015 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,88 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Frontend_Capture extends Zend_Cache_Core
|
||||
{
|
||||
/**
|
||||
* Page identifiers
|
||||
* @var array
|
||||
*/
|
||||
protected $_idStack = array();
|
||||
|
||||
/**
|
||||
* Tags
|
||||
* @var array
|
||||
*/
|
||||
protected $_tags = array();
|
||||
|
||||
protected $_extension = null;
|
||||
|
||||
/**
|
||||
* Start the cache
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas)
|
||||
*/
|
||||
public function start($id, array $tags, $extension = null)
|
||||
{
|
||||
$this->_tags = $tags;
|
||||
$this->_extension = $extension;
|
||||
ob_start(array($this, '_flush'));
|
||||
ob_implicit_flush(false);
|
||||
$this->_idStack[] = $id;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* callback for output buffering
|
||||
* (shouldn't really be called manually)
|
||||
*
|
||||
* @param string $data Buffered output
|
||||
* @return string Data to send to browser
|
||||
*/
|
||||
public function _flush($data)
|
||||
{
|
||||
$id = array_pop($this->_idStack);
|
||||
if ($id === null) {
|
||||
Zend_Cache::throwException('use of _flush() without a start()');
|
||||
}
|
||||
if ($this->_extension) {
|
||||
$this->save(serialize(array($data, $this->_extension)), $id, $this->_tags);
|
||||
} else {
|
||||
$this->save($data, $id, $this->_tags);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
<?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-2015 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-2015 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
|
||||
*/
|
||||
protected $_tags = array();
|
||||
|
||||
/**
|
||||
* SpecificLifetime value
|
||||
*
|
||||
* false => no specific life time
|
||||
*
|
||||
* @var bool|int
|
||||
*/
|
||||
protected $_specificLifetime = false;
|
||||
|
||||
/**
|
||||
* The cached object or the name of the cached abstract class
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_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
|
||||
*/
|
||||
protected $_cachedEntityLabel = '';
|
||||
|
||||
/**
|
||||
* Priority (used by some particular backends)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_priority = 8;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Associative array of options
|
||||
* @throws Zend_Cache_Exception
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$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 bool|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
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $parameters)
|
||||
{
|
||||
$callback = array($this->_cachedEntity, $name);
|
||||
|
||||
if (!is_callable($callback, false)) {
|
||||
Zend_Cache::throwException('Invalid callback');
|
||||
}
|
||||
|
||||
$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($callback, $parameters);
|
||||
}
|
||||
|
||||
$id = $this->makeId($name, $parameters);
|
||||
if (($rs = $this->load($id)) && (array_key_exists(0, $rs))
|
||||
&& (array_key_exists(1, $rs))
|
||||
) {
|
||||
// A cache is available
|
||||
$output = $rs[0];
|
||||
$return = $rs[1];
|
||||
} else {
|
||||
// A cache is not available (or not valid for this frontend)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
try {
|
||||
$return = call_user_func_array($callback, $parameters);
|
||||
$output = ob_get_clean();
|
||||
$data = array($output, $return);
|
||||
|
||||
$this->save(
|
||||
$data, $id, $this->_tags, $this->_specificLifetime,
|
||||
$this->_priority
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
ob_end_clean();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
echo $output;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ZF-9970
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
private function _makeId($name, $args)
|
||||
{
|
||||
return $this->makeId($name, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a cache id from the method name and parameters
|
||||
*
|
||||
* @param string $name Method name
|
||||
* @param array $args Method parameters
|
||||
* @return string Cache id
|
||||
*/
|
||||
public function makeId($name, array $args = array())
|
||||
{
|
||||
return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Frontend_File extends Zend_Cache_Core
|
||||
{
|
||||
|
||||
/**
|
||||
* Consts for master_files_mode
|
||||
*/
|
||||
const MODE_AND = 'AND';
|
||||
const MODE_OR = 'OR';
|
||||
|
||||
/**
|
||||
* Available options
|
||||
*
|
||||
* ====> (string) master_file :
|
||||
* - a complete path of the master file
|
||||
* - deprecated (see master_files)
|
||||
*
|
||||
* ====> (array) master_files :
|
||||
* - an array of complete path of master files
|
||||
* - this option has to be set !
|
||||
*
|
||||
* ====> (string) master_files_mode :
|
||||
* - Zend_Cache_Frontend_File::MODE_AND or Zend_Cache_Frontend_File::MODE_OR
|
||||
* - if MODE_AND, then all master files have to be touched to get a cache invalidation
|
||||
* - if MODE_OR (default), then a single touched master file is enough to get a cache invalidation
|
||||
*
|
||||
* ====> (boolean) ignore_missing_master_files
|
||||
* - if set to true, missing master files are ignored silently
|
||||
* - if set to false (default), an exception is thrown if there is a missing master file
|
||||
* @var array available options
|
||||
*/
|
||||
protected $_specificOptions = array(
|
||||
'master_file' => null,
|
||||
'master_files' => null,
|
||||
'master_files_mode' => 'OR',
|
||||
'ignore_missing_master_files' => false
|
||||
);
|
||||
|
||||
/**
|
||||
* Master file mtimes
|
||||
*
|
||||
* Array of int
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_masterFile_mtimes = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Associative array of options
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$this->setOption($name, $value);
|
||||
}
|
||||
if (!isset($this->_specificOptions['master_files'])) {
|
||||
Zend_Cache::throwException('master_files option must be set');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the master_files option
|
||||
*
|
||||
* @param array $masterFiles the complete paths and name of the master files
|
||||
*/
|
||||
public function setMasterFiles(array $masterFiles)
|
||||
{
|
||||
$this->_specificOptions['master_file'] = null; // to keep a compatibility
|
||||
$this->_specificOptions['master_files'] = null;
|
||||
$this->_masterFile_mtimes = array();
|
||||
|
||||
clearstatcache();
|
||||
$i = 0;
|
||||
foreach ($masterFiles as $masterFile) {
|
||||
if (file_exists($masterFile)) {
|
||||
$mtime = filemtime($masterFile);
|
||||
} else {
|
||||
$mtime = false;
|
||||
}
|
||||
|
||||
if (!$this->_specificOptions['ignore_missing_master_files'] && !$mtime) {
|
||||
Zend_Cache::throwException('Unable to read master_file : ' . $masterFile);
|
||||
}
|
||||
|
||||
$this->_masterFile_mtimes[$i] = $mtime;
|
||||
$this->_specificOptions['master_files'][$i] = $masterFile;
|
||||
if ($i === 0) { // to keep a compatibility
|
||||
$this->_specificOptions['master_file'] = $masterFile;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the master_file option
|
||||
*
|
||||
* To keep the compatibility
|
||||
*
|
||||
* @deprecated
|
||||
* @param string $masterFile the complete path and name of the master file
|
||||
*/
|
||||
public function setMasterFile($masterFile)
|
||||
{
|
||||
$this->setMasterFiles(array($masterFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Public frontend to set an option
|
||||
*
|
||||
* Just a wrapper to get a specific behaviour for master_file
|
||||
*
|
||||
* @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 == 'master_file') {
|
||||
$this->setMasterFile($value);
|
||||
} else if ($name == 'master_files') {
|
||||
$this->setMasterFiles($value);
|
||||
} else {
|
||||
parent::setOption($name, $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
|
||||
* @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 (!$doNotTestCacheValidity) {
|
||||
if ($this->test($id)) {
|
||||
return parent::load($id, true, $doNotUnserialize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return parent::load($id, true, $doNotUnserialize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a cache is available for the given id
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @return int|false Last modified time of cache entry if it is available, false otherwise
|
||||
*/
|
||||
public function test($id)
|
||||
{
|
||||
$lastModified = parent::test($id);
|
||||
if ($lastModified) {
|
||||
if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) {
|
||||
// MODE_AND
|
||||
foreach($this->_masterFile_mtimes as $masterFileMTime) {
|
||||
if ($masterFileMTime) {
|
||||
if ($lastModified > $masterFileMTime) {
|
||||
return $lastModified;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// MODE_OR
|
||||
$res = true;
|
||||
foreach($this->_masterFile_mtimes as $masterFileMTime) {
|
||||
if ($masterFileMTime) {
|
||||
if ($lastModified <= $masterFileMTime) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $lastModified;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Frontend_Function extends Zend_Cache_Core
|
||||
{
|
||||
/**
|
||||
* This frontend specific options
|
||||
*
|
||||
* ====> (boolean) cache_by_default :
|
||||
* - if true, function calls will be cached by default
|
||||
*
|
||||
* ====> (array) cached_functions :
|
||||
* - an array of function names which will be cached (even if cache_by_default = false)
|
||||
*
|
||||
* ====> (array) non_cached_functions :
|
||||
* - an array of function names which won't be cached (even if cache_by_default = true)
|
||||
*
|
||||
* @var array options
|
||||
*/
|
||||
protected $_specificOptions = array(
|
||||
'cache_by_default' => true,
|
||||
'cached_functions' => array(),
|
||||
'non_cached_functions' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Associative array of options
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$this->setOption($name, $value);
|
||||
}
|
||||
$this->setOption('automatic_serialization', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method : call the specified function or get the result from cache
|
||||
*
|
||||
* @param callback $callback A valid callback
|
||||
* @param array $parameters Function parameters
|
||||
* @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
|
||||
* @return mixed Result
|
||||
*/
|
||||
public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
|
||||
{
|
||||
if (!is_callable($callback, true, $name)) {
|
||||
Zend_Cache::throwException('Invalid callback');
|
||||
}
|
||||
|
||||
$cacheBool1 = $this->_specificOptions['cache_by_default'];
|
||||
$cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']);
|
||||
$cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']);
|
||||
$cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
|
||||
if (!$cache) {
|
||||
// Caching of this callback is disabled
|
||||
return call_user_func_array($callback, $parameters);
|
||||
}
|
||||
|
||||
$id = $this->_makeId($callback, $parameters);
|
||||
if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
|
||||
// A cache is available
|
||||
$output = $rs[0];
|
||||
$return = $rs[1];
|
||||
} else {
|
||||
// A cache is not available (or not valid for this frontend)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
$return = call_user_func_array($callback, $parameters);
|
||||
$output = ob_get_clean();
|
||||
$data = array($output, $return);
|
||||
$this->save($data, $id, $tags, $specificLifetime, $priority);
|
||||
}
|
||||
|
||||
echo $output;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ZF-9970
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
private function _makeId($callback, array $args)
|
||||
{
|
||||
return $this->makeId($callback, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a cache id from the function name and parameters
|
||||
*
|
||||
* @param callback $callback A valid callback
|
||||
* @param array $args Function parameters
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return string Cache id
|
||||
*/
|
||||
public function makeId($callback, array $args = array())
|
||||
{
|
||||
if (!is_callable($callback, true, $name)) {
|
||||
Zend_Cache::throwException('Invalid callback');
|
||||
}
|
||||
|
||||
// functions, methods and classnames are case-insensitive
|
||||
$name = strtolower($name);
|
||||
|
||||
// generate a unique id for object callbacks
|
||||
if (is_object($callback)) { // Closures & __invoke
|
||||
$object = $callback;
|
||||
} elseif (isset($callback[0])) { // array($object, 'method')
|
||||
$object = $callback[0];
|
||||
}
|
||||
if (isset($object)) {
|
||||
try {
|
||||
$tmp = @serialize($callback);
|
||||
} catch (Exception $e) {
|
||||
Zend_Cache::throwException($e->getMessage());
|
||||
}
|
||||
if (!$tmp) {
|
||||
$lastErr = error_get_last();
|
||||
Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}");
|
||||
}
|
||||
$name.= '__' . $tmp;
|
||||
}
|
||||
|
||||
// generate a unique id for arguments
|
||||
$argsStr = '';
|
||||
if ($args) {
|
||||
try {
|
||||
$argsStr = @serialize(array_values($args));
|
||||
} catch (Exception $e) {
|
||||
Zend_Cache::throwException($e->getMessage());
|
||||
}
|
||||
if (!$argsStr) {
|
||||
$lastErr = error_get_last();
|
||||
throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}");
|
||||
}
|
||||
}
|
||||
|
||||
return md5($name . $argsStr);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Frontend_Output extends Zend_Cache_Core
|
||||
{
|
||||
|
||||
private $_idStack = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Associative array of options
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->_idStack = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the cache
|
||||
*
|
||||
* @param string $id Cache id
|
||||
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
|
||||
* @param boolean $echoData If set to true, datas are sent to the browser if the cache is hit (simply returned else)
|
||||
* @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas)
|
||||
*/
|
||||
public function start($id, $doNotTestCacheValidity = false, $echoData = true)
|
||||
{
|
||||
$data = $this->load($id, $doNotTestCacheValidity);
|
||||
if ($data !== false) {
|
||||
if ( $echoData ) {
|
||||
echo($data);
|
||||
return true;
|
||||
} else {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
$this->_idStack[] = $id;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the cache
|
||||
*
|
||||
* @param array $tags Tags array
|
||||
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
|
||||
* @param string $forcedDatas If not null, force written datas with this
|
||||
* @param boolean $echoData If set to true, datas are sent to the browser
|
||||
* @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
|
||||
* @return void
|
||||
*/
|
||||
public function end($tags = array(), $specificLifetime = false, $forcedDatas = null, $echoData = true, $priority = 8)
|
||||
{
|
||||
if ($forcedDatas === null) {
|
||||
$data = ob_get_clean();
|
||||
} else {
|
||||
$data =& $forcedDatas;
|
||||
}
|
||||
$id = array_pop($this->_idStack);
|
||||
if ($id === null) {
|
||||
Zend_Cache::throwException('use of end() without a start()');
|
||||
}
|
||||
$this->save($data, $id, $tags, $specificLifetime, $priority);
|
||||
if ($echoData) {
|
||||
echo($data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
<?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-2015 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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Frontend_Page extends Zend_Cache_Core
|
||||
{
|
||||
/**
|
||||
* This frontend specific options
|
||||
*
|
||||
* ====> (boolean) http_conditional :
|
||||
* - if true, http conditional mode is on
|
||||
* WARNING : http_conditional OPTION IS NOT IMPLEMENTED FOR THE MOMENT (TODO)
|
||||
*
|
||||
* ====> (boolean) debug_header :
|
||||
* - if true, a debug text is added before each cached pages
|
||||
*
|
||||
* ====> (boolean) content_type_memorization :
|
||||
* - deprecated => use memorize_headers instead
|
||||
* - if the Content-Type header is sent after the cache was started, the
|
||||
* corresponding value can be memorized and replayed when the cache is hit
|
||||
* (if false (default), the frontend doesn't take care of Content-Type header)
|
||||
*
|
||||
* ====> (array) memorize_headers :
|
||||
* - an array of strings corresponding to some HTTP headers name. Listed headers
|
||||
* will be stored with cache datas and "replayed" when the cache is hit
|
||||
*
|
||||
* ====> (array) default_options :
|
||||
* - an associative array of default options :
|
||||
* - (boolean) cache : cache is on by default if true
|
||||
* - (boolean) cacheWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
|
||||
* if true, cache is still on even if there are some variables in this superglobal array
|
||||
* if false, cache is off if there are some variables in this superglobal array
|
||||
* - (boolean) makeIdWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
|
||||
* if true, we have to use the content of this superglobal array to make a cache id
|
||||
* if false, the cache id won't be dependent of the content of this superglobal array
|
||||
* - (int) specific_lifetime : cache specific lifetime
|
||||
* (false => global lifetime is used, null => infinite lifetime,
|
||||
* integer => this lifetime is used), this "lifetime" is probably only
|
||||
* usefull when used with "regexps" array
|
||||
* - (array) tags : array of tags (strings)
|
||||
* - (int) priority : integer between 0 (very low priority) and 10 (maximum priority) used by
|
||||
* some particular backends
|
||||
*
|
||||
* ====> (array) regexps :
|
||||
* - an associative array to set options only for some REQUEST_URI
|
||||
* - keys are (pcre) regexps
|
||||
* - values are associative array with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI']
|
||||
* (see default_options for the list of available options)
|
||||
* - if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used
|
||||
*
|
||||
* @var array options
|
||||
*/
|
||||
protected $_specificOptions = array(
|
||||
'http_conditional' => false,
|
||||
'debug_header' => false,
|
||||
'content_type_memorization' => false,
|
||||
'memorize_headers' => array(),
|
||||
'default_options' => array(
|
||||
'cache_with_get_variables' => false,
|
||||
'cache_with_post_variables' => false,
|
||||
'cache_with_session_variables' => false,
|
||||
'cache_with_files_variables' => false,
|
||||
'cache_with_cookie_variables' => false,
|
||||
'make_id_with_get_variables' => true,
|
||||
'make_id_with_post_variables' => true,
|
||||
'make_id_with_session_variables' => true,
|
||||
'make_id_with_files_variables' => true,
|
||||
'make_id_with_cookie_variables' => true,
|
||||
'cache' => true,
|
||||
'specific_lifetime' => false,
|
||||
'tags' => array(),
|
||||
'priority' => null
|
||||
),
|
||||
'regexps' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
* Internal array to store some options
|
||||
*
|
||||
* @var array associative array of options
|
||||
*/
|
||||
protected $_activeOptions = array();
|
||||
|
||||
/**
|
||||
* If true, the page won't be cached
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_cancel = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Associative array of options
|
||||
* @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$name = strtolower($name);
|
||||
switch ($name) {
|
||||
case 'regexps':
|
||||
$this->_setRegexps($value);
|
||||
break;
|
||||
case 'default_options':
|
||||
$this->_setDefaultOptions($value);
|
||||
break;
|
||||
case 'content_type_memorization':
|
||||
$this->_setContentTypeMemorization($value);
|
||||
break;
|
||||
default:
|
||||
$this->setOption($name, $value);
|
||||
}
|
||||
}
|
||||
if (isset($this->_specificOptions['http_conditional'])) {
|
||||
if ($this->_specificOptions['http_conditional']) {
|
||||
Zend_Cache::throwException('http_conditional is not implemented for the moment !');
|
||||
}
|
||||
}
|
||||
$this->setOption('automatic_serialization', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific setter for the 'default_options' option (with some additional tests)
|
||||
*
|
||||
* @param array $options Associative array
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return void
|
||||
*/
|
||||
protected function _setDefaultOptions($options)
|
||||
{
|
||||
if (!is_array($options)) {
|
||||
Zend_Cache::throwException('default_options must be an array !');
|
||||
}
|
||||
foreach ($options as $key=>$value) {
|
||||
if (!is_string($key)) {
|
||||
Zend_Cache::throwException("invalid option [$key] !");
|
||||
}
|
||||
$key = strtolower($key);
|
||||
if (isset($this->_specificOptions['default_options'][$key])) {
|
||||
$this->_specificOptions['default_options'][$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the deprecated contentTypeMemorization option
|
||||
*
|
||||
* @param boolean $value value
|
||||
* @return void
|
||||
* @deprecated
|
||||
*/
|
||||
protected function _setContentTypeMemorization($value)
|
||||
{
|
||||
$found = null;
|
||||
foreach ($this->_specificOptions['memorize_headers'] as $key => $value) {
|
||||
if (strtolower($value) == 'content-type') {
|
||||
$found = $key;
|
||||
}
|
||||
}
|
||||
if ($value) {
|
||||
if (!$found) {
|
||||
$this->_specificOptions['memorize_headers'][] = 'Content-Type';
|
||||
}
|
||||
} else {
|
||||
if ($found) {
|
||||
unset($this->_specificOptions['memorize_headers'][$found]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific setter for the 'regexps' option (with some additional tests)
|
||||
*
|
||||
* @param array $options Associative array
|
||||
* @throws Zend_Cache_Exception
|
||||
* @return void
|
||||
*/
|
||||
protected function _setRegexps($regexps)
|
||||
{
|
||||
if (!is_array($regexps)) {
|
||||
Zend_Cache::throwException('regexps option must be an array !');
|
||||
}
|
||||
foreach ($regexps as $regexp=>$conf) {
|
||||
if (!is_array($conf)) {
|
||||
Zend_Cache::throwException('regexps option must be an array of arrays !');
|
||||
}
|
||||
$validKeys = array_keys($this->_specificOptions['default_options']);
|
||||
foreach ($conf as $key=>$value) {
|
||||
if (!is_string($key)) {
|
||||
Zend_Cache::throwException("unknown option [$key] !");
|
||||
}
|
||||
$key = strtolower($key);
|
||||
if (!in_array($key, $validKeys)) {
|
||||
unset($regexps[$regexp][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->setOption('regexps', $regexps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the cache
|
||||
*
|
||||
* @param string $id (optional) A cache id (if you set a value here, maybe you have to use Output frontend instead)
|
||||
* @param boolean $doNotDie For unit testing only !
|
||||
* @return boolean True if the cache is hit (false else)
|
||||
*/
|
||||
public function start($id = false, $doNotDie = false)
|
||||
{
|
||||
$this->_cancel = false;
|
||||
$lastMatchingRegexp = null;
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
foreach ($this->_specificOptions['regexps'] as $regexp => $conf) {
|
||||
if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) {
|
||||
$lastMatchingRegexp = $regexp;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_activeOptions = $this->_specificOptions['default_options'];
|
||||
if ($lastMatchingRegexp !== null) {
|
||||
$conf = $this->_specificOptions['regexps'][$lastMatchingRegexp];
|
||||
foreach ($conf as $key=>$value) {
|
||||
$this->_activeOptions[$key] = $value;
|
||||
}
|
||||
}
|
||||
if (!($this->_activeOptions['cache'])) {
|
||||
return false;
|
||||
}
|
||||
if (!$id) {
|
||||
$id = $this->_makeId();
|
||||
if (!$id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$array = $this->load($id);
|
||||
if ($array !== false) {
|
||||
$data = $array['data'];
|
||||
$headers = $array['headers'];
|
||||
if (!headers_sent()) {
|
||||
foreach ($headers as $key=>$headerCouple) {
|
||||
$name = $headerCouple[0];
|
||||
$value = $headerCouple[1];
|
||||
header("$name: $value");
|
||||
}
|
||||
}
|
||||
if ($this->_specificOptions['debug_header']) {
|
||||
echo 'DEBUG HEADER : This is a cached page !';
|
||||
}
|
||||
echo $data;
|
||||
if ($doNotDie) {
|
||||
return true;
|
||||
}
|
||||
die();
|
||||
}
|
||||
ob_start(array($this, '_flush'));
|
||||
ob_implicit_flush(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the current caching process
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
$this->_cancel = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* callback for output buffering
|
||||
* (shouldn't really be called manually)
|
||||
*
|
||||
* @param string $data Buffered output
|
||||
* @return string Data to send to browser
|
||||
*/
|
||||
public function _flush($data)
|
||||
{
|
||||
if ($this->_cancel) {
|
||||
return $data;
|
||||
}
|
||||
$contentType = null;
|
||||
$storedHeaders = array();
|
||||
$headersList = headers_list();
|
||||
foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) {
|
||||
foreach ($headersList as $headerSent) {
|
||||
$tmp = explode(':', $headerSent);
|
||||
$headerSentName = trim(array_shift($tmp));
|
||||
if (strtolower($headerName) == strtolower($headerSentName)) {
|
||||
$headerSentValue = trim(implode(':', $tmp));
|
||||
$storedHeaders[] = array($headerSentName, $headerSentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
$array = array(
|
||||
'data' => $data,
|
||||
'headers' => $storedHeaders
|
||||
);
|
||||
$this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an id depending on REQUEST_URI and superglobal arrays (depending on options)
|
||||
*
|
||||
* @return mixed|false a cache id (string), false if the cache should have not to be used
|
||||
*/
|
||||
protected function _makeId()
|
||||
{
|
||||
$tmp = $_SERVER['REQUEST_URI'];
|
||||
$array = explode('?', $tmp, 2);
|
||||
$tmp = $array[0];
|
||||
foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) {
|
||||
$tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']);
|
||||
if ($tmp2===false) {
|
||||
return false;
|
||||
}
|
||||
$tmp = $tmp . $tmp2;
|
||||
}
|
||||
return md5($tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a partial id depending on options
|
||||
*
|
||||
* @param string $arrayName Superglobal array name
|
||||
* @param bool $bool1 If true, cache is still on even if there are some variables in the superglobal array
|
||||
* @param bool $bool2 If true, we have to use the content of the superglobal array to make a partial id
|
||||
* @return mixed|false Partial id (string) or false if the cache should have not to be used
|
||||
*/
|
||||
protected function _makePartialId($arrayName, $bool1, $bool2)
|
||||
{
|
||||
switch ($arrayName) {
|
||||
case 'Get':
|
||||
$var = $_GET;
|
||||
break;
|
||||
case 'Post':
|
||||
$var = $_POST;
|
||||
break;
|
||||
case 'Session':
|
||||
if (isset($_SESSION)) {
|
||||
$var = $_SESSION;
|
||||
} else {
|
||||
$var = null;
|
||||
}
|
||||
break;
|
||||
case 'Cookie':
|
||||
if (isset($_COOKIE)) {
|
||||
$var = $_COOKIE;
|
||||
} else {
|
||||
$var = null;
|
||||
}
|
||||
break;
|
||||
case 'Files':
|
||||
$var = $_FILES;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if ($bool1) {
|
||||
if ($bool2) {
|
||||
return serialize($var);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
if (count($var) > 0) {
|
||||
return false;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
<?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-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/** @see Zend_Cache_Exception */
|
||||
require_once 'Zend/Cache/Exception.php';
|
||||
|
||||
/** @see Zend_Cache */
|
||||
require_once 'Zend/Cache.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Cache
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Cache_Manager
|
||||
{
|
||||
/**
|
||||
* Constant holding reserved name for default Page Cache
|
||||
*/
|
||||
const PAGECACHE = 'page';
|
||||
|
||||
/**
|
||||
* Constant holding reserved name for default Page Tag Cache
|
||||
*/
|
||||
const PAGETAGCACHE = 'pagetag';
|
||||
|
||||
/**
|
||||
* Array of caches stored by the Cache Manager instance
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_caches = array();
|
||||
|
||||
/**
|
||||
* Array of ready made configuration templates for lazy
|
||||
* loading caches.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_optionTemplates = array(
|
||||
// Simple Common Default
|
||||
'default' => array(
|
||||
'frontend' => array(
|
||||
'name' => 'Core',
|
||||
'options' => array(
|
||||
'automatic_serialization' => true,
|
||||
),
|
||||
),
|
||||
'backend' => array(
|
||||
'name' => 'File',
|
||||
'options' => array(
|
||||
// use system temp dir by default of file backend
|
||||
// 'cache_dir' => '../cache',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Static Page HTML Cache
|
||||
'page' => array(
|
||||
'frontend' => array(
|
||||
'name' => 'Capture',
|
||||
'options' => array(
|
||||
'ignore_user_abort' => true,
|
||||
),
|
||||
),
|
||||
'backend' => array(
|
||||
'name' => 'Static',
|
||||
'options' => array(
|
||||
'public_dir' => '../public',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Tag Cache
|
||||
'pagetag' => array(
|
||||
'frontend' => array(
|
||||
'name' => 'Core',
|
||||
'options' => array(
|
||||
'automatic_serialization' => true,
|
||||
'lifetime' => null
|
||||
),
|
||||
),
|
||||
'backend' => array(
|
||||
'name' => 'File',
|
||||
'options' => array(
|
||||
// use system temp dir by default of file backend
|
||||
// 'cache_dir' => '../cache',
|
||||
// use default umask of file backend
|
||||
// 'cache_file_umask' => 0644
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Set a new cache for the Cache Manager to contain
|
||||
*
|
||||
* @param string $name
|
||||
* @param Zend_Cache_Core $cache
|
||||
* @return Zend_Cache_Manager
|
||||
*/
|
||||
public function setCache($name, Zend_Cache_Core $cache)
|
||||
{
|
||||
$this->_caches[$name] = $cache;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Cache Manager contains the named cache object, or a named
|
||||
* configuration template to lazy load the cache object
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCache($name)
|
||||
{
|
||||
if (isset($this->_caches[$name])
|
||||
|| $this->hasCacheTemplate($name)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the named cache object, or instantiate and return a cache object
|
||||
* using a named configuration template
|
||||
*
|
||||
* @param string $name
|
||||
* @return Zend_Cache_Core
|
||||
*/
|
||||
public function getCache($name)
|
||||
{
|
||||
if (isset($this->_caches[$name])) {
|
||||
return $this->_caches[$name];
|
||||
}
|
||||
if (isset($this->_optionTemplates[$name])) {
|
||||
if ($name == self::PAGECACHE
|
||||
&& (!isset($this->_optionTemplates[$name]['backend']['options']['tag_cache'])
|
||||
|| !$this->_optionTemplates[$name]['backend']['options']['tag_cache'] instanceof Zend_Cache_Core)
|
||||
) {
|
||||
$this->_optionTemplates[$name]['backend']['options']['tag_cache']
|
||||
= $this->getCache(self::PAGETAGCACHE);
|
||||
}
|
||||
|
||||
$this->_caches[$name] = Zend_Cache::factory(
|
||||
$this->_optionTemplates[$name]['frontend']['name'],
|
||||
$this->_optionTemplates[$name]['backend']['name'],
|
||||
isset($this->_optionTemplates[$name]['frontend']['options']) ? $this->_optionTemplates[$name]['frontend']['options'] : array(),
|
||||
isset($this->_optionTemplates[$name]['backend']['options']) ? $this->_optionTemplates[$name]['backend']['options'] : array(),
|
||||
isset($this->_optionTemplates[$name]['frontend']['customFrontendNaming']) ? $this->_optionTemplates[$name]['frontend']['customFrontendNaming'] : false,
|
||||
isset($this->_optionTemplates[$name]['backend']['customBackendNaming']) ? $this->_optionTemplates[$name]['backend']['customBackendNaming'] : false,
|
||||
isset($this->_optionTemplates[$name]['frontendBackendAutoload']) ? $this->_optionTemplates[$name]['frontendBackendAutoload'] : false
|
||||
);
|
||||
|
||||
return $this->_caches[$name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all available caches
|
||||
*
|
||||
* @return array An array of all available caches with it's names as key
|
||||
*/
|
||||
public function getCaches()
|
||||
{
|
||||
$caches = $this->_caches;
|
||||
foreach ($this->_optionTemplates as $name => $tmp) {
|
||||
if (!isset($caches[$name])) {
|
||||
$caches[$name] = $this->getCache($name);
|
||||
}
|
||||
}
|
||||
return $caches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a named configuration template from which a cache object can later
|
||||
* be lazy loaded
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $options
|
||||
* @return Zend_Cache_Manager
|
||||
* @throws Zend_Cache_Exception
|
||||
*/
|
||||
public function setCacheTemplate($name, $options)
|
||||
{
|
||||
if ($options instanceof Zend_Config) {
|
||||
$options = $options->toArray();
|
||||
} elseif (!is_array($options)) {
|
||||
require_once 'Zend/Cache/Exception.php';
|
||||
throw new Zend_Cache_Exception('Options passed must be in'
|
||||
. ' an associative array or instance of Zend_Config');
|
||||
}
|
||||
$this->_optionTemplates[$name] = $options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the named configuration template
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCacheTemplate($name)
|
||||
{
|
||||
if (isset($this->_optionTemplates[$name])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the named configuration template
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function getCacheTemplate($name)
|
||||
{
|
||||
if (isset($this->_optionTemplates[$name])) {
|
||||
return $this->_optionTemplates[$name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass an array containing changes to be applied to a named
|
||||
* configuration
|
||||
* template
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $options
|
||||
* @return Zend_Cache_Manager
|
||||
* @throws Zend_Cache_Exception for invalid options format or if option templates do not have $name
|
||||
*/
|
||||
public function setTemplateOptions($name, $options)
|
||||
{
|
||||
if ($options instanceof Zend_Config) {
|
||||
$options = $options->toArray();
|
||||
} elseif (!is_array($options)) {
|
||||
require_once 'Zend/Cache/Exception.php';
|
||||
throw new Zend_Cache_Exception('Options passed must be in'
|
||||
. ' an associative array or instance of Zend_Config');
|
||||
}
|
||||
if (!isset($this->_optionTemplates[$name])) {
|
||||
throw new Zend_Cache_Exception('A cache configuration template'
|
||||
. 'does not exist with the name "' . $name . '"');
|
||||
}
|
||||
$this->_optionTemplates[$name]
|
||||
= $this->_mergeOptions($this->_optionTemplates[$name], $options);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple method to merge two configuration arrays
|
||||
*
|
||||
* @param array $current
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function _mergeOptions(array $current, array $options)
|
||||
{
|
||||
if (isset($options['frontend']['name'])) {
|
||||
$current['frontend']['name'] = $options['frontend']['name'];
|
||||
}
|
||||
if (isset($options['backend']['name'])) {
|
||||
$current['backend']['name'] = $options['backend']['name'];
|
||||
}
|
||||
if (isset($options['frontend']['options'])) {
|
||||
foreach ($options['frontend']['options'] as $key => $value) {
|
||||
$current['frontend']['options'][$key] = $value;
|
||||
}
|
||||
}
|
||||
if (isset($options['backend']['options'])) {
|
||||
foreach ($options['backend']['options'] as $key => $value) {
|
||||
$current['backend']['options'][$key] = $value;
|
||||
}
|
||||
}
|
||||
if (isset($options['frontend']['customFrontendNaming'])) {
|
||||
$current['frontend']['customFrontendNaming'] = $options['frontend']['customFrontendNaming'];
|
||||
}
|
||||
if (isset($options['backend']['customBackendNaming'])) {
|
||||
$current['backend']['customBackendNaming'] = $options['backend']['customBackendNaming'];
|
||||
}
|
||||
if (isset($options['frontendBackendAutoload'])) {
|
||||
$current['frontendBackendAutoload'] = $options['frontendBackendAutoload'];
|
||||
}
|
||||
return $current;
|
||||
}
|
||||
}
|
||||
@@ -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_Config
|
||||
* @copyright Copyright (c) 2005-2015 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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config implements Countable, Iterator
|
||||
{
|
||||
/**
|
||||
* Whether in-memory modifications to configuration data are allowed
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_allowModifications;
|
||||
|
||||
/**
|
||||
* Iteration index
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_index;
|
||||
|
||||
/**
|
||||
* Number of elements in configuration data
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $_count;
|
||||
|
||||
/**
|
||||
* Contains array of configuration data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data;
|
||||
|
||||
/**
|
||||
* Used when unsetting values during iteration to ensure we do not skip
|
||||
* the next element
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_skipNextIteration;
|
||||
|
||||
/**
|
||||
* Contains which config file sections were loaded. This is null
|
||||
* if all sections were loaded, a string name if one section is loaded
|
||||
* and an array of string names if multiple sections were loaded.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_loadedSection;
|
||||
|
||||
/**
|
||||
* This is used to track section inheritance. The keys are names of sections that
|
||||
* extend other sections, and the values are the extended sections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_extends = array();
|
||||
|
||||
/**
|
||||
* Load file error string.
|
||||
*
|
||||
* Is null if there was no error while file loading
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_loadFileErrorStr = null;
|
||||
|
||||
/**
|
||||
* Zend_Config provides a property based interface to
|
||||
* an array. The data are read-only unless $allowModifications
|
||||
* is set to true on construction.
|
||||
*
|
||||
* Zend_Config also implements Countable and Iterator to
|
||||
* facilitate easy access to the data.
|
||||
*
|
||||
* @param array $array
|
||||
* @param boolean $allowModifications
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $array, $allowModifications = false)
|
||||
{
|
||||
$this->_allowModifications = (boolean) $allowModifications;
|
||||
$this->_loadedSection = null;
|
||||
$this->_index = 0;
|
||||
$this->_data = array();
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->_data[$key] = new self($value, $this->_allowModifications);
|
||||
} else {
|
||||
$this->_data[$key] = $value;
|
||||
}
|
||||
}
|
||||
$this->_count = count($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a value and return $default if there is no element set.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
$result = $default;
|
||||
if (array_key_exists($name, $this->_data)) {
|
||||
$result = $this->_data[$name];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic function so that $obj->value will work.
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allow setting of a property if $allowModifications
|
||||
* was set to true on construction. Otherwise, throw an exception.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @throws Zend_Config_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if ($this->_allowModifications) {
|
||||
if (is_array($value)) {
|
||||
$this->_data[$name] = new self($value, true);
|
||||
} else {
|
||||
$this->_data[$name] = $value;
|
||||
}
|
||||
$this->_count = count($this->_data);
|
||||
} else {
|
||||
/** @see Zend_Config_Exception */
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Zend_Config is read only');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep clone of this instance to ensure that nested Zend_Configs
|
||||
* are also cloned.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$array = array();
|
||||
foreach ($this->_data as $key => $value) {
|
||||
if ($value instanceof Zend_Config) {
|
||||
$array[$key] = clone $value;
|
||||
} else {
|
||||
$array[$key] = $value;
|
||||
}
|
||||
}
|
||||
$this->_data = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an associative array of the stored data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$array = array();
|
||||
$data = $this->_data;
|
||||
foreach ($data as $key => $value) {
|
||||
if ($value instanceof Zend_Config) {
|
||||
$array[$key] = $value->toArray();
|
||||
} else {
|
||||
$array[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support isset() overloading on PHP 5.1
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->_data[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Support unset() overloading on PHP 5.1
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Zend_Config_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
if ($this->_allowModifications) {
|
||||
unset($this->_data[$name]);
|
||||
$this->_count = count($this->_data);
|
||||
$this->_skipNextIteration = true;
|
||||
} else {
|
||||
/** @see Zend_Config_Exception */
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Zend_Config is read only');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Countable interface
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Iterator interface
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
$this->_skipNextIteration = false;
|
||||
return current($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Iterator interface
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Iterator interface
|
||||
*
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
if ($this->_skipNextIteration) {
|
||||
$this->_skipNextIteration = false;
|
||||
return;
|
||||
}
|
||||
next($this->_data);
|
||||
$this->_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Iterator interface
|
||||
*
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->_skipNextIteration = false;
|
||||
reset($this->_data);
|
||||
$this->_index = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined by Iterator interface
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->_index < $this->_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section name(s) loaded.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSectionName()
|
||||
{
|
||||
if(is_array($this->_loadedSection) && count($this->_loadedSection) == 1) {
|
||||
$this->_loadedSection = $this->_loadedSection[0];
|
||||
}
|
||||
return $this->_loadedSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all sections were loaded
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function areAllSectionsLoaded()
|
||||
{
|
||||
return $this->_loadedSection === null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge another Zend_Config with this one. The items
|
||||
* in $merge will override the same named items in
|
||||
* the current config.
|
||||
*
|
||||
* @param Zend_Config $merge
|
||||
* @return Zend_Config
|
||||
*/
|
||||
public function merge(Zend_Config $merge)
|
||||
{
|
||||
foreach($merge as $key => $item) {
|
||||
if(array_key_exists($key, $this->_data)) {
|
||||
if($item instanceof Zend_Config && $this->$key instanceof Zend_Config) {
|
||||
$this->$key = $this->$key->merge(new Zend_Config($item->toArray(), !$this->readOnly()));
|
||||
} else {
|
||||
$this->$key = $item;
|
||||
}
|
||||
} else {
|
||||
if($item instanceof Zend_Config) {
|
||||
$this->$key = new Zend_Config($item->toArray(), !$this->readOnly());
|
||||
} else {
|
||||
$this->$key = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent any more modifications being made to this instance. Useful
|
||||
* after merge() has been used to merge multiple Zend_Config objects
|
||||
* into one object which should then not be modified again.
|
||||
*
|
||||
*/
|
||||
public function setReadOnly()
|
||||
{
|
||||
$this->_allowModifications = false;
|
||||
foreach ($this->_data as $key => $value) {
|
||||
if ($value instanceof Zend_Config) {
|
||||
$value->setReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this Zend_Config object is read only or not.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function readOnly()
|
||||
{
|
||||
return !$this->_allowModifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current extends
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExtends()
|
||||
{
|
||||
return $this->_extends;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an extend for Zend_Config_Writer
|
||||
*
|
||||
* @param string $extendingSection
|
||||
* @param string $extendedSection
|
||||
* @return void
|
||||
*/
|
||||
public function setExtend($extendingSection, $extendedSection = null)
|
||||
{
|
||||
if ($extendedSection === null && isset($this->_extends[$extendingSection])) {
|
||||
unset($this->_extends[$extendingSection]);
|
||||
} else if ($extendedSection !== null) {
|
||||
$this->_extends[$extendingSection] = $extendedSection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if $extendingSection may not extend $extendedSection,
|
||||
* and tracks the section extension if it is valid.
|
||||
*
|
||||
* @param string $extendingSection
|
||||
* @param string $extendedSection
|
||||
* @throws Zend_Config_Exception
|
||||
* @return void
|
||||
*/
|
||||
protected function _assertValidExtend($extendingSection, $extendedSection)
|
||||
{
|
||||
// detect circular section inheritance
|
||||
$extendedSectionCurrent = $extendedSection;
|
||||
while (array_key_exists($extendedSectionCurrent, $this->_extends)) {
|
||||
if ($this->_extends[$extendedSectionCurrent] == $extendingSection) {
|
||||
/** @see Zend_Config_Exception */
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Illegal circular inheritance detected');
|
||||
}
|
||||
$extendedSectionCurrent = $this->_extends[$extendedSectionCurrent];
|
||||
}
|
||||
// remember that this section extends another section
|
||||
$this->_extends[$extendingSection] = $extendedSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle any errors from simplexml_load_file or parse_ini_file
|
||||
*
|
||||
* @param integer $errno
|
||||
* @param string $errstr
|
||||
* @param string $errfile
|
||||
* @param integer $errline
|
||||
*/
|
||||
public function _loadFileErrorHandler($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
if ($this->_loadFileErrorStr === null) {
|
||||
$this->_loadFileErrorStr = $errstr;
|
||||
} else {
|
||||
$this->_loadFileErrorStr .= (PHP_EOL . $errstr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two arrays recursively, overwriting keys of the same name
|
||||
* in $firstArray with the value in $secondArray.
|
||||
*
|
||||
* @param mixed $firstArray First array
|
||||
* @param mixed $secondArray Second array to merge into first array
|
||||
* @return array
|
||||
*/
|
||||
protected function _arrayMergeRecursive($firstArray, $secondArray)
|
||||
{
|
||||
if (is_array($firstArray) && is_array($secondArray)) {
|
||||
foreach ($secondArray as $key => $value) {
|
||||
if (isset($firstArray[$key])) {
|
||||
$firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
|
||||
} else {
|
||||
if($key === 0) {
|
||||
$firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value));
|
||||
} else {
|
||||
$firstArray[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$firstArray = $secondArray;
|
||||
}
|
||||
|
||||
return $firstArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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_Config
|
||||
* @copyright Copyright (c) 2005-2015 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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config_Exception extends Zend_Exception {}
|
||||
@@ -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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Zend_Config
|
||||
*/
|
||||
require_once 'Zend/Config.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config_Ini extends Zend_Config
|
||||
{
|
||||
/**
|
||||
* String that separates nesting levels of configuration data identifiers
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_nestSeparator = '.';
|
||||
|
||||
/**
|
||||
* String that separates the parent section name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_sectionSeparator = ':';
|
||||
|
||||
/**
|
||||
* Whether to skip extends or not
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_skipExtends = false;
|
||||
|
||||
/**
|
||||
* Loads the section $section from the config file $filename for
|
||||
* access facilitated by nested object properties.
|
||||
*
|
||||
* If the section name contains a ":" then the section name to the right
|
||||
* is loaded and included into the properties. Note that the keys in
|
||||
* this $section will override any keys of the same
|
||||
* name in the sections that have been included via ":".
|
||||
*
|
||||
* If the $section is null, then all sections in the ini file are loaded.
|
||||
*
|
||||
* If any key includes a ".", then this will act as a separator to
|
||||
* create a sub-property.
|
||||
*
|
||||
* example ini file:
|
||||
* [all]
|
||||
* db.connection = database
|
||||
* hostname = live
|
||||
*
|
||||
* [staging : all]
|
||||
* hostname = staging
|
||||
*
|
||||
* after calling $data = new Zend_Config_Ini($file, 'staging'); then
|
||||
* $data->hostname === "staging"
|
||||
* $data->db->connection === "database"
|
||||
*
|
||||
* The $options parameter may be provided as either a boolean or an array.
|
||||
* If provided as a boolean, this sets the $allowModifications option of
|
||||
* Zend_Config. If provided as an array, there are three configuration
|
||||
* directives that may be set. For example:
|
||||
*
|
||||
* $options = array(
|
||||
* 'allowModifications' => false,
|
||||
* 'nestSeparator' => ':',
|
||||
* 'skipExtends' => false,
|
||||
* );
|
||||
*
|
||||
* @param string $filename
|
||||
* @param mixed $section
|
||||
* @param boolean|array $options
|
||||
* @throws Zend_Config_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($filename, $section = null, $options = false)
|
||||
{
|
||||
if (empty($filename)) {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Filename is not set');
|
||||
}
|
||||
|
||||
$allowModifications = false;
|
||||
if (is_bool($options)) {
|
||||
$allowModifications = $options;
|
||||
} elseif (is_array($options)) {
|
||||
if (isset($options['allowModifications'])) {
|
||||
$allowModifications = (bool) $options['allowModifications'];
|
||||
}
|
||||
if (isset($options['nestSeparator'])) {
|
||||
$this->_nestSeparator = (string) $options['nestSeparator'];
|
||||
}
|
||||
if (isset($options['skipExtends'])) {
|
||||
$this->_skipExtends = (bool) $options['skipExtends'];
|
||||
}
|
||||
}
|
||||
|
||||
$iniArray = $this->_loadIniFile($filename);
|
||||
|
||||
if (null === $section) {
|
||||
// Load entire file
|
||||
$dataArray = array();
|
||||
foreach ($iniArray as $sectionName => $sectionData) {
|
||||
if(!is_array($sectionData)) {
|
||||
$dataArray = $this->_arrayMergeRecursive($dataArray, $this->_processKey(array(), $sectionName, $sectionData));
|
||||
} else {
|
||||
$dataArray[$sectionName] = $this->_processSection($iniArray, $sectionName);
|
||||
}
|
||||
}
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
} else {
|
||||
// Load one or more sections
|
||||
if (!is_array($section)) {
|
||||
$section = array($section);
|
||||
}
|
||||
$dataArray = array();
|
||||
foreach ($section as $sectionName) {
|
||||
if (!isset($iniArray[$sectionName])) {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $filename");
|
||||
}
|
||||
$dataArray = $this->_arrayMergeRecursive($this->_processSection($iniArray, $sectionName), $dataArray);
|
||||
|
||||
}
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
}
|
||||
|
||||
$this->_loadedSection = $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the INI file from disk using parse_ini_file(). Use a private error
|
||||
* handler to convert any loading errors into a Zend_Config_Exception
|
||||
*
|
||||
* @param string $filename
|
||||
* @throws Zend_Config_Exception
|
||||
* @return array
|
||||
*/
|
||||
protected function _parseIniFile($filename)
|
||||
{
|
||||
set_error_handler(array($this, '_loadFileErrorHandler'));
|
||||
$iniArray = parse_ini_file($filename, true); // Warnings and errors are suppressed
|
||||
restore_error_handler();
|
||||
|
||||
// Check if there was a error while loading file
|
||||
if ($this->_loadFileErrorStr !== null) {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception($this->_loadFileErrorStr);
|
||||
}
|
||||
|
||||
return $iniArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the ini file and preprocess the section separator (':' in the
|
||||
* section name (that is used for section extension) so that the resultant
|
||||
* array has the correct section names and the extension information is
|
||||
* stored in a sub-key called ';extends'. We use ';extends' as this can
|
||||
* never be a valid key name in an INI file that has been loaded using
|
||||
* parse_ini_file().
|
||||
*
|
||||
* @param string $filename
|
||||
* @throws Zend_Config_Exception
|
||||
* @return array
|
||||
*/
|
||||
protected function _loadIniFile($filename)
|
||||
{
|
||||
$loaded = $this->_parseIniFile($filename);
|
||||
$iniArray = array();
|
||||
foreach ($loaded as $key => $data)
|
||||
{
|
||||
$pieces = explode($this->_sectionSeparator, $key);
|
||||
$thisSection = trim($pieces[0]);
|
||||
switch (count($pieces)) {
|
||||
case 1:
|
||||
$iniArray[$thisSection] = $data;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$extendedSection = trim($pieces[1]);
|
||||
$iniArray[$thisSection] = array_merge(array(';extends'=>$extendedSection), $data);
|
||||
break;
|
||||
|
||||
default:
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Section '$thisSection' may not extend multiple sections in $filename");
|
||||
}
|
||||
}
|
||||
|
||||
return $iniArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process each element in the section and handle the ";extends" inheritance
|
||||
* key. Passes control to _processKey() to handle the nest separator
|
||||
* sub-property syntax that may be used within the key name.
|
||||
*
|
||||
* @param array $iniArray
|
||||
* @param string $section
|
||||
* @param array $config
|
||||
* @throws Zend_Config_Exception
|
||||
* @return array
|
||||
*/
|
||||
protected function _processSection($iniArray, $section, $config = array())
|
||||
{
|
||||
$thisSection = $iniArray[$section];
|
||||
|
||||
foreach ($thisSection as $key => $value) {
|
||||
if (strtolower($key) == ';extends') {
|
||||
if (isset($iniArray[$value])) {
|
||||
$this->_assertValidExtend($section, $value);
|
||||
|
||||
if (!$this->_skipExtends) {
|
||||
$config = $this->_processSection($iniArray, $value, $config);
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Parent section '$section' cannot be found");
|
||||
}
|
||||
} else {
|
||||
$config = $this->_processKey($config, $key, $value);
|
||||
}
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the key's value to the property list. Handles the
|
||||
* nest separator for sub-properties.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @throws Zend_Config_Exception
|
||||
* @return array
|
||||
*/
|
||||
protected function _processKey($config, $key, $value)
|
||||
{
|
||||
if (strpos($key, $this->_nestSeparator) !== false) {
|
||||
$pieces = explode($this->_nestSeparator, $key, 2);
|
||||
if (strlen($pieces[0]) && strlen($pieces[1])) {
|
||||
if (!isset($config[$pieces[0]])) {
|
||||
if ($pieces[0] === '0' && !empty($config)) {
|
||||
// convert the current values in $config into an array
|
||||
$config = array($pieces[0] => $config);
|
||||
} else {
|
||||
$config[$pieces[0]] = array();
|
||||
}
|
||||
} elseif (!is_array($config[$pieces[0]])) {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Cannot create sub-key for '{$pieces[0]}' as key already exists");
|
||||
}
|
||||
$config[$pieces[0]] = $this->_processKey($config[$pieces[0]], $pieces[1], $value);
|
||||
} else {
|
||||
/**
|
||||
* @see Zend_Config_Exception
|
||||
*/
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Invalid key '$key'");
|
||||
}
|
||||
} else {
|
||||
$config[$key] = $value;
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
Executable
+242
@@ -0,0 +1,242 @@
|
||||
<?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_Config
|
||||
* @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_Config
|
||||
*/
|
||||
require_once 'Zend/Config.php';
|
||||
|
||||
/**
|
||||
* @see Zend_Json
|
||||
*/
|
||||
require_once 'Zend/Json.php';
|
||||
|
||||
/**
|
||||
* JSON Adapter for Zend_Config
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @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_Config_Json extends Zend_Config
|
||||
{
|
||||
/**
|
||||
* Name of object key indicating section current section extends
|
||||
*/
|
||||
const EXTENDS_NAME = "_extends";
|
||||
|
||||
/**
|
||||
* Whether or not to ignore constants in the JSON string
|
||||
*
|
||||
* Note: if you do not have constant names in quotations in your JSON
|
||||
* string, they may lead to syntax errors when parsing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_ignoreConstants = false;
|
||||
|
||||
/**
|
||||
* Whether to skip extends or not
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_skipExtends = false;
|
||||
|
||||
/**
|
||||
* Loads the section $section from the config file encoded as JSON
|
||||
*
|
||||
* Sections are defined as properties of the main object
|
||||
*
|
||||
* In order to extend another section, a section defines the "_extends"
|
||||
* property having a value of the section name from which the extending
|
||||
* section inherits values.
|
||||
*
|
||||
* Note that the keys in $section will override any keys of the same
|
||||
* name in the sections that have been included via "_extends".
|
||||
*
|
||||
* @param string $json JSON file or string to process
|
||||
* @param mixed $section Section to process
|
||||
* @param boolean $options Whether modifiacations are allowed at runtime
|
||||
* @throws Zend_Config_Exception When JSON text is not set or cannot be loaded
|
||||
* @throws Zend_Config_Exception When section $sectionName cannot be found in $json
|
||||
*/
|
||||
public function __construct($json, $section = null, $options = false)
|
||||
{
|
||||
if (empty($json)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Filename is not set');
|
||||
}
|
||||
|
||||
$allowModifications = false;
|
||||
if (is_bool($options)) {
|
||||
$allowModifications = $options;
|
||||
} elseif (is_array($options)) {
|
||||
foreach ($options as $key => $value) {
|
||||
switch (strtolower($key)) {
|
||||
case 'allow_modifications':
|
||||
case 'allowmodifications':
|
||||
$allowModifications = (bool) $value;
|
||||
break;
|
||||
case 'skip_extends':
|
||||
case 'skipextends':
|
||||
$this->_skipExtends = (bool) $value;
|
||||
break;
|
||||
case 'ignore_constants':
|
||||
case 'ignoreconstants':
|
||||
$this->_ignoreConstants = (bool) $value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed
|
||||
if ($json[0] != '{') {
|
||||
$json = file_get_contents($json);
|
||||
}
|
||||
restore_error_handler();
|
||||
|
||||
// Check if there was a error while loading file
|
||||
if ($this->_loadFileErrorStr !== null) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception($this->_loadFileErrorStr);
|
||||
}
|
||||
|
||||
// Replace constants
|
||||
if (!$this->_ignoreConstants) {
|
||||
$json = $this->_replaceConstants($json);
|
||||
}
|
||||
|
||||
// Parse/decode
|
||||
try {
|
||||
$config = Zend_Json::decode($json);
|
||||
} catch (Zend_Json_Exception $e) {
|
||||
// decode failed
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Error parsing JSON data");
|
||||
}
|
||||
|
||||
if ($section === null) {
|
||||
$dataArray = array();
|
||||
foreach ($config as $sectionName => $sectionData) {
|
||||
$dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
} elseif (is_array($section)) {
|
||||
$dataArray = array();
|
||||
foreach ($section as $sectionName) {
|
||||
if (!isset($config[$sectionName])) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName));
|
||||
}
|
||||
|
||||
$dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
} else {
|
||||
if (!isset($config[$section])) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
|
||||
}
|
||||
|
||||
$dataArray = $this->_processExtends($config, $section);
|
||||
if (!is_array($dataArray)) {
|
||||
// Section in the JSON data contains just one top level string
|
||||
$dataArray = array($section => $dataArray);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
}
|
||||
|
||||
$this->_loadedSection = $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to process each element in the section and handle
|
||||
* the "_extends" inheritance attribute.
|
||||
*
|
||||
* @param array $data Data array to process
|
||||
* @param string $section Section to process
|
||||
* @param array $config Configuration which was parsed yet
|
||||
* @throws Zend_Config_Exception When $section cannot be found
|
||||
* @return array
|
||||
*/
|
||||
protected function _processExtends(array $data, $section, array $config = array())
|
||||
{
|
||||
if (!isset($data[$section])) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
|
||||
}
|
||||
|
||||
$thisSection = $data[$section];
|
||||
|
||||
if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) {
|
||||
if (is_array($thisSection[self::EXTENDS_NAME])) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received');
|
||||
}
|
||||
$this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]);
|
||||
|
||||
if (!$this->_skipExtends) {
|
||||
$config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config);
|
||||
}
|
||||
unset($thisSection[self::EXTENDS_NAME]);
|
||||
}
|
||||
|
||||
$config = $this->_arrayMergeRecursive($config, $thisSection);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any constants referenced in a string with their values
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function _replaceConstants($value)
|
||||
{
|
||||
foreach ($this->_getConstants() as $constant) {
|
||||
if (strstr($value, $constant)) {
|
||||
// handle backslashes that may represent windows path names for instance
|
||||
$replacement = str_replace('\\', '\\\\', constant($constant));
|
||||
$value = str_replace($constant, $replacement, $value);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get (reverse) sorted list of defined constant names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _getConstants()
|
||||
{
|
||||
$constants = array_keys(get_defined_constants());
|
||||
rsort($constants, SORT_STRING);
|
||||
return $constants;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?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_Config
|
||||
* @copyright Copyright (c) 2005-2015 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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_Config_Writer
|
||||
{
|
||||
/**
|
||||
* Option keys to skip when calling setOptions()
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_skipOptions = array(
|
||||
'options'
|
||||
);
|
||||
|
||||
/**
|
||||
* Config object to write
|
||||
*
|
||||
* @var Zend_Config
|
||||
*/
|
||||
protected $_config = null;
|
||||
|
||||
/**
|
||||
* Create a new adapter
|
||||
*
|
||||
* $options can only be passed as array or be omitted
|
||||
*
|
||||
* @param null|array $options
|
||||
*/
|
||||
public function __construct(array $options = null)
|
||||
{
|
||||
if (is_array($options)) {
|
||||
$this->setOptions($options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options via a Zend_Config instance
|
||||
*
|
||||
* @param Zend_Config $config
|
||||
* @return Zend_Config_Writer
|
||||
*/
|
||||
public function setConfig(Zend_Config $config)
|
||||
{
|
||||
$this->_config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options via an array
|
||||
*
|
||||
* @param array $options
|
||||
* @return Zend_Config_Writer
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
foreach ($options as $key => $value) {
|
||||
if (in_array(strtolower($key), $this->_skipOptions)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$method = 'set' . ucfirst($key);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->$method($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a Zend_Config object to it's target
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function write();
|
||||
}
|
||||
+21
-16
@@ -13,38 +13,43 @@
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
|
||||
* @see Zend_Config_Writer
|
||||
*/
|
||||
require_once 'Zend/Service/DeveloperGarden/Response/VoiceButler/VoiceButlerAbstract.php';
|
||||
require_once 'Zend/Config/Writer/FileAbstract.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Service
|
||||
* @subpackage DeveloperGarden
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @author Marco Kaiser
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Service_DeveloperGarden_Response_VoiceButler_TearDownCallResponse
|
||||
extends Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
|
||||
class Zend_Config_Writer_Array extends Zend_Config_Writer_FileAbstract
|
||||
{
|
||||
/**
|
||||
* returns the session id
|
||||
* Render a Zend_Config into a PHP Array config string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @return string
|
||||
*/
|
||||
public function getSessionId()
|
||||
public function render()
|
||||
{
|
||||
if (isset($this->return->sessionId)) {
|
||||
return $this->return->sessionId;
|
||||
$data = $this->_config->toArray();
|
||||
$sectionName = $this->_config->getSectionName();
|
||||
|
||||
if (is_string($sectionName)) {
|
||||
$data = array($sectionName => $data);
|
||||
}
|
||||
return null;
|
||||
|
||||
$arrayString = "<?php\n"
|
||||
. "return " . var_export($data, true) . ";\n";
|
||||
|
||||
return $arrayString;
|
||||
}
|
||||
}
|
||||
@@ -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_Config
|
||||
* @package Writer
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
require_once "Zend/Config/Writer.php";
|
||||
|
||||
/**
|
||||
* Abstract File Writer
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_package
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
class Zend_Config_Writer_FileAbstract extends Zend_Config_Writer
|
||||
{
|
||||
/**
|
||||
* Filename to write to
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_filename = null;
|
||||
|
||||
/**
|
||||
* Wether to exclusively lock the file or not
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_exclusiveLock = false;
|
||||
|
||||
/**
|
||||
* Set the target filename
|
||||
*
|
||||
* @param string $filename
|
||||
* @return Zend_Config_Writer_Array
|
||||
*/
|
||||
public function setFilename($filename)
|
||||
{
|
||||
$this->_filename = $filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set wether to exclusively lock the file or not
|
||||
*
|
||||
* @param boolean $exclusiveLock
|
||||
* @return Zend_Config_Writer_Array
|
||||
*/
|
||||
public function setExclusiveLock($exclusiveLock)
|
||||
{
|
||||
$this->_exclusiveLock = $exclusiveLock;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write configuration to file.
|
||||
*
|
||||
* @param string $filename
|
||||
* @param Zend_Config $config
|
||||
* @param bool $exclusiveLock
|
||||
* @return void
|
||||
*/
|
||||
public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
|
||||
{
|
||||
if ($filename !== null) {
|
||||
$this->setFilename($filename);
|
||||
}
|
||||
|
||||
if ($config !== null) {
|
||||
$this->setConfig($config);
|
||||
}
|
||||
|
||||
if ($exclusiveLock !== null) {
|
||||
$this->setExclusiveLock($exclusiveLock);
|
||||
}
|
||||
|
||||
if ($this->_filename === null) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('No filename was set');
|
||||
}
|
||||
|
||||
if ($this->_config === null) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('No config was set');
|
||||
}
|
||||
|
||||
$configString = $this->render();
|
||||
|
||||
$flags = 0;
|
||||
|
||||
if ($this->_exclusiveLock) {
|
||||
$flags |= LOCK_EX;
|
||||
}
|
||||
|
||||
$result = @file_put_contents($this->_filename, $configString, $flags);
|
||||
|
||||
if ($result === false) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a Zend_Config into a config file string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @todo For 2.0 this should be redone into an abstract method.
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_Config_Writer
|
||||
*/
|
||||
require_once 'Zend/Config/Writer/FileAbstract.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config_Writer_Ini extends Zend_Config_Writer_FileAbstract
|
||||
{
|
||||
/**
|
||||
* String that separates nesting levels of configuration data identifiers
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_nestSeparator = '.';
|
||||
|
||||
/**
|
||||
* If true the ini string is rendered in the global namespace without sections.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_renderWithoutSections = false;
|
||||
|
||||
/**
|
||||
* Set the nest separator
|
||||
*
|
||||
* @param string $filename
|
||||
* @return Zend_Config_Writer_Ini
|
||||
*/
|
||||
public function setNestSeparator($separator)
|
||||
{
|
||||
$this->_nestSeparator = $separator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if rendering should occour without sections or not.
|
||||
*
|
||||
* If set to true, the INI file is rendered without sections completely
|
||||
* into the global namespace of the INI file.
|
||||
*
|
||||
* @param bool $withoutSections
|
||||
* @return Zend_Config_Writer_Ini
|
||||
*/
|
||||
public function setRenderWithoutSections($withoutSections=true)
|
||||
{
|
||||
$this->_renderWithoutSections = (bool)$withoutSections;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a Zend_Config into a INI config string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$iniString = '';
|
||||
$extends = $this->_config->getExtends();
|
||||
$sectionName = $this->_config->getSectionName();
|
||||
|
||||
if($this->_renderWithoutSections == true) {
|
||||
$iniString .= $this->_addBranch($this->_config);
|
||||
} else if (is_string($sectionName)) {
|
||||
$iniString .= '[' . $sectionName . ']' . "\n"
|
||||
. $this->_addBranch($this->_config)
|
||||
. "\n";
|
||||
} else {
|
||||
$config = $this->_sortRootElements($this->_config);
|
||||
foreach ($config as $sectionName => $data) {
|
||||
if (!($data instanceof Zend_Config)) {
|
||||
$iniString .= $sectionName
|
||||
. ' = '
|
||||
. $this->_prepareValue($data)
|
||||
. "\n";
|
||||
} else {
|
||||
if (isset($extends[$sectionName])) {
|
||||
$sectionName .= ' : ' . $extends[$sectionName];
|
||||
}
|
||||
|
||||
$iniString .= '[' . $sectionName . ']' . "\n"
|
||||
. $this->_addBranch($data)
|
||||
. "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $iniString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a branch to an INI string recursively
|
||||
*
|
||||
* @param Zend_Config $config
|
||||
* @return void
|
||||
*/
|
||||
protected function _addBranch(Zend_Config $config, $parents = array())
|
||||
{
|
||||
$iniString = '';
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
$group = array_merge($parents, array($key));
|
||||
|
||||
if ($value instanceof Zend_Config) {
|
||||
$iniString .= $this->_addBranch($value, $group);
|
||||
} else {
|
||||
$iniString .= implode($this->_nestSeparator, $group)
|
||||
. ' = '
|
||||
. $this->_prepareValue($value)
|
||||
. "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $iniString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a value for INI
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function _prepareValue($value)
|
||||
{
|
||||
if (is_integer($value) || is_float($value)) {
|
||||
return $value;
|
||||
} elseif (is_bool($value)) {
|
||||
return ($value ? 'true' : 'false');
|
||||
} elseif (strpos($value, '"') === false) {
|
||||
return '"' . $value . '"';
|
||||
} else {
|
||||
/** @see Zend_Config_Exception */
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Value can not contain double quotes "');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Root elements that are not assigned to any section needs to be
|
||||
* on the top of config.
|
||||
*
|
||||
* @see http://framework.zend.com/issues/browse/ZF-6289
|
||||
* @param Zend_Config
|
||||
* @return Zend_Config
|
||||
*/
|
||||
protected function _sortRootElements(Zend_Config $config)
|
||||
{
|
||||
$configArray = $config->toArray();
|
||||
$sections = array();
|
||||
|
||||
// remove sections from config array
|
||||
foreach ($configArray as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$sections[$key] = $value;
|
||||
unset($configArray[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// readd sections to the end
|
||||
foreach ($sections as $key => $value) {
|
||||
$configArray[$key] = $value;
|
||||
}
|
||||
|
||||
return new Zend_Config($configArray);
|
||||
}
|
||||
}
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
<?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_Config
|
||||
* @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_Config_Writer
|
||||
*/
|
||||
require_once 'Zend/Config/Writer/FileAbstract.php';
|
||||
|
||||
/**
|
||||
* @see Zend_Config_Json
|
||||
*/
|
||||
require_once 'Zend/Config/Json.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @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_Config_Writer_Json extends Zend_Config_Writer_FileAbstract
|
||||
{
|
||||
/**
|
||||
* If we need to pretty-print JSON data
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_prettyPrint = false;
|
||||
|
||||
/**
|
||||
* Get prettyPrint flag
|
||||
*
|
||||
* @return the prettyPrint flag
|
||||
*/
|
||||
public function prettyPrint()
|
||||
{
|
||||
return $this->_prettyPrint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set prettyPrint flag
|
||||
*
|
||||
* @param bool $prettyPrint PrettyPrint flag
|
||||
* @return Zend_Config_Writer_Json
|
||||
*/
|
||||
public function setPrettyPrint($flag)
|
||||
{
|
||||
$this->_prettyPrint = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a Zend_Config into a JSON config string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$data = $this->_config->toArray();
|
||||
$sectionName = $this->_config->getSectionName();
|
||||
$extends = $this->_config->getExtends();
|
||||
|
||||
if (is_string($sectionName)) {
|
||||
$data = array($sectionName => $data);
|
||||
}
|
||||
|
||||
foreach ($extends as $section => $parentSection) {
|
||||
$data[$section][Zend_Config_Json::EXTENDS_NAME] = $parentSection;
|
||||
}
|
||||
|
||||
// Ensure that each "extends" section actually exists
|
||||
foreach ($data as $section => $sectionData) {
|
||||
if (is_array($sectionData) && isset($sectionData[Zend_Config_Json::EXTENDS_NAME])) {
|
||||
$sectionExtends = $sectionData[Zend_Config_Json::EXTENDS_NAME];
|
||||
if (!isset($data[$sectionExtends])) {
|
||||
// Remove "extends" declaration if section does not exist
|
||||
unset($data[$section][Zend_Config_Json::EXTENDS_NAME]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$out = Zend_Json::encode($data);
|
||||
if ($this->prettyPrint()) {
|
||||
$out = Zend_Json::prettyPrint($out);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_Config_Writer
|
||||
*/
|
||||
require_once 'Zend/Config/Writer/FileAbstract.php';
|
||||
|
||||
/**
|
||||
* @see Zend_Config_Xml
|
||||
*/
|
||||
require_once 'Zend/Config/Xml.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config_Writer_Xml extends Zend_Config_Writer_FileAbstract
|
||||
{
|
||||
/**
|
||||
* Render a Zend_Config into a XML config string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$xml = new SimpleXMLElement('<zend-config xmlns:zf="' . Zend_Config_Xml::XML_NAMESPACE . '"/>');
|
||||
$extends = $this->_config->getExtends();
|
||||
$sectionName = $this->_config->getSectionName();
|
||||
|
||||
if (is_string($sectionName)) {
|
||||
$child = $xml->addChild($sectionName);
|
||||
|
||||
$this->_addBranch($this->_config, $child, $xml);
|
||||
} else {
|
||||
foreach ($this->_config as $sectionName => $data) {
|
||||
if (!($data instanceof Zend_Config)) {
|
||||
$xml->addChild($sectionName, (string) $data);
|
||||
} else {
|
||||
$child = $xml->addChild($sectionName);
|
||||
|
||||
if (isset($extends[$sectionName])) {
|
||||
$child->addAttribute('zf:extends', $extends[$sectionName], Zend_Config_Xml::XML_NAMESPACE);
|
||||
}
|
||||
|
||||
$this->_addBranch($data, $child, $xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dom = dom_import_simplexml($xml)->ownerDocument;
|
||||
$dom->formatOutput = true;
|
||||
|
||||
$xmlString = $dom->saveXML();
|
||||
|
||||
return $xmlString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a branch to an XML object recursively
|
||||
*
|
||||
* @param Zend_Config $config
|
||||
* @param SimpleXMLElement $xml
|
||||
* @param SimpleXMLElement $parent
|
||||
* @return void
|
||||
*/
|
||||
protected function _addBranch(Zend_Config $config, SimpleXMLElement $xml, SimpleXMLElement $parent)
|
||||
{
|
||||
$branchType = null;
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
if ($branchType === null) {
|
||||
if (is_numeric($key)) {
|
||||
$branchType = 'numeric';
|
||||
$branchName = $xml->getName();
|
||||
$xml = $parent;
|
||||
|
||||
unset($parent->{$branchName});
|
||||
} else {
|
||||
$branchType = 'string';
|
||||
}
|
||||
} else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Mixing of string and numeric keys is not allowed');
|
||||
}
|
||||
|
||||
if ($branchType === 'numeric') {
|
||||
if ($value instanceof Zend_Config) {
|
||||
$child = $parent->addChild($branchName);
|
||||
|
||||
$this->_addBranch($value, $child, $parent);
|
||||
} else {
|
||||
$parent->addChild($branchName, (string) $value);
|
||||
}
|
||||
} else {
|
||||
if ($value instanceof Zend_Config) {
|
||||
$child = $xml->addChild($key);
|
||||
|
||||
$this->_addBranch($value, $child, $xml);
|
||||
} else {
|
||||
$xml->addChild($key, (string) $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+144
@@ -0,0 +1,144 @@
|
||||
<?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_Config
|
||||
* @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_Config_Writer
|
||||
*/
|
||||
require_once 'Zend/Config/Writer/FileAbstract.php';
|
||||
|
||||
/**
|
||||
* @see Zend_Config_Yaml
|
||||
*/
|
||||
require_once 'Zend/Config/Yaml.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @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_Config_Writer_Yaml extends Zend_Config_Writer_FileAbstract
|
||||
{
|
||||
/**
|
||||
* What to call when we need to decode some YAML?
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $_yamlEncoder = array('Zend_Config_Writer_Yaml', 'encode');
|
||||
|
||||
/**
|
||||
* Get callback for decoding YAML
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getYamlEncoder()
|
||||
{
|
||||
return $this->_yamlEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set callback for decoding YAML
|
||||
*
|
||||
* @param callable $yamlEncoder the decoder to set
|
||||
* @return Zend_Config_Yaml
|
||||
*/
|
||||
public function setYamlEncoder($yamlEncoder)
|
||||
{
|
||||
if (!is_callable($yamlEncoder)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Invalid parameter to setYamlEncoder - must be callable');
|
||||
}
|
||||
|
||||
$this->_yamlEncoder = $yamlEncoder;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a Zend_Config into a YAML config string.
|
||||
*
|
||||
* @since 1.10
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$data = $this->_config->toArray();
|
||||
$sectionName = $this->_config->getSectionName();
|
||||
$extends = $this->_config->getExtends();
|
||||
|
||||
if (is_string($sectionName)) {
|
||||
$data = array($sectionName => $data);
|
||||
}
|
||||
|
||||
foreach ($extends as $section => $parentSection) {
|
||||
$data[$section][Zend_Config_Yaml::EXTENDS_NAME] = $parentSection;
|
||||
}
|
||||
|
||||
// Ensure that each "extends" section actually exists
|
||||
foreach ($data as $section => $sectionData) {
|
||||
if (is_array($sectionData) && isset($sectionData[Zend_Config_Yaml::EXTENDS_NAME])) {
|
||||
$sectionExtends = $sectionData[Zend_Config_Yaml::EXTENDS_NAME];
|
||||
if (!isset($data[$sectionExtends])) {
|
||||
// Remove "extends" declaration if section does not exist
|
||||
unset($data[$section][Zend_Config_Yaml::EXTENDS_NAME]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return call_user_func($this->getYamlEncoder(), $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Very dumb YAML encoder
|
||||
*
|
||||
* Until we have Zend_Yaml...
|
||||
*
|
||||
* @param array $data YAML data
|
||||
* @return string
|
||||
*/
|
||||
public static function encode($data)
|
||||
{
|
||||
return self::_encodeYaml(0, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Service function for encoding YAML
|
||||
*
|
||||
* @param int $indent Current indent level
|
||||
* @param array $data Data to encode
|
||||
* @return string
|
||||
*/
|
||||
protected static function _encodeYaml($indent, $data)
|
||||
{
|
||||
reset($data);
|
||||
$result = "";
|
||||
$numeric = is_numeric(key($data));
|
||||
|
||||
foreach($data as $key => $value) {
|
||||
if(is_array($value)) {
|
||||
$encoded = "\n".self::_encodeYaml($indent+1, $value);
|
||||
} else {
|
||||
$encoded = (string)$value."\n";
|
||||
}
|
||||
$result .= str_repeat(" ", $indent).($numeric?"- ":"$key: ").$encoded;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
<?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_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_Config
|
||||
*/
|
||||
require_once 'Zend/Config.php';
|
||||
|
||||
/** @see Zend_Xml_Security */
|
||||
require_once 'Zend/Xml/Security.php';
|
||||
|
||||
/** @see Zend_Xml_Exception */
|
||||
require_once 'Zend/Xml/Exception.php';
|
||||
|
||||
/**
|
||||
* XML Adapter for Zend_Config
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Config
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Config_Xml extends Zend_Config
|
||||
{
|
||||
/**
|
||||
* XML namespace for ZF-related tags and attributes
|
||||
*/
|
||||
const XML_NAMESPACE = 'http://framework.zend.com/xml/zend-config-xml/1.0/';
|
||||
|
||||
/**
|
||||
* Whether to skip extends or not
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_skipExtends = false;
|
||||
|
||||
/**
|
||||
* Loads the section $section from the config file (or string $xml for
|
||||
* access facilitated by nested object properties.
|
||||
*
|
||||
* Sections are defined in the XML as children of the root element.
|
||||
*
|
||||
* In order to extend another section, a section defines the "extends"
|
||||
* attribute having a value of the section name from which the extending
|
||||
* section inherits values.
|
||||
*
|
||||
* Note that the keys in $section will override any keys of the same
|
||||
* name in the sections that have been included via "extends".
|
||||
*
|
||||
* The $options parameter may be provided as either a boolean or an array.
|
||||
* If provided as a boolean, this sets the $allowModifications option of
|
||||
* Zend_Config. If provided as an array, there are two configuration
|
||||
* directives that may be set. For example:
|
||||
*
|
||||
* $options = array(
|
||||
* 'allowModifications' => false,
|
||||
* 'skipExtends' => false
|
||||
* );
|
||||
*
|
||||
* @param string $xml XML file or string to process
|
||||
* @param mixed $section Section to process
|
||||
* @param array|boolean $options
|
||||
* @throws Zend_Config_Exception When xml is not set or cannot be loaded
|
||||
* @throws Zend_Config_Exception When section $sectionName cannot be found in $xml
|
||||
*/
|
||||
public function __construct($xml, $section = null, $options = false)
|
||||
{
|
||||
if (empty($xml)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception('Filename is not set');
|
||||
}
|
||||
|
||||
$allowModifications = false;
|
||||
if (is_bool($options)) {
|
||||
$allowModifications = $options;
|
||||
} elseif (is_array($options)) {
|
||||
if (isset($options['allowModifications'])) {
|
||||
$allowModifications = (bool) $options['allowModifications'];
|
||||
}
|
||||
if (isset($options['skipExtends'])) {
|
||||
$this->_skipExtends = (bool) $options['skipExtends'];
|
||||
}
|
||||
}
|
||||
|
||||
set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed
|
||||
if (strstr($xml, '<?xml')) {
|
||||
$config = Zend_Xml_Security::scan($xml);
|
||||
} else {
|
||||
try {
|
||||
if (!$config = Zend_Xml_Security::scanFile($xml)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception(
|
||||
"Error failed to load $xml file"
|
||||
);
|
||||
}
|
||||
} catch (Zend_Xml_Exception $e) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception(
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
restore_error_handler();
|
||||
// Check if there was a error while loading file
|
||||
if ($this->_loadFileErrorStr !== null) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception($this->_loadFileErrorStr);
|
||||
}
|
||||
|
||||
if ($section === null) {
|
||||
$dataArray = array();
|
||||
foreach ($config as $sectionName => $sectionData) {
|
||||
$dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
} else if (is_array($section)) {
|
||||
$dataArray = array();
|
||||
foreach ($section as $sectionName) {
|
||||
if (!isset($config->$sectionName)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $xml");
|
||||
}
|
||||
|
||||
$dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
} else {
|
||||
if (!isset($config->$section)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Section '$section' cannot be found in $xml");
|
||||
}
|
||||
|
||||
$dataArray = $this->_processExtends($config, $section);
|
||||
if (!is_array($dataArray)) {
|
||||
// Section in the XML file contains just one top level string
|
||||
$dataArray = array($section => $dataArray);
|
||||
}
|
||||
|
||||
parent::__construct($dataArray, $allowModifications);
|
||||
}
|
||||
|
||||
$this->_loadedSection = $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to process each element in the section and handle
|
||||
* the "extends" inheritance attribute.
|
||||
*
|
||||
* @param SimpleXMLElement $element XML Element to process
|
||||
* @param string $section Section to process
|
||||
* @param array $config Configuration which was parsed yet
|
||||
* @throws Zend_Config_Exception When $section cannot be found
|
||||
* @return array
|
||||
*/
|
||||
protected function _processExtends(SimpleXMLElement $element, $section, array $config = array())
|
||||
{
|
||||
if (!isset($element->$section)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Section '$section' cannot be found");
|
||||
}
|
||||
|
||||
$thisSection = $element->$section;
|
||||
$nsAttributes = $thisSection->attributes(self::XML_NAMESPACE);
|
||||
|
||||
if (isset($thisSection['extends']) || isset($nsAttributes['extends'])) {
|
||||
$extendedSection = (string) (isset($nsAttributes['extends']) ? $nsAttributes['extends'] : $thisSection['extends']);
|
||||
$this->_assertValidExtend($section, $extendedSection);
|
||||
|
||||
if (!$this->_skipExtends) {
|
||||
$config = $this->_processExtends($element, $extendedSection, $config);
|
||||
}
|
||||
}
|
||||
|
||||
$config = $this->_arrayMergeRecursive($config, $this->_toArray($thisSection));
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string or an associative and possibly multidimensional array from
|
||||
* a SimpleXMLElement.
|
||||
*
|
||||
* @param SimpleXMLElement $xmlObject Convert a SimpleXMLElement into an array
|
||||
* @return array|string
|
||||
*/
|
||||
protected function _toArray(SimpleXMLElement $xmlObject)
|
||||
{
|
||||
$config = array();
|
||||
$nsAttributes = $xmlObject->attributes(self::XML_NAMESPACE);
|
||||
|
||||
// Search for parent node values
|
||||
if (count($xmlObject->attributes()) > 0) {
|
||||
foreach ($xmlObject->attributes() as $key => $value) {
|
||||
if ($key === 'extends') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = (string) $value;
|
||||
|
||||
if (array_key_exists($key, $config)) {
|
||||
if (!is_array($config[$key])) {
|
||||
$config[$key] = array($config[$key]);
|
||||
}
|
||||
|
||||
$config[$key][] = $value;
|
||||
} else {
|
||||
$config[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search for local 'const' nodes and replace them
|
||||
if (count($xmlObject->children(self::XML_NAMESPACE)) > 0) {
|
||||
if (count($xmlObject->children()) > 0) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("A node with a 'const' childnode may not have any other children");
|
||||
}
|
||||
|
||||
$dom = dom_import_simplexml($xmlObject);
|
||||
$namespaceChildNodes = array();
|
||||
|
||||
// We have to store them in an array, as replacing nodes will
|
||||
// confuse the DOMNodeList later
|
||||
foreach ($dom->childNodes as $node) {
|
||||
if ($node instanceof DOMElement && $node->namespaceURI === self::XML_NAMESPACE) {
|
||||
$namespaceChildNodes[] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($namespaceChildNodes as $node) {
|
||||
switch ($node->localName) {
|
||||
case 'const':
|
||||
if (!$node->hasAttributeNS(self::XML_NAMESPACE, 'name')) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Misssing 'name' attribute in 'const' node");
|
||||
}
|
||||
|
||||
$constantName = $node->getAttributeNS(self::XML_NAMESPACE, 'name');
|
||||
|
||||
if (!defined($constantName)) {
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Constant with name '$constantName' was not defined");
|
||||
}
|
||||
|
||||
$constantValue = constant($constantName);
|
||||
|
||||
$dom->replaceChild($dom->ownerDocument->createTextNode($constantValue), $node);
|
||||
break;
|
||||
|
||||
default:
|
||||
require_once 'Zend/Config/Exception.php';
|
||||
throw new Zend_Config_Exception("Unknown node with name '$node->localName' found");
|
||||
}
|
||||
}
|
||||
|
||||
return (string) simplexml_import_dom($dom);
|
||||
}
|
||||
|
||||
// Search for children
|
||||
if (count($xmlObject->children()) > 0) {
|
||||
foreach ($xmlObject->children() as $key => $value) {
|
||||
if (count($value->children()) > 0 || count($value->children(self::XML_NAMESPACE)) > 0) {
|
||||
$value = $this->_toArray($value);
|
||||
} else if (count($value->attributes()) > 0) {
|
||||
$attributes = $value->attributes();
|
||||
if (isset($attributes['value'])) {
|
||||
$value = (string) $attributes['value'];
|
||||
} else {
|
||||
$value = $this->_toArray($value);
|
||||
}
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $config)) {
|
||||
if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) {
|
||||
$config[$key] = array($config[$key]);
|
||||
}
|
||||
|
||||
$config[$key][] = $value;
|
||||
} else {
|
||||
$config[$key] = $value;
|
||||
}
|
||||
}
|
||||
} else if (!isset($xmlObject['extends']) && !isset($nsAttributes['extends']) && (count($config) === 0)) {
|
||||
// Object has no children nor attributes and doesn't use the extends
|
||||
// attribute: it's a string
|
||||
$config = (string) $xmlObject;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user