PageRenderTime 40ms CodeModel.GetById 32ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Cache/Pattern/ObjectCache.php

http://github.com/zendframework/zf2
PHP | 284 lines | 133 code | 31 blank | 120 comment | 20 complexity | 60a25632e1ff476532545af53b3c6bb8 MD5 | raw file
  1<?php
  2/**
  3 * Zend Framework (http://framework.zend.com/)
  4 *
  5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
  6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7 * @license   http://framework.zend.com/license/new-bsd New BSD License
  8 */
  9
 10namespace Zend\Cache\Pattern;
 11
 12use Zend\Cache\Exception;
 13
 14class ObjectCache extends CallbackCache
 15{
 16    /**
 17     * Set options
 18     *
 19     * @param  PatternOptions $options
 20     * @return void
 21     * @throws Exception\InvalidArgumentException
 22     */
 23    public function setOptions(PatternOptions $options)
 24    {
 25        parent::setOptions($options);
 26
 27        if (!$options->getObject()) {
 28            throw new Exception\InvalidArgumentException("Missing option 'object'");
 29        } elseif (!$options->getStorage()) {
 30            throw new Exception\InvalidArgumentException("Missing option 'storage'");
 31        }
 32    }
 33
 34    /**
 35     * Call and cache a class method
 36     *
 37     * @param  string $method  Method name to call
 38     * @param  array  $args    Method arguments
 39     * @return mixed
 40     * @throws Exception\RuntimeException
 41     * @throws \Exception
 42     */
 43    public function call($method, array $args = array())
 44    {
 45        $options = $this->getOptions();
 46        $object  = $options->getObject();
 47        $method  = strtolower($method);
 48
 49        // handle magic methods
 50        switch ($method) {
 51            case '__set':
 52                $property = array_shift($args);
 53                $value    = array_shift($args);
 54
 55                $object->{$property} = $value;
 56
 57                if (!$options->getObjectCacheMagicProperties()
 58                    || property_exists($object, $property)
 59                ) {
 60                    // no caching if property isn't magic
 61                    // or caching magic properties is disabled
 62                    return;
 63                }
 64
 65                // remove cached __get and __isset
 66                $removeKeys = null;
 67                if (method_exists($object, '__get')) {
 68                    $removeKeys[] = $this->generateKey('__get', array($property));
 69                }
 70                if (method_exists($object, '__isset')) {
 71                    $removeKeys[] = $this->generateKey('__isset', array($property));
 72                }
 73                if ($removeKeys) {
 74                    $options->getStorage()->removeItems($removeKeys);
 75                }
 76                return;
 77
 78            case '__get':
 79                $property = array_shift($args);
 80
 81                if (!$options->getObjectCacheMagicProperties()
 82                    || property_exists($object, $property)
 83                ) {
 84                    // no caching if property isn't magic
 85                    // or caching magic properties is disabled
 86                    return $object->{$property};
 87                }
 88
 89                array_unshift($args, $property);
 90                return parent::call(array($object, '__get'), $args);
 91
 92            case '__isset':
 93                $property = array_shift($args);
 94
 95                if (!$options->getObjectCacheMagicProperties()
 96                    || property_exists($object, $property)
 97                ) {
 98                    // no caching if property isn't magic
 99                    // or caching magic properties is disabled
100                    return isset($object->{$property});
101                }
102
103                return parent::call(array($object, '__isset'), array($property));
104
105            case '__unset':
106                $property = array_shift($args);
107
108                unset($object->{$property});
109
110                if (!$options->getObjectCacheMagicProperties()
111                    || property_exists($object, $property)
112                ) {
113                    // no caching if property isn't magic
114                    // or caching magic properties is disabled
115                    return;
116                }
117
118                // remove previous cached __get and __isset calls
119                $removeKeys = null;
120                if (method_exists($object, '__get')) {
121                    $removeKeys[] = $this->generateKey('__get', array($property));
122                }
123                if (method_exists($object, '__isset')) {
124                    $removeKeys[] = $this->generateKey('__isset', array($property));
125                }
126                if ($removeKeys) {
127                    $options->getStorage()->removeItems($removeKeys);
128                }
129                return;
130        }
131
132        $cache = $options->getCacheByDefault();
133        if ($cache) {
134            $cache = !in_array($method, $options->getObjectNonCacheMethods());
135        } else {
136            $cache = in_array($method, $options->getObjectCacheMethods());
137        }
138
139        if (!$cache) {
140            if ($args) {
141                return call_user_func_array(array($object, $method), $args);
142            }
143            return $object->{$method}();
144        }
145
146        return parent::call(array($object, $method), $args);
147    }
148
149    /**
150     * Generate a unique key in base of a key representing the callback part
151     * and a key representing the arguments part.
152     *
153     * @param  string     $method  The method
154     * @param  array      $args    Callback arguments
155     * @return string
156     * @throws Exception\RuntimeException
157     */
158    public function generateKey($method, array $args = array())
159    {
160        return $this->generateCallbackKey(
161            array($this->getOptions()->getObject(), $method),
162            $args
163        );
164    }
165
166    /**
167     * Generate a unique key in base of a key representing the callback part
168     * and a key representing the arguments part.
169     *
170     * @param  callable   $callback  A valid callback
171     * @param  array      $args      Callback arguments
172     * @return string
173     * @throws Exception\RuntimeException
174     */
175    protected function generateCallbackKey($callback, array $args = array())
176    {
177        $callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1]));
178        $argumentKey = $this->generateArgumentsKey($args);
179        return $callbackKey . $argumentKey;
180    }
181
182    /**
183     * Class method call handler
184     *
185     * @param  string $method  Method name to call
186     * @param  array  $args    Method arguments
187     * @return mixed
188     * @throws Exception\RuntimeException
189     * @throws \Exception
190     */
191    public function __call($method, array $args)
192    {
193        return $this->call($method, $args);
194    }
195
196    /**
197     * Writing data to properties.
198     *
199     * NOTE:
200     * Magic properties will be cached too if the option cacheMagicProperties
201     * is enabled and the property doesn't exist in real. If so it calls __set
202     * and removes cached data of previous __get and __isset calls.
203     *
204     * @param  string $name
205     * @param  mixed  $value
206     * @return void
207     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
208     */
209    public function __set($name, $value)
210    {
211        return $this->call('__set', array($name, $value));
212    }
213
214    /**
215     * Reading data from properties.
216     *
217     * NOTE:
218     * Magic properties will be cached too if the option cacheMagicProperties
219     * is enabled and the property doesn't exist in real. If so it calls __get.
220     *
221     * @param  string $name
222     * @return mixed
223     * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
224     */
225    public function __get($name)
226    {
227        return $this->call('__get', array($name));
228    }
229
230    /**
231     * Checking existing properties.
232     *
233     * NOTE:
234     * Magic properties will be cached too if the option cacheMagicProperties
235     * is enabled and the property doesn't exist in real. If so it calls __get.
236     *
237     * @param  string $name
238     * @return bool
239     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
240     */
241    public function __isset($name)
242    {
243        return $this->call('__isset', array($name));
244    }
245
246    /**
247     * Unseting a property.
248     *
249     * NOTE:
250     * Magic properties will be cached too if the option cacheMagicProperties
251     * is enabled and the property doesn't exist in real. If so it removes
252     * previous cached __isset and __get calls.
253     *
254     * @param  string $name
255     * @return void
256     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
257     */
258    public function __unset($name)
259    {
260        return $this->call('__unset', array($name));
261    }
262
263    /**
264     * Handle casting to string
265     *
266     * @return string
267     * @see    http://php.net/manual/language.oop5.magic.php#language.oop5.magic.tostring
268     */
269    public function __toString()
270    {
271        return $this->call('__toString');
272    }
273
274    /**
275     * Handle invoke calls
276     *
277     * @return mixed
278     * @see    http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke
279     */
280    public function __invoke()
281    {
282        return $this->call('__invoke', func_get_args());
283    }
284}