diff --git a/Controller/Shell/Purge.php b/Controller/Shell/Purge.php new file mode 100644 index 0000000..7552a47 --- /dev/null +++ b/Controller/Shell/Purge.php @@ -0,0 +1,102 @@ +httpHeader = $httpHeader; + $this->litemageCache = $litemageCache; + } + + /** + * Returns block content as part of ESI request from Varnish + * + * @return void + */ + public function execute() + { + if (!$this->litemageCache->moduleEnabled()) { + return $this->_errorExit('Abort: LiteMage is not enabled'); + } + if ( $this->httpHeader->getHttpUserAgent() !== 'litemage_walker') { + return $this->_errorExit('Access denied'); + } + + $tags = []; + $req = $this->getRequest(); + if ($req->getParam('all')) { + $tags[] = '*'; + } + else { + if ($t = $req->getParam('tags')) { + $tags = explode(',', $t); + } + $types = array('P.' => 'products', 'C.' => 'cats', 'S.' => 'stores'); + foreach ($types as $prefix => $type) { + if ($ids = $req->getParam($type)) { + $tids = explode(',', $ids); + foreach ($tids as $id) { + $tags[] = $prefix . $id; + } + } + } + $tags = array_unique($tags); + } + if (empty($tags)) { + $this->_errorExit('Invalid url'); + } + else { + $this->litemageCache->addPurgeTags($tags, 'ShellPurgeController'); + $this->getResponse()->setBody('purged tags ' . implode(',', $tags)); + } + } + + protected function _errorExit($errorMesg) + { + $resp = $this->getResponse() ; + $resp->setHttpResponseCode(500) ; + $resp->setBody($errorMesg) ; + $this->litemageCache->debugLog('litemage/shell/purge ErrorExit: ' . $errorMesg) ; + } +} diff --git a/Model/App/Response/HttpPlugin.php b/Model/App/Response/HttpPlugin.php index 7b1fb98..f639e72 100644 --- a/Model/App/Response/HttpPlugin.php +++ b/Model/App/Response/HttpPlugin.php @@ -59,7 +59,7 @@ public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject if ($subject instanceof \Magento\Framework\App\PageCache\NotCacheableInterface) { return; } - if ($this->litemageCache->moduleEnabled()) { + if ($this->litemageCache->moduleEnabled()) { $this->litemageCache->setCacheControlHeaders($subject); } } diff --git a/Model/CacheControl.php b/Model/CacheControl.php index 3eb410b..939d007 100644 --- a/Model/CacheControl.php +++ b/Model/CacheControl.php @@ -59,8 +59,9 @@ class CacheControl protected $_ttl = 0; /** @var \Magento\Framework\App\Http\Context */ - protected $context; + protected $httpContext; protected $request; + protected $context; /** @var \Magento\Framework\Stdlib\CookieManagerInterface */ protected $cookieManager; @@ -76,6 +77,7 @@ class CacheControl * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, * @param \Magento\Framework\App\Request\Http $request, + * @param \Magento\Framework\App\Action\Context $context, * @param \Litespeed\Litemage\Model\Config $config, * @param \Litespeed\Litemage\Helper\Data $helper */ @@ -83,14 +85,16 @@ public function __construct(\Magento\Framework\App\Http\Context $httpContext, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory, \Magento\Framework\App\Request\Http $request, + \Magento\Framework\App\Action\Context $context, \Litespeed\Litemage\Model\Config $config, \Litespeed\Litemage\Helper\Data $helper ) { - $this->context = $httpContext; + $this->httpContext = $httpContext; $this->cookieManager = $cookieManager; $this->cookieMetadataFactory = $cookieMetadataFactory; $this->request = $request; + $this->context = $context; $this->config = $config; $this->helper = $helper; $this->_moduleEnabled = $config->moduleEnabled(); @@ -123,15 +127,22 @@ public function debugEnabled() return $this->_debug; } - public function addPurgeTags($tags) + /** + * Add purgeable tags + * @param array $tags + * @param string $source + * + */ + public function addPurgeTags($tags, $source) { - $this->debugLog("add purge Tags " . print_r($tags, true)); - if (is_array($tags)) { - $this->_purgeTags = array_merge($this->_purgeTags, $tags); - } else if ($tags) { - $this->_purgeTags[] = $tags; - } - $this->_purgeTags = array_unique(($this->_purgeTags)); + if (!empty($tags)) { + $this->_purgeTags = array_unique(array_merge($this->_purgeTags, $tags)); + } + if ($this->_debug) { + $this->debugLog('add purge tags from ' + . $source . ' : ' . implode(',', $tags) + . ' Result=' . implode(',',$this->_purgeTags) ); + } } public function setCacheable($isCacheable, $ttl = 0) @@ -274,7 +285,7 @@ protected function _setCacheTagHeader($response) protected function _checkCacheVary() { $varyString = null; - $data = $this->context->getData(); + $data = $this->httpContext->getData(); if (!empty($data)) { ksort($data); $varyString = sha1(serialize($data)); @@ -305,7 +316,14 @@ public function setPurgeHeaders($response) $purgeTags = $this->translateTags(implode(',', $this->_purgeTags)); } $response->setHeader(self::LSHEADER_PURGE, $purgeTags); - $this->debugLog('set purge header ' . $purgeTags); + $om = $this->context->getObjectManager(); + $state = $om->get('Magento\Framework\App\State'); + if ($state->getAreaCode() === \Magento\Framework\App\Area::AREA_ADMINHTML) { + // if in adminhtml, show the message + $this->context->getMessageManager()->addSuccessMessage('Informed LiteSpeed Web Server to purge ' . $purgeTags); + } + + $this->debugLog('Set purge header ' . $purgeTags); } } diff --git a/Model/Config.php b/Model/Config.php index 074df29..41f110a 100644 --- a/Model/Config.php +++ b/Model/Config.php @@ -27,13 +27,6 @@ use Magento\Framework\Filesystem; use Magento\Framework\Module\Dir; -/** - * Model is responsible for replacing default vcl template - * file configuration with user-defined from configuration - * - * @author Magento Core Team - */ - /** * Class Config * @@ -77,7 +70,13 @@ class Config protected $reader; protected $_debug = -1; // avail value: -1(not set), true, false - protected $_moduleEnabled = false; + /** + * @var int moduleStatus bitmask + * 1: SERVER variable set + * 2: FPC enabled + * 4: FPC type is LITEMAGE + */ + protected $_moduleStatus = 0; /** * @param Filesystem\Directory\ReadFactory $readFactory @@ -88,7 +87,6 @@ class Config public function __construct( \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Framework\App\Cache\StateInterface $cacheState, \Magento\PageCache\Model\Config $pagecacheConfig, \Magento\Framework\Module\Dir\Reader $reader, \Magento\Framework\App\State $state @@ -96,14 +94,17 @@ public function __construct( $this->readFactory = $readFactory; $this->scopeConfig = $scopeConfig; $this->reader = $reader; + + if (isset($_SERVER['X-LITEMAGE']) && $_SERVER['X-LITEMAGE']) { + $this->_moduleStatus |= 1; + } + if ($pagecacheConfig->isEnabled()) { + $this->_moduleStatus |= 2; + } + if ($pagecacheConfig->getType() == self::LITEMAGE) { + $this->_moduleStatus |= 4; + } - if (isset($_SERVER['X-LITEMAGE']) && $_SERVER['X-LITEMAGE']) { - if ($pagecacheConfig->isEnabled() - && $pagecacheConfig->getType() == self::LITEMAGE - && $cacheState->isEnabled(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER)) { - $this->_moduleEnabled = true; - } - } if ($state->getMode() === \Magento\Framework\App\State::MODE_PRODUCTION) { // turn off debug for production $this->_debug = 0; @@ -122,9 +123,14 @@ public function __construct( */ public function moduleEnabled() { - return $this->_moduleEnabled; + return ($this->_moduleStatus == 7); } + public function cliModuleEnabled() + { + return ($this->_moduleStatus == 6); + } + public function debugEnabled() { return $this->_debug; diff --git a/Model/System/Config/Source/ApplicationPlugin.php b/Model/System/Config/Source/ApplicationPlugin.php index 961f279..e55df9f 100644 --- a/Model/System/Config/Source/ApplicationPlugin.php +++ b/Model/System/Config/Source/ApplicationPlugin.php @@ -45,7 +45,7 @@ public function afterToOptionArray(\Magento\PageCache\Model\System\Config\Source if ($this->_hasLicense()) { $result[] = [ 'value' => \Litespeed\Litemage\Model\Config::LITEMAGE, - 'label' => __('LiteMage Cache in LiteSpeed Web Server') + 'label' => __('LiteMage Cache within LiteSpeed Server') ]; } return $result; @@ -66,7 +66,14 @@ public function afterToArray(Magento\PageCache\Model\System\Config\Source\Applic protected function _hasLicense() { - return (isset($_SERVER['X-LITEMAGE']) && $_SERVER['X-LITEMAGE']); + if (isset($_SERVER['X-LITEMAGE']) && $_SERVER['X-LITEMAGE']) { + return true; // for lsws + } + elseif (isset($_SERVER['HTTP_X_LITEMAGE']) && $_SERVER['HTTP_X_LITEMAGE']) { + return true; // for lslb + } + else + return false; } } diff --git a/Observer/FlushAllCache.php b/Observer/FlushAllCache.php index 1ade5e8..2e111f1 100644 --- a/Observer/FlushAllCache.php +++ b/Observer/FlushAllCache.php @@ -29,42 +29,40 @@ class FlushAllCache implements ObserverInterface { + protected $config; + + /** @var \Magento\Framework\Event\ManagerInterface */ + protected $eventManager; + /** - * @var \Litespeed\Litemage\Model\CacheControl + * @param \Litespeed\Litemage\Model\Config $config, + * @param \Magento\Framework\Event\ManagerInterface $eventManager, */ - protected $litemageCache; - - /** - * @var \Magento\Framework\App\Action\Context - */ - protected $context; - - /** - * @param \Litespeed\Litemage\Model\CacheControl $litemageCache - * @param \Magento\Framework\App\Action\Context $context - */ - public function __construct(\Litespeed\Litemage\Model\CacheControl $litemageCache, - \Magento\Framework\App\Action\Context $context) + public function __construct(\Litespeed\Litemage\Model\Config $config, + \Magento\Framework\Event\ManagerInterface $eventManager) { - $this->litemageCache = $litemageCache; - $this->context = $context; + $this->config = $config; + $this->eventManager = $eventManager; } /** - * Flush Litemage cache + * Flush All Litemage cache * @param \Magento\Framework\Event\Observer $observer * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function execute(\Magento\Framework\Event\Observer $observer) { - if ($this->litemageCache->moduleEnabled()) { - $this->litemageCache->addPurgeTags('*'); - $this->messageManager = $this->context->getMessageManager(); - $this->messageManager->addSuccess('litemage purge all'); - $this->litemageCache->debugLog('purge all invoked'); + if (PHP_SAPI == 'cli') { + // from command line + if ($this->config->cliModuleEnabled()) + $this->eventManager->dispatch('litemage_cli_purge_all'); + } + else if ($this->config->moduleEnabled()) { + $this->eventManager->dispatch('litemage_purge_all'); } } + } diff --git a/Observer/FlushCacheByCli.php b/Observer/FlushCacheByCli.php new file mode 100644 index 0000000..7a19601 --- /dev/null +++ b/Observer/FlushCacheByCli.php @@ -0,0 +1,127 @@ +config = $config; + $this->httpClientFactory = $httpClientFactory; + $this->coreRegistry = $coreRegistry; + $this->url = $url; + $this->logger = $logger; + } + + /** + * Flush All Litemage cache + * @param \Magento\Framework\Event\Observer $observer + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + if ($this->config->cliModuleEnabled() + && ($this->coreRegistry->registry('shellPurgeAll') === null)) { + $this->coreRegistry->register('shellPurgeAll', 1); + $this->_shellPurgeAll(); + } + } + + protected function _shellPurgeAll() + { + $client = $this->httpClientFactory->create(); + + $clientConfig = ['verifypeer' => 0, + 'timeout' => 180, + 'useragent' => 'litemage_walker']; + + $client->setConfig($clientConfig); + $client->setMethod(\Zend_Http_Client::POST); + $client->setParameterPost('all', 1); + + $server_ip = '127.0.0.1' ; //$helper->getConf($helper::CFG_WARMUP_SERVER_IP, $helper::CFG_WARMUP); + $base = $this->url->getBaseUrl(); + if ($server_ip) { + $pattern = "/:\/\/([^\/^:]+)(\/|:)?/"; + if (preg_match($pattern, $base, $m)) { + $domain = $m[1]; + $pos = strpos($base, $domain); + $base = substr($base, 0, $pos) . $server_ip . substr($base, $pos + strlen($domain)); + $client->setHeaders(['Host' => $domain]); + } + } + + $uri = $base . 'litemage/shell/purge'; + $client->setUri($uri); + $client->setUrlEncodeBody(false); + try { + $response = $client->request(); + $this->logger->debug($uri . ' ' . $response->getBody()); + } catch (\Zend_Http_Client_Exception $e) { + $this->logger->critical($uri . ' ' . $e->getMessage()); + return false; + } + + return true; + + } + +} diff --git a/Observer/FlushCacheByEvents.php b/Observer/FlushCacheByEvents.php index 3866de7..35f2547 100644 --- a/Observer/FlushCacheByEvents.php +++ b/Observer/FlushCacheByEvents.php @@ -53,16 +53,20 @@ public function __construct( public function execute(\Magento\Framework\Event\Observer $observer) { if ($this->litemageCache->moduleEnabled()) { - $eventName = $observer->getEventName(); + // do not use getEventName() directly, maybe empty + $eventName = $observer->getEvent()->getName(); $tags = []; switch ($eventName) { case 'catalog_category_save_after': case 'catalog_category_delete_after': $tags[] = 'topnav'; break; + case 'litemage_purge_all': + $tags[] = '*'; + break; } if (!empty($tags)) { - $this->litemageCache->addPurgeTags($tags); + $this->litemageCache->addPurgeTags($tags , "FlushCacheByEvents $eventName"); } } } diff --git a/Observer/FlushCacheByTags.php b/Observer/FlushCacheByTags.php index cdaa869..2a4d9b1 100644 --- a/Observer/FlushCacheByTags.php +++ b/Observer/FlushCacheByTags.php @@ -56,10 +56,11 @@ public function execute(\Magento\Framework\Event\Observer $observer) if ($object instanceof \Magento\Framework\DataObject\IdentityInterface) { $tags = $object->getIdentities(); if (!empty($tags)) { - $this->litemageCache->addPurgeTags($tags); + $this->litemageCache->addPurgeTags($tags, 'FlushCacheByTags-' . $observer->getEvent()->getName()); } } } + } } diff --git a/README.md b/README.md index af1cce0..3f9ada2 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ The following steps assume that the Prerequisites mentioned above are met. ``` php bin/magento setup:upgrade ``` -10. Recompile using the multi-tenant compiler. The single-tenant compiler has some issues. [link](http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-compiler.html#config-cli-subcommands-single) +10. Recompile code ``` - php bin/magento setup:di:compile-multi-tenant + php bin/magento setup:di:compile ``` 11. Once finished, delete `var/di/relations.ser` to work around a Magento bug. [link](https://github.com/magento/magento2/issues/4070) diff --git a/composer.json b/composer.json index d6aa75a..bb3f854 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "magento/framework": "100.0.*|100.1.*|100.2.*" }, "type": "magento2-module", - "version": "2.0.1", + "version": "2.0.2", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/etc/di.xml b/etc/di.xml index e456220..c9f40d5 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -19,12 +19,12 @@ * along with this program. If not, see https://opensource.org/licenses/GPL-3.0 . * * @package LiteSpeed_LiteMage - * @copyright Copyright (c) 2016 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com) + * @copyright Copyright (c) 2016-2017 LiteSpeed Technologies, Inc. (https://www.litespeedtech.com) * @license https://opensource.org/licenses/GPL-3.0 */ --> - + diff --git a/etc/events.xml b/etc/events.xml index c9d152a..f779dc9 100644 --- a/etc/events.xml +++ b/etc/events.xml @@ -25,43 +25,30 @@ --> - - - - - - - - - - - - - - - + - + - + + - + - + - + - + @@ -70,5 +57,11 @@ + + + + + +