From b67827bbd2215cefeac5f4d65c23846619c8d223 Mon Sep 17 00:00:00 2001 From: Thomas Steur Date: Mon, 23 Sep 2013 02:25:22 +0000 Subject: [PATCH] refs #4053 cleanup code of marketplace integration --- plugins/CorePluginsAdmin/Controller.php | 35 +++------ plugins/CorePluginsAdmin/Marketplace.php | 24 ++++--- .../CorePluginsAdmin/MarketplaceApiClient.php | 72 +++++++++++++------ plugins/CorePluginsAdmin/PluginInstaller.php | 46 ++++++++---- .../templates/installPlugin.twig | 13 ++-- .../templates/pluginMetadata.twig | 2 +- .../templates/pluginOverview.twig | 25 +++---- .../CorePluginsAdmin/templates/plugins.twig | 4 +- .../templates/themeOverview.twig | 27 +++---- .../CorePluginsAdmin/templates/themes.twig | 4 +- 10 files changed, 144 insertions(+), 108 deletions(-) diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php index 13ebc522c57..706a16c8d8e 100644 --- a/plugins/CorePluginsAdmin/Controller.php +++ b/plugins/CorePluginsAdmin/Controller.php @@ -37,13 +37,8 @@ private function createUpdateOrInstallView($template, $nonceName) $view = $this->configureView('@CorePluginsAdmin/' . $template); - $pluginName = Common::getRequestVar('pluginName', '', 'string'); - $pluginName = strip_tags($pluginName); - $nonce = Common::getRequestVar('nonce', '', 'string'); - - if (empty($pluginName)) { - throw new \Exception('Plugin parameter is missing'); - } + $pluginName = Common::getRequestVar('pluginName', null, 'string'); + $nonce = Common::getRequestVar('nonce', null, 'string'); $view->plugin = array('name' => $pluginName); @@ -58,7 +53,7 @@ private function createUpdateOrInstallView($template, $nonceName) $pluginInstaller = new PluginInstaller($pluginName); $pluginInstaller->installOrUpdatePluginFromMarketplace(); - } catch (PluginInstallerException $e) { + } catch (\Exception $e) { $view->errorMessage = $e->getMessage(); return $view; } @@ -85,12 +80,7 @@ public function installPlugin() public function pluginDetails() { - $pluginName = Common::getRequestVar('pluginName', '', 'string'); - $pluginName = strip_tags($pluginName); - - if (empty($pluginName)) { - return; - } + $pluginName = Common::getRequestVar('pluginName', null, 'string'); $view = $this->configureView('@CorePluginsAdmin/pluginDetails'); @@ -107,7 +97,6 @@ public function pluginDetails() private function createBrowsePluginsOrThemesView($template, $themesOnly) { $query = Common::getRequestVar('query', '', 'string', $_POST); - $query = strip_tags($query); $sort = Common::getRequestVar('sort', $this->defaultSortMethod, 'string'); if (!in_array($sort, $this->validSortMethods)) { @@ -263,13 +252,8 @@ public function activate($redirectAfter = true) { Piwik::checkUserIsSuperUser(); - $pluginName = Common::getRequestVar('pluginName', '', 'string'); - $pluginName = strip_tags($pluginName); - $nonce = Common::getRequestVar('nonce', '', 'string'); - - if (empty($pluginName)) { - throw new \Exception('Plugin parameter is missing'); - } + $pluginName = Common::getRequestVar('pluginName', null, 'string'); + $nonce = Common::getRequestVar('nonce', null, 'string'); if (!Nonce::verifyNonce('CorePluginsAdmin.activatePlugin', $nonce)) { throw new \Exception(Piwik_Translate('General_ExceptionNonceMismatch')); @@ -283,11 +267,12 @@ public function activate($redirectAfter = true) $params = array('activated' => 1, 'pluginName' => $pluginName); $plugin = PluginsManager::getInstance()->loadPlugin($pluginName); + $actionToRedirect = 'plugins'; if ($plugin->isTheme()) { - $this->redirectToIndex('CorePluginsAdmin', 'themes', null, null, null, $params); - } else { - $this->redirectToIndex('CorePluginsAdmin', 'plugins', null, null, null, $params); + $actionToRedirect = 'themes'; } + + $this->redirectToIndex('CorePluginsAdmin', $actionToRedirect, null, null, null, $params); } } diff --git a/plugins/CorePluginsAdmin/Marketplace.php b/plugins/CorePluginsAdmin/Marketplace.php index f2b9e18df56..40dfec54797 100644 --- a/plugins/CorePluginsAdmin/Marketplace.php +++ b/plugins/CorePluginsAdmin/Marketplace.php @@ -47,10 +47,10 @@ public function searchPlugins($query, $sort, $themesOnly) $dateFormat = Piwik_Translate('CoreHome_ShortDateFormatWithYear'); - foreach ($plugins as $plugin) { - $plugin->canBeUpdated = $this->hasPluginUpdate($plugin); - $plugin->isInstalled = PluginsManager::getInstance()->isPluginLoaded($plugin->name); - $plugin->lastUpdated = Date::factory($plugin->lastUpdated)->getLocalized($dateFormat); + foreach ($plugins as &$plugin) { + $plugin['canBeUpdated'] = $this->hasPluginUpdate($plugin); + $plugin['isInstalled'] = PluginsManager::getInstance()->isPluginLoaded($plugin['name']); + $plugin['lastUpdated'] = Date::factory($plugin['lastUpdated'])->getLocalized($dateFormat); } return $plugins; @@ -58,14 +58,14 @@ public function searchPlugins($query, $sort, $themesOnly) private function hasPluginUpdate($plugin) { - if (empty($plugin->name)) { + if (empty($plugin['name'])) { return false; } - $pluginsHavingUpdate = $this->getPluginsHavingUpdate($plugin->isTheme); + $pluginsHavingUpdate = $this->getPluginsHavingUpdate($plugin['isTheme']); foreach ($pluginsHavingUpdate as $pluginHavingUpdate) { - if ($plugin->name == $pluginHavingUpdate->name) { + if ($plugin['name'] == $pluginHavingUpdate['name']) { return true; } } @@ -89,12 +89,14 @@ public function getPluginsHavingUpdate($themesOnly) $pluginsHavingUpdate = array(); } - foreach ($pluginsHavingUpdate as $updatePlugin) { + foreach ($pluginsHavingUpdate as &$updatePlugin) { foreach ($loadedPlugins as $loadedPlugin) { - if (!empty($updatePlugin->name) && $loadedPlugin->getPluginName() == $updatePlugin->name) { - $updatePlugin->currentVersion = $loadedPlugin->getVersion(); - $updatePlugin->isActivated = $pluginManager->isPluginActivated($updatePlugin->name); + if (!empty($updatePlugin['name']) + && $loadedPlugin->getPluginName() == $updatePlugin['name']) { + + $updatePlugin['currentVersion'] = $loadedPlugin->getVersion(); + $updatePlugin['isActivated'] = $pluginManager->isPluginActivated($updatePlugin['name']); break; } } diff --git a/plugins/CorePluginsAdmin/MarketplaceApiClient.php b/plugins/CorePluginsAdmin/MarketplaceApiClient.php index 19c8cf636a3..dc7b3841a16 100644 --- a/plugins/CorePluginsAdmin/MarketplaceApiClient.php +++ b/plugins/CorePluginsAdmin/MarketplaceApiClient.php @@ -11,6 +11,7 @@ namespace Piwik\Plugins\CorePluginsAdmin; use Piwik\CacheFile; use Piwik\Http; +use Piwik\PluginsManager; /** * @@ -18,6 +19,9 @@ */ class MarketplaceApiClient { + const CACHE_TIMEOUT_IN_SECONDS = 1200; + const HTTP_REQUEST_TIMEOUT = 30; + private $domain = 'http://plugins.piwik.org'; /** @@ -27,7 +31,7 @@ class MarketplaceApiClient public function __construct() { - $this->cache = new CacheFile('marketplace', 1200); + $this->cache = new CacheFile('marketplace', self::CACHE_TIMEOUT_IN_SECONDS); } public static function clearAllCacheEntries() @@ -45,16 +49,13 @@ public function getPluginInfo($name) public function download($pluginOrThemeName, $target) { - $plugin = $this->getPluginInfo($pluginOrThemeName); + $downloadUrl = $this->getDownloadUrl($pluginOrThemeName); - if (empty($plugin->versions)) { + if (empty($downloadUrl)) { return false; } - $latestVersion = array_pop($plugin->versions); - $downloadUrl = $latestVersion->download; - - $success = Http::fetchRemoteFile($this->domain . $downloadUrl, $target); + $success = Http::fetchRemoteFile($downloadUrl, $target, 0, static::HTTP_REQUEST_TIMEOUT); return $success; } @@ -68,7 +69,10 @@ public function checkUpdates($plugins) $params = array(); foreach ($plugins as $plugin) { - $params[] = array('name' => $plugin->getPluginName(), 'version' => $plugin->getVersion()); + $pluginName = $plugin->getPluginName(); + if (!PluginsManager::getInstance()->isPluginBundledWithCore($pluginName)) { + $params[] = array('name' => $plugin->getPluginName(), 'version' => $plugin->getVersion()); + } } $params = array('plugins' => $params); @@ -94,9 +98,9 @@ public function getInfoOfPluginsHavingUpdate($plugins, $themesOnly) $pluginDetails = array(); foreach ($hasUpdates as $pluginHavingUpdate) { - $plugin = $this->getPluginInfo($pluginHavingUpdate->name); + $plugin = $this->getPluginInfo($pluginHavingUpdate['name']); - if (!empty($plugin->isTheme) == $themesOnly) { + if (!empty($plugin['isTheme']) == $themesOnly) { $pluginDetails[] = $plugin; } } @@ -108,8 +112,8 @@ public function searchForPlugins($keywords, $query, $sort) { $response = $this->fetch('plugins', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort)); - if (!empty($response->plugins)) { - return $response->plugins; + if (!empty($response['plugins'])) { + return $response['plugins']; } return array(); @@ -119,8 +123,8 @@ public function searchForThemes($keywords, $query, $sort) { $response = $this->fetch('themes', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort)); - if (!empty($response->plugins)) { - return $response->plugins; + if (!empty($response['plugins'])) { + return $response['plugins']; } return array(); @@ -128,24 +132,27 @@ public function searchForThemes($keywords, $query, $sort) private function fetch($action, $params) { + ksort($params); $query = http_build_query($params); $result = $this->getCachedResult($action, $query); if (false === $result) { $endpoint = $this->domain . '/api/1.0/'; $url = sprintf('%s%s?%s', $endpoint, $action, $query); - $result = Http::sendHttpRequest($url, 5); - $this->cacheResult($action, $query, $result); - } + $response = Http::sendHttpRequest($url, static::HTTP_REQUEST_TIMEOUT); + $result = json_decode($response, true); - $result = json_decode($result); + if (is_null($result)) { + $message = sprintf('There was an error reading the response from the Marketplace: %s. Please try again later.', + substr($response, 0, 50)); + throw new MarketplaceApiException($message); + } - if (is_null($result)) { - throw new MarketplaceApiException('Failure during communication with marketplace, unable to read response'); - } + if (!empty($result['error'])) { + throw new MarketplaceApiException($result['error']); + } - if (!empty($result->error)) { - throw new MarketplaceApiException($result->error); + $this->cacheResult($action, $query, $result); } return $result; @@ -170,4 +177,23 @@ private function getCacheKey($action, $query) return sprintf('api.1.0.%s.%s', str_replace('/', '.', $action), md5($query)); } + /** + * @param $pluginOrThemeName + * @throws MarketplaceApiException + * @return string + */ + public function getDownloadUrl($pluginOrThemeName) + { + $plugin = $this->getPluginInfo($pluginOrThemeName); + + if (empty($plugin['versions'])) { + throw new MarketplaceApiException('Plugin has no versions.'); + } + + $latestVersion = array_pop($plugin['versions']); + $downloadUrl = $latestVersion['download']; + + return $this->domain . $downloadUrl; + } + } diff --git a/plugins/CorePluginsAdmin/PluginInstaller.php b/plugins/CorePluginsAdmin/PluginInstaller.php index e77b79757d1..cd664b3aefa 100644 --- a/plugins/CorePluginsAdmin/PluginInstaller.php +++ b/plugins/CorePluginsAdmin/PluginInstaller.php @@ -35,6 +35,7 @@ public function installOrUpdatePluginFromMarketplace() $tmpPluginFolder = PIWIK_USER_PATH . self::PATH_TO_DOWNLOAD . $this->pluginName; $this->makeSureFoldersAreWritable(); + $this->makeSurePluginNameIsValid(); $this->downloadPluginFromMarketplace($tmpPluginZip); $this->extractPluginFiles($tmpPluginZip, $tmpPluginFolder); $this->makeSurePluginJsonExists($tmpPluginFolder); @@ -53,21 +54,21 @@ private function downloadPluginFromMarketplace($pluginZipTargetFile) { $this->removeFileIfExists($pluginZipTargetFile); - try { - $marketplace = new MarketplaceApiClient(); - $pluginDetails = $marketplace->getPluginInfo($this->pluginName); - } catch (\Exception $e) { - throw new PluginInstallerException($e->getMessage()); - } - - if (empty($pluginDetails)) { - throw new PluginInstallerException('A plugin with this name does not exist'); - } + $marketplace = new MarketplaceApiClient(); try { $marketplace->download($this->pluginName, $pluginZipTargetFile); } catch (\Exception $e) { - throw new PluginInstallerException('Failed to download plugin: ' . $e->getMessage()); + + try { + $downloadUrl = $marketplace->getDownloadUrl($this->pluginName); + $errorMessage = sprintf('Failed to download plugin from %s: %s', $downloadUrl, $e->getMessage()); + + } catch (\Exception $ex) { + $errorMessage = sprintf('Failed to download plugin: %s', $e->getMessage()); + } + + throw new PluginInstallerException($errorMessage); } } @@ -94,7 +95,7 @@ private function extractPluginFiles($pluginZipFile, $pathExtracted) private function makeSurePluginJsonExists($tmpPluginFolder) { if (!file_exists($tmpPluginFolder . DIRECTORY_SEPARATOR . $this->pluginName . DIRECTORY_SEPARATOR . 'plugin.json')) { - throw new PluginInstallerException('Plugin is not valid, missing plugin.json'); + throw new PluginInstallerException('Plugin is not valid, it is missing the plugin.json file.'); } } @@ -112,9 +113,7 @@ private function copyPluginToDestination($tmpPluginFolder) */ private function removeFolderIfExists($pathExtracted) { - if (file_exists($pathExtracted)) { - Filesystem::unlinkRecursive($pathExtracted, true); - } + Filesystem::unlinkRecursive($pathExtracted, true); } /** @@ -127,4 +126,21 @@ private function removeFileIfExists($targetTmpFile) } } + /** + * @throws PluginInstallerException + */ + private function makeSurePluginNameIsValid() + { + try { + $marketplace = new MarketplaceApiClient(); + $pluginDetails = $marketplace->getPluginInfo($this->pluginName); + } catch (\Exception $e) { + throw new PluginInstallerException($e->getMessage()); + } + + if (empty($pluginDetails)) { + throw new PluginInstallerException('This plugin was not found in the Marketplace.'); + } + } + } diff --git a/plugins/CorePluginsAdmin/templates/installPlugin.twig b/plugins/CorePluginsAdmin/templates/installPlugin.twig index 41757a56d66..9ef95329dd3 100644 --- a/plugins/CorePluginsAdmin/templates/installPlugin.twig +++ b/plugins/CorePluginsAdmin/templates/installPlugin.twig @@ -18,30 +18,29 @@

Unzipping theme

-

Installing theme

-

You have successfully installed the theme {{ plugin.name }} {{ plugin.latestVersion }}.

Activate Theme + | + Back to Extend Piwik

+ {% else %}

Downloading plugin from Marketplace

Unzipping plugin

-

Installing plugin

-

You have successfully installed the Plugin {{ plugin.name }} {{ plugin.latestVersion }}.

Activate Plugin + | + Back to Extend Piwik

+ {% endif %} - | - Back to Extend Piwik

- {% endif %} diff --git a/plugins/CorePluginsAdmin/templates/pluginMetadata.twig b/plugins/CorePluginsAdmin/templates/pluginMetadata.twig index f6752d0e645..831dc3b2200 100644 --- a/plugins/CorePluginsAdmin/templates/pluginMetadata.twig +++ b/plugins/CorePluginsAdmin/templates/pluginMetadata.twig @@ -1,4 +1,4 @@ -
+