Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

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: 
 12: 
 13: /**
 14:  * Implements the cache for a application.
 15:  *
 16:  * @author     David Grudl
 17:  *
 18:  * @property-read IStorage $storage
 19:  * @property-read string $namespace
 20:  */
 21: class Cache extends Nette\Object implements \ArrayAccess
 22: {
 23:     /** dependency */
 24:     const PRIORITY = 'priority',
 25:         EXPIRATION = 'expire',
 26:         EXPIRE = 'expire',
 27:         SLIDING = 'sliding',
 28:         TAGS = 'tags',
 29:         FILES = 'files',
 30:         ITEMS = 'items',
 31:         CONSTS = 'consts',
 32:         CALLBACKS = 'callbacks',
 33:         ALL = 'all';
 34: 
 35:     /** @internal */
 36:     const NAMESPACE_SEPARATOR = "\x00";
 37: 
 38:     /** @var IStorage */
 39:     private $storage;
 40: 
 41:     /** @var string */
 42:     private $namespace;
 43: 
 44:     /** @var string  last query cache used by offsetGet() */
 45:     private $key;
 46: 
 47:     /** @var mixed  last query cache used by offsetGet()  */
 48:     private $data;
 49: 
 50: 
 51:     public function __construct(IStorage $storage, $namespace = NULL)
 52:     {
 53:         $this->storage = $storage;
 54:         $this->namespace = $namespace . self::NAMESPACE_SEPARATOR;
 55:     }
 56: 
 57: 
 58:     /**
 59:      * Returns cache storage.
 60:      * @return IStorage
 61:      */
 62:     public function getStorage()
 63:     {
 64:         return $this->storage;
 65:     }
 66: 
 67: 
 68:     /**
 69:      * Returns cache namespace.
 70:      * @return string
 71:      */
 72:     public function getNamespace()
 73:     {
 74:         return (string) substr($this->namespace, 0, -1);
 75:     }
 76: 
 77: 
 78:     /**
 79:      * Returns new nested cache object.
 80:      * @param  string
 81:      * @return Cache
 82:      */
 83:     public function derive($namespace)
 84:     {
 85:         $derived = new static($this->storage, $this->namespace . $namespace);
 86:         return $derived;
 87:     }
 88: 
 89: 
 90:     /**
 91:      * Reads the specified item from the cache or generate it.
 92:      * @param  mixed key
 93:      * @param  callable
 94:      * @return mixed|NULL
 95:      */
 96:     public function load($key, $fallback = NULL)
 97:     {
 98:         $data = $this->storage->read($this->generateKey($key));
 99:         if ($data === NULL && $fallback) {
100:             return $this->save($key, new Nette\Callback($fallback));
101:         }
102:         return $data;
103:     }
104: 
105: 
106:     /**
107:      * Writes item into the cache.
108:      * Dependencies are:
109:      * - Cache::PRIORITY => (int) priority
110:      * - Cache::EXPIRATION => (timestamp) expiration
111:      * - Cache::SLIDING => (bool) use sliding expiration?
112:      * - Cache::TAGS => (array) tags
113:      * - Cache::FILES => (array|string) file names
114:      * - Cache::ITEMS => (array|string) cache items
115:      * - Cache::CONSTS => (array|string) cache items
116:      *
117:      * @param  mixed  key
118:      * @param  mixed  value
119:      * @param  array  dependencies
120:      * @return mixed  value itself
121:      * @throws Nette\InvalidArgumentException
122:      */
123:     public function save($key, $data, array $dependencies = NULL)
124:     {
125:         $this->release();
126:         $key = $this->generateKey($key);
127: 
128:         if ($data instanceof Nette\Callback || $data instanceof \Closure) {
129:             $this->storage->lock($key);
130:             $data = Nette\Callback::create($data)->invokeArgs(array(& $dependencies));
131:         }
132: 
133:         if ($data === NULL) {
134:             $this->storage->remove($key);
135:         } else {
136:             $this->storage->write($key, $data, $this->completeDependencies($dependencies, $data));
137:             return $data;
138:         }
139:     }
140: 
141: 
142:     private function completeDependencies($dp, $data)
143:     {
144:         if (is_object($data)) {
145:             $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkSerializationVersion'), get_class($data),
146:                 Nette\Reflection\ClassType::from($data)->getAnnotation('serializationVersion'));
147:         }
148: 
149:         // convert expire into relative amount of seconds
150:         if (isset($dp[Cache::EXPIRATION])) {
151:             $dp[Cache::EXPIRATION] = Nette\DateTime::from($dp[Cache::EXPIRATION])->format('U') - time();
152:         }
153: 
154:         // convert FILES into CALLBACKS
155:         if (isset($dp[self::FILES])) {
156:             //clearstatcache();
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->release();
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:         return $this->load($key, function() use ($function, $key) {
218:             return Nette\Callback::create($function)->invokeArgs(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:             $data = $cache->load($key);
235:             if ($data === NULL) {
236:                 $data = $cache->save($key, Nette\Callback::create($function)->invokeArgs($key[1]), $dependencies);
237:             }
238:             return $data;
239:         };
240:     }
241: 
242: 
243:     /**
244:      * Starts the output cache.
245:      * @param  mixed  key
246:      * @return OutputHelper|NULL
247:      */
248:     public function start($key)
249:     {
250:         $data = $this->load($key);
251:         if ($data === NULL) {
252:             return new OutputHelper($this, $key);
253:         }
254:         echo $data;
255:     }
256: 
257: 
258:     /**
259:      * Generates internal cache key.
260:      *
261:      * @param  string
262:      * @return string
263:      */
264:     protected function generateKey($key)
265:     {
266:         return $this->namespace . md5(is_scalar($key) ? $key : serialize($key));
267:     }
268: 
269: 
270:     /********************* interface ArrayAccess ****************d*g**/
271: 
272: 
273:     /**
274:      * Inserts (replaces) item into the cache (\ArrayAccess implementation).
275:      * @param  mixed key
276:      * @param  mixed
277:      * @return void
278:      * @throws Nette\InvalidArgumentException
279:      */
280:     public function offsetSet($key, $data)
281:     {
282:         $this->save($key, $data);
283:     }
284: 
285: 
286:     /**
287:      * Retrieves the specified item from the cache or NULL if the key is not found (\ArrayAccess implementation).
288:      * @param  mixed key
289:      * @return mixed|NULL
290:      * @throws Nette\InvalidArgumentException
291:      */
292:     public function offsetGet($key)
293:     {
294:         $key = is_scalar($key) ? (string) $key : serialize($key);
295:         if ($this->key !== $key) {
296:             $this->key = $key;
297:             $this->data = $this->load($key);
298:         }
299:         return $this->data;
300:     }
301: 
302: 
303:     /**
304:      * Exists item in cache? (\ArrayAccess implementation).
305:      * @param  mixed key
306:      * @return bool
307:      * @throws Nette\InvalidArgumentException
308:      */
309:     public function offsetExists($key)
310:     {
311:         $this->release();
312:         return $this->offsetGet($key) !== NULL;
313:     }
314: 
315: 
316:     /**
317:      * Removes the specified item from the cache.
318:      * @param  mixed key
319:      * @return void
320:      * @throws Nette\InvalidArgumentException
321:      */
322:     public function offsetUnset($key)
323:     {
324:         $this->save($key, NULL);
325:     }
326: 
327: 
328:     /**
329:      * Discards the internal cache used by ArrayAccess.
330:      * @return void
331:      */
332:     public function release()
333:     {
334:         $this->key = $this->data = NULL;
335:     }
336: 
337: 
338:     /********************* dependency checkers ****************d*g**/
339: 
340: 
341:     /**
342:      * Checks CALLBACKS dependencies.
343:      * @param  array
344:      * @return bool
345:      */
346:     public static function checkCallbacks($callbacks)
347:     {
348:         foreach ($callbacks as $callback) {
349:             if (!call_user_func_array(array_shift($callback), $callback)) {
350:                 return FALSE;
351:             }
352:         }
353:         return TRUE;
354:     }
355: 
356: 
357:     /**
358:      * Checks CONSTS dependency.
359:      * @param  string
360:      * @param  mixed
361:      * @return bool
362:      */
363:     private static function checkConst($const, $value)
364:     {
365:         return defined($const) && constant($const) === $value;
366:     }
367: 
368: 
369:     /**
370:      * Checks FILES dependency.
371:      * @param  string
372:      * @param  int
373:      * @return bool
374:      */
375:     private static function checkFile($file, $time)
376:     {
377:         return @filemtime($file) == $time; // @ - stat may fail
378:     }
379: 
380: 
381:     /**
382:      * Checks object @serializationVersion label.
383:      * @param  string
384:      * @param  mixed
385:      * @return bool
386:      */
387:     private static function checkSerializationVersion($class, $value)
388:     {
389:         return Nette\Reflection\ClassType::from($class)->getAnnotation('serializationVersion') === $value;
390:     }
391: 
392: }
393: 
Nette Framework 2.0.14 API API documentation generated by ApiGen 2.8.0