Feed.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\AdminNotification\Model;
  7. use Magento\Framework\Config\ConfigOptionsListConstants;
  8. /**
  9. * AdminNotification Feed model
  10. *
  11. * @author Magento Core Team <core@magentocommerce.com>
  12. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  13. * @api
  14. * @since 100.0.2
  15. */
  16. class Feed extends \Magento\Framework\Model\AbstractModel
  17. {
  18. const XML_USE_HTTPS_PATH = 'system/adminnotification/use_https';
  19. const XML_FEED_URL_PATH = 'system/adminnotification/feed_url';
  20. const XML_FREQUENCY_PATH = 'system/adminnotification/frequency';
  21. const XML_LAST_UPDATE_PATH = 'system/adminnotification/last_update';
  22. /**
  23. * Feed url
  24. *
  25. * @var string
  26. */
  27. protected $_feedUrl;
  28. /**
  29. * @var \Magento\Backend\App\ConfigInterface
  30. */
  31. protected $_backendConfig;
  32. /**
  33. * @var \Magento\AdminNotification\Model\InboxFactory
  34. */
  35. protected $_inboxFactory;
  36. /**
  37. * @var \Magento\Framework\HTTP\Adapter\CurlFactory
  38. *
  39. */
  40. protected $curlFactory;
  41. /**
  42. * Deployment configuration
  43. *
  44. * @var \Magento\Framework\App\DeploymentConfig
  45. */
  46. protected $_deploymentConfig;
  47. /**
  48. * @var \Magento\Framework\App\ProductMetadataInterface
  49. */
  50. protected $productMetadata;
  51. /**
  52. * @var \Magento\Framework\UrlInterface
  53. */
  54. protected $urlBuilder;
  55. /**
  56. * @param \Magento\Framework\Model\Context $context
  57. * @param \Magento\Framework\Registry $registry
  58. * @param \Magento\Backend\App\ConfigInterface $backendConfig
  59. * @param InboxFactory $inboxFactory
  60. * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory
  61. * @param \Magento\Framework\App\DeploymentConfig $deploymentConfig
  62. * @param \Magento\Framework\App\ProductMetadataInterface $productMetadata
  63. * @param \Magento\Framework\UrlInterface $urlBuilder
  64. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  65. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  66. * @param array $data
  67. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  68. */
  69. public function __construct(
  70. \Magento\Framework\Model\Context $context,
  71. \Magento\Framework\Registry $registry,
  72. \Magento\Backend\App\ConfigInterface $backendConfig,
  73. \Magento\AdminNotification\Model\InboxFactory $inboxFactory,
  74. \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory,
  75. \Magento\Framework\App\DeploymentConfig $deploymentConfig,
  76. \Magento\Framework\App\ProductMetadataInterface $productMetadata,
  77. \Magento\Framework\UrlInterface $urlBuilder,
  78. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  79. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  80. array $data = []
  81. ) {
  82. parent::__construct($context, $registry, $resource, $resourceCollection, $data);
  83. $this->_backendConfig = $backendConfig;
  84. $this->_inboxFactory = $inboxFactory;
  85. $this->curlFactory = $curlFactory;
  86. $this->_deploymentConfig = $deploymentConfig;
  87. $this->productMetadata = $productMetadata;
  88. $this->urlBuilder = $urlBuilder;
  89. }
  90. /**
  91. * Init model
  92. *
  93. * @return void
  94. */
  95. protected function _construct()
  96. {
  97. }
  98. /**
  99. * Retrieve feed url
  100. *
  101. * @return string
  102. */
  103. public function getFeedUrl()
  104. {
  105. $httpPath = $this->_backendConfig->isSetFlag(self::XML_USE_HTTPS_PATH) ? 'https://' : 'http://';
  106. if ($this->_feedUrl === null) {
  107. $this->_feedUrl = $httpPath . $this->_backendConfig->getValue(self::XML_FEED_URL_PATH);
  108. }
  109. return $this->_feedUrl;
  110. }
  111. /**
  112. * Check feed for modification
  113. *
  114. * @return $this
  115. */
  116. public function checkUpdate()
  117. {
  118. if ($this->getFrequency() + $this->getLastUpdate() > time()) {
  119. return $this;
  120. }
  121. $feedData = [];
  122. $feedXml = $this->getFeedData();
  123. $installDate = strtotime($this->_deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_INSTALL_DATE));
  124. if ($feedXml && $feedXml->channel && $feedXml->channel->item) {
  125. foreach ($feedXml->channel->item as $item) {
  126. $itemPublicationDate = strtotime((string)$item->pubDate);
  127. if ($installDate <= $itemPublicationDate) {
  128. $feedData[] = [
  129. 'severity' => (int)$item->severity,
  130. 'date_added' => date('Y-m-d H:i:s', $itemPublicationDate),
  131. 'title' => $this->escapeString($item->title),
  132. 'description' => $this->escapeString($item->description),
  133. 'url' => $this->escapeString($item->link),
  134. ];
  135. }
  136. }
  137. if ($feedData) {
  138. $this->_inboxFactory->create()->parse(array_reverse($feedData));
  139. }
  140. }
  141. $this->setLastUpdate();
  142. return $this;
  143. }
  144. /**
  145. * Retrieve Update Frequency
  146. *
  147. * @return int
  148. */
  149. public function getFrequency()
  150. {
  151. return $this->_backendConfig->getValue(self::XML_FREQUENCY_PATH) * 3600;
  152. }
  153. /**
  154. * Retrieve Last update time
  155. *
  156. * @return int
  157. */
  158. public function getLastUpdate()
  159. {
  160. return $this->_cacheManager->load('admin_notifications_lastcheck');
  161. }
  162. /**
  163. * Set last update time (now)
  164. *
  165. * @return $this
  166. */
  167. public function setLastUpdate()
  168. {
  169. $this->_cacheManager->save(time(), 'admin_notifications_lastcheck');
  170. return $this;
  171. }
  172. /**
  173. * Retrieve feed data as XML element
  174. *
  175. * @return \SimpleXMLElement
  176. */
  177. public function getFeedData()
  178. {
  179. $curl = $this->curlFactory->create();
  180. $curl->setConfig(
  181. [
  182. 'timeout' => 2,
  183. 'useragent' => $this->productMetadata->getName()
  184. . '/' . $this->productMetadata->getVersion()
  185. . ' (' . $this->productMetadata->getEdition() . ')',
  186. 'referer' => $this->urlBuilder->getUrl('*/*/*')
  187. ]
  188. );
  189. $curl->write(\Zend_Http_Client::GET, $this->getFeedUrl(), '1.0');
  190. $data = $curl->read();
  191. $data = preg_split('/^\r?$/m', $data, 2);
  192. $data = trim($data[1]);
  193. $curl->close();
  194. try {
  195. $xml = new \SimpleXMLElement($data);
  196. } catch (\Exception $e) {
  197. return false;
  198. }
  199. return $xml;
  200. }
  201. /**
  202. * Retrieve feed as XML element
  203. *
  204. * @return \SimpleXMLElement
  205. */
  206. public function getFeedXml()
  207. {
  208. try {
  209. $data = $this->getFeedData();
  210. $xml = new \SimpleXMLElement($data);
  211. } catch (\Exception $e) {
  212. $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?>');
  213. }
  214. return $xml;
  215. }
  216. /**
  217. * Converts incoming data to string format and escapes special characters.
  218. *
  219. * @param \SimpleXMLElement $data
  220. * @return string
  221. */
  222. private function escapeString(\SimpleXMLElement $data)
  223. {
  224. return htmlspecialchars((string)$data);
  225. }
  226. }