├── .gitignore ├── Api ├── CacheRouteManagementInterface.php ├── CacheRouteRepositoryInterface.php ├── CacheTagManagementInterface.php ├── CacheTagRepositoryInterface.php ├── CacheVaryDataRepositoryInterface.php ├── Data │ ├── CacheRouteInterface.php │ └── CacheTagInterface.php └── RoutesTagsLinkManagementInterface.php ├── Console └── Command │ └── CacheWarmup.php ├── Model ├── CacheRouteManagement.php ├── CacheRouteRepository.php ├── CacheTagManagement.php ├── CacheTagRepository.php ├── CacheVaryDataRepository.php ├── Route │ ├── CacheRoute.php │ ├── Management │ │ ├── IncrementPopularityById.php │ │ └── IncrementPopularityByRoute.php │ └── Query │ │ ├── GetById.php │ │ ├── GetByRoute.php │ │ └── SaveRoute.php ├── RoutesTagsLink │ └── Management │ │ └── LinkRouteToTags.php ├── RoutesTagsLinkManagement.php ├── Tag │ ├── CacheTag.php │ ├── Management │ │ └── InvalidateRoutesByTags.php │ └── Query │ │ ├── GetById.php │ │ ├── GetByTag.php │ │ └── SaveTag.php └── VaryData │ ├── Applicator │ ├── CustomerGroupApplicator.php │ ├── VaryDataApplicatorInterface.php │ └── VaryDataApplicatorList.php │ └── Query │ ├── GetAllVaryData.php │ └── SaveVaryData.php ├── Plugin └── CacheIdentifier │ └── SaveVaryData.php ├── Service ├── Route │ ├── GetExistingOrNewRouteModel.php │ └── NewRouteModelProvider.php └── Tag │ ├── GetExistingOrNewTagModel.php │ └── NewTagModelProvider.php ├── Setup └── InstallSchema.php ├── composer.json ├── etc ├── di.xml ├── frontend │ └── di.xml ├── module.xml └── webapi.xml ├── registration.php └── view └── frontend ├── layout └── default.xml └── web └── increment-popularity.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /Api/CacheRouteManagementInterface.php: -------------------------------------------------------------------------------- 1 | urlInterface = $urlInterface; 52 | $this->urlRewriteCollectionFactory = $urlRewriteCollectionFactory; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | protected function configure() 59 | { 60 | $this->setName("cache:warmup") 61 | ->addOption( 62 | 'pageTypes', 63 | 'p', 64 | InputArgument::OPTIONAL, 65 | 'Comma-separated PageTypes like cms-page,product,category or all -> Default: all' 66 | ) 67 | ->addArgument( 68 | 'concurrency', 69 | InputArgument::OPTIONAL, 70 | 'Maximum number of concurrent curl requests -> Default: 10' 71 | ) 72 | ->addOption( 73 | 'stopAfter', 74 | 's', 75 | InputArgument::OPTIONAL 76 | ) 77 | ->setDescription('Fire curl requests to warm up varnish cache'); 78 | 79 | parent::configure(); 80 | } 81 | 82 | private function initParams(InputInterface $input) 83 | { 84 | $pageTypes = $input->getOption("pageTypes"); 85 | if (strlen($pageTypes) > 0) { 86 | $this->pageTypes = explode(",", $pageTypes); 87 | } 88 | $maxThreads = $input->getArgument("concurrency"); 89 | if (intval($maxThreads) > 0) { 90 | $this->maxConcurrentRequests = $maxThreads; 91 | } 92 | $stopAfter = $input->getOption("stopAfter"); 93 | if (intval($stopAfter) > 0) { 94 | $this->stopAfter = $stopAfter; 95 | } 96 | } 97 | 98 | /** 99 | * @param InputInterface $input 100 | * @param OutputInterface $output 101 | * @return int|null|void 102 | * @throws \Exception 103 | */ 104 | protected function execute(InputInterface $input, OutputInterface $output) 105 | { 106 | $this->initParams($input); 107 | 108 | $urlCollection = $this->getRewriteCollection(); 109 | 110 | if (!$urlCollection) { 111 | $up = new \Exception("No Rewrite Collection Loaded, may you misspelled the params?"); 112 | throw $up; // haha 113 | } 114 | 115 | $client = $this->getClient(); 116 | $requests = $this->getRequests($client, $urlCollection); 117 | $pool = $this->getPool($client, $requests, $output); 118 | $promise = $pool->promise(); 119 | $promise->wait(); 120 | } 121 | 122 | /** 123 | * @param Client $client 124 | * @param callable $requests 125 | * @param OutputInterface $output 126 | * @return Pool 127 | */ 128 | private function getPool(Client $client, callable $requests, OutputInterface $output) 129 | { 130 | return new Pool($client, $requests(), [ 131 | 'concurrency' => $this->maxConcurrentRequests, 132 | 'fulfilled' => function ($response, $index) use ($output) { 133 | $output->writeln("Successful: " . $index); 134 | }, 135 | 'rejected' => function ($reason, $index) use ($output) { 136 | $output->writeln("Rejected: " . $index); 137 | }, 138 | ]); 139 | } 140 | 141 | /** 142 | * @param Client $client 143 | * @param $urlCollection 144 | * @return \Closure 145 | */ 146 | private function getRequests(Client $client, $urlCollection) 147 | { 148 | return function () use ($client, $urlCollection) { 149 | /** @var UrlRewrite $url */ 150 | foreach ($urlCollection as $url) { 151 | yield function() use ($client, $url) { 152 | return $client->getAsync($url->getRequestPath()); 153 | }; 154 | } 155 | }; 156 | } 157 | 158 | /** 159 | * @return Client 160 | */ 161 | private function getClient() 162 | { 163 | $baseUrl = $this->urlInterface->getBaseUrl(); 164 | return new Client([ 165 | RequestOptions::ALLOW_REDIRECTS => true, 166 | 'base_uri' => $baseUrl 167 | ]); 168 | } 169 | 170 | /** 171 | * @return UrlRewriteCollection|null 172 | */ 173 | private function getRewriteCollection() 174 | { 175 | $rewriteFilter = $this->getRewriteFilter(); 176 | return $rewriteFilter 177 | ? $this->urlRewriteCollectionFactory->create()->addFieldToFilter("entity_type", $rewriteFilter) 178 | : null; 179 | } 180 | 181 | /** 182 | * @param OutputInterface $output 183 | * @return bool 184 | */ 185 | public function isVerbose(OutputInterface $output) 186 | { 187 | return $output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE; 188 | } 189 | 190 | /** 191 | * @return array|null 192 | */ 193 | private function getRewriteFilter() 194 | { 195 | if ($this->pageTypes == 'all') { 196 | return $this->possiblePageTypes; 197 | } 198 | 199 | if (!is_array($this->pageTypes)) { 200 | $this->pageTypes = [$this->pageTypes]; 201 | } 202 | 203 | $filter = []; 204 | 205 | foreach ($this->pageTypes as $pageType) { 206 | if (in_array($pageType, $this->possiblePageTypes)) { 207 | $filter[] = $pageType; 208 | } 209 | } 210 | 211 | return !empty($filter) ? $filter : null; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /Model/CacheRouteManagement.php: -------------------------------------------------------------------------------- 1 | incrementPopularityById = $incrementPopularityById; 25 | $this->incrementPopularityByRoute = $incrementPopularityByRoute; 26 | } 27 | 28 | public function incrementPopularityByRoute(string $route): void 29 | { 30 | $this->incrementPopularityByRoute->execute($route); 31 | } 32 | 33 | public function incrementPopularityById(int $routeId): void 34 | { 35 | $this->incrementPopularityById->execute($routeId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Model/CacheRouteRepository.php: -------------------------------------------------------------------------------- 1 | getByIdQuery = $getByIdQuery; 34 | $this->getByRoute = $getByRoute; 35 | $this->saveCommand = $saveCommand; 36 | } 37 | 38 | public function getById(int $id):? CacheRouteInterface 39 | { 40 | return $this->getByIdQuery->execute($id); 41 | } 42 | 43 | public function getByRoute(string $route):? CacheRouteInterface 44 | { 45 | return $this->getByRoute->execute($route); 46 | } 47 | 48 | public function save(CacheRouteInterface $cacheRoute): void 49 | { 50 | $this->saveCommand->execute($cacheRoute); 51 | } 52 | } -------------------------------------------------------------------------------- /Model/CacheTagManagement.php: -------------------------------------------------------------------------------- 1 | invalidateRoutesByTags = $invalidateRoutesByTags; 20 | } 21 | 22 | /** 23 | * @param string[] $tags 24 | */ 25 | public function invalidateRoutesByTags(array $tags): void 26 | { 27 | $this->invalidateRoutesByTags->execute($tags); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Model/CacheTagRepository.php: -------------------------------------------------------------------------------- 1 | getById = $getById; 34 | $this->getByTag = $getByTag; 35 | $this->saveCommand = $saveCommand; 36 | } 37 | 38 | public function getById(int $id):? CacheTagInterface 39 | { 40 | return $this->getById->execute($id); 41 | } 42 | 43 | public function getByTag(string $cacheTag):? CacheTagInterface 44 | { 45 | return $this->getByTag->execute($cacheTag); 46 | } 47 | 48 | public function save(CacheTagInterface $cacheTag): void 49 | { 50 | $this->saveCommand->execute($cacheTag); 51 | } 52 | } -------------------------------------------------------------------------------- /Model/CacheVaryDataRepository.php: -------------------------------------------------------------------------------- 1 | saveVaryData = $saveVaryData; 24 | $this->getAllVaryData = $getAllVaryData; 25 | } 26 | 27 | /** 28 | * @param array $varyData 29 | */ 30 | public function save(array $varyData): void 31 | { 32 | $this->saveVaryData->execute($varyData); 33 | } 34 | 35 | /** 36 | * @return array[] 37 | */ 38 | public function getAll(): array 39 | { 40 | return $this->getAllVaryData->execute(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Model/Route/CacheRoute.php: -------------------------------------------------------------------------------- 1 | id; 44 | } 45 | 46 | /** 47 | * @param int $id 48 | * @return void 49 | */ 50 | public function setId(int $id): void 51 | { 52 | $this->id = $id; 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function getRoute():? string 59 | { 60 | return $this->route; 61 | } 62 | 63 | /** 64 | * @param string $route 65 | * @return void 66 | */ 67 | public function setRoute(string $route): void 68 | { 69 | $this->route = $route; 70 | } 71 | 72 | /** 73 | * @return bool 74 | */ 75 | public function getCacheStatus():? bool 76 | { 77 | return $this->cacheStatus; 78 | } 79 | 80 | /** 81 | * @param int|bool $cacheStatus 82 | * @return void 83 | */ 84 | public function setCacheStatus($cacheStatus): void 85 | { 86 | $this->cacheStatus = $cacheStatus; 87 | } 88 | 89 | /** 90 | * @return int 91 | */ 92 | public function getLifetime():? int 93 | { 94 | return $this->lifetime; 95 | } 96 | 97 | /** 98 | * @param int $lifetime 99 | * @return void 100 | */ 101 | public function setLifetime(int $lifetime): void 102 | { 103 | $this->lifetime = $lifetime; 104 | } 105 | 106 | /** 107 | * @return int 108 | */ 109 | public function getPopularity():? int 110 | { 111 | return $this->popularity; 112 | } 113 | 114 | /** 115 | * @param int $popularity 116 | * @return void 117 | */ 118 | public function setPopularity(int $popularity): void 119 | { 120 | $this->popularity = $popularity; 121 | } 122 | } -------------------------------------------------------------------------------- /Model/Route/Management/IncrementPopularityById.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 18 | } 19 | 20 | public function execute(int $id): void 21 | { 22 | $connection = $this->resourceConnection->getConnection(); 23 | 24 | $connection->update( 25 | 'cache_routes', 26 | ['popularity' => new \Zend_Db_Expr('popularity + 1')], 27 | ['id = ?' => $id] 28 | ); 29 | } 30 | } -------------------------------------------------------------------------------- /Model/Route/Management/IncrementPopularityByRoute.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 18 | } 19 | 20 | public function execute(string $route): void 21 | { 22 | $connection = $this->resourceConnection->getConnection(); 23 | 24 | $connection->update( 25 | 'cache_routes', 26 | ['popularity' => new \Zend_Db_Expr('popularity + 1')], 27 | ['cache_route = ?' => $route] 28 | ); 29 | } 30 | } -------------------------------------------------------------------------------- /Model/Route/Query/GetById.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 25 | $this->cacheRouteFactory = $cacheRouteFactory; 26 | } 27 | 28 | public function execute($id):? CacheRouteInterface 29 | { 30 | $connection = $this->resourceConnection->getConnection(); 31 | 32 | $dbRoute = array_pop($connection 33 | ->select() 34 | ->from('cache_routes') 35 | ->where('id = ?', $id) 36 | ->query() 37 | ->fetchAll() 38 | ); 39 | 40 | if ($dbRoute) { 41 | /** @var CacheRouteInterface $cacheRoute */ 42 | $cacheRoute = $this->cacheRouteFactory->create(); 43 | 44 | array_walk($dbRoute, function ($value, $key) use ($cacheRoute) { 45 | $camelCaseKey = "set" . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key); 46 | $cacheRoute->$camelCaseKey($value); 47 | }); 48 | } 49 | 50 | return $cacheRoute ?? null; 51 | } 52 | } -------------------------------------------------------------------------------- /Model/Route/Query/GetByRoute.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 25 | $this->cacheRouteFactory = $cacheRouteFactory; 26 | } 27 | 28 | public function execute(string $route):? CacheRouteInterface 29 | { 30 | $connection = $this->resourceConnection->getConnection(); 31 | 32 | $dbRoute = array_pop($connection 33 | ->select() 34 | ->from('cache_routes') 35 | ->where('route = ?', $route) 36 | ->query() 37 | ->fetchAll() 38 | ); 39 | 40 | if ($dbRoute) { 41 | /** @var CacheRouteInterface $cacheRoute */ 42 | $cacheRoute = $this->cacheRouteFactory->create(); 43 | 44 | array_walk($dbRoute, function ($value, $key) use ($cacheRoute) { 45 | $camelCaseKey = "set" . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key); 46 | $cacheRoute->$camelCaseKey($value); 47 | }); 48 | } 49 | 50 | return $cacheRoute ?? null; 51 | } 52 | } -------------------------------------------------------------------------------- /Model/Route/Query/SaveRoute.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 18 | } 19 | 20 | public function execute(CacheRouteInterface $cacheRoute): void 21 | { 22 | $connection = $this->resourceConnection->getConnection(); 23 | 24 | $connection->insertOnDuplicate( 25 | 'cache_routes', 26 | [ 27 | 'route' => $cacheRoute->getRoute(), 28 | 'cache_status' => $cacheRoute->getCacheStatus() ? 1 : 0, 29 | 'popularity' => $cacheRoute->getPopularity(), 30 | 'lifetime' => $cacheRoute->getLifetime() 31 | ], 32 | ['cache_status', 'popularity', 'lifetime'] 33 | ); 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /Model/RoutesTagsLink/Management/LinkRouteToTags.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 19 | } 20 | 21 | /** 22 | * @param int $routeId 23 | * @param int[] $tagIds 24 | * @throws \Zend_Db_Exception 25 | */ 26 | public function execute(int $routeId, array $tagIds): void 27 | { 28 | $routeToTags = []; 29 | array_walk($tagIds, function ($tagId) use ($routeId, $routeToTags) { 30 | $routeToTags[] = [ 31 | 'tag_id' => $tagId, 32 | 'route_id' => $routeId 33 | ]; 34 | }); 35 | 36 | /** @var Mysql $connection */ 37 | $connection = $this->resourceConnection->getConnection(); 38 | $connection->insertArray( 39 | 'cache_routes_tags', 40 | ['route_id', 'tag_id'], 41 | $routeToTags, 42 | $connection::INSERT_IGNORE 43 | ); 44 | } 45 | } -------------------------------------------------------------------------------- /Model/RoutesTagsLinkManagement.php: -------------------------------------------------------------------------------- 1 | linkRouteToTags = $linkRouteToTags; 22 | } 23 | 24 | /** 25 | * Take care, that this only works if both (route & tags) exists 26 | * 27 | * @param CacheRouteInterface $cacheRoute 28 | * @param CacheTagInterface[] $tags 29 | * 30 | * @throws \Zend_Db_Exception 31 | */ 32 | public function linkRouteToTags(CacheRouteInterface $cacheRoute, array $tags): void 33 | { 34 | array_walk($tags, function (&$value) {return $value->getId();}); 35 | $this->linkRouteToTags->execute($cacheRoute->getId(), $tags); 36 | } 37 | } -------------------------------------------------------------------------------- /Model/Tag/CacheTag.php: -------------------------------------------------------------------------------- 1 | id; 30 | } 31 | 32 | /** 33 | * @param int $id 34 | * @return mixed 35 | */ 36 | public function setId(int $id): void 37 | { 38 | $this->id = $id; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getCacheTag():? string 45 | { 46 | return $this->cacheTag; 47 | } 48 | 49 | /** 50 | * @param string $cacheTag 51 | * @return mixed 52 | */ 53 | public function setCacheTag(string $cacheTag): void 54 | { 55 | $this->cacheTag = $cacheTag; 56 | } 57 | } -------------------------------------------------------------------------------- /Model/Tag/Management/InvalidateRoutesByTags.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 18 | } 19 | 20 | /** 21 | * @param string[] $tags 22 | */ 23 | public function execute(array $tags): void 24 | { 25 | $connection = $this->resourceConnection->getConnection(); 26 | 27 | $routesSql = $connection 28 | ->select() 29 | ->from(["crt" => 'cache_routes_tags'], ['id' => 'route_id']) 30 | ->joinLeft( 31 | ['ct' => 'cache_tags'], 32 | "crt.tag_id = ct.id", 33 | ['tag_id' => 'id'] 34 | )->where('ct.tag in (?)', $tags)->__toString(); 35 | 36 | $connection->update( 37 | 'cache_routes', 38 | ['cache_status' => 0], 39 | ['id IN (?)' => $routesSql] 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /Model/Tag/Query/GetById.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 26 | $this->cacheTagFactory = $cacheTagFactory; 27 | } 28 | 29 | public function execute(int $id):? CacheTagInterface 30 | { 31 | $connection = $this->resourceConnection->getConnection(); 32 | 33 | $dbRoute = array_pop($connection 34 | ->select() 35 | ->from('cache_tags') 36 | ->where('id = ?', $id) 37 | ->query() 38 | ->fetchAll() 39 | ); 40 | 41 | if ($dbRoute) { 42 | /** @var CacheTagInterface $cacheTag */ 43 | $cacheRoute = $this->cacheTagFactory->create(); 44 | 45 | array_walk($dbRoute, function ($value, $key) use ($cacheRoute) { 46 | $camelCaseKey = "set" . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key); 47 | $cacheRoute->$camelCaseKey($value); 48 | }); 49 | } 50 | 51 | return $cacheRoute ?? null; 52 | } 53 | } -------------------------------------------------------------------------------- /Model/Tag/Query/GetByTag.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 26 | $this->cacheTagFactory = $cacheTagFactory; 27 | } 28 | 29 | public function execute(string $tag):? CacheTagInterface 30 | { 31 | $connection = $this->resourceConnection->getConnection(); 32 | 33 | $dbRoute = array_pop($connection 34 | ->select() 35 | ->from('cache_tags') 36 | ->where('cache_tag = ?', $tag) 37 | ->query() 38 | ->fetchAll() 39 | ); 40 | 41 | if ($dbRoute) { 42 | /** @var CacheTagInterface $cacheTag */ 43 | $cacheRoute = $this->cacheTagFactory->create(); 44 | 45 | array_walk($dbRoute, function ($value, $key) use ($cacheRoute) { 46 | $camelCaseKey = "set" . SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key); 47 | $cacheRoute->$camelCaseKey($value); 48 | }); 49 | } 50 | 51 | return $cacheRoute ?? null; 52 | } 53 | } -------------------------------------------------------------------------------- /Model/Tag/Query/SaveTag.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 18 | } 19 | 20 | public function execute(CacheTagInterface $cacheTag): void 21 | { 22 | $connection = $this->resourceConnection->getConnection(); 23 | 24 | $connection->insert( 25 | 'cache_routes', 26 | ['cache_tag' => $cacheTag->getCacheTag()] 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Model/VaryData/Applicator/CustomerGroupApplicator.php: -------------------------------------------------------------------------------- 1 | customerSession = $customerSession; 25 | $this->customerFactory = $customerFactory; 26 | } 27 | 28 | public function apply(array $varyData): void 29 | { 30 | $this->customerSession->clearStorage(); 31 | $customerGroupId = $varyData[self::VARY_DATA_KEY]; 32 | $customer = $this->customerFactory->create()->setGroupId($customerGroupId); 33 | $this->customerSession->setCustomerGroupId($customerGroupId); 34 | $this->customerSession->setCustomer($customer); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Model/VaryData/Applicator/VaryDataApplicatorInterface.php: -------------------------------------------------------------------------------- 1 | varyDataApplicators = $varyDataApplicators; 20 | } 21 | 22 | public function applyAll(array $varyData): void 23 | { 24 | foreach ($this->varyDataApplicators as $varyDataApplicator) { 25 | $varyDataApplicator->apply($varyData); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Model/VaryData/Query/GetAllVaryData.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 29 | $this->serializer = $serializer; 30 | } 31 | 32 | /** 33 | * @return array[] 34 | */ 35 | public function execute(): array 36 | { 37 | $connection = $this->resourceConnection->getConnection(); 38 | return $connection->select() 39 | ->from('cache_vary_data') 40 | ->query() 41 | ->fetchAll(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Model/VaryData/Query/SaveVaryData.php: -------------------------------------------------------------------------------- 1 | resourceConnection = $resourceConnection; 23 | $this->serializer = $serializer; 24 | } 25 | 26 | public function execute(array $varyData): void 27 | { 28 | $connection = $this->resourceConnection->getConnection(); 29 | $connection->insertOnDuplicate( 30 | 'cache_vary_data', 31 | ['vary_data' => $this->serializer->serialize($varyData)], 32 | ['vary_data'] 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Plugin/CacheIdentifier/SaveVaryData.php: -------------------------------------------------------------------------------- 1 | httpContext = $httpContext; 29 | $this->varyDataRepository = $varyDataRepository; 30 | } 31 | 32 | /** 33 | * Adds a theme key to identifier for a built-in cache if user-agent theme rule is actual 34 | * 35 | * @param \Magento\Framework\App\PageCache\Identifier $identifier 36 | * @param string $result 37 | * @return string 38 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) 39 | */ 40 | public function afterGetValue(\Magento\Framework\App\PageCache\Identifier $identifier, $result): string 41 | { 42 | $varyData = $this->httpContext->toArray()['data']; 43 | $this->varyDataRepository->save($varyData); 44 | return $result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Service/Route/GetExistingOrNewRouteModel.php: -------------------------------------------------------------------------------- 1 | cacheRouteRepository = $cacheRouteRepository; 31 | $this->newRouteModelProvider = $newRouteModelProvider; 32 | } 33 | 34 | public function getByRoute(string $route): CacheRouteInterface 35 | { 36 | $routeModel = $this->cacheRouteRepository->getByRoute($route); 37 | 38 | if (!$routeModel) { 39 | $routeModel = $this->newRouteModelProvider->createForRoute($route); 40 | $this->cacheRouteRepository->save($routeModel); 41 | $routeModel = $this->cacheRouteRepository->getByRoute($route); 42 | } 43 | 44 | return $routeModel; 45 | } 46 | } -------------------------------------------------------------------------------- /Service/Route/NewRouteModelProvider.php: -------------------------------------------------------------------------------- 1 | cacheRouteInterfaceFactory = $cacheRouteInterfaceFactory; 26 | } 27 | 28 | public function createForRoute(string $route, int $cacheStatus = 0, int $lifetime = 86400, int $popularity = 0): CacheRouteInterface 29 | { 30 | /** @var CacheRouteInterface $freshCacheRoute */ 31 | $freshCacheRoute = $this->cacheRouteInterfaceFactory->create(); 32 | $freshCacheRoute->setRoute($route); 33 | $freshCacheRoute->setCacheStatus($cacheStatus); 34 | $freshCacheRoute->setLifetime($lifetime); 35 | $freshCacheRoute->setPopularity($popularity); 36 | 37 | return $freshCacheRoute; 38 | } 39 | } -------------------------------------------------------------------------------- /Service/Tag/GetExistingOrNewTagModel.php: -------------------------------------------------------------------------------- 1 | cacheTagRepository = $cacheTagRepository; 25 | $this->newTagModelProvider = $newTagModelProvider; 26 | } 27 | 28 | public function getByTag(string $cacheTag): CacheTagInterface 29 | { 30 | $cacheTag = $this->cacheTagRepository->getByTag($cacheTag); 31 | 32 | if (!$cacheTag) { 33 | $cacheTag = $this->newTagModelProvider->createForTag($cacheTag); 34 | $this->cacheTagRepository->save($cacheTag); 35 | $cacheTag = $this->cacheTagRepository->getByTag($cacheTag); 36 | } 37 | 38 | return $cacheTag; 39 | } 40 | } -------------------------------------------------------------------------------- /Service/Tag/NewTagModelProvider.php: -------------------------------------------------------------------------------- 1 | cacheTagInterfaceFactory = $cacheTagInterfaceFactory; 19 | } 20 | 21 | public function createForTag(string $cacheTag): CacheTagInterface 22 | { 23 | /** @var CacheTagInterface $tagModel */ 24 | $tagModel = $this->cacheTagInterfaceFactory->create(); 25 | $tagModel->setCacheTag($cacheTag); 26 | 27 | return $tagModel; 28 | } 29 | } -------------------------------------------------------------------------------- /Setup/InstallSchema.php: -------------------------------------------------------------------------------- 1 | startSetup(); 18 | $setup->getConnection()->createTable($this->getCacheTagTableDefinition($setup)); 19 | $setup->getConnection()->createTable($this->getCacheRouteTableDefinition($setup)); 20 | $setup->getConnection()->createTable($this->getCacheRouteTagTableDefinition($setup)); 21 | $setup->getConnection()->createTable($this->getVaryDataTableDefinition($setup)); 22 | $this->addCacheRouteTagForeignKeys($setup); 23 | $setup->endSetup(); 24 | } 25 | 26 | /** 27 | * @param SchemaSetupInterface $setup 28 | * @return \Magento\Framework\DB\Ddl\Table 29 | * @throws \Zend_Db_Exception 30 | */ 31 | private function getCacheTagTableDefinition(SchemaSetupInterface $setup): \Magento\Framework\DB\Ddl\Table 32 | { 33 | return $setup->getConnection()->newTable($setup->getTable('cache_tags')) 34 | ->addColumn( 35 | 'id', 36 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 37 | null, 38 | [ 39 | 'identity' => true, 40 | 'nullable' => false, 41 | 'primary' => true, 42 | 'unsigned' => true, 43 | ], 44 | 'Cache Tag ID' 45 | ) 46 | ->addColumn( 47 | 'cache_tag', 48 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 49 | 255, 50 | ['nullable' => false], 51 | 'Cache Tag' 52 | ) 53 | ->setComment('Cache Tag Table'); 54 | } 55 | 56 | /** 57 | * @param SchemaSetupInterface $setup 58 | * @return \Magento\Framework\DB\Ddl\Table 59 | * @throws \Zend_Db_Exception 60 | */ 61 | private function getVaryDataTableDefinition(SchemaSetupInterface $setup): \Magento\Framework\DB\Ddl\Table 62 | { 63 | return $setup->getConnection()->newTable($setup->getTable('cache_vary_data')) 64 | ->addColumn( 65 | 'vary_data', 66 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 67 | 255, 68 | [ 69 | 'nullable' => false, 70 | 'primary' => true 71 | ], 72 | 'Cache Vary Data' 73 | ) 74 | ->addIndex( 75 | $setup->getIdxName( 76 | 'cache_vary_data', 77 | ['vary_data'], 78 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 79 | ), 80 | ['vary_data'], 81 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 82 | ) 83 | ->setComment('Cache Vary Data Table'); 84 | } 85 | 86 | /** 87 | * @param SchemaSetupInterface $setup 88 | * @return \Magento\Framework\DB\Ddl\Table 89 | * @throws \Zend_Db_Exception 90 | */ 91 | private function getCacheRouteTableDefinition(SchemaSetupInterface $setup): \Magento\Framework\DB\Ddl\Table 92 | { 93 | return $setup->getConnection()->newTable($setup->getTable('cache_routes')) 94 | ->addColumn( 95 | 'id', 96 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 97 | null, 98 | [ 99 | 'identity' => true, 100 | 'nullable' => false, 101 | 'primary' => true, 102 | 'unsigned' => true, 103 | ], 104 | 'Cache Route ID' 105 | ) 106 | ->addColumn( 107 | 'cache_route', 108 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 109 | 255, 110 | ['nullable' => false], 111 | 'Cache Route' 112 | ) 113 | ->addIndex( 114 | $setup->getIdxName( 115 | 'cache_routes', 116 | ['cache_route'], 117 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE 118 | ), 119 | ['cache_route'], 120 | ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] 121 | ) 122 | ->addColumn( 123 | 'cache_status', 124 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 125 | 1, 126 | ['nullable' => false], 127 | 'Cache Status' 128 | ) 129 | ->addColumn( 130 | 'lifetime', 131 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 132 | null, 133 | ['nullable' => false], 134 | 'Cache Route Lifetime' 135 | ) 136 | ->addColumn( 137 | 'popularity', 138 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 139 | null, 140 | ['nullable' => false], 141 | 'Cache Route Populariy' 142 | ) 143 | ->setComment('Cache Route Table'); 144 | } 145 | 146 | /** 147 | * @param SchemaSetupInterface $setup 148 | * @return \Magento\Framework\DB\Ddl\Table 149 | * @throws \Zend_Db_Exception 150 | */ 151 | private function getCacheRouteTagTableDefinition(SchemaSetupInterface $setup): \Magento\Framework\DB\Ddl\Table 152 | { 153 | return $setup->getConnection()->newTable($setup->getTable('cache_routes_tags')) 154 | ->addColumn( 155 | 'route_id', 156 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 157 | null, 158 | ['nullable' => false, 'unsigned' => true], 159 | 'Cache Tag ID' 160 | ) 161 | ->addColumn( 162 | 'tag_id', 163 | \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, 164 | null, 165 | ['nullable => false', 'unsigned' => true], 166 | 'Cache Tag' 167 | ) 168 | ->setComment('Cache Tag Table'); 169 | } 170 | 171 | /** 172 | * @param SchemaSetupInterface $setup 173 | */ 174 | private function addCacheRouteTagForeignKeys(SchemaSetupInterface $setup): void 175 | { 176 | /** 177 | * Add foreign keys again 178 | */ 179 | $setup->getConnection()->addForeignKey( 180 | $setup->getFkName( 181 | 'cache_routes', 182 | 'id', 183 | 'cache_route_tags', 184 | 'route_id' 185 | ), 186 | $setup->getTable('cache_routes_tags'), 187 | 'route_id', 188 | $setup->getTable('cache_routes'), 189 | 'id', 190 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 191 | ); 192 | $setup->getConnection()->addForeignKey( 193 | $setup->getFkName( 194 | 'cache_tags', 195 | 'id', 196 | 'cache_route_tags', 197 | 'tag_id' 198 | ), 199 | $setup->getTable('cache_routes_tags'), 200 | 'tag_id', 201 | $setup->getTable('cache_tags'), 202 | 'id', 203 | \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE 204 | ); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "firegento/m2-cache-warmup", 3 | "description": "Warmup Pagecache by crawling all url_rewrites", 4 | "repositories": [ 5 | { 6 | "type": "composer", 7 | "url": "https://repo.magento.com/" 8 | } 9 | ], 10 | "require": { 11 | "php": "~7.0.0|~7.1.0|~7.2.0", 12 | "magento/framework": "*", 13 | "guzzlehttp/guzzle": "~6.2" 14 | }, 15 | "type": "magento2-module", 16 | "version": "0.1.0", 17 | "autoload": { 18 | "files": [ 19 | "registration.php" 20 | ], 21 | "psr-4": { 22 | "Firegento\\CacheWarmup\\": "" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Magento\\Framework\\": "lib/internal/Magento/Framework/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Firegento\CacheWarmup\Console\Command\CacheWarmup 8 | 9 | 10 | 11 | 15 | 19 | 23 | 27 | 31 | 35 | 39 | 40 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /etc/frontend/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Firegento\CacheWarmup\Model\VaryData\Applicator\CustomerGroupApplicator 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/webapi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 |