diff --git a/Block/Adminhtml/Cache.php b/Block/Adminhtml/Cache.php new file mode 100644 index 0000000..480d29b --- /dev/null +++ b/Block/Adminhtml/Cache.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +namespace Igorludgero\WarmCache\Block\Adminhtml; + +class Cache extends \Magento\Backend\Block\Cache +{ + /** + * Cache block constructor. + */ + protected function _construct() + { + parent::_construct(); + $message = __('The Warm Cache will access a lot of store urls like product, category and cms pages to rebuild the caches. Do you agree to start now?'); + $this->buttonList->add( + 'warm_cache', + [ + 'label' => __('Run Warm Cache'), + 'onclick' => 'confirmSetLocation(\'' . $message . '\', \'' . $this->getWarmCacheUrl() . '\')', + 'class' => 'run-warm-cache' + ] + ); + } + + /** + * Get warm cache action url. + * @return string + */ + private function getWarmCacheUrl(){ + return $this->getUrl('warmcache/WarmCache/run'); + } + +} \ No newline at end of file diff --git a/Console/Command/WarmCache.php b/Console/Command/WarmCache.php new file mode 100644 index 0000000..6264d91 --- /dev/null +++ b/Console/Command/WarmCache.php @@ -0,0 +1,68 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +namespace Igorludgero\WarmCache\Console\Command; + +class WarmCache extends \Symfony\Component\Console\Command\Command +{ + + /** + * @var \Igorludgero\WarmCache\Helper\Data + */ + protected $_helper; + + /** + * @var \Magento\Framework\App\State + */ + protected $_appState; + + /** + * WarmCache constructor. + * @param \Igorludgero\WarmCache\Helper\Data $helper + */ + public function __construct(\Magento\Framework\App\State $appState, + \Igorludgero\WarmCache\Helper\Data $helper) + { + $this->_helper = $helper; + $this->_appState = $appState; + parent::__construct('igorludgero:warmcache'); + } + + /** + * Configure cli command. + */ + protected function configure() + { + $this->setName('igorludgero:warmcache')->setDescription('Run the warm cache and cache all available pages in the store.'); + } + + /** + * Execute cli command. + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * @return $this + */ + protected function execute(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output) + { + $this->_appState->setAreaCode('adminhtml'); + if($this->_helper->run()){ + $this->_helper->logMessage("Warm cache process finished."); + $output->writeln('Warm cache process finished.'); + } + else{ + $output->writeln('Was not possible to run the command, please try again later.'); + } + return $this; + } + +} \ No newline at end of file diff --git a/Controller/Adminhtml/WarmCache/Run.php b/Controller/Adminhtml/WarmCache/Run.php new file mode 100644 index 0000000..786c1e2 --- /dev/null +++ b/Controller/Adminhtml/WarmCache/Run.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +namespace Igorludgero\WarmCache\Controller\Adminhtml\WarmCache; + +use Magento\Backend\App\Action; + +class Run extends \Magento\Backend\App\Action +{ + + /** + * @var \Igorludgero\WarmCache\Helper\Data + */ + protected $_helper; + + /** + * Run constructor. + * @param Action\Context $context + * @param \Igorludgero\WarmCache\Helper\Data $helper + */ + public function __construct(\Magento\Backend\App\Action\Context $context, \Igorludgero\WarmCache\Helper\Data $helper) + { + parent::__construct($context); + $this->_helper = $helper; + } + + /** + * Start the WarmCache. + */ + public function execute() + { + $resultRedirect = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT); + $this->_helper->run(); + $this->messageManager->addSuccessMessage(__("Warm cache ran successfully!")); + $resultRedirect->setUrl($this->_redirect->getRefererUrl()); + return $resultRedirect; + } + +} \ No newline at end of file diff --git a/Cron/Run.php b/Cron/Run.php new file mode 100644 index 0000000..4fded8f --- /dev/null +++ b/Cron/Run.php @@ -0,0 +1,44 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +namespace Igorludgero\WarmCache\Cron; + +class Run +{ + + /** + * @var \Igorludgero\WarmCache\Helper\Data + */ + protected $_helper; + + /** + * Run constructor. + * @param \Igorludgero\WarmCache\Helper\Data $helper + */ + public function __construct(\Igorludgero\WarmCache\Helper\Data $helper) + { + $this->_helper = $helper; + } + + /** + * Run the warm cache process. + * @return $this + */ + public function execute() + { + + $this->_helper->run(); + return $this; + } + +} \ No newline at end of file diff --git a/Helper/Data.php b/Helper/Data.php new file mode 100644 index 0000000..6f1e6b4 --- /dev/null +++ b/Helper/Data.php @@ -0,0 +1,204 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +namespace Igorludgero\WarmCache\Helper; + +class Data extends \Magento\Framework\App\Helper\AbstractHelper +{ + + /** + * @var array + */ + protected $_urls = array(); + + /** + * @var \Magento\Catalog\Model\Product + */ + protected $_productModel; + + /** + * @var \Magento\Catalog\Model\Category + */ + protected $_categoryModel; + + /** + * @var \Magento\Cms\Model\Page + */ + protected $_pageModel; + + /** + * @var \Magento\UrlRewrite\Model\UrlRewrite + */ + protected $_urlRewriteModel; + + /** + * @var \Zend\Log\Logger + */ + protected $_logger; + + /** + * @var \Magento\Framework\Url + */ + protected $_frontUrlModel; + + /** + * Data constructor. + * @param \Magento\Framework\App\Helper\Context $context + * @param \Magento\Catalog\Model\Product $productModel + * @param \Magento\Catalog\Model\Category $categoryModel + * @param \Magento\Cms\Model\Page $pageModel + * @param \Magento\UrlRewrite\Model\UrlRewrite $urlRewriteModel + * @param \Magento\Framework\Url $frontUrlModel + */ + public function __construct(\Magento\Framework\App\Helper\Context $context, + \Magento\Catalog\Model\Product $productModel, + \Magento\Catalog\Model\Category $categoryModel, + \Magento\Cms\Model\Page $pageModel, + \Magento\UrlRewrite\Model\UrlRewrite $urlRewriteModel, + \Magento\Framework\Url $frontUrlModel) + { + parent::__construct($context); + $this->_productModel = $productModel; + $this->_categoryModel = $categoryModel; + $this->_pageModel = $pageModel; + $this->_urlRewriteModel = $urlRewriteModel; + $this->_frontUrlModel = $frontUrlModel; + $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/igorludgero_warmcache.log'); + $this->_logger = new \Zend\Log\Logger(); + $this->_logger->addWriter($writer); + $this->getUrls(); + } + + /** + * Log a custom message. + * @param $message + */ + public function logMessage($message){ + $this->_logger->info($message); + } + + /** + * Get all urls to be cached. + */ + private function getUrls(){ + + //Add Products url + if($this->scopeConfig->getValue('warmcache/settings/product', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) { + $_productCollection = $this->_productModel->getCollection() + ->addAttributeToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->addAttributeToFilter('visibility', array(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG, \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)) + ->addAttributeToSelect(["entity_id"]); + foreach ($_productCollection as $_product) { + $url = $this->_frontUrlModel->getUrl("catalog/product/view", ['id' => $_product->getId()]); + if (!in_array($url, $this->_urls)) { + $this->_urls[] = $url; + } + } + } + + //Add category url + if($this->scopeConfig->getValue('warmcache/settings/category', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) { + $_categoryCollection = $this->_categoryModel->getCollection() + ->addAttributeToFilter('is_active', 1) + ->addAttributeToSelect(["entity_id"]); + foreach ($_categoryCollection as $_category) { + $url = $this->_frontUrlModel->getUrl("catalog/category/view", ['id' => $_category->getId()]); + if (!in_array($url, $this->_urls)) { + $this->_urls[] = $url; + } + } + } + + //Add cms pages + if($this->scopeConfig->getValue('warmcache/settings/cms_pages', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) { + $_cmsPageCollection = $this->_pageModel->getCollection()->addFieldToFilter("is_active", 1) + ->addFieldToSelect("page_id"); + foreach ($_cmsPageCollection as $page) { + $url = $this->_frontUrlModel->getUrl("cms/page/view", ['id' => $page->getId()]); + if (!in_array($url, $this->_urls)) { + $this->_urls[] = $url; + } + } + } + + //Custom urls in url rewrite. + if($this->scopeConfig->getValue('warmcache/settings/url_rewrite', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) { + $_urlRewriteCollection = $this->_urlRewriteModel->getCollection() + ->addFieldToSelect("target_path") + ->addFieldToFilter('entity_type', array('nin' => array('cms-page', 'category', 'product'))); + foreach ($_urlRewriteCollection as $urlRewrite) { + $newUrl = $this->_frontUrlModel->getBaseUrl() . $urlRewrite->getRequestPath(); + if (!in_array($newUrl, $this->_urls)) { + $this->_urls[] = $newUrl; + } + } + } + + } + + /** + * Run the crawler. + */ + public function run() + { + try { + foreach ($this->_urls as $url) { + $this->checkUrl($url); + } + return true; + } + catch (\Exception $ex){ + $this->logMessage("Error in WarmCache: ".$ex->getMessage()); + return false; + } + } + + /** + * Render the url. + * @param $url + */ + function checkUrl( $url ) + { + $user_agent='Mozilla/4.0 (compatible;)'; + + $options = array( + + CURLOPT_CUSTOMREQUEST =>"GET", //set request type post or get + CURLOPT_POST =>false, //set to GET + CURLOPT_USERAGENT => $user_agent, //set user agent + CURLOPT_COOKIEFILE =>"cookie.txt", //set cookie file + CURLOPT_COOKIEJAR =>"cookie.txt", //set cookie jar + CURLOPT_RETURNTRANSFER => true, // return web page + CURLOPT_HEADER => false, // don't return headers + CURLOPT_FOLLOWLOCATION => true, // follow redirects + CURLOPT_ENCODING => "", // handle all encodings + CURLOPT_AUTOREFERER => true, // set referer on redirect + CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect + CURLOPT_TIMEOUT => 120, // timeout on response + CURLOPT_MAXREDIRS => 4, // stop after 10 redirects + ); + + $ch = curl_init( $url ); + curl_setopt_array( $ch, $options ); + $content = curl_exec( $ch ); + $err = curl_errno( $ch ); + $errmsg = curl_error( $ch ); + $header = curl_getinfo( $ch ); + curl_close( $ch ); + + $header['errno'] = $err; + $header['errmsg'] = $errmsg; + $header['content'] = $content; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a34bbfe --- /dev/null +++ b/composer.json @@ -0,0 +1,17 @@ +{ + "name": "igorludgero/warmcache", + "require": { + "php": "~5.6.0|~7.0.0|~7.1.0" + }, + "type": "magento2-module", + "version": "1.0.0", + "description": "A warm cache extension.", + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Igorludgero\\WarmCache\\": "" + } + } +} diff --git a/etc/acl.xml b/etc/acl.xml new file mode 100644 index 0000000..41fb0ae --- /dev/null +++ b/etc/acl.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml new file mode 100644 index 0000000..75522c3 --- /dev/null +++ b/etc/adminhtml/routes.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml new file mode 100644 index 0000000..860a105 --- /dev/null +++ b/etc/adminhtml/system.xml @@ -0,0 +1,45 @@ + + + + + + + +
+ + igorludgero + Igorludgero_WarmCache::settings + + + Select each entity type you want to add in the warm cache process. + + + Magento\Config\Model\Config\Source\Yesno + + + + Magento\Config\Model\Config\Source\Yesno + + + + Magento\Config\Model\Config\Source\Yesno + + + + Magento\Config\Model\Config\Source\Yesno + + +
+
+
\ No newline at end of file diff --git a/etc/cron_groups.xml b/etc/cron_groups.xml new file mode 100644 index 0000000..778c4d9 --- /dev/null +++ b/etc/cron_groups.xml @@ -0,0 +1,24 @@ + + + + + 1 + 4 + 2 + 10 + 60 + 600 + 1 + + \ No newline at end of file diff --git a/etc/crontab.xml b/etc/crontab.xml new file mode 100644 index 0000000..633d752 --- /dev/null +++ b/etc/crontab.xml @@ -0,0 +1,20 @@ + + + + + + * * * * * + + + \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml new file mode 100755 index 0000000..91ce3a4 --- /dev/null +++ b/etc/di.xml @@ -0,0 +1,23 @@ + + + + + + + + Igorludgero\WarmCache\Console\Command\WarmCache + + + + \ No newline at end of file diff --git a/etc/module.xml b/etc/module.xml new file mode 100644 index 0000000..91cf290 --- /dev/null +++ b/etc/module.xml @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/registration.php b/registration.php new file mode 100755 index 0000000..6733e08 --- /dev/null +++ b/registration.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) + * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 + */ + +\Magento\Framework\Component\ComponentRegistrar::register( + \Magento\Framework\Component\ComponentRegistrar::MODULE, + 'Igorludgero_WarmCache', + __DIR__ +); \ No newline at end of file