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
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Cache
  • OutputHelper

Interfaces

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