From 58f13f7693a781f9971de3b2a01e2e8b69c9fa1b Mon Sep 17 00:00:00 2001 From: Waleed Qadi Date: Sat, 4 May 2019 15:32:59 +0300 Subject: [PATCH 1/5] Added enumerated update statuses --- .../update_helper_checklist.module | 14 ++- src/Updater.php | 110 ++++++++++++++---- 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/modules/update_helper_checklist/update_helper_checklist.module b/modules/update_helper_checklist/update_helper_checklist.module index 3b9bb0c..be47c97 100644 --- a/modules/update_helper_checklist/update_helper_checklist.module +++ b/modules/update_helper_checklist/update_helper_checklist.module @@ -14,6 +14,11 @@ use Drupal\update_helper_checklist\UpdateChecklist; use Symfony\Component\Yaml\Yaml; use Drupal\update_helper_checklist\Entity\Update; +const CONFIG_NOT_FOUND = 0; +const CONFIG_ALREADY_APPLIED = 1; +const CONFIG_NOT_EXPECTED = 2; +const CONFIG_APPLIED_SUCCESSFULLY = 3; + /** * Implements hook_checklistapi_checklist_info(). */ @@ -62,10 +67,10 @@ function _update_helper_checklist_checklistapi_checklist_items() { $entry = Update::load($update_key); $status = ($entry && $entry->wasSuccessfulByHook()) ? TRUE : FALSE; - if ($status && !empty($update['#description_successful'])) { + if ($entry && $status && !empty($update['#description_successful'])) { $update['#description'] .= $update['#description_successful']; } - elseif (!$status && !empty($update['#description_failed'])) { + elseif ($entry && !$status && !empty($update['#description_failed'])) { $update['#description'] .= $update['#description_failed']; } } @@ -107,6 +112,7 @@ function _update_helper_checklist_checklistapi_checklist_items() { function update_helper_checklist_modules_installed(array $modules) { /** @var \Drupal\Core\Extension\ModuleHandler $module_handler */ $module_handler = \Drupal::service('module_handler'); + $updateHelper = \Drupal::service('update_helper.updater'); $modules_checklist = []; $module_directories = $module_handler->getModuleDirectories(); @@ -120,6 +126,10 @@ function update_helper_checklist_modules_installed(array $modules) { foreach ($updates_checklist as $version_items) { foreach ($version_items as $update_hook_name => $checklist_definition) { if (is_array($checklist_definition)) { + + $status = $updateHelper->checkUpdate($module_name, $update_hook_name); + if ($status != CONFIG_ALREADY_APPLIED && $status != CONFIG_APPLIED_SUCCESSFULLY) continue; + if (!isset($modules_checklist[$module_name])) { $modules_checklist[$module_name] = []; } diff --git a/src/Updater.php b/src/Updater.php index 6f91b36..39051b6 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -20,6 +20,11 @@ class Updater implements UpdaterInterface { use StringTranslationTrait; + const CONFIG_NOT_FOUND = 0; + const CONFIG_ALREADY_APPLIED = 1; + const CONFIG_NOT_EXPECTED = 2; + const CONFIG_APPLIED_SUCCESSFULLY = 3; + /** * Site configFactory object. * @@ -130,7 +135,7 @@ protected function logInfo($message) { /** * {@inheritdoc} */ - public function executeUpdate($module, $update_definition_name) { + public function executeUpdate($module, $update_definition_name, $force = FALSE) { $this->warningCount = 0; $update_definitions = $this->configHandler->loadUpdate($module, $update_definition_name); @@ -141,7 +146,7 @@ public function executeUpdate($module, $update_definition_name) { } if (!empty($update_definitions)) { - $this->executeConfigurationActions($update_definitions); + $this->executeConfigurationActions($update_definitions, $force); } // Dispatch event after update has finished. @@ -151,6 +156,29 @@ public function executeUpdate($module, $update_definition_name) { return $this->warningCount === 0; } + /** + * Check update status of configuration from update definitions. + * + * @param string $module + * Module name where update definition is saved. + * @param string $update_definition_name + * Update definition name. Usually same name as update hook. + * + * @return bool + * Returns update status. + */ + public function checkUpdate($module, $update_definition_name) { + $this->warningCount = 0; + + $update_definitions = $this->configHandler->loadUpdate($module, $update_definition_name); + + if (!empty($update_definitions)) { + return $this->executeConfigurationActions($update_definitions, FALSE, TRUE); + } + + return Updater::CONFIG_NOT_FOUND; + } + /** * Get array with defined global actions. * @@ -176,8 +204,15 @@ protected function executeGlobalActions(array $global_actions) { * * @param array $update_definitions * List of configurations with update definitions for them. + * @param bool $force + * Force the update. + * @param bool $checkOnly + * Check the update status and don't apply the update. + * + * @return bool + * Returns update status if checkOnly flag is set. */ - protected function executeConfigurationActions(array $update_definitions) { + protected function executeConfigurationActions(array $update_definitions, $force = FALSE, $checkOnly = FALSE) { foreach ($update_definitions as $configName => $configChange) { $update_actions = $configChange['update_actions']; @@ -198,15 +233,33 @@ protected function executeConfigurationActions(array $update_definitions) { $new_config = NestedArray::mergeDeep($new_config, $update_actions['add']); } - if ($this->updateConfig($configName, $new_config, $configChange['expected_config'], $delete_keys)) { - $this->logInfo($this->t('Configuration @configName has been successfully updated.', ['@configName' => $configName])); + $result = $this->updateConfig($configName, $new_config, $configChange['expected_config'], $delete_keys, $force, $checkOnly); + + if ($checkOnly) { + return $result; } - else { - $this->logWarning($this->t('Unable to update configuration for @configName.', ['@configName' => $configName])); + + switch ($result) { + case Updater::CONFIG_APPLIED_SUCCESSFULLY: + $this->logInfo($this->t('Configuration @configName has been successfully updated.', ['@configName' => $configName])); + break; + + case Updater::CONFIG_ALREADY_APPLIED: + $this->logWarning($this->t('Configuration @configName is already updated.', ['@configName' => $configName])); + break; + + case Updater::CONFIG_NOT_EXPECTED: + $this->logWarning($this->t('Expected current configuration is modefied, Unable to apply new config @configName.', ['@configName' => $configName])); + break; + + case Updater::CONFIG_NOT_FOUND: + $this->logWarning($this->t('Unable to find config @configName. Skipping update.', ['@configName' => $configName])); + break; } } } + /** * Installs modules. * @@ -321,41 +374,54 @@ protected function getFlatKeys(array $nested_array) { * Only if current config is same like old config we are updating. * @param array $delete_keys * List of parent keys to remove. @see NestedArray::unsetValue() + * @param bool $force + * Force the update. + * @param bool $checkOnly + * Check the update status and don't apply the update. * * @return bool * Returns TRUE if update of configuration was successful. */ - protected function updateConfig($config_name, array $configuration, array $expected_configuration = [], array $delete_keys = []) { + protected function updateConfig($config_name, array $configuration, array $expected_configuration = [], array $delete_keys = [], $force = FALSE, $checkOnly = FALSE) { $config = $this->configFactory->getEditable($config_name); $config_data = $config->get(); + // Reset expected_config in case of force flag. + if ($force) { + $expected_configuration = []; + } + // Check that configuration exists before executing update. if (empty($config_data)) { - return FALSE; + return Updater::CONFIG_NOT_FOUND; } // Check if configuration is already in new state. $merged_data = NestedArray::mergeDeep($expected_configuration, $configuration); - if (empty(DiffArray::diffAssocRecursive($merged_data, $config_data))) { - return TRUE; + if (!$force && empty(DiffArray::diffAssocRecursive($merged_data, $config_data))) { + return Updater::CONFIG_ALREADY_APPLIED; } - if (!empty($expected_configuration) && DiffArray::diffAssocRecursive($expected_configuration, $config_data)) { - return FALSE; - } + if (empty($expected_configuration) || !DiffArray::diffAssocRecursive($expected_configuration, $config_data)) { + // Delete configuration keys from config. + if($checkOnly){ + return Updater::CONFIG_APPLIED_SUCCESSFULLY; + } - // Delete configuration keys from config. - if (!empty($delete_keys)) { - foreach ($delete_keys as $key_path) { - NestedArray::unsetValue($config_data, $key_path); + if (!empty($delete_keys)) { + foreach ($delete_keys as $key_path) { + NestedArray::unsetValue($config_data, $key_path); + } } - } - $config->setData(NestedArray::mergeDeep($config_data, $configuration)); - $config->save(); + $config->setData(NestedArray::mergeDeep($config_data, $configuration)); + $config->save(); - return TRUE; + return Updater::CONFIG_APPLIED_SUCCESSFULLY; + }else{ + return Updater::CONFIG_NOT_EXPECTED; + } } } From 66f3162e6f00d4cfb1a78a9befc8eadaff6cee27 Mon Sep 17 00:00:00 2001 From: Waleed Qadi Date: Sun, 5 May 2019 15:30:05 +0300 Subject: [PATCH 2/5] fixed typo in message --- src/Updater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Updater.php b/src/Updater.php index 39051b6..7533b9e 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -249,7 +249,7 @@ protected function executeConfigurationActions(array $update_definitions, $force break; case Updater::CONFIG_NOT_EXPECTED: - $this->logWarning($this->t('Expected current configuration is modefied, Unable to apply new config @configName.', ['@configName' => $configName])); + $this->logWarning($this->t('Expected current configuration for @configName is not matching. Unable to apply new config.', ['@configName' => $configName])); break; case Updater::CONFIG_NOT_FOUND: From 667eb9255c7785970c1ca4c2a8b36cb7c912df99 Mon Sep 17 00:00:00 2001 From: Waleed Qadi Date: Mon, 6 May 2019 16:06:38 +0300 Subject: [PATCH 3/5] added fix for global actions error on check update --- src/Updater.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Updater.php b/src/Updater.php index 7533b9e..d24d6f7 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -171,7 +171,9 @@ public function checkUpdate($module, $update_definition_name) { $this->warningCount = 0; $update_definitions = $this->configHandler->loadUpdate($module, $update_definition_name); - + if (isset($update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS])) { + unset($update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS]); + } if (!empty($update_definitions)) { return $this->executeConfigurationActions($update_definitions, FALSE, TRUE); } From 6d398f8fab93dfc23594ec76f1dba70b07aba414 Mon Sep 17 00:00:00 2001 From: Waleed Qadi Date: Thu, 16 May 2019 13:38:05 +0300 Subject: [PATCH 4/5] fixing already updated check, and removed CONSTANTS from checklist helper, added check for installed modules --- .../update_helper_checklist.module | 8 ++------ src/Updater.php | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/update_helper_checklist/update_helper_checklist.module b/modules/update_helper_checklist/update_helper_checklist.module index be47c97..46a9685 100644 --- a/modules/update_helper_checklist/update_helper_checklist.module +++ b/modules/update_helper_checklist/update_helper_checklist.module @@ -13,11 +13,7 @@ use Drupal\Core\Url; use Drupal\update_helper_checklist\UpdateChecklist; use Symfony\Component\Yaml\Yaml; use Drupal\update_helper_checklist\Entity\Update; - -const CONFIG_NOT_FOUND = 0; -const CONFIG_ALREADY_APPLIED = 1; -const CONFIG_NOT_EXPECTED = 2; -const CONFIG_APPLIED_SUCCESSFULLY = 3; +use Drupal\update_helper\Updater; /** * Implements hook_checklistapi_checklist_info(). @@ -128,7 +124,7 @@ function update_helper_checklist_modules_installed(array $modules) { if (is_array($checklist_definition)) { $status = $updateHelper->checkUpdate($module_name, $update_hook_name); - if ($status != CONFIG_ALREADY_APPLIED && $status != CONFIG_APPLIED_SUCCESSFULLY) continue; + if ($status != Updater::CONFIG_ALREADY_APPLIED && $status != Updater::CONFIG_APPLIED_SUCCESSFULLY) continue; if (!isset($modules_checklist[$module_name])) { $modules_checklist[$module_name] = []; diff --git a/src/Updater.php b/src/Updater.php index d24d6f7..44ba307 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -24,7 +24,8 @@ class Updater implements UpdaterInterface { const CONFIG_ALREADY_APPLIED = 1; const CONFIG_NOT_EXPECTED = 2; const CONFIG_APPLIED_SUCCESSFULLY = 3; - + const MODULES_FOUND = 4; + const MODULES_NOT_FOUND = 5; /** * Site configFactory object. * @@ -169,11 +170,20 @@ public function executeUpdate($module, $update_definition_name, $force = FALSE) */ public function checkUpdate($module, $update_definition_name) { $this->warningCount = 0; - + $moduleHandler = \Drupal::service('module_handler'); + $modulesInstalled = []; $update_definitions = $this->configHandler->loadUpdate($module, $update_definition_name); if (isset($update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS])) { + if (isset($update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS][UpdateDefinitionInterface::GLOBAL_ACTION_INSTALL_MODULES])) { + $modules = $update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS][UpdateDefinitionInterface::GLOBAL_ACTION_INSTALL_MODULES]; + foreach ($modules as $module) { + if (!$moduleHandler->moduleExists($module)) return Updater::MODULES_NOT_FOUND; + $modulesInstalled[] = $module; + } + } unset($update_definitions[UpdateDefinitionInterface::GLOBAL_ACTIONS]); } + if (!empty($update_definitions)) { return $this->executeConfigurationActions($update_definitions, FALSE, TRUE); } @@ -401,7 +411,7 @@ protected function updateConfig($config_name, array $configuration, array $expec // Check if configuration is already in new state. $merged_data = NestedArray::mergeDeep($expected_configuration, $configuration); - if (!$force && empty(DiffArray::diffAssocRecursive($merged_data, $config_data))) { + if (!$force && empty(DiffArray::diffAssocRecursive($configuration, $config_data))) { return Updater::CONFIG_ALREADY_APPLIED; } From 5d743c65db2562d844d7b94f01974a50127c739a Mon Sep 17 00:00:00 2001 From: Waleed Qadi Date: Thu, 16 May 2019 13:39:24 +0300 Subject: [PATCH 5/5] added missing check --- src/Updater.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Updater.php b/src/Updater.php index 44ba307..8f2ced6 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -188,6 +188,10 @@ public function checkUpdate($module, $update_definition_name) { return $this->executeConfigurationActions($update_definitions, FALSE, TRUE); } + if (empty($update_definitions) && !empty($modulesInstalled)) { + return Updater::MODULES_FOUND; + } + return Updater::CONFIG_NOT_FOUND; }