Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Cache
  • OutputHelper

Interfaces

  • IStorage
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Caching;
  9: 
 10: use Nette;
 11: use Nette\Utils\Callback;
 12: 
 13: 
 14: /**
 15:  * Implements the cache for a application.
 16:  */
 17: class Cache extends Nette\Object implements \ArrayAccess
 18: {
 19:     /** dependency */
 20:     const PRIORITY = 'priority',
 21:         EXPIRATION = 'expire',
 22:         EXPIRE = 'expire',
 23:         SLIDING = 'sliding',
 24:         TAGS = 'tags',
 25:         FILES = 'files',
 26:         ITEMS = 'items',
 27:         CONSTS = 'consts',
 28:         CALLBACKS = 'callbacks',
 29:         ALL = 'all';
 30: 
 31:     /** @internal */
 32:     const NAMESPACE_SEPARATOR = "\x00";
 33: 
 34:     /** @var IStorage */
 35:     private $storage;
 36: 
 37:     /** @var string */
 38:     private $namespace;
 39: 
 40:     /** @var string  last query cache used by offsetGet() */
 41:     private $key;
 42: 
 43:     /** @var mixed  last query cache used by offsetGet()  */
 44:     private $data;
 45: 
 46: 
 47:     public function __construct(IStorage $storage, $namespace = NULL)
 48:     {
 49:         $this->storage = $storage;
 50:         $this->namespace = $namespace . self::NAMESPACE_SEPARATOR;
 51:     }
 52: 
 53: 
 54:     /**
 55:      * Returns cache storage.
 56:      * @return IStorage
 57:      */
 58:     public function getStorage()
 59:     {
 60:         return $this->storage;
 61:     }
 62: 
 63: 
 64:     /**
 65:      * Returns cache namespace.
 66:      * @return string
 67:      */
 68:     public function getNamespace()
 69:     {
 70:         return (string) substr($this->namespace, 0, -1);
 71:     }
 72: 
 73: 
 74:     /**
 75:      * Returns new nested cache object.
 76:      * @param  string
 77:      * @return self
 78:      */
 79:     public function derive($namespace)
 80:     {
 81:         $derived = new static($this->storage, $this->namespace . $namespace);
 82:         return $derived;
 83:     }
 84: 
 85: 
 86:     /**
 87:      * Reads the specified item from the cache or generate it.
 88:      * @param  mixed key
 89:      * @param  callable
 90:      * @return mixed|NULL
 91:      */
 92:     public function load($key, $fallback = NULL)
 93:     {
 94:         $data = $this->storage->read($this->generateKey($key));
 95:         if ($data === NULL && $fallback) {
 96:             return $this->save($key, function (& $dependencies) use ($fallback) {
 97:                 return call_user_func_array($fallback, array(& $dependencies));
 98:             });
 99:         }
100:         return $data;
101:     }
102: 
103: 
104:     /**
105:      * Writes item into the cache.
106:      * Dependencies are:
107:      * - Cache::PRIORITY => (int) priority
108:      * - Cache::EXPIRATION => (timestamp) expiration
109:      * - Cache::SLIDING => (bool) use sliding expiration?
110:      * - Cache::TAGS => (array) tags
111:      * - Cache::FILES => (array|string) file names
112:      * - Cache::ITEMS => (array|string) cache items
113:      * - Cache::CONSTS => (array|string) cache items
114:      *
115:      * @param  mixed  key
116:      * @param  mixed  value
117:      * @param  array  dependencies
118:      * @return mixed  value itself
119:      * @throws Nette\InvalidArgumentException
120:      */
121:     public function save($key, $data, array $dependencies = NULL)
122:     {
123:         $this->key = $this->data = NULL;
124:         $key = $this->generateKey($key);
125: 
126:         if ($data instanceof Nette\Callback || $data instanceof \Closure) {
127:             $this->storage->lock($key);
128:             try {
129:                 $data = call_user_func_array($data, array(& $dependencies));
130:             } catch (\Throwable $e) {
131:                 $this->storage->remove($key);
132:                 throw $e;
133:             } catch (\Exception $e) {
134:                 $this->storage->remove($key);
135:                 throw $e;
136:             }
137:         }
138: 
139:         if ($data === NULL) {
140:             $this->storage->remove($key);
141:         } else {
142:             $this->storage->write($key, $data, $this->completeDependencies($dependencies, $data));
143:             return $data;
144:         }
145:     }
146: 
147: 
148:     private function completeDependencies($dp, $data)
149:     {
150:         // convert expire into relative amount of seconds
151:         if (isset($dp[self::EXPIRATION])) {
152:             $dp[self::EXPIRATION] = Nette\Utils\DateTime::from($dp[self::EXPIRATION])->format('U') - time();
153:         }
154: 
155:         // convert FILES into CALLBACKS
156:         if (isset($dp[self::FILES])) {
157:             foreach (array_unique((array) $dp[self::FILES]) as $item) {
158:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkFile'), $item, @filemtime($item)); // @ - stat may fail
159:             }
160:             unset($dp[self::FILES]);
161:         }
162: 
163:         // add namespaces to items
164:         if (isset($dp[self::ITEMS])) {
165:             $dp[self::ITEMS] = array_unique(array_map(array($this, 'generateKey'), (array) $dp[self::ITEMS]));
166:         }
167: 
168:         // convert CONSTS into CALLBACKS
169:         if (isset($dp[self::CONSTS])) {
170:             foreach (array_unique((array) $dp[self::CONSTS]) as $item) {
171:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkConst'), $item, constant($item));
172:             }
173:             unset($dp[self::CONSTS]);
174:         }
175: 
176:         if (!is_array($dp)) {
177:             $dp = array();
178:         }
179:         return $dp;
180:     }
181: 
182: 
183:     /**
184:      * Removes item from the cache.
185:      * @param  mixed  key
186:      * @return void
187:      */
188:     public function remove($key)
189:     {
190:         $this->save($key, NULL);
191:     }
192: 
193: 
194:     /**
195:      * Removes items from the cache by conditions.
196:      * Conditions are:
197:      * - Cache::PRIORITY => (int) priority
198:      * - Cache::TAGS => (array) tags
199:      * - Cache::ALL => TRUE
200:      * @return void
201:      */
202:     public function clean(array $conditions = NULL)
203:     {
204:         $this->key = $this->data = NULL;
205:         $this->storage->clean((array) $conditions);
206:     }
207: 
208: 
209:     /**
210:      * Caches results of function/method calls.
211:      * @param  mixed
212:      * @return mixed
213:      */
214:     public function call($function)
215:     {
216:         $key = func_get_args();
217:         if (is_array($function) && is_object($function[0])) {
218:             $key[0][0] = get_class($function[0]);
219:         }
220:         return $this->load($key, function () use ($function, $key) {
221:             return Callback::invokeArgs($function, array_slice($key, 1));
222:         });
223:     }
224: 
225: 
226:     /**
227:      * Caches results of function/method calls.
228:      * @param  mixed
229:      * @param  array  dependencies
230:      * @return \Closure
231:      */
232:     public function wrap($function, array $dependencies = NULL)
233:     {
234:         $cache = $this;
235:         return function () use ($cache, $function, $dependencies) {
236:             $key = array($function, func_get_args());
237:             if (is_array($function) && is_object($function[0])) {
238:                 $key[0][0] = get_class($function[0]);
239:             }
240:             $data = $cache->load($key);
241:             if ($data === NULL) {
242:                 $data = $cache->save($key, Callback::invokeArgs($function, $key[1]), $dependencies);
243:             }
244:             return $data;
245:         };
246:     }
247: 
248: 
249:     /**
250:      * Starts the output cache.
251:      * @param  mixed  key
252:      * @return OutputHelper|NULL
253:      */
254:     public function start($key)
255:     {
256:         $data = $this->load($key);
257:         if ($data === NULL) {
258:             return new OutputHelper($this, $key);
259:         }
260:         echo $data;
261:     }
262: 
263: 
264:     /**
265:      * Generates internal cache key.
266:      *
267:      * @param  string
268:      * @return string
269:      */
270:     protected function generateKey($key)
271:     {
272:         return $this->namespace . md5(is_scalar($key) ? $key : serialize($key));
273:     }
274: 
275: 
276:     /********************* interface ArrayAccess ****************d*g**/
277: 
278: 
279:     /**
280:      * @deprecated
281:      */
282:     public function offsetSet($key, $data)
283:     {
284:         trigger_error('Using [] is deprecated; use Cache::save(key, data) instead.', E_USER_DEPRECATED);
285:         $this->save($key, $data);
286:     }
287: 
288: 
289:     /**
290:      * @deprecated
291:      */
292:     public function offsetGet($key)
293:     {
294:         trigger_error('Using [] is deprecated; use Cache::load(key) instead.', E_USER_DEPRECATED);
295:         $key = is_scalar($key) ? (string) $key : serialize($key);
296:         if ($this->key !== $key) {
297:             $this->key = $key;
298:             $this->data = $this->load($key);
299:         }
300:         return $this->data;
301:     }
302: 
303: 
304:     /**
305:      * @deprecated
306:      */
307:     public function offsetExists($key)
308:     {
309:         trigger_error('Using [] is deprecated; use Cache::load(key) !== NULL instead.', E_USER_DEPRECATED);
310:         $this->key = $this->data = NULL;
311:         return $this->offsetGet($key) !== NULL;
312:     }
313: 
314: 
315:     /**
316:      * @deprecated
317:      */
318:     public function offsetUnset($key)
319:     {
320:         trigger_error('Using [] is deprecated; use Cache::remove(key) instead.', E_USER_DEPRECATED);
321:         $this->save($key, NULL);
322:     }
323: 
324: 
325:     /**
326:      * @deprecated
327:      */
328:     public function release()
329:     {
330:         trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED);
331:         $this->key = $this->data = NULL;
332:     }
333: 
334: 
335:     /********************* dependency checkers ****************d*g**/
336: 
337: 
338:     /**
339:      * Checks CALLBACKS dependencies.
340:      * @param  array
341:      * @return bool
342:      */
343:     public static function checkCallbacks($callbacks)
344:     {
345:         foreach ($callbacks as $callback) {
346:             if (!call_user_func_array(array_shift($callback), $callback)) {
347:                 return FALSE;
348:             }
349:         }
350:         return TRUE;
351:     }
352: 
353: 
354:     /**
355:      * Checks CONSTS dependency.
356:      * @param  string
357:      * @param  mixed
358:      * @return bool
359:      */
360:     private static function checkConst($const, $value)
361:     {
362:         return defined($const) && constant($const) === $value;
363:     }
364: 
365: 
366:     /**
367:      * Checks FILES dependency.
368:      * @param  string
369:      * @param  int
370:      * @return bool
371:      */
372:     private static function checkFile($file, $time)
373:     {
374:         return @filemtime($file) == $time; // @ - stat may fail
375:     }
376: 
377: }
378: 
Nette 2.3-20161221 API API documentation generated by ApiGen 2.8.0