PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/CorePluginsAdmin/MarketplaceApiClient.php

https://github.com/CodeYellowBV/piwik
PHP | 202 lines | 129 code | 46 blank | 27 comment | 12 complexity | 65a72cadd6a53908d4149e5a7ae5cc3f MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik\Plugins\CorePluginsAdmin;
  10. use Piwik\CacheFile;
  11. use Piwik\Http;
  12. use Piwik\Version;
  13. /**
  14. *
  15. */
  16. class MarketplaceApiClient
  17. {
  18. const CACHE_TIMEOUT_IN_SECONDS = 1200;
  19. const HTTP_REQUEST_TIMEOUT = 3;
  20. private $domain = 'http://plugins.piwik.org';
  21. /**
  22. * @var CacheFile
  23. */
  24. private $cache = null;
  25. public function __construct()
  26. {
  27. $this->cache = new CacheFile('marketplace', self::CACHE_TIMEOUT_IN_SECONDS);
  28. }
  29. public static function clearAllCacheEntries()
  30. {
  31. $cache = new CacheFile('marketplace');
  32. $cache->deleteAll();
  33. }
  34. public function getPluginInfo($name)
  35. {
  36. $action = sprintf('plugins/%s/info', $name);
  37. return $this->fetch($action, array());
  38. }
  39. public function download($pluginOrThemeName, $target)
  40. {
  41. $downloadUrl = $this->getDownloadUrl($pluginOrThemeName);
  42. if (empty($downloadUrl)) {
  43. return false;
  44. }
  45. $success = Http::fetchRemoteFile($downloadUrl, $target, 0, static::HTTP_REQUEST_TIMEOUT);
  46. return $success;
  47. }
  48. /**
  49. * @param \Piwik\Plugin[] $plugins
  50. * @return array|mixed
  51. */
  52. public function checkUpdates($plugins)
  53. {
  54. $params = array();
  55. foreach ($plugins as $plugin) {
  56. $pluginName = $plugin->getPluginName();
  57. if (!\Piwik\Plugin\Manager::getInstance()->isPluginBundledWithCore($pluginName)) {
  58. $params[] = array('name' => $plugin->getPluginName(), 'version' => $plugin->getVersion());
  59. }
  60. }
  61. if (empty($params)) {
  62. return array();
  63. }
  64. $params = array('plugins' => $params);
  65. $hasUpdates = $this->fetch('plugins/checkUpdates', array('plugins' => json_encode($params)));
  66. if (empty($hasUpdates)) {
  67. return array();
  68. }
  69. return $hasUpdates;
  70. }
  71. /**
  72. * @param \Piwik\Plugin[] $plugins
  73. * @param bool $themesOnly
  74. * @return array
  75. */
  76. public function getInfoOfPluginsHavingUpdate($plugins, $themesOnly)
  77. {
  78. $hasUpdates = $this->checkUpdates($plugins);
  79. $pluginDetails = array();
  80. foreach ($hasUpdates as $pluginHavingUpdate) {
  81. $plugin = $this->getPluginInfo($pluginHavingUpdate['name']);
  82. $plugin['repositoryChangelogUrl'] = $pluginHavingUpdate['repositoryChangelogUrl'];
  83. if (!empty($plugin['isTheme']) == $themesOnly) {
  84. $pluginDetails[] = $plugin;
  85. }
  86. }
  87. return $pluginDetails;
  88. }
  89. public function searchForPlugins($keywords, $query, $sort)
  90. {
  91. $response = $this->fetch('plugins', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort));
  92. if (!empty($response['plugins'])) {
  93. return $response['plugins'];
  94. }
  95. return array();
  96. }
  97. public function searchForThemes($keywords, $query, $sort)
  98. {
  99. $response = $this->fetch('themes', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort));
  100. if (!empty($response['plugins'])) {
  101. return $response['plugins'];
  102. }
  103. return array();
  104. }
  105. private function fetch($action, $params)
  106. {
  107. ksort($params);
  108. $query = http_build_query($params);
  109. $result = $this->getCachedResult($action, $query);
  110. if (false === $result) {
  111. $endpoint = $this->domain . '/api/1.0/';
  112. $url = sprintf('%s%s?%s', $endpoint, $action, $query);
  113. $response = Http::sendHttpRequest($url, static::HTTP_REQUEST_TIMEOUT);
  114. $result = json_decode($response, true);
  115. if (is_null($result)) {
  116. $message = sprintf('There was an error reading the response from the Marketplace: %s. Please try again later.',
  117. substr($response, 0, 50));
  118. throw new MarketplaceApiException($message);
  119. }
  120. if (!empty($result['error'])) {
  121. throw new MarketplaceApiException($result['error']);
  122. }
  123. $this->cacheResult($action, $query, $result);
  124. }
  125. return $result;
  126. }
  127. private function getCachedResult($action, $query)
  128. {
  129. $cacheKey = $this->getCacheKey($action, $query);
  130. return $this->cache->get($cacheKey);
  131. }
  132. private function cacheResult($action, $query, $result)
  133. {
  134. $cacheKey = $this->getCacheKey($action, $query);
  135. $this->cache->set($cacheKey, $result);
  136. }
  137. private function getCacheKey($action, $query)
  138. {
  139. return sprintf('api.1.0.%s.%s', str_replace('/', '.', $action), md5($query));
  140. }
  141. /**
  142. * @param $pluginOrThemeName
  143. * @throws MarketplaceApiException
  144. * @return string
  145. */
  146. public function getDownloadUrl($pluginOrThemeName)
  147. {
  148. $plugin = $this->getPluginInfo($pluginOrThemeName);
  149. if (empty($plugin['versions'])) {
  150. throw new MarketplaceApiException('Plugin has no versions.');
  151. }
  152. $latestVersion = array_pop($plugin['versions']);
  153. $downloadUrl = $latestVersion['download'];
  154. return $this->domain . $downloadUrl . '?coreVersion=' . Version::VERSION;
  155. }
  156. }