Packages

  • 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

Classes

Interfaces

  • Overview
  • Package
  • 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 (http://davidgrudl.com)
  6:  * @package Nette\Caching
  7:  */
  8: 
  9: 
 10: 
 11: /**
 12:  * Implements the cache for a application.
 13:  *
 14:  * @author     David Grudl
 15:  *
 16:  * @property-read ICacheStorage $storage
 17:  * @property-read string $namespace
 18:  * @package Nette\Caching
 19:  */
 20: class NCache extends NObject 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 ICacheStorage */
 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(ICacheStorage $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 ICacheStorage
 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 NCache
 81:      */
 82:     public function derive($namespace)
 83:     {
 84:         $derived = new self($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, new NCallback($fallback));
100:         }
101:         return $data;
102:     }
103: 
104: 
105:     /**
106:      * Writes item into the cache.
107:      * Dependencies are:
108:      * - NCache::PRIORITY => (int) priority
109:      * - NCache::EXPIRATION => (timestamp) expiration
110:      * - NCache::SLIDING => (bool) use sliding expiration?
111:      * - NCache::TAGS => (array) tags
112:      * - NCache::FILES => (array|string) file names
113:      * - NCache::ITEMS => (array|string) cache items
114:      * - NCache::CONSTS => (array|string) cache items
115:      *
116:      * @param  mixed  key
117:      * @param  mixed  value
118:      * @param  array  dependencies
119:      * @return mixed  value itself
120:      * @throws InvalidArgumentException
121:      */
122:     public function save($key, $data, array $dependencies = NULL)
123:     {
124:         $this->release();
125:         $key = $this->generateKey($key);
126: 
127:         if ($data instanceof NCallback || $data instanceof Closure) {
128:             $this->storage->lock($key);
129:             $data = NCallback::create($data)->invokeArgs(array(& $dependencies));
130:         }
131: 
132:         if ($data === NULL) {
133:             $this->storage->remove($key);
134:         } else {
135:             $this->storage->write($key, $data, $this->completeDependencies($dependencies, $data));
136:             return $data;
137:         }
138:     }
139: 
140: 
141:     private function completeDependencies($dp, $data)
142:     {
143:         if (is_object($data)) {
144:             $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkSerializationVersion'), get_class($data),
145:                 NClassReflection::from($data)->getAnnotation('serializationVersion'));
146:         }
147: 
148:         // convert expire into relative amount of seconds
149:         if (isset($dp[NCache::EXPIRATION])) {
150:             $dp[NCache::EXPIRATION] = NDateTime53::from($dp[NCache::EXPIRATION])->format('U') - time();
151:         }
152: 
153:         // convert FILES into CALLBACKS
154:         if (isset($dp[self::FILES])) {
155:             foreach (array_unique((array) $dp[self::FILES]) as $item) {
156:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkFile'), $item, @filemtime($item)); // @ - stat may fail
157:             }
158:             unset($dp[self::FILES]);
159:         }
160: 
161:         // add namespaces to items
162:         if (isset($dp[self::ITEMS])) {
163:             $dp[self::ITEMS] = array_unique(array_map(array($this, 'generateKey'), (array) $dp[self::ITEMS]));
164:         }
165: 
166:         // convert CONSTS into CALLBACKS
167:         if (isset($dp[self::CONSTS])) {
168:             foreach (array_unique((array) $dp[self::CONSTS]) as $item) {
169:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkConst'), $item, constant($item));
170:             }
171:             unset($dp[self::CONSTS]);
172:         }
173: 
174:         if (!is_array($dp)) {
175:             $dp = array();
176:         }
177:         return $dp;
178:     }
179: 
180: 
181:     /**
182:      * Removes item from the cache.
183:      * @param  mixed  key
184:      * @return void
185:      */
186:     public function remove($key)
187:     {
188:         $this->save($key, NULL);
189:     }
190: 
191: 
192:     /**
193:      * Removes items from the cache by conditions.
194:      * Conditions are:
195:      * - NCache::PRIORITY => (int) priority
196:      * - NCache::TAGS => (array) tags
197:      * - NCache::ALL => TRUE
198:      * @return void
199:      */
200:     public function clean(array $conditions = NULL)
201:     {
202:         $this->release();
203:         $this->storage->clean((array) $conditions);
204:     }
205: 
206: 
207:     /**
208:      * Caches results of function/method calls.
209:      * @param  mixed
210:      * @return mixed
211:      */
212:     public function call($function)
213:     {
214:         $key = func_get_args();
215:         return $this->load($key, create_function('', 'extract($GLOBALS[0]['.array_push($GLOBALS[0], array('function'=>$function,'key'=> $key)).'-1], EXTR_REFS);
216:             return NCallback::create($function)->invokeArgs(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 NClosure
226:      */
227:     public function wrap($function, array $dependencies = NULL)
228:     {
229:         $cache = $this;
230:         return create_function('', 'extract($GLOBALS[0]['.array_push($GLOBALS[0], array('cache'=>$cache,'function'=> $function,'dependencies'=> $dependencies)).'-1], EXTR_REFS);
231:             $_args=func_get_args(); $key = array($function, $_args);
232:             $data = $cache->load($key);
233:             if ($data === NULL) {
234:                 $data = $cache->save($key, NCallback::create($function)->invokeArgs($key[1]), $dependencies);
235:             }
236:             return $data;
237:         ');
238:     }
239: 
240: 
241:     /**
242:      * Starts the output cache.
243:      * @param  mixed  key
244:      * @return NCachingHelper|NULL
245:      */
246:     public function start($key)
247:     {
248:         $data = $this->load($key);
249:         if ($data === NULL) {
250:             return new NCachingHelper($this, $key);
251:         }
252:         echo $data;
253:     }
254: 
255: 
256:     /**
257:      * Generates internal cache key.
258:      *
259:      * @param  string
260:      * @return string
261:      */
262:     protected function generateKey($key)
263:     {
264:         return $this->namespace . md5(is_scalar($key) ? $key : serialize($key));
265:     }
266: 
267: 
268:     /********************* interface ArrayAccess ****************d*g**/
269: 
270: 
271:     /**
272:      * Inserts (replaces) item into the cache (ArrayAccess implementation).
273:      * @param  mixed key
274:      * @param  mixed
275:      * @return void
276:      * @throws InvalidArgumentException
277:      */
278:     public function offsetSet($key, $data)
279:     {
280:         $this->save($key, $data);
281:     }
282: 
283: 
284:     /**
285:      * Retrieves the specified item from the cache or NULL if the key is not found (ArrayAccess implementation).
286:      * @param  mixed key
287:      * @return mixed|NULL
288:      * @throws InvalidArgumentException
289:      */
290:     public function offsetGet($key)
291:     {
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:      * Exists item in cache? (ArrayAccess implementation).
303:      * @param  mixed key
304:      * @return bool
305:      * @throws InvalidArgumentException
306:      */
307:     public function offsetExists($key)
308:     {
309:         $this->release();
310:         return $this->offsetGet($key) !== NULL;
311:     }
312: 
313: 
314:     /**
315:      * Removes the specified item from the cache.
316:      * @param  mixed key
317:      * @return void
318:      * @throws InvalidArgumentException
319:      */
320:     public function offsetUnset($key)
321:     {
322:         $this->save($key, NULL);
323:     }
324: 
325: 
326:     /**
327:      * Discards the internal cache used by ArrayAccess.
328:      * @return void
329:      */
330:     public function release()
331:     {
332:         $this->key = $this->data = NULL;
333:     }
334: 
335: 
336:     /********************* dependency checkers ****************d*g**/
337: 
338: 
339:     /**
340:      * Checks CALLBACKS dependencies.
341:      * @param  array
342:      * @return bool
343:      */
344:     public static function checkCallbacks($callbacks)
345:     {
346:         foreach ($callbacks as $callback) {
347:             if (!call_user_func_array(array_shift($callback), $callback)) {
348:                 return FALSE;
349:             }
350:         }
351:         return TRUE;
352:     }
353: 
354: 
355:     /**
356:      * Checks CONSTS dependency.
357:      * @param  string
358:      * @param  mixed
359:      * @return bool
360:      */
361:     private static function checkConst($const, $value)
362:     {
363:         return defined($const) && constant($const) === $value;
364:     }
365: 
366: 
367:     /**
368:      * Checks FILES dependency.
369:      * @param  string
370:      * @param  int
371:      * @return bool
372:      */
373:     private static function checkFile($file, $time)
374:     {
375:         return @filemtime($file) == $time; // @ - stat may fail
376:     }
377: 
378: 
379:     /**
380:      * Checks object @serializationVersion label.
381:      * @param  string
382:      * @param  mixed
383:      * @return bool
384:      */
385:     private static function checkSerializationVersion($class, $value)
386:     {
387:         return NClassReflection::from($class)->getAnnotation('serializationVersion') === $value;
388:     }
389: 
390: }
391: 
Nette Framework 2.0.18 (for PHP 5.2, prefixed) API documentation generated by ApiGen 2.8.0