diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php index 050a10f4598..3671203a21d 100644 --- a/plugins/CorePluginsAdmin/Controller.php +++ b/plugins/CorePluginsAdmin/Controller.php @@ -50,6 +50,32 @@ public function activatePlugin() $this->extend(); } + public function updatePlugin() + { + $pluginName = Common::getRequestVar('pluginName', '', 'string'); + $nonce = Common::getRequestVar('nonce', '', 'string'); + + if (empty($pluginName)) { + return; + } + + if (!Nonce::verifyNonce('CorePluginsAdmin.updatePlugin', $nonce)) { + // todo display error + return; + } + + Nonce::discardNonce('CorePluginsAdmin.updatePlugin'); + + $pluginInstaller = new PluginInstaller($pluginName); + $pluginInstaller->installOrUpdatePluginFromMarketplace(); + $marketplace = new MarketplaceApiClient(); + + $view = $this->configureView('@CorePluginsAdmin/updatePlugin'); + $view->plugin = $marketplace->getPluginInfo($pluginName); + + echo $view->render(); + } + public function installPlugin() { $pluginName = Common::getRequestVar('pluginName', '', 'string'); @@ -59,7 +85,7 @@ public function installPlugin() return; } - if (Nonce::verifyNonce('CorePluginsAdmin.installPlugin', $nonce)) { + if (!Nonce::verifyNonce('CorePluginsAdmin.installPlugin', $nonce)) { // todo display error return; } @@ -142,14 +168,26 @@ function extend() function plugins() { $view = $this->configureView('@CorePluginsAdmin/plugins'); - $view->pluginsInfo = $this->getPluginsInfo(); + + $pluginsInfo = $this->getPluginsInfo(); + + $view->updateNonce = Nonce::getNonce('CorePluginsAdmin.updatePlugin'); + $view->pluginsInfo = $pluginsInfo; + $view->pluginsHavingUpdate = $this->getPluginsHavingUpdate($pluginsInfo, $themesOnly = false); + echo $view->render(); } function themes() { $view = $this->configureView('@CorePluginsAdmin/themes'); - $view->pluginsInfo = $this->getPluginsInfo($themesOnly = true); + + $pluginsInfo = $this->getPluginsInfo(); + + $view->updateNonce = Nonce::getNonce('CorePluginsAdmin.updatePlugin'); + $view->pluginsInfo = $pluginsInfo; + $view->pluginsHavingUpdate = $this->getPluginsHavingUpdate($pluginsInfo, $themesOnly = true); + echo $view->render(); } @@ -166,27 +204,31 @@ protected function getPluginsInfo($themesOnly = false) { $plugins = array(); + $pluginsManager = \Piwik\PluginsManager::getInstance(); $listPlugins = array_merge( - \Piwik\PluginsManager::getInstance()->readPluginsDirectory(), + $pluginsManager->readPluginsDirectory(), Config::getInstance()->Plugins['Plugins'] ); $listPlugins = array_unique($listPlugins); foreach ($listPlugins as $pluginName) { \Piwik\PluginsManager::getInstance()->loadPlugin($pluginName); $plugins[$pluginName] = array( - 'activated' => \Piwik\PluginsManager::getInstance()->isPluginActivated($pluginName), - 'alwaysActivated' => \Piwik\PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName), - 'uninstallable' => \Piwik\PluginsManager::getInstance()->isPluginUninstallable($pluginName), + 'activated' => $pluginsManager->isPluginActivated($pluginName), + 'alwaysActivated' => $pluginsManager->isPluginAlwaysActivated($pluginName), + 'uninstallable' => $pluginsManager->isPluginUninstallable($pluginName), ); } - \Piwik\PluginsManager::getInstance()->loadPluginTranslations(); + $pluginsManager->loadPluginTranslations(); + + $loadedPlugins = $pluginsManager->getLoadedPlugins(); - $loadedPlugins = \Piwik\PluginsManager::getInstance()->getLoadedPlugins(); foreach ($loadedPlugins as $oPlugin) { $pluginName = $oPlugin->getPluginName(); + $plugins[$pluginName]['info'] = $oPlugin->getInformation(); } + foreach ($plugins as $pluginName => &$plugin) { if (!isset($plugin['info'])) { $plugin['info'] = array( @@ -264,4 +306,33 @@ public function uninstall($redirectAfter = true) } $this->redirectAfterModification($redirectAfter); } + + /** + * @param $pluginsInfo + * @param bool $themesOnly + * @return array + */ + private function getPluginsHavingUpdate($pluginsInfo, $themesOnly) + { + $loadedPlugins = PluginsManager::getInstance()->getLoadedPlugins(); + + $marketplace = new MarketplaceApiClient(); + + if ($themesOnly) { + $pluginsHavingUpdate = $marketplace->getInfoOfThemesHavingUpdate($loadedPlugins); + } else { + $pluginsHavingUpdate = $marketplace->getInfoOfPluginsHavingUpdate($loadedPlugins); + } + + foreach ($pluginsHavingUpdate as $updatePlugin) { + foreach ($pluginsInfo as $pluginName => $plugin) { + // TODO check if pluginName == $plugin + $updatePlugin->currentVersion = $plugin['info']['version']; + $updatePlugin->isActivated = $plugin['activated']; + break; + } + + } + return $pluginsHavingUpdate; + } } diff --git a/plugins/CorePluginsAdmin/MarketplaceApiClient.php b/plugins/CorePluginsAdmin/MarketplaceApiClient.php index e806b07824d..bf2de856993 100644 --- a/plugins/CorePluginsAdmin/MarketplaceApiClient.php +++ b/plugins/CorePluginsAdmin/MarketplaceApiClient.php @@ -17,7 +17,7 @@ */ class MarketplaceApiClient { - private $domain = 'http://plugins.piwik'; + private $domain = 'http://plugins.piwik.org/'; /** * @var array array(pluginName => stdClass pluginInfo) @@ -34,6 +34,11 @@ private function fetch($action, $params) $result = Http::sendHttpRequest($url, 5); $result = json_decode($result); + if (!empty($result->error)) { + // TODO create own exception + throw new \Exception($result->error); + } + return $result; } @@ -67,6 +72,66 @@ public function download($pluginOrThemeName, $target) return $success; } + /** + * @param \Piwik\Plugin[] $plugins + */ + public function checkUpdates($plugins) + { + $params = array(); + + foreach ($plugins as $plugin) { + $pluginName = $plugin->getPluginName(); + + $params[] = array('name' => $pluginName, 'version' => $plugin->getVersion()); + } + + $params = array('plugins' => $params); + + $hasUpdates = $this->fetch('plugins/checkUpdates', array('plugins' => json_encode($params))); + + if (empty($hasUpdates)) { + return array(); + } + + return $hasUpdates; + } + + /** + * @param \Piwik\Plugin[] $plugins + */ + public function getInfoOfPluginsHavingUpdate($plugins) + { + $hasUpdates = $this->checkUpdates($plugins); + + $pluginDetails = array(); + foreach ($hasUpdates as $pluginHavingUpdate) { + $plugin = $this->getPluginInfo($pluginHavingUpdate->name); + if (!$plugin->isTheme) { + $pluginDetails[] = $plugin; + } + } + + return $pluginDetails; + } + + /** + * @param \Piwik\Plugin[] $plugins + */ + public function getInfoOfThemesHavingUpdate($plugins) + { + $hasUpdates = $this->checkUpdates($plugins); + + $pluginDetails = array(); + foreach ($hasUpdates as $pluginHavingUpdate) { + $plugin = $this->getPluginInfo($pluginHavingUpdate->name); + if ($plugin->isTheme) { + $pluginDetails[] = $plugin; + } + } + + return $pluginDetails; + } + public function searchForPlugins($keywords, $query, $sort) { $response = $this->fetch('plugins', array('keywords' => $keywords, 'query' => $query, 'sort' => $sort)); diff --git a/plugins/CorePluginsAdmin/templates/macros.twig b/plugins/CorePluginsAdmin/templates/macros.twig index f45cef342bd..b658796b06f 100644 --- a/plugins/CorePluginsAdmin/templates/macros.twig +++ b/plugins/CorePluginsAdmin/templates/macros.twig @@ -1,3 +1,46 @@ +{% macro tablePluginUpdates(pluginsHavingUpdate, pluginsInfo, nonce, isTheme) %} + +
+ + + + + + + + + + + + {% for name,plugin in pluginsHavingUpdate %} + + + + + + + + {% endfor %} + +
{% if isTheme %}{{ 'CorePluginsAdmin_Theme'|translate }}{% else %}{{ 'General_Plugin'|translate }}{% endif %}{{ 'CorePluginsAdmin_Version'|translate }}{{ 'General_Description'|translate }}{{ 'CorePluginsAdmin_Status'|translate }}{{ 'General_Action'|translate }}
+ {{ plugin.name }} + + {{ plugin.currentVersion }} => {{ plugin.latestVersion }} + + {{ plugin.description }} + + {% if plugin.isActivated %} + {{ 'CorePluginsAdmin_Active'|translate }} + {% else %} + {{ 'CorePluginsAdmin_Inactive'|translate }} + {% endif %} +
+
+ +{% endmacro %} + {% macro tablePlugins(pluginsInfo, token_auth, isTheme) %}
diff --git a/plugins/CorePluginsAdmin/templates/plugins.twig b/plugins/CorePluginsAdmin/templates/plugins.twig index 576deee30cc..9accec902b9 100644 --- a/plugins/CorePluginsAdmin/templates/plugins.twig +++ b/plugins/CorePluginsAdmin/templates/plugins.twig @@ -5,6 +5,12 @@ {% block content %}
+ {% if pluginsHavingUpdate|length %} +

{{ pluginsHavingUpdate|length }} Update(s) available

+ + {{ plugins.tablePluginUpdates(pluginsHavingUpdate, pluginsInfo, updateNonce, 0) }} + {% endif %} +

{{ 'CorePluginsAdmin_PluginsManagement'|translate }}

{{ 'CorePluginsAdmin_MainDescription'|translate }}

diff --git a/plugins/CorePluginsAdmin/templates/themes.twig b/plugins/CorePluginsAdmin/templates/themes.twig index 0e8086e7fe2..41874eebf6e 100644 --- a/plugins/CorePluginsAdmin/templates/themes.twig +++ b/plugins/CorePluginsAdmin/templates/themes.twig @@ -5,6 +5,12 @@ {% block content %}
+ {% if pluginsHavingUpdate|length %} +

{{ pluginsHavingUpdate|length }} Update(s) available

+ + {{ plugins.tablePluginUpdates(pluginsHavingUpdate, pluginsInfo, updateNonce, 1) }} + {% endif %} +

{{ 'CorePluginsAdmin_ThemesManagement'|translate }}

{{ 'CorePluginsAdmin_ThemesDescription'|translate }}

diff --git a/plugins/CorePluginsAdmin/templates/updatePlugin.twig b/plugins/CorePluginsAdmin/templates/updatePlugin.twig new file mode 100644 index 00000000000..67ea8b79513 --- /dev/null +++ b/plugins/CorePluginsAdmin/templates/updatePlugin.twig @@ -0,0 +1,21 @@ +{% extends 'admin.twig' %} + +{% block content %} + +
+ +

Updating plugin {{ plugin.name}}

+ +
+

Downloading plugin from Marketplace

+ +

Unzipping plugin

+ +

Replacing existing plugin

+ +

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

+ +
+
+ +{% endblock %}