<frontend> <cache> <requests> <_no_route>enterprise_pagecache/processor_noroute</_no_route> <cms>enterprise_pagecache/processor_default</cms> <catalog> <category> <view>enterprise_pagecache/processor_category</view> </category> </catalog> <catalog> <product> <view>enterprise_pagecache/processor_product</view> </product> </catalog> </requests> </cache> </frontend>
<frontend> <cache> <requests> <productinfo> <index>enterprise_pagecache/processor_default</index> </productinfo> </requests> </cache> </frontend>
/** * Do basic validation for request to be cached * * @param Zend_Controller_Request_Http $request * @return bool */ public function canProcessRequest(Zend_Controller_Request_Http $request) { $res = $this->isAllowed(); $res = $res && Mage::app()->useCache('full_page'); if ($request->getParam('no_cache')) { $res = false; } if ($res) { $maxDepth = Mage::getStoreConfig(self::XML_PATH_ALLOWED_DEPTH); $queryParams = $request->getQuery(); unset($queryParams[Enterprise_PageCache_Model_Cache::REQUEST_MESSAGE_GET_PARAM]); $res = count($queryParams)<=$maxDepth; } if ($res) { $multicurrency = Mage::getStoreConfig(self::XML_PATH_CACHE_MULTICURRENCY); if (!$multicurrency && !empty($_COOKIE['currency'])) { $res = false; } } return $res; }
/** * Check if processor is allowed for current HTTP request. * Disable processing HTTPS requests and requests with "NO_CACHE" cookie * * @return bool */ public function isAllowed() { if (!$this->_requestId) { return false; } if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { return false; } if (isset($_COOKIE['NO_CACHE'])) { return false; } if (isset($_GET['no_cache'])) { return false; } if (isset($_GET[Mage_Core_Model_Session_Abstract::SESSION_ID_QUERY_PARAM])) { return false; } if (!Mage::app()->useCache('full_page')) { return false; } return true; }
/** * Check when cache should be disabled * * @param Varien_Event_Observer $observer * @return Enterprise_PageCache_Model_Observer */ public function processPreDispatch(Varien_Event_Observer $observer) { if (!$this->isCacheEnabled()) { return $this; } $action = $observer->getEvent()->getControllerAction(); /* @var $request Mage_Core_Controller_Request_Http */ $request = $action->getRequest(); $noCache = $this->_getCookie()->get(Enterprise_PageCache_Model_Processor::NO_CACHE_COOKIE); if ($noCache) { Mage::getSingleton('catalog/session')->setParamsMemorizeDisabled(false); $this->_getCookie()->renew(Enterprise_PageCache_Model_Processor::NO_CACHE_COOKIE); } elseif ($action) { Mage::getSingleton('catalog/session')->setParamsMemorizeDisabled(true); } /** * Check if request will be cached */ if ($this->_processor->canProcessRequest($request)) { Mage::app()->getCacheInstance()->banUse(Mage_Core_Block_Abstract::CACHE_GROUP); } $this->_getCookie()->updateCustomerCookies(); return $this; }
/** * Populate request ids * @return Enterprise_PageCache_Model_Processor */ protected function _createRequestIds() { $uri = $this->_getFullPageUrl(); //Removing get params $pieces = explode('?', $uri); $uri = array_shift($pieces); /** * Define COOKIE state */ if ($uri) { if (isset($_COOKIE['store'])) { $uri = $uri.'_'.$_COOKIE['store']; } if (isset($_COOKIE['currency'])) { $uri = $uri.'_'.$_COOKIE['currency']; } if (isset($_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_GROUP])) { $uri .= '_' . $_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_GROUP]; } if (isset($_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_LOGGED_IN])) { $uri .= '_' . $_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_LOGGED_IN]; } if (isset($_COOKIE[Enterprise_PageCache_Model_Cookie::CUSTOMER_SEGMENT_IDS])) { $uri .= '_' . $_COOKIE[Enterprise_PageCache_Model_Cookie::CUSTOMER_SEGMENT_IDS]; } if (isset($_COOKIE[Enterprise_PageCache_Model_Cookie::IS_USER_ALLOWED_SAVE_COOKIE])) { $uri .= '_' . $_COOKIE[Enterprise_PageCache_Model_Cookie::IS_USER_ALLOWED_SAVE_COOKIE]; } $designPackage = $this->_getDesignPackage(); if ($designPackage) { $uri .= '_' . $designPackage; } } $this->_requestId = $uri; $this->_requestCacheId = $this->prepareCacheId($this->_requestId); return $this; }
<?xml version="1.0" encoding="UTF-8"?> <config> <placeholders> <turnkeye_popup> <block>turnkeye_popup/popup</block> <placeholder>POPUP</placeholder> <container>Turnkeye_Popup_Model_PageCache_Container_Popup</container> <cache_lifetime>86400</cache_lifetime> </turnkeye_popup> </placeholders> </config>
/** * Render placeholder tags around the block if needed * * @param Varien_Event_Observer $observer * @return Enterprise_PageCache_Model_Observer */ public function renderBlockPlaceholder(Varien_Event_Observer $observer) { if (!$this->_isEnabled) { return $this; } $block = $observer->getEvent()->getBlock(); $transport = $observer->getEvent()->getTransport(); $placeholder = $this->_config->getBlockPlaceholder($block); if ($transport && $placeholder && !$block->getSkipRenderTag()) { $blockHtml = $transport->getHtml(); $request = Mage::app()->getFrontController()->getRequest(); /** @var $processor Enterprise_PageCache_Model_Processor_Default */ $processor = $this->_processor->getRequestProcessor($request); if ($processor && $processor->allowCache($request)) { $container = $placeholder->getContainerClass(); if ($container && !Mage::getIsDeveloperMode()) { $container = new $container($placeholder); $container->setProcessor(Mage::getSingleton('enterprise_pagecache/processor')); $container->setPlaceholderBlock($block); $container->saveCache($blockHtml); } } $blockHtml = $placeholder->getStartTag() . $blockHtml . $placeholder->getEndTag(); $transport->setHtml($blockHtml); } return $this; }
/** * Create placeholder object based on block information * * @param Mage_Core_Block_Abstract $block * @return Enterprise_PageCache_Model_Container_Placeholder */ public function getBlockPlaceholder($block) { $this->_initPlaceholders(); $type = $block->getType(); if (isset($this->_placeholders[$type])) { $placeholderData = false; foreach ($this->_placeholders[$type] as $placeholderInfo) { if (!empty($placeholderInfo['name'])) { if ($placeholderInfo['name'] == $block->getNameInLayout()) { $placeholderData = $placeholderInfo; } } else { $placeholderData = $placeholderInfo; } } if (!$placeholderData) { return false; } $placeholder = $placeholderData['code'] . ' container="' . $placeholderData['container'] . '"' . ' block="' . get_class($block) . '"'; $placeholder.= ' cache_id="' . $block->getCacheKey() . '"'; if (!empty($placeholderData['cache_lifetime'])) { $placeholder .= ' cache_lifetime="' . $placeholderData['cache_lifetime'] . '"'; } foreach ($block->getCacheKeyInfo() as $k => $v) { if (is_string($k) && !empty($k)) { $placeholder .= ' ' . $k . '="' . $v . '"'; } } $placeholder = Mage::getModel('enterprise_pagecache/container_placeholder', $placeholder); return $placeholder; } return false; }
/** * Class constructor. * Initialize placeholder name and attributes based on definition * * @param string $definition */ public function __construct($definition) { if ($definition && array_key_exists($definition, self::$_definitionMap)) { $definition = self::$_definitionMap[$definition]; } $this->_definition = $definition; $definition = explode(' ', $definition); $this->_name = $definition[0]; $count = count($definition); if ($count>1) { for ($i=1; $i_attributes[$info[0]] = isset($info[1]) ? trim($info[1], '"\'') : null; } } }
/** * Get attribute by specific code * @param $code string * @return string */ public function getAttribute($code) { return isset($this->_attributes[$code]) ? $this->_attributes[$code] : null; }
/** * Retrieve placeholder definition hash * * @return string */ protected function _getDefinitionHash() { $definition = $this->getDefinition(); $result = array_search($definition, self::$_definitionMap); if ($result === false) { $result = $this->getName() . '_' . md5($definition); self::$_definitionMap[$result] = $definition; } return $result; } /** * Get placeholder start tag for block html generation * * @return string */ public function getStartTag() { return '<!--{' . $this->_getDefinitionHash() . '}-->'; } /** * Get placeholder end tag for block html generation * * @return string */ public function getEndTag() { return '<!--/{' . $this->_getDefinitionHash() . '}-->'; }
< !--{TOPMENU_21c7f778e21d072d331836703b6295f5}--> < div class="nav-container"> < ul id="nav"> < li class="level0 nav-1 first last level-top"> < a class="level-top" href="http://example.com/test-category.html"> < span>Test category</span> </a> </li> </ul> </div> < !--/{TOPMENU_21c7f778e21d072d331836703b6295f5}-->
/** * Save page body to cache storage * * @param Varien_Event_Observer $observer * @return Enterprise_PageCache_Model_Observer */ public function cacheResponse(Varien_Event_Observer $observer) { if (!$this->isCacheEnabled()) { return $this; } $frontController = $observer->getEvent()->getFront(); $request = $frontController->getRequest(); $response = $frontController->getResponse(); $this->_saveDesignException(); $this->_processor->processRequestResponse($request, $response); return $this; }
/** * Process response body by specific request * * @param Zend_Controller_Request_Http $request * @param Zend_Controller_Response_Http $response * @return Enterprise_PageCache_Model_Processor */ public function processRequestResponse(Zend_Controller_Request_Http $request, Zend_Controller_Response_Http $response ) { // we should add original path info tag as another way we can't drop some entities from cron job $this->addRequestTag(Enterprise_PageCache_Helper_Url::prepareRequestPathTag($request->getOriginalPathInfo())); $cacheInstance = Enterprise_PageCache_Model_Cache::getCacheInstance(); /** * Basic validation for request processing */ if ($this->canProcessRequest($request)) { $processor = $this->getRequestProcessor($request); if ($processor && $processor->allowCache($request)) { $this->setMetadata('cache_subprocessor', get_class($processor)); $cacheId = $this->prepareCacheId($processor->getPageIdInApp($this)); $content = $processor->prepareContent($response); /** * Replace all occurrences of session_id with unique marker */ Enterprise_PageCache_Helper_Url::replaceSid($content); Enterprise_PageCache_Helper_Form_Key::replaceFormKey($content); if (function_exists('gzcompress')) { $content = gzcompress($content); } $contentSize = strlen($content); $currentStorageSize = (int) $cacheInstance->load(self::CACHE_SIZE_KEY); if (Mage::getStoreConfig(Enterprise_PageCache_Model_Processor::XML_PATH_CACHE_DEBUG)) { $response->setBody(implode(', ', $this->getRequestTags()) . $response->getBody()); } $maxSizeInBytes = Mage::getStoreConfig(self::XML_PATH_CACHE_MAX_SIZE) * 1024 * 1024; if ($currentStorageSize >= $maxSizeInBytes) { Mage::app()->getCacheInstance()->invalidateType('full_page'); return $this; } $cacheInstance->save($content, $cacheId, $this->getRequestTags()); $cacheInstance->save( $currentStorageSize + $contentSize, self::CACHE_SIZE_KEY, $this->getRequestTags() ); /* * Save design change in cache */ $designChange = Mage::getSingleton('core/design'); if ($designChange->getData()) { $cacheInstance->save( serialize($designChange->getData()), $this->getRequestCacheId() . self::DESIGN_CHANGE_CACHE_SUFFIX, $this->getRequestTags() ); } // save response headers $this->setMetadata('response_headers', $response->getHeaders()); // save original routing info $this->setMetadata('routing_aliases', Mage::app()->getRequest()->getAliases()); $this->setMetadata('routing_requested_route', Mage::app()->getRequest()->getRequestedRouteName()); $this->setMetadata('routing_requested_controller', Mage::app()->getRequest()->getRequestedControllerName()); $this->setMetadata('routing_requested_action', Mage::app()->getRequest()->getRequestedActionName()); $this->setMetadata('sid_cookie_name', Mage::getSingleton('core/session')->getSessionName()); Mage::dispatchEvent('pagecache_processor_metadata_before_save', array('processor' => $this)); $this->_saveMetadata(); } if (isset($_GET[Mage_Core_Model_Session_Abstract::SESSION_ID_QUERY_PARAM])) { Mage::getSingleton('enterprise_pagecache/cookie')->updateCustomerCookies(); Mage::getModel('enterprise_pagecache/observer')->updateCustomerProductIndex(); } } return $this; }
/** * Prepare response body before caching * * @param Zend_Controller_Response_Http $response * @return string */ public function prepareContent(Zend_Controller_Response_Http $response) { return $this->replaceContentToPlaceholderReplacer($response->getBody()); }
/** * Replace block content to placeholder replacer * * @param string $content * @return string */ public function replaceContentToPlaceholderReplacer($content) { $placeholders = array(); preg_match_all( Enterprise_PageCache_Model_Container_Placeholder::HTML_NAME_PATTERN, $content, $placeholders, PREG_PATTERN_ORDER ); $placeholders = array_unique($placeholders[1]); try { foreach ($placeholders as $definition) { $this->_placeholder = Mage::getModel('enterprise_pagecache/container_placeholder', $definition); $content = preg_replace_callback($this->_placeholder->getPattern(), array($this, '_getPlaceholderReplacer'), $content); } $this->_placeholder = null; } catch (Exception $e) { $this->_placeholder = null; throw $e; } return $content; }
< !--{POPUP container="Turnkeye_Popup_Model_PageCache_Container_Popup" block="Turnkeye_Popup_Block_Popup" cache_id="c3b32091a1ebd3b276a8fd70496a8e6da20865d0" cache_lifetime="86400" template="turnkeye/popup/popup.phtml" handles="a:2:{i:0;s:15:"cms_index_index";i:1;s:8:"cms_page";}" customer_segment_ids="a:1:{i:0;i:0;}" popup_ids="a:1:{i:0;s:1:"1";}" excluded_popup_ids="a:1:{i:0;i:1;}"}-->
/** * Determine and process all defined containers. * Direct request to pagecache/request/process action if necessary for additional processing * * @param string $content * @return string|false */ protected function _processContent($content) { $containers = $this->_processContainers($content); $isProcessed = empty($containers); // renew session cookie $sessionInfo = Enterprise_PageCache_Model_Cache::getCacheInstance()->load($this->getSessionInfoCacheId()); if ($sessionInfo) { $sessionInfo = unserialize($sessionInfo); foreach ($sessionInfo as $cookieName => $cookieInfo) { if (isset($_COOKIE[$cookieName]) && isset($cookieInfo['lifetime']) && isset($cookieInfo['path']) && isset($cookieInfo['domain']) && isset($cookieInfo['secure']) && isset($cookieInfo['httponly']) ) { $lifeTime = (0 == $cookieInfo['lifetime']) ? 0 : time() + $cookieInfo['lifetime']; setcookie($cookieName, $_COOKIE[$cookieName], $lifeTime, $cookieInfo['path'], $cookieInfo['domain'], $cookieInfo['secure'], $cookieInfo['httponly'] ); } } } else { $isProcessed = false; } if (isset($_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_FORM_KEY])) { $formKey = $_COOKIE[Enterprise_PageCache_Model_Cookie::COOKIE_FORM_KEY]; } else { $formKey = Enterprise_PageCache_Helper_Data::getRandomString(16); Enterprise_PageCache_Model_Cookie::setFormKeyCookieValue($formKey); } Enterprise_PageCache_Helper_Form_Key::restoreFormKey($content, $formKey); /** * restore session_id in content whether content is completely processed or not */ $sidCookieName = $this->getMetadata('sid_cookie_name'); $sidCookieValue = $sidCookieName && isset($_COOKIE[$sidCookieName]) ? $_COOKIE[$sidCookieName] : ''; // XSS vulnerability protection provided by htmlspcialchars call - escape & " ' < > chars Enterprise_PageCache_Helper_Url::restoreSid($content, htmlspecialchars($sidCookieValue, ENT_QUOTES)); if ($isProcessed) { return $content; } else { Mage::register('cached_page_content', $content); Mage::register('cached_page_containers', $containers); Mage::app()->getRequest() ->setModuleName('pagecache') ->setControllerName('request') ->setActionName('process') ->isStraight(true); // restore original routing info $routingInfo = array( 'aliases' => $this->getMetadata('routing_aliases'), 'requested_route' => $this->getMetadata('routing_requested_route'), 'requested_controller' => $this->getMetadata('routing_requested_controller'), 'requested_action' => $this->getMetadata('routing_requested_action') ); Mage::app()->getRequest()->setRoutingInfo($routingInfo); return false; } }
/** * Process Containers * * @param $content * @return array */ protected function _processContainers(&$content) { $placeholders = array(); preg_match_all( Enterprise_PageCache_Model_Container_Placeholder::HTML_NAME_PATTERN, $content, $placeholders, PREG_PATTERN_ORDER ); $placeholders = array_unique($placeholders[1]); $containers = array(); foreach ($placeholders as $definition) { $placeholder = new Enterprise_PageCache_Model_Container_Placeholder($definition); $container = $placeholder->getContainerClass(); if (!$container) { continue; } $container = new $container($placeholder); $container->setProcessor($this); if (!$container->applyWithoutApp($content)) { $containers[] = $container; } else { preg_match($placeholder->getPattern(), $content, $matches); if (array_key_exists(1,$matches)) { $containers = array_merge($this->_processContainers($matches[1]), $containers); $content = preg_replace($placeholder->getPattern(), str_replace('$', '\\$', $matches[1]), $content); } } } return $containers; }
/** * Generate placeholder content before application was initialized and apply to page content if possible * * @param string $content * @return bool */ public function applyWithoutApp(&$content) { $cacheId = $this->_getCacheId(); if ($cacheId === false) { $this->_applyToContent($content, ''); return true; } $block = $this->_loadCache($cacheId); if ($block === false) { return false; } $block = Enterprise_PageCache_Helper_Url::replaceUenc($block); $this->_applyToContent($content, $block); return true; }
/** * Request processing action */ public function processAction() { $processor = Mage::getSingleton('enterprise_pagecache/processor'); $content = Mage::registry('cached_page_content'); $containers = Mage::registry('cached_page_containers'); $cacheInstance = Enterprise_PageCache_Model_Cache::getCacheInstance(); foreach ($containers as $container) { $container->applyInApp($content); } $this->getResponse()->appendBody($content); // save session cookie lifetime info $cacheId = $processor->getSessionInfoCacheId(); $sessionInfo = $cacheInstance->load($cacheId); if ($sessionInfo) { $sessionInfo = unserialize($sessionInfo); } else { $sessionInfo = array(); } $session = Mage::getSingleton('core/session'); $cookieName = $session->getSessionName(); $cookieInfo = array( 'lifetime' => $session->getCookie()->getLifetime(), 'path' => $session->getCookie()->getPath(), 'domain' => $session->getCookie()->getDomain(), 'secure' => $session->getCookie()->isSecure(), 'httponly' => $session->getCookie()->getHttponly(), ); if (!isset($sessionInfo[$cookieName]) || $sessionInfo[$cookieName] != $cookieInfo) { $sessionInfo[$cookieName] = $cookieInfo; // customer cookies have to be refreshed as well as the session cookie $sessionInfo[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER] = $cookieInfo; $sessionInfo[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_GROUP] = $cookieInfo; $sessionInfo[Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER_LOGGED_IN] = $cookieInfo; $sessionInfo[Enterprise_PageCache_Model_Cookie::CUSTOMER_SEGMENT_IDS] = $cookieInfo; $sessionInfo[Enterprise_PageCache_Model_Cookie::COOKIE_MESSAGE] = $cookieInfo; $sessionInfo = serialize($sessionInfo); $cacheInstance->save($sessionInfo, $cacheId, array(Enterprise_PageCache_Model_Processor::CACHE_TAG)); } }
/** * Generate and apply container content in controller after application is initialized * * @param string $content * @return bool */ public function applyInApp(&$content) { $blockContent = $this->_renderBlock(); if ($blockContent === false) { return false; } if (Mage::getStoreConfig(Enterprise_PageCache_Model_Processor::XML_PATH_CACHE_DEBUG)) { $debugBlock = new Enterprise_PageCache_Block_Debug(); $debugBlock->setDynamicBlockContent($blockContent); $debugBlock->setTags($this->_getPlaceHolderBlock()->getCacheTags()); $debugBlock->setType($this->_placeholder->getName()); $this->_applyToContent($content, $debugBlock->toHtml()); } else { $this->_applyToContent($content, $blockContent); } $subprocessor = $this->_processor->getSubprocessor(); if ($subprocessor) { $contentWithoutNestedBlocks = $subprocessor->replaceContentToPlaceholderReplacer($blockContent); $this->saveCache($contentWithoutNestedBlocks); } return true; }
/** * Get Placeholder Block * * @return Mage_Core_Block_Abstract */ protected function _getPlaceHolderBlock() { if (null === $this->_placeholderBlock) { $blockName = $this->_placeholder->getAttribute('block'); $this->_placeholderBlock = new $blockName; $this->_placeholderBlock->setTemplate($this->_placeholder->getAttribute('template')); $this->_placeholderBlock->setLayout(Mage::app()->getLayout()); $this->_placeholderBlock->setSkipRenderTag(true); } return $this->_placeholderBlock; }
/** * Render block content from placeholder * * @return string|false */ protected function _renderBlock() { /** * @var $block Turnkeye_Popup_Block_Popup */ $block = $this->_getPlaceHolderBlock(); $placeholder = $this->_placeholder; $serializedParameters = array('handles', 'popup_ids'); foreach ($serializedParameters as $parameter) { $value = unserialize($placeholder->getAttribute($parameter)); $block->setDataUsingMethod($parameter, $value); } return $block->toHtml(); }
public function getPopupIds() { if (!$this->hasData('popup_ids')) { $popupIds = ... ... $this->setData('popup_ids', $popupIds); } return $this->getData('popup_ids'); }
Source: https://habr.com/ru/post/214645/
All Articles