Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

  • Swift_Plugins_Logger
  • Swift_Plugins_Pop_Pop3Exception
  • Swift_Transport
  • Swift_Transport_Esmtp_Authenticator
  • Swift_Transport_EsmtpHandler
  • Swift_Transport_IoBuffer
  • Swift_Transport_MailInvoker
  • Swift_Transport_SmtpAgent
  • Swift_TransportException
  • Overview
  • Package
  • Function
  • Todo
  • Download
  1: <?php
  2: /**
  3:  * Smarty Internal Plugin
  4:  *
  5:  * @package    Smarty
  6:  * @subpackage Cacher
  7:  */
  8: 
  9: /**
 10:  * Smarty Cache Handler Base for Key/Value Storage Implementations
 11:  * This class implements the functionality required to use simple key/value stores
 12:  * for hierarchical cache groups. key/value stores like memcache or APC do not support
 13:  * wildcards in keys, therefore a cache group cannot be cleared like "a|*" - which
 14:  * is no problem to filesystem and RDBMS implementations.
 15:  * This implementation is based on the concept of invalidation. While one specific cache
 16:  * can be identified and cleared, any range of caches cannot be identified. For this reason
 17:  * each level of the cache group hierarchy can have its own value in the store. These values
 18:  * are nothing but microtimes, telling us when a particular cache group was cleared for the
 19:  * last time. These keys are evaluated for every cache read to determine if the cache has
 20:  * been invalidated since it was created and should hence be treated as inexistent.
 21:  * Although deep hierarchies are possible, they are not recommended. Try to keep your
 22:  * cache groups as shallow as possible. Anything up 3-5 parents should be ok. So
 23:  * »a|b|c« is a good depth where »a|b|c|d|e|f|g|h|i|j|k« isn't. Try to join correlating
 24:  * cache groups: if your cache groups look somewhat like »a|b|$page|$items|$whatever«
 25:  * consider using »a|b|c|$page-$items-$whatever« instead.
 26:  *
 27:  * @package    Smarty
 28:  * @subpackage Cacher
 29:  * @author     Rodney Rehm
 30:  */
 31: abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
 32: {
 33:     /**
 34:      * cache for contents
 35:      *
 36:      * @var array
 37:      */
 38:     protected $contents = array();
 39:     /**
 40:      * cache for timestamps
 41:      *
 42:      * @var array
 43:      */
 44:     protected $timestamps = array();
 45: 
 46:     /**
 47:      * populate Cached Object with meta data from Resource
 48:      *
 49:      * @param  Smarty_Template_Cached   $cached    cached object
 50:      * @param  Smarty_Internal_Template $_template template object
 51:      *
 52:      * @return void
 53:      */
 54:     public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
 55:     {
 56:         $cached->filepath = $_template->source->uid
 57:             . '#' . $this->sanitize($cached->source->resource)
 58:             . '#' . $this->sanitize($cached->cache_id)
 59:             . '#' . $this->sanitize($cached->compile_id);
 60: 
 61:         $this->populateTimestamp($cached);
 62:     }
 63: 
 64:     /**
 65:      * populate Cached Object with timestamp and exists from Resource
 66:      *
 67:      * @param  Smarty_Template_Cached $cached cached object
 68:      *
 69:      * @return void
 70:      */
 71:     public function populateTimestamp(Smarty_Template_Cached $cached)
 72:     {
 73:         if (!$this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $content, $timestamp, $cached->source->uid)) {
 74:             return;
 75:         }
 76:         $cached->content = $content;
 77:         $cached->timestamp = (int) $timestamp;
 78:         $cached->exists = $cached->timestamp;
 79:     }
 80: 
 81:     /**
 82:      * Read the cached template and process the header
 83:      *
 84:      * @param  Smarty_Internal_Template $_template template object
 85:      * @param  Smarty_Template_Cached   $cached    cached object
 86:      *
 87:      * @return boolean                 true or false if the cached content does not exist
 88:      */
 89:     public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null)
 90:     {
 91:         if (!$cached) {
 92:             $cached = $_template->cached;
 93:         }
 94:         $content = $cached->content ? $cached->content : null;
 95:         $timestamp = $cached->timestamp ? $cached->timestamp : null;
 96:         if ($content === null || !$timestamp) {
 97:             if (!$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp, $_template->source->uid)) {
 98:                 return false;
 99:             }
100:         }
101:         if (isset($content)) {
102:             /** @var Smarty_Internal_Template $_smarty_tpl
103:              * used in evaluated code
104:              */
105:             $_smarty_tpl = $_template;
106:             eval("?>" . $content);
107: 
108:             return true;
109:         }
110: 
111:         return false;
112:     }
113: 
114:     /**
115:      * Write the rendered template output to cache
116:      *
117:      * @param  Smarty_Internal_Template $_template template object
118:      * @param  string                   $content   content to cache
119:      *
120:      * @return boolean                  success
121:      */
122:     public function writeCachedContent(Smarty_Internal_Template $_template, $content)
123:     {
124:         $this->addMetaTimestamp($content);
125: 
126:         return $this->write(array($_template->cached->filepath => $content), $_template->properties['cache_lifetime']);
127:     }
128: 
129:     /**
130:      * Empty cache
131:      * {@internal the $exp_time argument is ignored altogether }}
132:      *
133:      * @param  Smarty  $smarty   Smarty object
134:      * @param  integer $exp_time expiration time [being ignored]
135:      *
136:      * @return integer number of cache files deleted [always -1]
137:      * @uses purge() to clear the whole store
138:      * @uses invalidate() to mark everything outdated if purge() is inapplicable
139:      */
140:     public function clearAll(Smarty $smarty, $exp_time = null)
141:     {
142:         if (!$this->purge()) {
143:             $this->invalidate(null);
144:         }
145: 
146:         return - 1;
147:     }
148: 
149:     /**
150:      * Empty cache for a specific template
151:      * {@internal the $exp_time argument is ignored altogether}}
152:      *
153:      * @param  Smarty  $smarty        Smarty object
154:      * @param  string  $resource_name template name
155:      * @param  string  $cache_id      cache id
156:      * @param  string  $compile_id    compile id
157:      * @param  integer $exp_time      expiration time [being ignored]
158:      *
159:      * @return integer number of cache files deleted [always -1]
160:      * @uses buildCachedFilepath() to generate the CacheID
161:      * @uses invalidate() to mark CacheIDs parent chain as outdated
162:      * @uses delete() to remove CacheID from cache
163:      */
164:     public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
165:     {
166:         $uid = $this->getTemplateUid($smarty, $resource_name, $cache_id, $compile_id);
167:         $cid = $uid . '#' . $this->sanitize($resource_name) . '#' . $this->sanitize($cache_id) . '#' . $this->sanitize($compile_id);
168:         $this->delete(array($cid));
169:         $this->invalidate($cid, $resource_name, $cache_id, $compile_id, $uid);
170: 
171:         return - 1;
172:     }
173: 
174:     /**
175:      * Get template's unique ID
176:      *
177:      * @param  Smarty $smarty        Smarty object
178:      * @param  string $resource_name template name
179:      * @param  string $cache_id      cache id
180:      * @param  string $compile_id    compile id
181:      *
182:      * @return string filepath of cache file
183:      */
184:     protected function getTemplateUid(Smarty $smarty, $resource_name, $cache_id, $compile_id)
185:     {
186:         $uid = '';
187:         if (isset($resource_name)) {
188:             $tpl = new $smarty->template_class($resource_name, $smarty);
189:             if ($tpl->source->exists) {
190:                 $uid = $tpl->source->uid;
191:             }
192: 
193:             // remove from template cache
194:             if ($smarty->allow_ambiguous_resources) {
195:                 $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id;
196:             } else {
197:                 $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id;
198:             }
199:             if (isset($_templateId[150])) {
200:                 $_templateId = sha1($_templateId);
201:             }
202:             unset($smarty->template_objects[$_templateId]);
203:         }
204: 
205:         return $uid;
206:     }
207: 
208:     /**
209:      * Sanitize CacheID components
210:      *
211:      * @param  string $string CacheID component to sanitize
212:      *
213:      * @return string sanitized CacheID component
214:      */
215:     protected function sanitize($string)
216:     {
217:         // some poeple smoke bad weed
218:         $string = trim($string, '|');
219:         if (!$string) {
220:             return null;
221:         }
222: 
223:         return preg_replace('#[^\w\|]+#S', '_', $string);
224:     }
225: 
226:     /**
227:      * Fetch and prepare a cache object.
228:      *
229:      * @param  string  $cid           CacheID to fetch
230:      * @param  string  $resource_name template name
231:      * @param  string  $cache_id      cache id
232:      * @param  string  $compile_id    compile id
233:      * @param  string  $content       cached content
234:      * @param  integer &$timestamp    cached timestamp (epoch)
235:      * @param  string  $resource_uid  resource's uid
236:      *
237:      * @return boolean success
238:      */
239:     protected function fetch($cid, $resource_name = null, $cache_id = null, $compile_id = null, &$content = null, &$timestamp = null, $resource_uid = null)
240:     {
241:         $t = $this->read(array($cid));
242:         $content = !empty($t[$cid]) ? $t[$cid] : null;
243:         $timestamp = null;
244: 
245:         if ($content && ($timestamp = $this->getMetaTimestamp($content))) {
246:             $invalidated = $this->getLatestInvalidationTimestamp($cid, $resource_name, $cache_id, $compile_id, $resource_uid);
247:             if ($invalidated > $timestamp) {
248:                 $timestamp = null;
249:                 $content = null;
250:             }
251:         }
252: 
253:         return !!$content;
254:     }
255: 
256:     /**
257:      * Add current microtime to the beginning of $cache_content
258:      * {@internal the header uses 8 Bytes, the first 4 Bytes are the seconds, the second 4 Bytes are the microseconds}}
259:      *
260:      * @param string &$content the content to be cached
261:      */
262:     protected function addMetaTimestamp(&$content)
263:     {
264:         $mt = explode(" ", microtime());
265:         $ts = pack("NN", $mt[1], (int) ($mt[0] * 100000000));
266:         $content = $ts . $content;
267:     }
268: 
269:     /**
270:      * Extract the timestamp the $content was cached
271:      *
272:      * @param  string &$content the cached content
273:      *
274:      * @return float  the microtime the content was cached
275:      */
276:     protected function getMetaTimestamp(&$content)
277:     {
278:         $s = unpack("N", substr($content, 0, 4));
279:         $m = unpack("N", substr($content, 4, 4));
280:         $content = substr($content, 8);
281: 
282:         return $s[1] + ($m[1] / 100000000);
283:     }
284: 
285:     /**
286:      * Invalidate CacheID
287:      *
288:      * @param  string $cid           CacheID
289:      * @param  string $resource_name template name
290:      * @param  string $cache_id      cache id
291:      * @param  string $compile_id    compile id
292:      * @param  string $resource_uid  source's uid
293:      *
294:      * @return void
295:      */
296:     protected function invalidate($cid = null, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
297:     {
298:         $now = microtime(true);
299:         $key = null;
300:         // invalidate everything
301:         if (!$resource_name && !$cache_id && !$compile_id) {
302:             $key = 'IVK#ALL';
303:         } // invalidate all caches by template
304:         else {
305:             if ($resource_name && !$cache_id && !$compile_id) {
306:                 $key = 'IVK#TEMPLATE#' . $resource_uid . '#' . $this->sanitize($resource_name);
307:             } // invalidate all caches by cache group
308:             else {
309:                 if (!$resource_name && $cache_id && !$compile_id) {
310:                     $key = 'IVK#CACHE#' . $this->sanitize($cache_id);
311:                 } // invalidate all caches by compile id
312:                 else {
313:                     if (!$resource_name && !$cache_id && $compile_id) {
314:                         $key = 'IVK#COMPILE#' . $this->sanitize($compile_id);
315:                     } // invalidate by combination
316:                     else {
317:                         $key = 'IVK#CID#' . $cid;
318:                     }
319:                 }
320:             }
321:         }
322:         $this->write(array($key => $now));
323:     }
324: 
325:     /**
326:      * Determine the latest timestamp known to the invalidation chain
327:      *
328:      * @param  string $cid           CacheID to determine latest invalidation timestamp of
329:      * @param  string $resource_name template name
330:      * @param  string $cache_id      cache id
331:      * @param  string $compile_id    compile id
332:      * @param  string $resource_uid  source's filepath
333:      *
334:      * @return float  the microtime the CacheID was invalidated
335:      */
336:     protected function getLatestInvalidationTimestamp($cid, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
337:     {
338:         // abort if there is no CacheID
339:         if (false && !$cid) {
340:             return 0;
341:         }
342:         // abort if there are no InvalidationKeys to check
343:         if (!($_cid = $this->listInvalidationKeys($cid, $resource_name, $cache_id, $compile_id, $resource_uid))) {
344:             return 0;
345:         }
346: 
347:         // there are no InValidationKeys
348:         if (!($values = $this->read($_cid))) {
349:             return 0;
350:         }
351:         // make sure we're dealing with floats
352:         $values = array_map('floatval', $values);
353: 
354:         return max($values);
355:     }
356: 
357:     /**
358:      * Translate a CacheID into the list of applicable InvalidationKeys.
359:      * Splits "some|chain|into|an|array" into array( '#clearAll#', 'some', 'some|chain', 'some|chain|into', ... )
360:      *
361:      * @param  string $cid           CacheID to translate
362:      * @param  string $resource_name template name
363:      * @param  string $cache_id      cache id
364:      * @param  string $compile_id    compile id
365:      * @param  string $resource_uid  source's filepath
366:      *
367:      * @return array  list of InvalidationKeys
368:      * @uses $invalidationKeyPrefix to prepend to each InvalidationKey
369:      */
370:     protected function listInvalidationKeys($cid, $resource_name = null, $cache_id = null, $compile_id = null, $resource_uid = null)
371:     {
372:         $t = array('IVK#ALL');
373:         $_name = $_compile = '#';
374:         if ($resource_name) {
375:             $_name .= $resource_uid . '#' . $this->sanitize($resource_name);
376:             $t[] = 'IVK#TEMPLATE' . $_name;
377:         }
378:         if ($compile_id) {
379:             $_compile .= $this->sanitize($compile_id);
380:             $t[] = 'IVK#COMPILE' . $_compile;
381:         }
382:         $_name .= '#';
383:         // some poeple smoke bad weed
384:         $cid = trim($cache_id, '|');
385:         if (!$cid) {
386:             return $t;
387:         }
388:         $i = 0;
389:         while (true) {
390:             // determine next delimiter position
391:             $i = strpos($cid, '|', $i);
392:             // add complete CacheID if there are no more delimiters
393:             if ($i === false) {
394:                 $t[] = 'IVK#CACHE#' . $cid;
395:                 $t[] = 'IVK#CID' . $_name . $cid . $_compile;
396:                 $t[] = 'IVK#CID' . $_name . $_compile;
397:                 break;
398:             }
399:             $part = substr($cid, 0, $i);
400:             // add slice to list
401:             $t[] = 'IVK#CACHE#' . $part;
402:             $t[] = 'IVK#CID' . $_name . $part . $_compile;
403:             // skip past delimiter position
404:             $i ++;
405:         }
406: 
407:         return $t;
408:     }
409: 
410:     /**
411:      * Check is cache is locked for this template
412:      *
413:      * @param  Smarty                 $smarty Smarty object
414:      * @param  Smarty_Template_Cached $cached cached object
415:      *
416:      * @return boolean               true or false if cache is locked
417:      */
418:     public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
419:     {
420:         $key = 'LOCK#' . $cached->filepath;
421:         $data = $this->read(array($key));
422: 
423:         return $data && time() - $data[$key] < $smarty->locking_timeout;
424:     }
425: 
426:     /**
427:      * Lock cache for this template
428:      *
429:      * @param Smarty                 $smarty Smarty object
430:      * @param Smarty_Template_Cached $cached cached object
431:      *
432:      * @return bool|void
433:      */
434:     public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
435:     {
436:         $cached->is_locked = true;
437:         $key = 'LOCK#' . $cached->filepath;
438:         $this->write(array($key => time()), $smarty->locking_timeout);
439:     }
440: 
441:     /**
442:      * Unlock cache for this template
443:      *
444:      * @param Smarty                 $smarty Smarty object
445:      * @param Smarty_Template_Cached $cached cached object
446:      *
447:      * @return bool|void
448:      */
449:     public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
450:     {
451:         $cached->is_locked = false;
452:         $key = 'LOCK#' . $cached->filepath;
453:         $this->delete(array($key));
454:     }
455: 
456:     /**
457:      * Read values for a set of keys from cache
458:      *
459:      * @param  array $keys list of keys to fetch
460:      *
461:      * @return array list of values with the given keys used as indexes
462:      */
463:     abstract protected function read(array $keys);
464: 
465:     /**
466:      * Save values for a set of keys to cache
467:      *
468:      * @param  array $keys   list of values to save
469:      * @param  int   $expire expiration time
470:      *
471:      * @return boolean true on success, false on failure
472:      */
473:     abstract protected function write(array $keys, $expire = null);
474: 
475:     /**
476:      * Remove values from cache
477:      *
478:      * @param  array $keys list of keys to delete
479:      *
480:      * @return boolean true on success, false on failure
481:      */
482:     abstract protected function delete(array $keys);
483: 
484:     /**
485:      * Remove *all* values from cache
486:      *
487:      * @return boolean true on success, false on failure
488:      */
489:     protected function purge()
490:     {
491:         return false;
492:     }
493: }
494: 
CMS CONTENIDO 4.9.7 API documentation generated by ApiGen