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