Packages

  • Nette
    • Application
    • Caching
    • Collections
    • Config
    • Forms
    • IO
    • Loaders
    • Mail
    • Reflection
    • Security
    • Templates
    • Web
  • None
  • PHP

Classes

  • NCache
  • NDummyStorage
  • NFileStorage
  • NMemcachedStorage

Interfaces

  • ICacheStorage
  • Overview
  • Package
  • Class
  • Tree
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://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:  * @package Nette\Caching
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * Implements the cache for a application.
 17:  *
 18:  * @author     David Grudl
 19:  * @package Nette\Caching
 20:  */
 21: class NCache extends NObject implements ArrayAccess
 22: {
 23:     /**#@+ dependency */
 24:     const PRIORITY = 'priority';
 25:     const EXPIRATION = 'expire';
 26:     const EXPIRE = 'expire';
 27:     const SLIDING = 'sliding';
 28:     const TAGS = 'tags';
 29:     const FILES = 'files';
 30:     const ITEMS = 'items';
 31:     const CONSTS = 'consts';
 32:     const CALLBACKS = 'callbacks';
 33:     const ALL = 'all';
 34:     /**#@-*/
 35: 
 36:     /** @deprecated */
 37:     const REFRESH = 'sliding';
 38: 
 39:     /** @internal */
 40:     const NAMESPACE_SEPARATOR = "\x00";
 41: 
 42:     /** @var ICacheStorage */
 43:     private $storage;
 44: 
 45:     /** @var string */
 46:     private $namespace;
 47: 
 48:     /** @var string  last query cache */
 49:     private $key;
 50: 
 51:     /** @var mixed  last query cache */
 52:     private $data;
 53: 
 54: 
 55: 
 56:     public function __construct(ICacheStorage $storage, $namespace = NULL)
 57:     {
 58:         $this->storage = $storage;
 59:         $this->namespace = (string) $namespace;
 60: 
 61:         if (strpos($this->namespace, self::NAMESPACE_SEPARATOR) !== FALSE) {
 62:             throw new InvalidArgumentException("Namespace name contains forbidden character.");
 63:         }
 64:     }
 65: 
 66: 
 67: 
 68:     /**
 69:      * Returns cache storage.
 70:      * @return ICacheStorage
 71:      */
 72:     public function getStorage()
 73:     {
 74:         return $this->storage;
 75:     }
 76: 
 77: 
 78: 
 79:     /**
 80:      * Returns cache namespace.
 81:      * @return string
 82:      */
 83:     public function getNamespace()
 84:     {
 85:         return $this->namespace;
 86:     }
 87: 
 88: 
 89: 
 90:     /**
 91:      * Discards the internal cache.
 92:      * @return void
 93:      */
 94:     public function release()
 95:     {
 96:         $this->key = $this->data = NULL;
 97:     }
 98: 
 99: 
100: 
101:     /**
102:      * Writes item into the cache.
103:      * Dependencies are:
104:      * - NCache::PRIORITY => (int) priority
105:      * - NCache::EXPIRATION => (timestamp) expiration
106:      * - NCache::SLIDING => (bool) use sliding expiration?
107:      * - NCache::TAGS => (array) tags
108:      * - NCache::FILES => (array|string) file names
109:      * - NCache::ITEMS => (array|string) cache items
110:      * - NCache::CONSTS => (array|string) cache items
111:      *
112:      * @param  string key
113:      * @param  mixed  value
114:      * @param  array  dependencies
115:      * @return mixed  value itself
116:      * @throws InvalidArgumentException
117:      */
118:     public function save($key, $data, array $dp = NULL)
119:     {
120:         if (!is_string($key) && !is_int($key)) {
121:             throw new InvalidArgumentException("Cache key name must be string or integer, " . gettype($key) ." given.");
122:         }
123:         $this->key = (string) $key;
124:         $key = $this->namespace . self::NAMESPACE_SEPARATOR . $key;
125: 
126:         // convert expire into relative amount of seconds
127:         if (isset($dp[NCache::EXPIRATION])) {
128:             $dp[NCache::EXPIRATION] = NDateTime53::from($dp[NCache::EXPIRATION])->format('U') - time();
129:         }
130: 
131:         // convert FILES into CALLBACKS
132:         if (isset($dp[self::FILES])) {
133:             //clearstatcache();
134:             foreach ((array) $dp[self::FILES] as $item) {
135:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkFile'), $item, @filemtime($item)); // @ - stat may fail
136:             }
137:             unset($dp[self::FILES]);
138:         }
139: 
140:         // add namespaces to items
141:         if (isset($dp[self::ITEMS])) {
142:             $dp[self::ITEMS] = (array) $dp[self::ITEMS];
143:             foreach ($dp[self::ITEMS] as $k => $item) {
144:                 $dp[self::ITEMS][$k] = $this->namespace . self::NAMESPACE_SEPARATOR . $item;
145:             }
146:         }
147: 
148:         // convert CONSTS into CALLBACKS
149:         if (isset($dp[self::CONSTS])) {
150:             foreach ((array) $dp[self::CONSTS] as $item) {
151:                 $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkConst'), $item, constant($item));
152:             }
153:             unset($dp[self::CONSTS]);
154:         }
155: 
156:         if ($data instanceof NCallback || $data instanceof Closure) {
157:             NEnvironment::enterCriticalSection('Nette\Caching/' . $key);
158:             $data = $data->__invoke();
159:             NEnvironment::leaveCriticalSection('Nette\Caching/' . $key);
160:         }
161: 
162:         if (is_object($data)) {
163:             $dp[self::CALLBACKS][] = array(array(__CLASS__, 'checkSerializationVersion'), get_class($data),
164:                 NClassReflection::from($data)->getAnnotation('serializationVersion'));
165:         }
166: 
167:         $this->data = $data;
168:         if ($data === NULL) {
169:             $this->storage->remove($key);
170:         } else {
171:             $this->storage->write($key, $data, (array) $dp);
172:         }
173:         return $data;
174:     }
175: 
176: 
177: 
178:     /**
179:      * Removes items from the cache by conditions.
180:      * Conditions are:
181:      * - NCache::PRIORITY => (int) priority
182:      * - NCache::TAGS => (array) tags
183:      * - NCache::ALL => TRUE
184:      *
185:      * @param  array
186:      * @return void
187:      */
188:     public function clean(array $conds = NULL)
189:     {
190:         $this->release();
191:         $this->storage->clean((array) $conds);
192:     }
193: 
194: 
195: 
196:     /********************* interface ArrayAccess ****************d*g**/
197: 
198: 
199: 
200:     /**
201:      * Inserts (replaces) item into the cache (ArrayAccess implementation).
202:      * @param  string key
203:      * @param  mixed
204:      * @return void
205:      * @throws InvalidArgumentException
206:      */
207:     public function offsetSet($key, $data)
208:     {
209:         $this->save($key, $data);
210:     }
211: 
212: 
213: 
214:     /**
215:      * Retrieves the specified item from the cache or NULL if the key is not found (ArrayAccess implementation).
216:      * @param  string key
217:      * @return mixed|NULL
218:      * @throws InvalidArgumentException
219:      */
220:     public function offsetGet($key)
221:     {
222:         if (!is_string($key) && !is_int($key)) {
223:             throw new InvalidArgumentException("Cache key name must be string or integer, " . gettype($key) ." given.");
224:         }
225: 
226:         $key = (string) $key;
227:         if ($this->key === $key) {
228:             return $this->data;
229:         }
230:         $this->key = $key;
231:         $this->data = $this->storage->read($this->namespace . self::NAMESPACE_SEPARATOR . $key);
232:         return $this->data;
233:     }
234: 
235: 
236: 
237:     /**
238:      * Exists item in cache? (ArrayAccess implementation).
239:      * @param  string key
240:      * @return bool
241:      * @throws InvalidArgumentException
242:      */
243:     public function offsetExists($key)
244:     {
245:         return $this->offsetGet($key) !== NULL;
246:     }
247: 
248: 
249: 
250:     /**
251:      * Removes the specified item from the cache.
252:      * @param  string key
253:      * @return void
254:      * @throws InvalidArgumentException
255:      */
256:     public function offsetUnset($key)
257:     {
258:         $this->save($key, NULL);
259:     }
260: 
261: 
262: 
263:     /********************* dependency checkers ****************d*g**/
264: 
265: 
266: 
267:     /**
268:      * Checks CALLBACKS dependencies.
269:      * @param  array
270:      * @return bool
271:      */
272:     public static function checkCallbacks($callbacks)
273:     {
274:         foreach ($callbacks as $callback) {
275:             $func = array_shift($callback);
276:             if (!call_user_func_array($func, $callback)) {
277:                 return FALSE;
278:             }
279:         }
280:         return TRUE;
281:     }
282: 
283: 
284: 
285:     /**
286:      * Checks CONSTS dependency.
287:      * @param  string
288:      * @param  mixed
289:      * @return bool
290:      */
291:     private static function checkConst($const, $value)
292:     {
293:         return defined($const) && constant($const) === $value;
294:     }
295: 
296: 
297: 
298:     /**
299:      * Checks FILES dependency.
300:      * @param  string
301:      * @param  int
302:      * @return bool
303:      */
304:     private static function checkFile($file, $time)
305:     {
306:         return @filemtime($file) == $time; // @ - stat may fail
307:     }
308: 
309: 
310: 
311:     /**
312:      * Checks object @serializationVersion label.
313:      * @param  string
314:      * @param  mixed
315:      * @return bool
316:      */
317:     private static function checkSerializationVersion($class, $value)
318:     {
319:         return NClassReflection::from($class)->getAnnotation('serializationVersion') === $value;
320:     }
321: 
322: }
323: 
Nette Framework 0.9.7 (for PHP 5.2) API documentation generated by ApiGen 2.3.0