From 772aa904d97216a30bee85d531218dfc6398fa2b Mon Sep 17 00:00:00 2001 From: Dmitriy Simushev Date: Fri, 28 Nov 2014 14:20:47 +0000 Subject: [PATCH] Add plugins update stuff --- src/mibew/configs/routing.yml | 7 ++ .../Mibew/Controller/PluginController.php | 38 +++++++++- .../libs/classes/Mibew/Plugin/PluginInfo.php | 32 ++++++++ .../classes/Mibew/Plugin/PluginManager.php | 75 ++++++++++++++++++- .../server_side/plugins.handlebars | 7 ++ 5 files changed, 157 insertions(+), 2 deletions(-) diff --git a/src/mibew/configs/routing.yml b/src/mibew/configs/routing.yml index bad93070..6ac5baff 100644 --- a/src/mibew/configs/routing.yml +++ b/src/mibew/configs/routing.yml @@ -570,6 +570,13 @@ plugin_uninstall: _access_check: Mibew\AccessControl\Check\PermissionsCheck _access_permissions: [CAN_ADMINISTRATE] +plugin_update: + path: /operator/plugin/{plugin_name}/update + defaults: + _controller: Mibew\Controller\PluginController::updateAction + _access_check: Mibew\AccessControl\Check\PermissionsCheck + _access_permissions: [CAN_ADMINISTRATE] + plugins: path: /operator/plugin defaults: diff --git a/src/mibew/libs/classes/Mibew/Controller/PluginController.php b/src/mibew/libs/classes/Mibew/Controller/PluginController.php index 7076fb60..e5950829 100644 --- a/src/mibew/libs/classes/Mibew/Controller/PluginController.php +++ b/src/mibew/libs/classes/Mibew/Controller/PluginController.php @@ -158,6 +158,40 @@ class PluginController extends AbstractController return $this->redirect($this->generateUrl('plugins')); } + /** + * Updates a plugin. + * + * @param Request $request Incoming request. + * @return string Rendered page content. + * @throws NotFoundException If the plugin with specified name is not found + * in the system. + */ + public function updateAction(Request $request) + { + csrf_check_token($request); + + $plugin_name = $request->attributes->get('plugin_name'); + + if (!PluginUtils::pluginExists($plugin_name)) { + throw new NotFoundException('The plugin is not found.'); + } + + // Update the plugin + if (!PluginManager::getInstance()->update($plugin_name)) { + $error = getlocal( + 'Plugin "{0}" cannot be updated.', + array($plugin_name) + ); + $request->attributes->set('errors', array($error)); + + // The plugin cannot be updated by some reasons. Just rebuild + // index page and show errors there. + return $this->indexAction($request); + } + + return $this->redirect($this->generateUrl('plugins')); + } + /** * Builds plugins list that will be passed to templates engine. * @@ -170,13 +204,15 @@ class PluginController extends AbstractController $plugin = new PluginInfo($plugin_name); $plugins[] = array( 'name' => $plugin_name, - 'version' => $plugin->getInstalledVersion() ?: $plugin->getVersion(), + 'version' => $plugin->isInstalled() ? $plugin->getInstalledVersion() : $plugin->getVersion(), 'dependencies' => $plugin->getDependencies(), 'enabled' => $plugin->isEnabled(), 'installed' => $plugin->isInstalled(), + 'needsUpdate' => $plugin->needsUpdate(), 'canBeEnabled' => $plugin->canBeEnabled(), 'canBeDisabled' => $plugin->canBeDisabled(), 'canBeUninstalled' => $plugin->canBeUninstalled(), + 'canBeUpdated' => $plugin->canBeUpdated(), ); } diff --git a/src/mibew/libs/classes/Mibew/Plugin/PluginInfo.php b/src/mibew/libs/classes/Mibew/Plugin/PluginInfo.php index 573b6bab..4820bf91 100644 --- a/src/mibew/libs/classes/Mibew/Plugin/PluginInfo.php +++ b/src/mibew/libs/classes/Mibew/Plugin/PluginInfo.php @@ -217,6 +217,17 @@ class PluginInfo return $this->getState()->installed; } + /** + * Checks if the plugin needs to be updated. + * + * @return bool + */ + public function needsUpdate() + { + return $this->isInstalled() + && (version_compare($this->getVersion(), $this->getInstalledVersion()) > 0); + } + /** * Checks if the plugin can be enabled. * @@ -294,6 +305,27 @@ class PluginInfo return true; } + /** + * Checks if the plugin can be updated. + * + * @return boolean + */ + public function canBeUpdated() + { + if (!$this->needsUpdate()) { + return false; + } + + foreach (array_keys($this->getDependencies()) as $dependency_name) { + $dependency = new PluginInfo($dependency_name); + if ($dependency->needsUpdate()) { + return false; + } + } + + return true; + } + /** * Creates plugin info object based on a state object. * diff --git a/src/mibew/libs/classes/Mibew/Plugin/PluginManager.php b/src/mibew/libs/classes/Mibew/Plugin/PluginManager.php index 97ec956c..07aea7df 100644 --- a/src/mibew/libs/classes/Mibew/Plugin/PluginManager.php +++ b/src/mibew/libs/classes/Mibew/Plugin/PluginManager.php @@ -19,6 +19,9 @@ namespace Mibew\Plugin; +use Mibew\Plugin\Utils as PluginUtils; +use Mibew\Maintenance\Utils as MaintenanceUtils; + /** * Manage plugins. * @@ -102,7 +105,7 @@ class PluginManager // Builds Dependency graph with available plugins. $graph = new DependencyGraph(); foreach (State::loadAllEnabled() as $plugin_state) { - if (!Utils::pluginExists($plugin_state->pluginName)) { + if (!PluginUtils::pluginExists($plugin_state->pluginName)) { trigger_error( sprintf( 'Plugin "%s" exists in database base but is not found in file system!', @@ -266,4 +269,74 @@ class PluginManager return true; } + + /** + * Tries to update a plugin. + * + * @param string $plugin_name Name of the plugin to update. + * @return boolean Indicates if the plugin has been updated or not. + */ + public function update($plugin_name) + { + $plugin = new PluginInfo($plugin_name); + + if (!$plugin->needsUpdate()) { + // There is no need to update the plugin + return true; + } + + if (!$plugin->canBeUpdated()) { + // The plugin cannot be updated. + return false; + } + + try { + // Perform incremental updates + $updates = MaintenanceUtils::getUpdates($plugin->getClass()); + foreach ($updates as $version => $method) { + // Skip updates to lower versions. + if (version_compare($version, $plugin->getInstalledVersion()) <= 0) { + continue; + } + + // Skip updates to versions that greater then the current plugin + // version. + if (version_compare($version, $plugin->getVersion()) > 0) { + break; + } + + // Run the update + if (!$method()) { + // By some reasons we cannot update to the next version. + // Stop the process here. + return false; + } + + // Store new version number in the database. With this info + // we can rerun the updating process if one of pending + // updates fails. + $plugin->getState()->version = $version; + $plugin->getState()->save(); + } + } catch (\Exception $e) { + // Something went wrong + trigger_error( + sprintf( + 'Update of "%s" plugin failed: %s', + $plugin->getName(), + $e->getMessage() + ), + E_USER_WARNING + ); + + return false; + } + + // All updates are done. Make sure the state of the plugin contains + // current plugin version. + $plugin->getState()->version = $plugin->getVersion(); + $plugin->getState()->save(); + + return true; + } } diff --git a/src/mibew/styles/pages/default/templates_src/server_side/plugins.handlebars b/src/mibew/styles/pages/default/templates_src/server_side/plugins.handlebars index bd3cd857..97552964 100644 --- a/src/mibew/styles/pages/default/templates_src/server_side/plugins.handlebars +++ b/src/mibew/styles/pages/default/templates_src/server_side/plugins.handlebars @@ -48,6 +48,13 @@ {{/if}} {{/if}} {{/if}} + {{#if needsUpdate}} + {{#if canBeUpdated}} + {{l10n "update"}} + {{else}} + {{l10n "update"}} + {{/if}} + {{/if}} {{else}}