* @package Vhs * @subpackage ViewHelpers\Once */ abstract class AbstractOnceViewHelper extends AbstractConditionViewHelper { /** * Standard storage - static variable meaning uniqueness of $identifier * across each Request, i.e. unique to each individual plugin/content. * * @var array */ protected static $identifiers = array(); /** * Initialize arguments * * @return void */ public function initializeArguments() { parent::initializeArguments(); $this->registerArgument('identifier', 'string', 'Identity of this condition - if used in other places, the condition applies to the same identity in the storage (i.e. cookie name or session key)'); $this->registerArgument('lockToDomain', 'boolean', 'If TRUE, locks this condition to a specific domain, i.e. the storage of $identity is associated with a domain. If same identity is also used without domain lock, it matches any domain locked condition', FALSE, FALSE); $this->registerArgument('ttl', 'integer', 'Time-to-live for skip registration, number of seconds. After this expires the registration is unset', FALSE, 86400); } /** * Standard render method. Implementers should override * the assertShouldSkip() method and/or the getIdentifier() * and storeIdentifier() methods as applies to each * implementers method of storing identifiers. * * @return string */ public function render() { $this->removeIfExpired(); $evaluation = $this->assertShouldSkip(); if (FALSE === $evaluation) { $content = $this->renderThenChild(); } else { $content = $this->renderElseChild(); } $this->storeIdentifier(); return $content; } /** * @return string */ protected function getIdentifier() { if (TRUE === isset($this->arguments['identifier'])) { return $this->arguments['identifier']; } return get_class($this); } /** * @retrun void */ protected function storeIdentifier() { $identifier = $this->getIdentifier(); if (FALSE === isset(self::$identifiers[$identifier])) { self::$identifiers[$identifier] = time(); } } /** * @return void */ protected function removeIfExpired() { $identifier = $this->getIdentifier(); if (TRUE === isset(self::$identifiers[$identifier]) && self::$identifiers[$identifier] <= time() - $this->arguments['ttl']) { unset(self::$identifiers[$identifier]); } } /** * @return boolean */ protected function assertShouldSkip() { $identifier = $this->getIdentifier(); return (TRUE === isset(self::$identifiers[$identifier])); } /** * Override: forcibly disables page caching - a TRUE condition * in this ViewHelper means page content would be depending on * the current visitor's session/cookie/auth etc. * * Returns value of "then" attribute. * If then attribute is not set, iterates through child nodes and renders ThenViewHelper. * If then attribute is not set and no ThenViewHelper and no ElseViewHelper is found, all child nodes are rendered * * @return string rendered ThenViewHelper or contents of if no ThenViewHelper was found * @api */ protected function renderThenChild() { $GLOBALS['TSFE']->no_cache = 1; return parent::renderThenChild(); } }