From b8d85c239308239b8b92559d1d024f4325962ba2 Mon Sep 17 00:00:00 2001 From: Renon Stewart Date: Sat, 4 Jul 2020 18:18:28 -0400 Subject: [PATCH] Improve local caching --- Controller/Adminhtml/Version/Index.php | 6 +- Model/Module.php | 142 +++++++++++++++--- composer.json | 2 +- .../system/config/field/extensions.phtml | 4 +- view/adminhtml/web/js/notification-icon.js | 3 +- 5 files changed, 133 insertions(+), 24 deletions(-) diff --git a/Controller/Adminhtml/Version/Index.php b/Controller/Adminhtml/Version/Index.php index 93468a7..867681c 100755 --- a/Controller/Adminhtml/Version/Index.php +++ b/Controller/Adminhtml/Version/Index.php @@ -47,15 +47,15 @@ public function __construct( */ public function execute() { - $date = [ + $data = [ 'success' => 1, - 'count' => $this->module->getUpdateCount() + 'count' => $this->module->getCachedUpdateCount() ]; $result = $this->resultJsonFactory->create(); $result->setHeader('Cache-Control', 'max-age=302400', true); $result->setHeader('Pragma', 'cache', true); - $result->setData($date); + $result->setData($data); return $result; } } diff --git a/Model/Module.php b/Model/Module.php index 48fb65a..631dd90 100644 --- a/Model/Module.php +++ b/Model/Module.php @@ -9,6 +9,7 @@ use Exception; use InvalidArgumentException; +use Magento\Backend\Model\Session; use Magento\Framework\App\Cache\Type\Config; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Component\ComponentRegistrarInterface; @@ -20,7 +21,7 @@ class Module { const URL = "https://updates.magepal.com/extensions.json"; const CACHE_KEY = 'magepal_extension_installed_list'; - const DATA_VERSION = '1.0.1'; + const DATA_VERSION = '1.0.2'; const LIFE_TIME = 604800; /** @var int $updateCounter */ @@ -31,6 +32,7 @@ class Module 'MagePal_Core' ]; + /** @var string */ private $filterModule = 'MagePal_'; private $composerJsonData = []; @@ -59,6 +61,12 @@ class Module * @var Config */ private $cache; + /** + * @var Session + */ + private $session; + + private $timeStamp; /** * @param ModuleListInterface $moduleList @@ -66,49 +74,133 @@ class Module * @param ClientFactory $httpClientFactory * @param ReadFactory $readFactory * @param Config $cache + * @param Session $session */ public function __construct( ModuleListInterface $moduleList, ComponentRegistrarInterface $componentRegistrar, ClientFactory $httpClientFactory, ReadFactory $readFactory, - Config $cache + Config $cache, + Session $session ) { $this->moduleList = $moduleList; $this->componentRegistrar = $componentRegistrar; $this->readFactory = $readFactory; $this->httpClientFactory = $httpClientFactory; $this->cache = $cache; + $this->session = $session; + } + + /** + * @param string $needle + * @param array $haystack + * @param bool $defaultValue + * @return bool|mixed + */ + public function getArrayKeyIfExist($needle, $haystack, $defaultValue = false) + { + return array_key_exists($needle, $haystack) ? $haystack[$needle] : $defaultValue; } + /** + * @return int + */ public function getUpdateCount() { $this->getOutDatedExtension(); return $this->updateCounter; } + /** + * @return int + */ + protected function getTimeStamp() + { + if (empty($this->timeStamp)) { + $this->timeStamp = strtotime("now"); + } + + return $this->timeStamp; + } + + /** + * @return int + */ + protected function getTtl() + { + return $this->getTimeStamp() + 60 * 60 * 24; + } + + /** + * @return int + */ + public function getCachedUpdateCount() + { + $now = $this->getTimeStamp(); + $hash = $this->getHash(); + $data = (array) $this->session->getData('magepal-core-notification-data'); + + if (empty($data) || !is_array($data) + || $this->getArrayKeyIfExist('hash', $data, '') !== $hash + || $now > (int) $this->getArrayKeyIfExist('ttl', $data, 0) + ) { + $data = $this->setCountCache($this->getUpdateCount()); + } + + return (int) $data['count'] ?? 0; + } + + /** + * @param $amount + * @return array + */ + protected function setCountCache($amount) + { + $data = [ + 'count' => $amount, + 'hash' => $this->getHash(), + 'ttl' => $this->getTtl() + ]; + + $this->session->setData('magepal-core-notification-data', $data); + return $data; + } + + /** + * @return string + */ + public function getHash() + { + return md5(json_encode($this->getPostData())); + } + /** * @return array */ public function getOutDatedExtension() { if (empty($this->outDatedExtensionList)) { - if (!$data = $this->cache->load(self::CACHE_KEY)) { - $this->loadOutDatedExtension(); + $data = $this->cache->load(self::CACHE_KEY); + + try { + $dataObject = $data ? $this->decodeJson($data, true) : []; + } catch (Exception $e) { + $dataObject = []; + } + + if (!$data + || $this->getArrayKeyIfExist('data_version', $dataObject, 0) != self::DATA_VERSION + || $this->getArrayKeyIfExist('hash', $dataObject, '') !== $this->getHash() + ) { + $this->loadOutDatedExtensionCollection(); } else { - $dataObject = $this->decodeJson($data, true); - - if (!array_key_exists('data_version', $dataObject) - || $dataObject['data_version'] != self::DATA_VERSION) { - $this->loadOutDatedExtension(); - } else { - if (array_key_exists('count', $dataObject)) { - $this->updateCounter = $dataObject['count']; - } + if (array_key_exists('count', $dataObject)) { + $this->updateCounter = $dataObject['count']; + } - if (array_key_exists('extensions', $dataObject)) { - $this->outDatedExtensionList = $dataObject['extensions']; - } + if (array_key_exists('extensions', $dataObject)) { + $this->outDatedExtensionList = $dataObject['extensions']; } } } @@ -116,12 +208,16 @@ public function getOutDatedExtension() return $this->outDatedExtensionList; } - public function loadOutDatedExtension() + /** + * @return array + */ + public function loadOutDatedExtensionCollection() { try { $extensionList = $this->getMyExtensionList(); $feed = $this->callApi(self::URL, $this->getPostData()); $latestVersions = $feed['extensions'] ?? []; + $hasUpdate = false; foreach ($extensionList as $item) { $item['latest_version'] = $item['install_version']; @@ -138,16 +234,22 @@ public function loadOutDatedExtension() if ($item['has_update']) { $this->updateCounter += 1; + $hasUpdate = true; } } $this->outDatedExtensionList[] = $item; } + if ($hasUpdate) { + $this->setCountCache($this->updateCounter); + } + $dataObject = [ 'count' => $this->updateCounter, 'extensions' => $this->outDatedExtensionList, - 'data_version' => self::DATA_VERSION + 'data_version' => self::DATA_VERSION, + 'hash' => $this->getHash() ]; $this->cache->save(json_encode($dataObject), self::CACHE_KEY, [], self::LIFE_TIME); @@ -158,6 +260,10 @@ public function loadOutDatedExtension() return $this->outDatedExtensionList; } + /** + * @param $moduleName + * @return string + */ private function getTitleFromModuleName($moduleName) { $moduleName = str_replace($this->filterModule, '', $moduleName); diff --git a/composer.json b/composer.json index 5fddee5..e85482d 100755 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "type": "magento2-module", - "version": "1.1.2", + "version": "1.1.3", "autoload": { "files": [ "registration.php" diff --git a/view/adminhtml/templates/system/config/field/extensions.phtml b/view/adminhtml/templates/system/config/field/extensions.phtml index 3511f7e..eba11bd 100644 --- a/view/adminhtml/templates/system/config/field/extensions.phtml +++ b/view/adminhtml/templates/system/config/field/extensions.phtml @@ -50,7 +50,9 @@
escapeHtml($item['name'] ?? '') ?>
-
escapeHtml($item['latest_version'] ?? '') ?>
+
+ escapeHtml($item['latest_version'] ?? '') ?> +
diff --git a/view/adminhtml/web/js/notification-icon.js b/view/adminhtml/web/js/notification-icon.js index 06d9390..4013fd6 100644 --- a/view/adminhtml/web/js/notification-icon.js +++ b/view/adminhtml/web/js/notification-icon.js @@ -20,7 +20,8 @@ define([ $.ajax({ url: config.url, type: 'get', - dataType: 'json' + dataType: 'json', + error: function (){} }).done(function (response) { if (typeof response === 'object' && response.hasOwnProperty('count') && response.count > 0) { var html = '' + response.count + '';