2023-03-11 12:04:29 +03:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Zend Framework (http://framework.zend.com/)
|
|
|
|
*
|
|
|
|
* @link http://github.com/zendframework/zf2 for the canonical source repository
|
2023-04-01 09:03:34 +03:00
|
|
|
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
2023-03-11 12:04:29 +03:00
|
|
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Zend\Cache\Pattern;
|
|
|
|
|
|
|
|
use Zend\Cache\Exception;
|
|
|
|
|
|
|
|
class ObjectCache extends CallbackCache
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Set options
|
|
|
|
*
|
|
|
|
* @param PatternOptions $options
|
|
|
|
* @return void
|
|
|
|
* @throws Exception\InvalidArgumentException
|
|
|
|
*/
|
|
|
|
public function setOptions(PatternOptions $options)
|
|
|
|
{
|
|
|
|
parent::setOptions($options);
|
|
|
|
|
|
|
|
if (!$options->getObject()) {
|
|
|
|
throw new Exception\InvalidArgumentException("Missing option 'object'");
|
|
|
|
} elseif (!$options->getStorage()) {
|
|
|
|
throw new Exception\InvalidArgumentException("Missing option 'storage'");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call and cache a class method
|
|
|
|
*
|
|
|
|
* @param string $method Method name to call
|
|
|
|
* @param array $args Method arguments
|
|
|
|
* @return mixed
|
|
|
|
* @throws Exception\RuntimeException
|
|
|
|
* @throws \Exception
|
|
|
|
*/
|
|
|
|
public function call($method, array $args = array())
|
|
|
|
{
|
|
|
|
$options = $this->getOptions();
|
|
|
|
$object = $options->getObject();
|
|
|
|
$method = strtolower($method);
|
|
|
|
|
|
|
|
// handle magic methods
|
|
|
|
switch ($method) {
|
|
|
|
case '__set':
|
|
|
|
$property = array_shift($args);
|
|
|
|
$value = array_shift($args);
|
|
|
|
|
|
|
|
$object->{$property} = $value;
|
|
|
|
|
|
|
|
if (!$options->getObjectCacheMagicProperties()
|
|
|
|
|| property_exists($object, $property)
|
|
|
|
) {
|
|
|
|
// no caching if property isn't magic
|
|
|
|
// or caching magic properties is disabled
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove cached __get and __isset
|
|
|
|
$removeKeys = null;
|
|
|
|
if (method_exists($object, '__get')) {
|
|
|
|
$removeKeys[] = $this->generateKey('__get', array($property));
|
|
|
|
}
|
|
|
|
if (method_exists($object, '__isset')) {
|
|
|
|
$removeKeys[] = $this->generateKey('__isset', array($property));
|
|
|
|
}
|
|
|
|
if ($removeKeys) {
|
|
|
|
$options->getStorage()->removeItems($removeKeys);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
case '__get':
|
|
|
|
$property = array_shift($args);
|
|
|
|
|
|
|
|
if (!$options->getObjectCacheMagicProperties()
|
|
|
|
|| property_exists($object, $property)
|
|
|
|
) {
|
|
|
|
// no caching if property isn't magic
|
|
|
|
// or caching magic properties is disabled
|
|
|
|
return $object->{$property};
|
|
|
|
}
|
|
|
|
|
|
|
|
array_unshift($args, $property);
|
|
|
|
return parent::call(array($object, '__get'), $args);
|
|
|
|
|
|
|
|
case '__isset':
|
|
|
|
$property = array_shift($args);
|
|
|
|
|
|
|
|
if (!$options->getObjectCacheMagicProperties()
|
|
|
|
|| property_exists($object, $property)
|
|
|
|
) {
|
|
|
|
// no caching if property isn't magic
|
|
|
|
// or caching magic properties is disabled
|
|
|
|
return isset($object->{$property});
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::call(array($object, '__isset'), array($property));
|
|
|
|
|
|
|
|
case '__unset':
|
|
|
|
$property = array_shift($args);
|
|
|
|
|
|
|
|
unset($object->{$property});
|
|
|
|
|
|
|
|
if (!$options->getObjectCacheMagicProperties()
|
|
|
|
|| property_exists($object, $property)
|
|
|
|
) {
|
|
|
|
// no caching if property isn't magic
|
|
|
|
// or caching magic properties is disabled
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove previous cached __get and __isset calls
|
|
|
|
$removeKeys = null;
|
|
|
|
if (method_exists($object, '__get')) {
|
|
|
|
$removeKeys[] = $this->generateKey('__get', array($property));
|
|
|
|
}
|
|
|
|
if (method_exists($object, '__isset')) {
|
|
|
|
$removeKeys[] = $this->generateKey('__isset', array($property));
|
|
|
|
}
|
|
|
|
if ($removeKeys) {
|
|
|
|
$options->getStorage()->removeItems($removeKeys);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$cache = $options->getCacheByDefault();
|
|
|
|
if ($cache) {
|
|
|
|
$cache = !in_array($method, $options->getObjectNonCacheMethods());
|
|
|
|
} else {
|
|
|
|
$cache = in_array($method, $options->getObjectCacheMethods());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$cache) {
|
|
|
|
if ($args) {
|
|
|
|
return call_user_func_array(array($object, $method), $args);
|
|
|
|
}
|
|
|
|
return $object->{$method}();
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::call(array($object, $method), $args);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a unique key in base of a key representing the callback part
|
|
|
|
* and a key representing the arguments part.
|
|
|
|
*
|
|
|
|
* @param string $method The method
|
|
|
|
* @param array $args Callback arguments
|
|
|
|
* @return string
|
|
|
|
* @throws Exception\RuntimeException
|
|
|
|
*/
|
|
|
|
public function generateKey($method, array $args = array())
|
|
|
|
{
|
|
|
|
return $this->generateCallbackKey(
|
|
|
|
array($this->getOptions()->getObject(), $method),
|
|
|
|
$args
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a unique key in base of a key representing the callback part
|
|
|
|
* and a key representing the arguments part.
|
|
|
|
*
|
|
|
|
* @param callable $callback A valid callback
|
|
|
|
* @param array $args Callback arguments
|
|
|
|
* @return string
|
|
|
|
* @throws Exception\RuntimeException
|
|
|
|
*/
|
|
|
|
protected function generateCallbackKey($callback, array $args = array())
|
|
|
|
{
|
|
|
|
$callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1]));
|
|
|
|
$argumentKey = $this->generateArgumentsKey($args);
|
|
|
|
return $callbackKey . $argumentKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class method call handler
|
|
|
|
*
|
|
|
|
* @param string $method Method name to call
|
|
|
|
* @param array $args Method arguments
|
|
|
|
* @return mixed
|
|
|
|
* @throws Exception\RuntimeException
|
|
|
|
* @throws \Exception
|
|
|
|
*/
|
|
|
|
public function __call($method, array $args)
|
|
|
|
{
|
|
|
|
return $this->call($method, $args);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writing data to properties.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* Magic properties will be cached too if the option cacheMagicProperties
|
|
|
|
* is enabled and the property doesn't exist in real. If so it calls __set
|
|
|
|
* and removes cached data of previous __get and __isset calls.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $value
|
|
|
|
* @return void
|
|
|
|
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
|
|
|
*/
|
|
|
|
public function __set($name, $value)
|
|
|
|
{
|
|
|
|
return $this->call('__set', array($name, $value));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reading data from properties.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* Magic properties will be cached too if the option cacheMagicProperties
|
|
|
|
* is enabled and the property doesn't exist in real. If so it calls __get.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @return mixed
|
|
|
|
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
|
|
|
*/
|
|
|
|
public function __get($name)
|
|
|
|
{
|
|
|
|
return $this->call('__get', array($name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checking existing properties.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* Magic properties will be cached too if the option cacheMagicProperties
|
|
|
|
* is enabled and the property doesn't exist in real. If so it calls __get.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @return bool
|
|
|
|
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
|
|
|
*/
|
|
|
|
public function __isset($name)
|
|
|
|
{
|
|
|
|
return $this->call('__isset', array($name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unseting a property.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* Magic properties will be cached too if the option cacheMagicProperties
|
|
|
|
* is enabled and the property doesn't exist in real. If so it removes
|
|
|
|
* previous cached __isset and __get calls.
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @return void
|
|
|
|
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
|
|
|
*/
|
|
|
|
public function __unset($name)
|
|
|
|
{
|
|
|
|
return $this->call('__unset', array($name));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle casting to string
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
* @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.tostring
|
|
|
|
*/
|
|
|
|
public function __toString()
|
|
|
|
{
|
|
|
|
return $this->call('__toString');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle invoke calls
|
|
|
|
*
|
|
|
|
* @return mixed
|
|
|
|
* @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke
|
|
|
|
*/
|
|
|
|
public function __invoke()
|
|
|
|
{
|
|
|
|
return $this->call('__invoke', func_get_args());
|
|
|
|
}
|
|
|
|
}
|