├── .gitignore ├── Block └── Adminhtml │ └── Cache.php ├── Console └── Command │ ├── Disable.php │ └── WarmCache.php ├── Controller └── Adminhtml │ └── WarmCache │ └── Run.php ├── Cron └── Run.php ├── Helper └── Data.php ├── README.md ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ ├── routes.xml │ └── system.xml ├── cron_groups.xml ├── crontab.xml ├── di.xml └── module.xml └── registration.php /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | \.idea/ 3 | 4 | \.DS_Store 5 | -------------------------------------------------------------------------------- /Block/Adminhtml/Cache.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Block\Adminhtml; 15 | 16 | use Magento\Backend\Block\Cache as OriginalCache; 17 | 18 | class Cache extends OriginalCache 19 | { 20 | /** 21 | * Cache block constructor. 22 | */ 23 | protected function _construct() 24 | { 25 | parent::_construct(); 26 | $this->buttonList->add( 27 | 'warm_cache', 28 | [ 29 | 'label' => __('Run Warm Cache'), 30 | 'onclick' => "window.location.href = '".$this->getWarmCacheUrl()."'", 31 | 'class' => 'run-warm-cache' 32 | ] 33 | ); 34 | } 35 | 36 | /** 37 | * Get warm cache action url. 38 | * @return string 39 | */ 40 | private function getWarmCacheUrl() 41 | { 42 | return $this->getUrl('warmcache/WarmCache/run'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Console/Command/Disable.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Console\Command; 15 | 16 | use Igorludgero\WarmCache\Helper\Data; 17 | use Magento\Framework\App\State; 18 | use Magento\Framework\App\ObjectManager; 19 | use Symfony\Component\Console\Command\Command; 20 | use Symfony\Component\Console\Input\InputInterface; 21 | use Symfony\Component\Console\Output\OutputInterface; 22 | 23 | class Disable extends Command 24 | { 25 | /** 26 | * @var State 27 | */ 28 | protected $appState; 29 | 30 | /** 31 | * Disable constructor. 32 | * @param State $appState 33 | */ 34 | public function __construct( 35 | State $appState 36 | ) { 37 | $this->appState = $appState; 38 | parent::__construct('igorludgero:warmcache_disable'); 39 | } 40 | 41 | /** 42 | * Configure cli command. 43 | */ 44 | protected function configure() 45 | { 46 | $this->setName('igorludgero:warmcache_disable') 47 | ->setDescription('Disable warm cache.'); 48 | } 49 | 50 | /** 51 | * Execute cli command 52 | * @param InputInterface $input 53 | * @param OutputInterface $output 54 | * @return $this|int|null 55 | * @throws \Magento\Framework\Exception\LocalizedException 56 | */ 57 | protected function execute( 58 | InputInterface $input, 59 | OutputInterface $output 60 | ) { 61 | $this->appState->setAreaCode('adminhtml'); 62 | /** 63 | * @var $helper Data 64 | */ 65 | $helper = ObjectManager::getInstance()->create(Data::class); 66 | $helper->disableExtension(); 67 | $helper->logMessage("Warm cache disabled. Please clear the caches."); 68 | $output->writeln('Warm cache disabled. Please clear the caches.'); 69 | return $this; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Console/Command/WarmCache.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Console\Command; 15 | 16 | use Igorludgero\WarmCache\Helper\Data; 17 | use Magento\Framework\App\State; 18 | use Magento\Framework\App\ObjectManager; 19 | use Symfony\Component\Console\Command\Command; 20 | use Symfony\Component\Console\Input\InputInterface; 21 | use Symfony\Component\Console\Output\OutputInterface; 22 | 23 | class WarmCache extends Command 24 | { 25 | /** 26 | * @var State 27 | */ 28 | protected $appState; 29 | 30 | /** 31 | * WarmCache constructor. 32 | * @param State $appState 33 | */ 34 | public function __construct( 35 | State $appState 36 | ) { 37 | $this->appState = $appState; 38 | parent::__construct('igorludgero:warmcache'); 39 | } 40 | 41 | /** 42 | * Configure cli command. 43 | */ 44 | protected function configure() 45 | { 46 | $this->setName('igorludgero:warmcache') 47 | ->setDescription('Run the warm cache and cache all available pages in the store.'); 48 | } 49 | 50 | /** 51 | * Execute cli command 52 | * @param InputInterface $input 53 | * @param OutputInterface $output 54 | * @return $this|int|null 55 | * @throws \Magento\Framework\Exception\LocalizedException 56 | */ 57 | protected function execute( 58 | InputInterface $input, 59 | OutputInterface $output 60 | ) { 61 | $this->appState->setAreaCode('adminhtml'); 62 | /** 63 | * @var $helper Data 64 | */ 65 | $helper = ObjectManager::getInstance()->create(Data::class); 66 | if ($helper->run()) { 67 | $helper->logMessage("Warm cache process finished."); 68 | $output->writeln('Warm cache process finished.'); 69 | } else { 70 | $output->writeln('Was not possible to run the command, please try again later. '. 71 | 'Check if the extension is enabled on admin and if you enabled at least one warm cache type.'); 72 | } 73 | return $this; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Controller/Adminhtml/WarmCache/Run.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Controller\Adminhtml\WarmCache; 15 | 16 | use Magento\Backend\App\Action; 17 | use Magento\Backend\App\Action\Context; 18 | use Magento\Framework\Controller\ResultFactory; 19 | use Igorludgero\WarmCache\Helper\Data; 20 | 21 | class Run extends Action 22 | { 23 | /** 24 | * @var Data 25 | */ 26 | protected $helper; 27 | 28 | /** 29 | * Run constructor. 30 | * @param Action\Context $context 31 | * @param Data $helper 32 | */ 33 | public function __construct( 34 | Context $context, 35 | Data $helper 36 | ) { 37 | parent::__construct($context); 38 | $this->_helper = $helper; 39 | } 40 | 41 | /** 42 | * Start the WarmCache. 43 | */ 44 | public function execute() 45 | { 46 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); 47 | $this->_helper->run(); 48 | $this->messageManager->addSuccessMessage(__("Warm cache ran successfully!")); 49 | $resultRedirect->setUrl($this->_redirect->getRefererUrl()); 50 | return $resultRedirect; 51 | } 52 | 53 | protected function _isAllowed() 54 | { 55 | return $this->_authorization->isAllowed('Igorludgero_Warmcache::settings'); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Cron/Run.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Cron; 15 | 16 | use Igorludgero\WarmCache\Helper\Data; 17 | 18 | class Run 19 | { 20 | 21 | /** 22 | * @var Data 23 | */ 24 | protected $helper; 25 | 26 | /** 27 | * Run constructor. 28 | * @param Data $helper 29 | */ 30 | public function __construct(Data $helper) 31 | { 32 | $this->helper = $helper; 33 | } 34 | 35 | /** 36 | * Run the warm cache process. 37 | * @return $this 38 | */ 39 | public function execute() 40 | { 41 | $this->helper->run(); 42 | return $this; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Helper/Data.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | namespace Igorludgero\WarmCache\Helper; 15 | 16 | use Magento\Catalog\Model\CategoryFactory; 17 | use Magento\Catalog\Model\Product\Attribute\Source\Status; 18 | use Magento\Catalog\Model\Product\Visibility; 19 | use Magento\Catalog\Model\ProductFactory; 20 | use Magento\Cms\Model\PageFactory; 21 | use Magento\Framework\App\Config\Storage\WriterInterface; 22 | use Magento\Framework\App\Helper\AbstractHelper; 23 | use Magento\Framework\App\Helper\Context; 24 | use Magento\Framework\Url; 25 | use Magento\Store\Model\ScopeInterface; 26 | use Magento\UrlRewrite\Model\UrlRewriteFactory; 27 | use Zend\Log\Logger; 28 | 29 | class Data extends AbstractHelper 30 | { 31 | 32 | /** 33 | * @var array 34 | */ 35 | protected $urls = array(); 36 | 37 | /** 38 | * @var ProductFactory 39 | */ 40 | protected $productModel; 41 | 42 | /** 43 | * @var CategoryFactory 44 | */ 45 | protected $categoryModel; 46 | 47 | /** 48 | * @var PageFactory 49 | */ 50 | protected $pageModel; 51 | 52 | /** 53 | * @var UrlRewriteFactory 54 | */ 55 | protected $urlRewriteModel; 56 | 57 | /** 58 | * @var Logger 59 | */ 60 | protected $logger; 61 | 62 | /** 63 | * @var Url 64 | */ 65 | protected $frontUrlModel; 66 | 67 | /** 68 | * @var WriterInterface 69 | */ 70 | protected $writerInterface; 71 | 72 | /** 73 | * Data constructor. 74 | * @param Context $context 75 | * @param ProductFactory $productModel 76 | * @param CategoryFactory $categoryModel 77 | * @param PageFactory $pageModel 78 | * @param UrlRewriteFactory $urlRewriteModel 79 | * @param Url $frontUrlModel 80 | * @param WriterInterface $writerInterface 81 | */ 82 | public function __construct( 83 | Context $context, 84 | ProductFactory $productModel, 85 | CategoryFactory $categoryModel, 86 | PageFactory $pageModel, 87 | UrlRewriteFactory $urlRewriteModel, 88 | Url $frontUrlModel, 89 | WriterInterface $writerInterface 90 | ) { 91 | parent::__construct($context); 92 | $this->productModel = $productModel; 93 | $this->categoryModel = $categoryModel; 94 | $this->pageModel = $pageModel; 95 | $this->urlRewriteModel = $urlRewriteModel; 96 | $this->frontUrlModel = $frontUrlModel; 97 | $this->writerInterface = $writerInterface; 98 | $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/igorludgero_warmcache.log'); 99 | $this->logger = new \Zend\Log\Logger(); 100 | $this->logger->addWriter($writer); 101 | } 102 | 103 | /** 104 | * Log a custom message. 105 | * @param $message 106 | */ 107 | public function logMessage($message) 108 | { 109 | $this->logger->info($message); 110 | } 111 | 112 | /** 113 | * Get all urls to be cached. 114 | */ 115 | private function getUrls() 116 | { 117 | //Add Products url 118 | if ($this->scopeConfig->getValue('warmcache/settings/product', ScopeInterface::SCOPE_STORE)) { 119 | $_productCollection = $this->productModel->create()->getCollection() 120 | ->addAttributeToFilter('status', Status::STATUS_ENABLED) 121 | ->addAttributeToFilter( 122 | 'visibility', 123 | array(Visibility::VISIBILITY_IN_CATALOG, Visibility::VISIBILITY_BOTH) 124 | ) 125 | ->addAttributeToSelect(["entity_id"]); 126 | foreach ($_productCollection as $_product) { 127 | $url = $this->frontUrlModel->getUrl("catalog/product/view", ['id' => $_product->getId()]); 128 | if (!in_array($url, $this->urls)) { 129 | $this->urls[] = $url; 130 | } 131 | } 132 | } 133 | 134 | //Add category url 135 | if ($this->scopeConfig->getValue('warmcache/settings/category', ScopeInterface::SCOPE_STORE)) { 136 | $_categoryCollection = $this->categoryModel->create()->getCollection() 137 | ->addAttributeToFilter('is_active', 1) 138 | ->addAttributeToSelect(["entity_id"]); 139 | foreach ($_categoryCollection as $_category) { 140 | $url = $this->frontUrlModel->getUrl("catalog/category/view", ['id' => $_category->getId()]); 141 | if (!in_array($url, $this->urls)) { 142 | $this->urls[] = $url; 143 | } 144 | } 145 | } 146 | 147 | //Add cms pages 148 | if ($this->scopeConfig->getValue('warmcache/settings/cms_pages', ScopeInterface::SCOPE_STORE)) { 149 | $_cmsPageCollection = $this->pageModel->create()->getCollection()->addFieldToFilter("is_active", 1) 150 | ->addFieldToSelect("page_id"); 151 | foreach ($_cmsPageCollection as $page) { 152 | $url = $this->frontUrlModel->getUrl("cms/page/view", ['id' => $page->getId()]); 153 | if (!in_array($url, $this->urls)) { 154 | $this->urls[] = $url; 155 | } 156 | } 157 | } 158 | 159 | //Custom urls in url rewrite. 160 | if ($this->scopeConfig->getValue('warmcache/settings/url_rewrite', ScopeInterface::SCOPE_STORE)) { 161 | $_urlRewriteCollection = $this->urlRewriteModel->create() 162 | ->getCollection() 163 | ->addFieldToSelect("target_path") 164 | ->addFieldToFilter('entity_type', array('nin' => array('cms-page', 'category', 'product'))); 165 | foreach ($_urlRewriteCollection as $urlRewrite) { 166 | $newUrl = $this->frontUrlModel->getBaseUrl() . $urlRewrite->getRequestPath(); 167 | if (!in_array($newUrl, $this->urls)) { 168 | $this->urls[] = $newUrl; 169 | } 170 | } 171 | } 172 | } 173 | 174 | /** 175 | * Run the crawler. 176 | */ 177 | public function run() 178 | { 179 | if ($this->isEnabled()) { 180 | $this->getUrls(); 181 | if (count($this->urls) > 0) { 182 | try { 183 | foreach ($this->urls as $url) { 184 | $this->checkUrl($url); 185 | } 186 | return true; 187 | } catch (\Exception $ex) { 188 | $this->logMessage("Error in WarmCache: " . $ex->getMessage()); 189 | return false; 190 | } 191 | } 192 | } 193 | return false; 194 | } 195 | 196 | /** 197 | * Render the url. 198 | * @param $url 199 | */ 200 | private function checkUrl($url) 201 | { 202 | $user_agent='Mozilla/4.0 (compatible;)'; 203 | 204 | $options = array( 205 | 206 | CURLOPT_CUSTOMREQUEST =>"GET", //set request type post or get 207 | CURLOPT_POST =>false, //set to GET 208 | CURLOPT_USERAGENT => $user_agent, //set user agent 209 | CURLOPT_COOKIEFILE =>"cookie.txt", //set cookie file 210 | CURLOPT_COOKIEJAR =>"cookie.txt", //set cookie jar 211 | CURLOPT_RETURNTRANSFER => true, // return web page 212 | CURLOPT_HEADER => false, // don't return headers 213 | CURLOPT_FOLLOWLOCATION => true, // follow redirects 214 | CURLOPT_ENCODING => "", // handle all encodings 215 | CURLOPT_AUTOREFERER => true, // set referer on redirect 216 | CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect 217 | CURLOPT_TIMEOUT => 120, // timeout on response 218 | CURLOPT_MAXREDIRS => 4, // stop after 10 redirects 219 | ); 220 | 221 | $ch = curl_init($url); 222 | curl_setopt_array($ch, $options); 223 | $content = curl_exec($ch); 224 | $err = curl_errno($ch); 225 | $errmsg = curl_error($ch); 226 | $header = curl_getinfo($ch); 227 | curl_close($ch); 228 | 229 | $header['errno'] = $err; 230 | $header['errmsg'] = $errmsg; 231 | $header['content'] = $content; 232 | } 233 | 234 | /** 235 | * Disable warm cache enable setting 236 | */ 237 | public function disableExtension() 238 | { 239 | $this->writerInterface->save("warmcache/settings/enable", 0); 240 | } 241 | 242 | /** 243 | * Is the extension enabled 244 | * @return bool 245 | */ 246 | public function isEnabled() 247 | { 248 | return (bool)$this->scopeConfig->getValue('warmcache/settings/enable', ScopeInterface::SCOPE_STORE); 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cache warm extension for Magento 2 (FREE). 2 | A warm cache extension for Magento 2. 3 | This extension adds the feature of cache warm to Magento 2. It's possible to start the cache warm process from admin inside the cache management section, by the cronjob or using a command line. 4 | 5 | ### Install using composer: 6 | composer require igorludgero/warmcache 7 | 8 | ### Run the warmer from admin: 9 | http://prntscr.com/gj8ebu 10 | 11 | ### Cron job: 12 | http://prntscr.com/gj8ejs 13 | 14 | ### Cli command: 15 | php bin/magento igorludgero:warmcache 16 | 17 | #### Contact me in my email: igor@igorludgero.com 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "igorludgero/warmcache", 3 | "require": { 4 | }, 5 | "type": "magento2-module", 6 | "version": "1.0.2", 7 | "description": "A warm cache extension for Magento 2.1 and 2.2", 8 | "autoload": { 9 | "files": [ 10 | "registration.php" 11 | ], 12 | "psr-4": { 13 | "Igorludgero\\WarmCache\\": "" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /etc/adminhtml/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | igorludgero 22 | Igorludgero_WarmCache::settings 23 | 24 | 25 | Select each entity type you want to add in the warm cache process. 26 | 27 | 28 | Magento\Config\Model\Config\Source\Yesno 29 | 30 | 31 | 32 | Magento\Config\Model\Config\Source\Yesno 33 | 34 | 1 35 | 36 | 37 | 38 | 39 | Magento\Config\Model\Config\Source\Yesno 40 | 41 | 1 42 | 43 | 44 | 45 | 46 | Magento\Config\Model\Config\Source\Yesno 47 | 48 | 1 49 | 50 | 51 | 52 | 53 | Magento\Config\Model\Config\Source\Yesno 54 | 55 | 1 56 | 57 | 58 | 59 |
60 |
61 |
-------------------------------------------------------------------------------- /etc/cron_groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 1380 17 | 4 18 | 2 19 | 10 20 | 60 21 | 600 22 | 1 23 | 24 | -------------------------------------------------------------------------------- /etc/crontab.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | * * * * * 18 | 19 | 20 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | Igorludgero\WarmCache\Console\Command\WarmCache 20 | Igorludgero\WarmCache\Console\Command\Disable 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright Copyright (c) 2017 Igor Ludgero Miura (https://www.igorludgero.com/) 11 | * @license https://opensource.org/licenses/OSL-3.0.php Open Software License 3.0 12 | */ 13 | 14 | \Magento\Framework\Component\ComponentRegistrar::register( 15 | \Magento\Framework\Component\ComponentRegistrar::MODULE, 16 | 'Igorludgero_WarmCache', 17 | __DIR__ 18 | ); --------------------------------------------------------------------------------