diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php index 77c841c..58ece4d 100644 --- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php +++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php @@ -9,13 +9,54 @@ use Drupal\Core\Form\ConfirmFormBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Controller\ControllerInterface; +use Drupal\Core\KeyValueStore\KeyValueExpirableFactory; +use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; /** * Builds a confirmation form to uninstall selected modules. * * Used internally from system_modules_uninstall(). */ -class ModulesUninstallConfirmForm extends ConfirmFormBase { +class ModulesUninstallConfirmForm extends ConfirmFormBase implements ControllerInterface { + + /** + * The key value interface. + * + * @var \Drupal\Core|KeyValueStore\KeyValueStoreExpirableInterface + */ + protected $keyValueInterface; + + /** + * The module handler interface. + * + * @var |Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** + * Constructs a ModulesUninstallConfirmForm form object. + * + * @param \Drupal\user\TempStoreFactory $temp_store_factory + * The tempstore factory. + */ + public function __construct(KeyValueExpirableFactory $key_value_factory, ModuleHandlerInterface $module_handler) { + $this->keyValueInterface = $key_value_factory->get('modules_uninstall_list'); + $this->moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('keyvalue.expirable'), + $container->get('module_handler') + ); + } /** * {@inheritdoc} @@ -54,21 +95,25 @@ public function getFormID() { /** * {@inheritdoc} - * - * @param array $modules - * The array of modules. */ - public function buildForm(array $form, array &$form_state, $modules = array(), Request $request = NULL) { + public function buildForm(array $form, array &$form_state, Request $request = NULL) { + $this->modules = $this->keyValueInterface->get("modules_uninstall:{$GLOBALS['user']->uid}"); + + // Prevent this page from showing when the module list is empty. + if (empty($this->modules)) { + return new RedirectResponse('/admin/modules/uninstall'); + } + $uninstall = array(); + $data = system_rebuild_module_data(); + // Construct the hidden form elements and list items. - foreach ($modules as $module => $value) { - $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info.yml'); - $uninstall[] = $info['name']; - $form['uninstall'][$module] = array('#type' => 'hidden', '#value' => 1); + foreach ($this->modules as $module => $value) { + if ($value) { + $uninstall[] = $data[$module]->info['name']; + } } - $form['#confirmed'] = TRUE; - $form['uninstall']['#tree'] = TRUE; $form['text'] = array('#markup' => '

' . t('The following modules will be completely uninstalled from your site, and all data from these modules will be lost!') . '

'); $form['modules'] = array('#theme' => 'item_list', '#items' => $uninstall); @@ -79,6 +124,20 @@ public function buildForm(array $form, array &$form_state, $modules = array(), R * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { + // Create a list of modules that should be removed. + $uninstall = array(); + foreach ($this->modules as $module => $value) { + if ($value) { + $uninstall[] = $module; + } + } + // Uninstall the modules. + $this->moduleHandler->uninstall($uninstall); + + $this->keyValueInterface->delete("modules_uninstall:{$GLOBALS['user']->uid}"); + + drupal_set_message(t('The selected modules have been uninstalled.')); + $form_state['redirect'] = 'admin/modules/uninstall'; } } diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php new file mode 100644 index 0000000..ae72ff5 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php @@ -0,0 +1,151 @@ +keyValueInterface = $key_value_factory->get('modules_uninstall_list'); + $this->moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('keyvalue.expirable'), + $container->get('module_handler') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'system_modules_uninstall'; + } + + /** + * Form builder; provides a list of currently disabled modules. + * + * @return + * A form array representing the currently disabled modules. + * + * @ingroup forms + */ + public function buildForm(array $form, array &$form_state) { + // Make sure the install API is available. + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + + // Get a list of disabled, installed modules. + $all_modules = system_rebuild_module_data(); + $disabled_modules = array(); + foreach ($all_modules as $name => $module) { + if (empty($module->status) && drupal_get_installed_schema_version($name) > SCHEMA_UNINSTALLED) { + $disabled_modules[$name] = $module; + } + } + + // Only build the rest of the form if there are any modules available to + // uninstall. + if (!empty($disabled_modules)) { + $profile = drupal_get_profile(); + $this->moduleHandler->loadInclude('system', 'inc', 'system.admin'); + uasort($disabled_modules, 'system_sort_modules_by_info_name'); + $form['uninstall'] = array('#tree' => TRUE); + foreach ($disabled_modules as $module) { + $module_name = $module->info['name'] ? $module->info['name'] : $module->name; + $form['modules'][$module->name]['#module_name'] = $module_name; + $form['modules'][$module->name]['name']['#markup'] = $module_name; + $form['modules'][$module->name]['description']['#markup'] = t($module->info['description']); + $form['uninstall'][$module->name] = array( + '#type' => 'checkbox', + '#title' => t('Uninstall @module module', array('@module' => $module_name)), + '#title_display' => 'invisible', + ); + // All modules which depend on this one must be uninstalled first, before + // we can allow this module to be uninstalled. (The installation profile + // is excluded from this list.) + foreach (array_keys($module->required_by) as $dependent) { + if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) { + $dependent_name = isset($all_modules[$dependent]->info['name']) ? $all_modules[$dependent]->info['name'] : $dependent; + $form['modules'][$module->name]['#required_by'][] = $dependent_name; + $form['uninstall'][$module->name]['#disabled'] = TRUE; + } + } + } + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Uninstall'), + ); + } + else { + $form['modules'] = array(); + } + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + // Form submitted, but no modules selected. + if (!array_filter($form_state['values']['uninstall'])) { + drupal_set_message(t('No modules selected.'), 'error'); + $form_state['redirect'] = 'admin/modules/uninstall'; + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + // Make sure the install API is available. + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + + // Save all the values in the keyValueInterface. Time to expire is set to + // 2 minutes. This could be less because we only need it for the duration + // of the page request. + $this->keyValueInterface->setWithExpire("modules_uninstall:{$GLOBALS['user']->uid}", $form_state['values']['uninstall'], 120); + // Redirect to the confirm form. + $form_state['redirect'] = 'admin/modules/uninstall/confirm'; + } +} diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 957db86..bc8bd37 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -764,110 +764,96 @@ function system_modules_submit($form, &$form_state) { } /** - * Uninstall functions - */ - -/** - * Form constructor for the uninstalling disabled modules form. - * - * @see system_menu() - * @see system_modules_uninstall_validate() - * @see system_modules_uninstall_submit() + * Confirm uninstall of selected modules. * * @ingroup forms + * @param $storage + * An associative array of modules selected to be uninstalled. + * @return + * A form array representing modules to confirm. */ -function system_modules_uninstall($form, $form_state = NULL) { - // Make sure the install API is available. - include_once DRUPAL_ROOT . '/core/includes/install.inc'; - - // Display the confirm form if any modules have been submitted. - if (!empty($form_state['storage']['uninstall']) && $modules = array_filter($form_state['storage']['uninstall'])) { - // Contents of confirm form is injected here because already in form - // building function. - $confirm_form = new ModulesUninstallConfirmForm(); - return $confirm_form->buildForm($form, $form_state, $modules, Drupal::request()); - } - - // Get a list of disabled, installed modules. - $all_modules = system_rebuild_module_data(); - $disabled_modules = array(); - foreach ($all_modules as $name => $module) { - if (empty($module->status) && drupal_get_installed_schema_version($name) > SCHEMA_UNINSTALLED) { - $disabled_modules[$name] = $module; - } +function system_modules_uninstall_confirm_form($storage) { + // Nothing to build. + if (empty($storage)) { + return; } - // Only build the rest of the form if there are any modules available to - // uninstall. - if (!empty($disabled_modules)) { - $profile = drupal_get_profile(); - uasort($disabled_modules, 'system_sort_modules_by_info_name'); - $form['uninstall'] = array('#tree' => TRUE); - foreach ($disabled_modules as $module) { - $module_name = $module->info['name'] ? $module->info['name'] : $module->name; - $form['modules'][$module->name]['#module_name'] = $module_name; - $form['modules'][$module->name]['name']['#markup'] = $module_name; - $form['modules'][$module->name]['description']['#markup'] = t($module->info['description']); - $form['uninstall'][$module->name] = array( - '#type' => 'checkbox', - '#title' => t('Uninstall @module module', array('@module' => $module_name)), - '#title_display' => 'invisible', - ); - // All modules which depend on this one must be uninstalled first, before - // we can allow this module to be uninstalled. (The installation profile - // is excluded from this list.) - foreach (array_keys($module->required_by) as $dependent) { - if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) { - $dependent_name = isset($all_modules[$dependent]->info['name']) ? $all_modules[$dependent]->info['name'] : $dependent; - $form['modules'][$module->name]['#required_by'][] = $dependent_name; - $form['uninstall'][$module->name]['#disabled'] = TRUE; - } - } - } - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Uninstall'), + // Construct the hidden form elements and list items. + foreach (array_filter($storage['uninstall']) as $module => $value) { + $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info.yml'); + $uninstall[] = $info['name']; + $form['uninstall'][$module] = array('#type' => 'hidden', + '#value' => 1, ); - $form['#action'] = url('admin/modules/uninstall/confirm'); - } - else { - $form['modules'] = array(); } - return $form; + // Display a confirm form if modules have been selected. + if (isset($uninstall)) { + $form['#confirmed'] = TRUE; + $form['uninstall']['#tree'] = TRUE; + $form['text'] = array('#markup' => '

' . t('The following modules will be completely uninstalled from your site, and all data from these modules will be lost!') . '

'); + $form['modules'] = array('#theme' => 'item_list', '#items' => $uninstall); + $form = confirm_form( + $form, + t('Confirm uninstall'), + 'admin/modules/uninstall', + t('Would you like to continue with uninstalling the above?'), + t('Uninstall'), + t('Cancel')); + return $form; + } } /** - * Validates the submitted uninstall form. + * Menu callback: displays the site status report. Can also be used as a pure check. + * + * @param $check + * If true, only returns a boolean whether there are system status errors. */ -function system_modules_uninstall_validate($form, &$form_state) { - // Form submitted, but no modules selected. - if (!count(array_filter($form_state['values']['uninstall']))) { - drupal_set_message(t('No modules selected.'), 'error'); - return new RedirectResponse(url('admin/modules/uninstall', array('absolute' => TRUE))); +function system_status($check = FALSE) { + // Load .install files + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + drupal_load_updates(); + + // Check run-time requirements and status information. + $requirements = module_invoke_all('requirements', 'runtime'); + usort($requirements, '_system_sort_requirements'); + + if ($check) { + return drupal_requirements_severity($requirements) == REQUIREMENT_ERROR; } + // MySQL import might have set the uid of the anonymous user to autoincrement + // value. Let's try fixing it. See http://drupal.org/node/204411 + db_update('users') + ->expression('uid', 'uid - uid') + ->condition('name', '') + ->condition('pass', '') + ->condition('status', 0) + ->execute(); + return theme('status_report', array('requirements' => $requirements)); } /** - * Processes the submitted uninstall form. + * Menu callback: run cron manually. */ -function system_modules_uninstall_submit($form, &$form_state) { - // Make sure the install API is available. - include_once DRUPAL_ROOT . '/core/includes/install.inc'; - - if (!empty($form['#confirmed'])) { - // Call the uninstall routine for each selected module. - $modules = array_keys($form_state['values']['uninstall']); - module_uninstall($modules); - drupal_set_message(t('The selected modules have been uninstalled.')); - - $form_state['redirect'] = 'admin/modules/uninstall'; +function system_run_cron() { + // Run cron manually + if (drupal_cron_run()) { + drupal_set_message(t('Cron ran successfully.')); } else { - $form_state['storage'] = $form_state['values']; - $form_state['rebuild'] = TRUE; + drupal_set_message(t('Cron run failed.'), 'error'); } + + drupal_goto('admin/reports/status'); +} + +/** + * Menu callback: return information about PHP. + */ +function system_php() { + phpinfo(); + drupal_exit(); } /** diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 8802ead..7254dff 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -748,17 +748,14 @@ function system_menu() { ); $items['admin/modules/uninstall'] = array( 'title' => 'Uninstall', - 'page arguments' => array('system_modules_uninstall'), - 'access arguments' => array('administer modules'), + 'route_name' => 'system_modules_uninstall', 'type' => MENU_LOCAL_TASK, - 'file' => 'system.admin.inc', 'weight' => 20, ); $items['admin/modules/uninstall/confirm'] = array( 'title' => 'Uninstall', - 'access arguments' => array('administer modules'), + 'route_name' => 'system_modules_uninstall_confirm', 'type' => MENU_VISIBLE_IN_BREADCRUMB, - 'file' => 'system.admin.inc', ); // Configuration. diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index 45ce1e5..b1c2175 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -157,3 +157,17 @@ system_theme_settings_global: _form: '\Drupal\system\Form\ThemeSettingsForm' requirements: _permission: 'administer themes' + +system_modules_uninstall: + pattern: 'admin/modules/uninstall' + defaults: + _form: 'Drupal\system\Form\ModulesUninstallForm' + requirements: + _permission: 'administer modules' + +system_modules_uninstall_confirm: + pattern: 'admin/modules/uninstall/confirm' + defaults: + _form: 'Drupal\system\Form\ModulesUninstallConfirmForm' + requirements: + _permission: 'administer modules'