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