diff --git a/core/lib/Drupal/Core/Updater/Module.php b/core/lib/Drupal/Core/Updater/Module.php index a28768d..d4f24ea 100644 --- a/core/lib/Drupal/Core/Updater/Module.php +++ b/core/lib/Drupal/Core/Updater/Module.php @@ -100,7 +100,7 @@ public function getSchemaUpdates() { public function postInstallTasks() { return array( \Drupal::l(t('Install another module'), new Url('update.module_install')), - \Drupal::l(t('Enable newly added modules'), new Url('system.modules_list')), + \Drupal::l(t('Enable newly added modules'), new Url('system.modules_install')), \Drupal::l(t('Administration pages'), new Url('system.admin')), ); } diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php index cff60a4..ac81890 100644 --- a/core/modules/config/src/Tests/ConfigInstallWebTest.php +++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php @@ -126,7 +126,7 @@ public function testPreExistingConfigInstall() { // Try to install config_install_fail_test and config_test. Doing this // will install the config_test module first because it is a dependency of // config_install_fail_test. - // @see \Drupal\system\Form\ModulesListForm::submitForm() + // @see \Drupal\system\Form\ModulesInstallForm::submitForm() $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE, 'modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration')); $this->assertRaw('Unable to install Configuration install fail test, config_test.dynamic.dotted.default already exists in active configuration.'); @@ -137,7 +137,7 @@ public function testPreExistingConfigInstall() { // Try to install config_install_fail_test without selecting config_test. // The user is shown a confirm form because the config_test module is a // dependency. - // @see \Drupal\system\Form\ModulesListConfirmForm::submitForm() + // @see \Drupal\system\Form\ModulesInstallConfirmForm::submitForm() $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration')); $this->drupalPostForm(NULL, array(), t('Continue')); $this->assertRaw('Unable to install Configuration install fail test, config_test.dynamic.dotted.default already exists in active configuration.'); diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module index 7fa3c05..47bbf01 100644 --- a/core/modules/editor/editor.module +++ b/core/modules/editor/editor.module @@ -28,7 +28,7 @@ function editor_help($route_name, RouteMatchInterface $route_match) { $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Installing text editors') . '
'; - $output .= '
' . t('The Text Editor module provides a framework for managing editors. To use it, you also need to enable a text editor. This can either be the core CKEditor module, which can be enabled on the Extend page, or a contributed module for any other text editor. When installing a contributed text editor module, be sure to check the installation instructions, because you will most likely need to download and install an external library as well as the Drupal module.', array('!ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', array('name' => 'ckeditor')) : '#', '!extend' => \Drupal::url('system.modules_list'))) . '
'; + $output .= '
' . t('The Text Editor module provides a framework for managing editors. To use it, you also need to enable a text editor. This can either be the core CKEditor module, which can be enabled on the Extend page, or a contributed module for any other text editor. When installing a contributed text editor module, be sure to check the installation instructions, because you will most likely need to download and install an external library as well as the Drupal module.', array('!ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', array('name' => 'ckeditor')) : '#', '!extend' => \Drupal::url('system.modules_install'))) . '
'; $output .= '
' . t('Enabling a text editor for a text format') . '
'; $output .= '
' . t('On the Text formats and editors page you can see which text editor is associated with each text format. You can change this by clicking on the Configure link, and then choosing a text editor or none from the Text editor drop-down list. The text editor will then be displayed with any text field for which this text format is chosen.', array('!formats' => \Drupal::url('filter.admin_overview'))) . '
'; $output .= '
' . t('Configuring a text editor') . '
'; diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 88ccff9..52b6158 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -83,7 +83,7 @@ function field_help($route_name, RouteMatchInterface $route_match) { $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Enabling field types, widgets, and formatters') . '
'; - $output .= '
' . t('The Field module provides the infrastructure for fields; the field types, formatters, and widgets are provided by Drupal core or additional modules. Some of the modules are required; the optional modules can be enabled from the Extend administration page. Additional fields, formatters, and widgets may be provided by contributed modules, which you can find in the contributed module section of Drupal.org.', array('!modules' => \Drupal::url('system.modules_list'), '!contrib' => 'https://www.drupal.org/project/modules')) . '
'; + $output .= '
' . t('The Field module provides the infrastructure for fields; the field types, formatters, and widgets are provided by Drupal core or additional modules. Some of the modules are required; the optional modules can be enabled from the Extend administration page. Additional fields, formatters, and widgets may be provided by contributed modules, which you can find in the contributed module section of Drupal.org.', array('!modules' => \Drupal::url('system.modules_install'), '!contrib' => 'https://www.drupal.org/project/modules')) . '
'; $output .= '

' . t('Field, widget, and formatter information') . '

'; diff --git a/core/modules/help/help.module b/core/modules/help/help.module index 3ec6fd8..b790c1b 100644 --- a/core/modules/help/help.module +++ b/core/modules/help/help.module @@ -18,7 +18,7 @@ function help_help($route_name, RouteMatchInterface $route_match) { $output .= '

' . t('Follow these steps to set up and start using your website:') . '

'; $output .= '
    '; $output .= '
  1. ' . t('Configure your website Once logged in, visit the Administration page, where you may customize and configure all aspects of your website.', array('!admin' => \Drupal::url('system.admin'), '!config' => \Drupal::url('system.admin_config'))) . '
  2. '; - $output .= '
  3. ' . t('Enable additional functionality Next, visit the Extend page and enable modules that suit your specific needs. You can find additional modules at the Drupal.org modules page.', array('!modules' => \Drupal::url('system.modules_list'), '!download_modules' => 'https://www.drupal.org/project/modules')) . '
  4. '; + $output .= '
  5. ' . t('Enable additional functionality Next, visit the Extend page and enable modules that suit your specific needs. You can find additional modules at the Drupal.org modules page.', array('!modules' => \Drupal::url('system.modules_install'), '!download_modules' => 'https://www.drupal.org/project/modules')) . '
  6. '; $output .= '
  7. ' . t('Customize your website design To change the "look and feel" of your website, visit the Appearance page. You may choose from one of the included themes or download additional themes from the Drupal.org themes page.', array('!themes' => \Drupal::url('system.themes_page'), '!download_themes' => 'https://www.drupal.org/project/themes')) . '
  8. '; // Display a link to the create content page if Node module is enabled. if (\Drupal::moduleHandler()->moduleExists('node')) { diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Controller/ModulesListController.php similarity index 69% copy from core/modules/system/src/Form/ModulesListForm.php copy to core/modules/system/src/Controller/ModulesListController.php index 173fcc7..29300a0 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Controller/ModulesListController.php @@ -2,21 +2,19 @@ /** * @file - * Contains \Drupal\system\Form\ModulesListForm. + * Contains \Drupal\system\Form\ModulesInstallForm. */ -namespace Drupal\system\Form; +namespace Drupal\system\Controller; use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; -use Drupal\Core\Config\PreExistingConfigException; -use Drupal\Core\Config\UnmetDependenciesException; +use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Access\AccessManagerInterface; use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleInstallerInterface; -use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; use Drupal\Core\Menu\MenuLinkManagerInterface; @@ -36,7 +34,7 @@ * requires. See \Drupal\Core\Extension\InfoParser for info on module.info.yml * descriptors. */ -class ModulesListForm extends FormBase { +class ModulesListController extends ControllerBase { /** * The current user. @@ -112,7 +110,7 @@ public static function create(ContainerInterface $container) { } /** - * Constructs a ModulesListForm object. + * Constructs a ModulesInstallForm object. * * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. @@ -153,19 +151,28 @@ public function getFormId() { } /** - * {@inheritdoc} + * @todo */ - public function buildForm(array $form, FormStateInterface $form_state) { + public function listModules() { require_once DRUPAL_ROOT . '/core/includes/install.inc'; $distribution = SafeMarkup::checkPlain(drupal_install_profile_distribution_name()); // Include system.admin.inc so we can use the sort callbacks. $this->moduleHandler->loadInclude('system', 'inc', 'system.admin'); - $form['filters'] = array( + $form = array( '#type' => 'container', '#attributes' => array( - 'class' => array('table-filter', 'js-show'), + 'class' => array('system-modules', 'system-modules__list'), + ), + '#attached' => array( + 'library' => array('system/drupal.system.modules'), + ), + 'filters' => array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('table-filter', 'js-show'), + ), ), ); @@ -176,7 +183,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#placeholder' => $this->t('Enter module name'), '#attributes' => array( 'class' => array('table-filter-text'), - 'data-table' => '#system-modules', + 'data-table' => '.system-modules', 'autocomplete' => 'off', 'title' => $this->t('Enter a part of the module name or description to filter by.'), ), @@ -189,7 +196,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Iterate over each of the modules. $form['modules']['#tree'] = TRUE; foreach ($modules as $filename => $module) { - if (empty($module->info['hidden'])) { + if ($module->status && empty($module->info['hidden'])) { $package = $module->info['package']; $form['modules'][$package][$filename] = $this->buildRow($modules, $module, $distribution); } @@ -203,7 +210,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#open' => TRUE, '#theme' => 'system_modules_details', '#header' => array( - array('data' => $this->t('Installed'), 'class' => array('checkbox', 'visually-hidden')), array('data' => $this->t('Name'), 'class' => array('name', 'visually-hidden')), array('data' => $this->t('Description'), 'class' => array('description', 'visually-hidden', RESPONSIVE_PRIORITY_LOW)), ), @@ -222,14 +228,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Lastly, sort all packages by title. uasort($form['modules'], array('\Drupal\Component\Utility\SortArray', 'sortByTitleProperty')); - $form['#attached']['library'][] = 'system/drupal.system.modules'; - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => $this->t('Save configuration'), - '#button_type' => 'primary', - ); - return $form; } @@ -250,6 +248,7 @@ protected function buildRow(array $modules, Extension $module, $distribution) { $row['#required'] = array(); $row['#requires'] = array(); $row['#required_by'] = array(); + $row['#checkbox'] = FALSE; $row['name']['#markup'] = $module->info['name']; $row['description']['#markup'] = $this->t($module->info['description']); @@ -316,18 +315,7 @@ protected function buildRow(array $modules, Extension $module, $distribution) { } } - // Present a checkbox for installing and indicating the status of a module. - $row['enable'] = array( - '#type' => 'checkbox', - '#title' => $this->t('Install'), - '#default_value' => (bool) $module->status, - '#disabled' => (bool) $module->status, - ); - - // Disable the checkbox for required modules. if (!empty($module->info['required'])) { - // Used when displaying modules that are required by the installation profile - $row['enable']['#disabled'] = TRUE; $row['#required_by'][] = $distribution . (!empty($module->info['explanation']) ? ' ('. $module->info['explanation'] .')' : ''); } @@ -359,7 +347,6 @@ protected function buildRow(array $modules, Extension $module, $distribution) { // If this module is not compatible, disable the checkbox. if (!$compatible) { $status = implode(' ', $reasons); - $row['enable']['#disabled'] = TRUE; $row['description']['#markup'] = $status; $row['#attributes']['class'][] = 'incompatible'; } @@ -368,7 +355,6 @@ protected function buildRow(array $modules, Extension $module, $distribution) { foreach ($module->requires as $dependency => $version) { if (!isset($modules[$dependency])) { $row['#requires'][$dependency] = $this->t('@module (missing)', array('@module' => Unicode::ucfirst($dependency))); - $row['enable']['#disabled'] = TRUE; } // Only display visible modules. elseif (empty($modules[$dependency]->hidden)) { @@ -380,7 +366,6 @@ protected function buildRow(array $modules, Extension $module, $distribution) { '@module' => $name . $incompatible_version, '@version' => $modules[$dependency]->info['version'], )); - $row['enable']['#disabled'] = TRUE; } // Disable the checkbox if the dependency is incompatible with this // version of Drupal core. @@ -388,7 +373,6 @@ protected function buildRow(array $modules, Extension $module, $distribution) { $row['#requires'][$dependency] = $this->t('@module (incompatible with this version of Drupal core)', array( '@module' => $name, )); - $row['enable']['#disabled'] = TRUE; } elseif ($modules[$dependency]->status) { $row['#requires'][$dependency] = $this->t('@module', array('@module' => $name)); @@ -405,7 +389,6 @@ protected function buildRow(array $modules, Extension $module, $distribution) { if (isset($modules[$dependent]) && empty($modules[$dependent]->info['hidden'])) { if ($modules[$dependent]->status == 1 && $module->status == 1) { $row['#required_by'][$dependent] = $this->t('@module', array('@module' => $modules[$dependent]->info['name'])); - $row['enable']['#disabled'] = TRUE; } else { $row['#required_by'][$dependent] = $this->t('@module (disabled)', array('@module' => $modules[$dependent]->info['name'])); @@ -416,130 +399,4 @@ protected function buildRow(array $modules, Extension $module, $distribution) { return $row; } - /** - * Helper function for building a list of modules to install. - * - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * - * @return array - * An array of modules to install and their dependencies. - */ - protected function buildModuleList(FormStateInterface $form_state) { - $packages = $form_state->getValue('modules'); - - // Build a list of modules to install. - $modules = array( - 'install' => array(), - 'dependencies' => array(), - ); - - // Required modules have to be installed. - // @todo This should really not be handled here. - $data = system_rebuild_module_data(); - foreach ($data as $name => $module) { - if (!empty($module->required) && !$this->moduleHandler->moduleExists($name)) { - $modules['install'][$name] = $module->info['name']; - } - } - - // First, build a list of all modules that were selected. - foreach ($packages as $items) { - foreach ($items as $name => $checkbox) { - if ($checkbox['enable'] && !$this->moduleHandler->moduleExists($name)) { - $modules['install'][$name] = $data[$name]->info['name']; - } - } - } - - // Add all dependencies to a list. - while (list($module) = each($modules['install'])) { - foreach (array_keys($data[$module]->requires) as $dependency) { - if (!isset($modules['install'][$dependency]) && !$this->moduleHandler->moduleExists($dependency)) { - $modules['dependencies'][$module][$dependency] = $data[$dependency]->info['name']; - $modules['install'][$dependency] = $data[$dependency]->info['name']; - } - } - } - - // Make sure the install API is available. - include_once DRUPAL_ROOT . '/core/includes/install.inc'; - - // Invoke hook_requirements('install'). If failures are detected, make - // sure the dependent modules aren't installed either. - foreach (array_keys($modules['install']) as $module) { - if (!drupal_check_module($module)) { - unset($modules['install'][$module]); - foreach (array_keys($data[$module]->required_by) as $dependent) { - unset($modules['install'][$dependent]); - unset($modules['dependencies'][$dependent]); - } - } - } - - return $modules; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Retrieve a list of modules to install and their dependencies. - $modules = $this->buildModuleList($form_state); - - // Check if we have to install any dependencies. If there is one or more - // dependencies that are not installed yet, redirect to the confirmation - // form. - if (!empty($modules['dependencies']) || !empty($modules['missing'])) { - // Write the list of changed module states into a key value store. - $account = $this->currentUser()->id(); - $this->keyValueExpirable->setWithExpire($account, $modules, 60); - - // Redirect to the confirmation form. - $form_state->setRedirect('system.modules_list_confirm'); - - // We can exit here because at least one modules has dependencies - // which we have to prompt the user for in a confirmation form. - return; - } - - // Gets list of modules prior to install process. - $before = $this->moduleHandler->getModuleList(); - - // There seem to be no dependencies that would need approval. - if (!empty($modules['install'])) { - try { - $this->moduleInstaller->install(array_keys($modules['install'])); - } - catch (PreExistingConfigException $e) { - $config_objects = $e->flattenConfigObjects($e->getConfigObjects()); - drupal_set_message( - $this->formatPlural( - count($config_objects), - 'Unable to install @extension, %config_names already exists in active configuration.', - 'Unable to install @extension, %config_names already exist in active configuration.', - array( - '%config_names' => implode(', ', $config_objects), - '@extension' => $modules['install'][$e->getExtension()] - )), - 'error' - ); - return; - } - catch (UnmetDependenciesException $e) { - drupal_set_message( - $e->getTranslatedMessage($this->getStringTranslation(), $modules['install'][$e->getExtension()]), - 'error' - ); - return; - } - } - - // Gets module list after install process, flushes caches and displays a - // message if there are changes. - if ($before != $this->moduleHandler->getModuleList()) { - drupal_set_message(t('The configuration options have been saved.')); - } - } - } diff --git a/core/modules/system/src/Form/ModulesListConfirmForm.php b/core/modules/system/src/Form/ModulesInstallConfirmForm.php similarity index 95% rename from core/modules/system/src/Form/ModulesListConfirmForm.php rename to core/modules/system/src/Form/ModulesInstallConfirmForm.php index 5449b41..dd1d9cc 100644 --- a/core/modules/system/src/Form/ModulesListConfirmForm.php +++ b/core/modules/system/src/Form/ModulesInstallConfirmForm.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\system\Form\ModulesListConfirmForm. + * Contains \Drupal\system\Form\ModulesInstallConfirmForm. */ namespace Drupal\system\Form; @@ -20,7 +20,7 @@ /** * Builds a confirmation form for enabling modules with dependencies. */ -class ModulesListConfirmForm extends ConfirmFormBase { +class ModulesInstallConfirmForm extends ConfirmFormBase { /** * The module handler service. @@ -51,7 +51,7 @@ class ModulesListConfirmForm extends ConfirmFormBase { protected $moduleInstaller; /** - * Constructs a ModulesListConfirmForm object. + * Constructs a ModulesInstallConfirmForm object. * * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. @@ -88,7 +88,7 @@ public function getQuestion() { * {@inheritdoc} */ public function getCancelUrl() { - return new Url('system.modules_list'); + return new Url('system.modules_install'); } /** @@ -121,7 +121,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Redirect to the modules list page if the key value store is empty. if (!$this->modules) { - return $this->redirect('system.modules_list'); + return $this->redirect('system.modules_install'); } $items = array(); diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesInstallForm.php similarity index 98% rename from core/modules/system/src/Form/ModulesListForm.php rename to core/modules/system/src/Form/ModulesInstallForm.php index 173fcc7..ee0332d 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Form/ModulesInstallForm.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\system\Form\ModulesListForm. + * Contains \Drupal\system\Form\ModulesInstallForm. */ namespace Drupal\system\Form; @@ -36,7 +36,7 @@ * requires. See \Drupal\Core\Extension\InfoParser for info on module.info.yml * descriptors. */ -class ModulesListForm extends FormBase { +class ModulesInstallForm extends FormBase { /** * The current user. @@ -112,7 +112,7 @@ public static function create(ContainerInterface $container) { } /** - * Constructs a ModulesListForm object. + * Constructs a ModulesInstallForm object. * * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. @@ -189,7 +189,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Iterate over each of the modules. $form['modules']['#tree'] = TRUE; foreach ($modules as $filename => $module) { - if (empty($module->info['hidden'])) { + if (!$module->status && empty($module->info['hidden'])) { $package = $module->info['package']; $form['modules'][$package][$filename] = $this->buildRow($modules, $module, $distribution); } @@ -250,6 +250,7 @@ protected function buildRow(array $modules, Extension $module, $distribution) { $row['#required'] = array(); $row['#requires'] = array(); $row['#required_by'] = array(); + $row['#checkbox'] = TRUE; $row['name']['#markup'] = $module->info['name']; $row['description']['#markup'] = $this->t($module->info['description']); @@ -496,7 +497,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $this->keyValueExpirable->setWithExpire($account, $modules, 60); // Redirect to the confirmation form. - $form_state->setRedirect('system.modules_list_confirm'); + $form_state->setRedirect('system.modules_install_confirm'); // We can exit here because at least one modules has dependencies // which we have to prompt the user for in a confirmation form. diff --git a/core/modules/system/src/Tests/Form/ModulesListFormWebTest.php b/core/modules/system/src/Tests/Module/ModulesListWebTest.php similarity index 74% rename from core/modules/system/src/Tests/Form/ModulesListFormWebTest.php rename to core/modules/system/src/Tests/Module/ModulesListWebTest.php index 7f4f2d6..4cd7fe0 100644 --- a/core/modules/system/src/Tests/Form/ModulesListFormWebTest.php +++ b/core/modules/system/src/Tests/Module/ModulesListWebTest.php @@ -2,19 +2,19 @@ /** * @file - * Contains \Drupal\system\Form\ModulesListFormWebTest. + * Contains \Drupal\system\Tests\Module\ModulesListWebTest. */ -namespace Drupal\system\Tests\Form; +namespace Drupal\system\Tests\Module; use Drupal\simpletest\WebTestBase; /** - * Tests \Drupal\system\Form\ModulesListForm. + * Tests \Drupal\system\Form\ModulesInstallForm. * * @group Form */ -class ModulesListFormWebTest extends WebTestBase { +class ModulesListWebTest extends WebTestBase { /** * {@inheritdoc} @@ -34,7 +34,7 @@ protected function setUp() { */ public function testModuleListForm() { $this->drupalLogin($this->drupalCreateUser(array('administer modules'))); - $this->drupalGet('admin/modules'); + $this->drupalGet('admin/modules/list'); $this->assertResponse('200'); // Check that system_test's configure link was rendered correctly. diff --git a/core/modules/system/src/Tests/Module/RequiredTest.php b/core/modules/system/src/Tests/Module/RequiredTest.php deleted file mode 100644 index c14d293..0000000 --- a/core/modules/system/src/Tests/Module/RequiredTest.php +++ /dev/null @@ -1,36 +0,0 @@ -drupalGet('admin/modules'); - foreach ($module_info as $module => $info) { - // Check to make sure the checkbox for each required module is disabled - // and checked (or absent from the page if the module is also hidden). - if (!empty($info['required'])) { - $field_name = "modules[{$info['package']}][$module][enable]"; - if (empty($info['hidden'])) { - $this->assertFieldByXPath("//input[@name='$field_name' and @disabled='disabled' and @checked='checked']", '', format_string('Field @name was disabled and checked.', array('@name' => $field_name))); - } - else { - $this->assertNoFieldByName($field_name); - } - } - } - } -} diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 276e393..2bf12ab 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -214,10 +214,6 @@ function theme_system_modules_details($variables) { foreach (Element::children($form) as $key) { // Stick the key into $module for easier access. $module = $form[$key]; - // Create the row for the table. - $row = array(); - // Add the checkbox into the first cell. - unset($module['enable']['#title']); $module['#requires'] = array_filter($module['#requires']); $module['#required_by'] = array_filter($module['#required_by']); @@ -225,11 +221,23 @@ function theme_system_modules_details($variables) { $required_by = !empty($module['#required_by']); $version = !empty($module['version']['#markup']); - $row[] = array('class' => array('checkbox'), 'data' => drupal_render($module['enable'])); + // Create the row for the table. + $row = array(); // Add the module label and expand/collapse functionality. $id = Html::getUniqueId('module-' . $key); - $col2 = ''; + if ($module['#checkbox']) { + // Add the checkbox into the first cell. + unset($module['enable']['#title']); + $row[] = array( + 'class' => array('checkbox'), + 'data' => drupal_render($module['enable']) + ); + $col2 = ''; + } + else { + $col2 = ''; + } $row[] = array('class' => array('module'), 'data' => SafeMarkup::set($col2)); // Add the description, along with any modules it requires. @@ -260,13 +268,14 @@ function theme_system_modules_details($variables) { $details = array( '#type' => 'details', '#title' => SafeMarkup::set(' ' . drupal_render($module['description']) . ''), - '#attributes' => array('id' => $module['enable']['#id'] . '-description'), + '#attributes' => array('id' => $id . '-description'), '#description' => $description, ); $col4 = drupal_render($details); $row[] = array('class' => array('description', 'expand'), 'data' => $col4); - $rows[] = $module['#attributes'] + array('data' => $row); + $attributes = isset($module['#attributes']) ? $module['#attributes'] : array(); + $rows[] = $attributes + array('data' => $row); } $table = array( diff --git a/core/modules/system/system.install b/core/modules/system/system.install index a0849b1..057bc0d 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -597,7 +597,7 @@ function system_requirements($phase) { 'severity' => REQUIREMENT_WARNING, 'description' => t('Update notifications are not enabled. It is highly recommended that you enable the Update Manager module from the module administration page in order to stay up-to-date on new releases. For more information, Update status handbook page.', array( '@update' => 'https://www.drupal.org/documentation/modules/update', - '@module' => \Drupal::url('system.modules_list'), + '@module' => \Drupal::url('system.modules_install'), )), ); } diff --git a/core/modules/system/system.links.menu.yml b/core/modules/system/system.links.menu.yml index ba21cee..325eaf2 100644 --- a/core/modules/system/system.links.menu.yml +++ b/core/modules/system/system.links.menu.yml @@ -21,11 +21,11 @@ system.themes_page: description: 'Select and configure your themes.' parent: system.admin weight: -6 -system.modules_list: +system.modules_install: title: Extend description: 'Add and enable modules to extend site functionality.' parent: system.admin - route_name: system.modules_list + route_name: system.modules_install weight: -2 system.admin_config: title: Configuration diff --git a/core/modules/system/system.links.task.yml b/core/modules/system/system.links.task.yml index a151835..bf03cbd 100644 --- a/core/modules/system/system.links.task.yml +++ b/core/modules/system/system.links.task.yml @@ -34,13 +34,18 @@ system.theme_settings_theme: parent_id: system.theme_settings deriver: Drupal\system\Plugin\Derivative\ThemeLocalTask +system.modules_install: + route_name: system.modules_install + base_route: system.modules_install + title: 'Install' system.modules_list: route_name: system.modules_list - base_route: system.modules_list - title: 'List' + base_route: system.modules_install + title: 'Currently installed' + weight: 5 system.modules_uninstall: route_name: system.modules_uninstall - base_route: system.modules_list + base_route: system.modules_install title: 'Uninstall' weight: 20 diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 96f0083..bf4add7 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -78,7 +78,7 @@ function system_help($route_name, RouteMatchInterface $route_match) { $output .= '

    ' . t('Uses') . '

    '; $output .= '
    '; $output .= '
    ' . t('Managing modules') . '
    '; - $output .= '
    ' . t('Users with appropriate permission can install and uninstall modules from the Extend page. Depending on which distribution or installation profile you choose when you install your site, several modules are installed and others are provided but not installed. Each module provides a discrete set of features; modules may be installed or uninstalled depending on the needs of the site. Many additional modules contributed by members of the Drupal community are available for download from the Drupal.org module page. Note that uninstalling a module is a destructive action: when you uninstall a module, you will permanently lose all data connected to the module.', array('!modules' => \Drupal::url('system.modules_list'), '!drupal-modules' => 'https://www.drupal.org/project/modules')) . '
    '; + $output .= '
    ' . t('Users with appropriate permission can install and uninstall modules from the Extend page. Depending on which distribution or installation profile you choose when you install your site, several modules are installed and others are provided but not installed. Each module provides a discrete set of features; modules may be installed or uninstalled depending on the needs of the site. Many additional modules contributed by members of the Drupal community are available for download from the Drupal.org module page. Note that uninstalling a module is a destructive action: when you uninstall a module, you will permanently lose all data connected to the module.', array('!modules' => \Drupal::url('system.modules_install'), '!drupal-modules' => 'https://www.drupal.org/project/modules')) . '
    '; $output .= '
    ' . t('Managing themes') . '
    '; $output .= '
    ' . t('Users with appropriate permission can install and uninstall themes on the Appearance page. Themes determine the design and presentation of your site. Depending on which distribution or installation profile you choose when you install your site, a default theme is installed, and possibly a different theme for administration pages. Other themes are provided but not installed, and additional contributed themes are available at the Drupal.org theme page.', array('!themes' => \Drupal::url('system.themes_page'), '!drupal-themes' => 'https://www.drupal.org/project/themes')) . '
    '; $output .= '
    ' . t('Disabling drag-and-drop functionality') . '
    '; @@ -113,8 +113,11 @@ function system_help($route_name, RouteMatchInterface $route_match) { case 'system.theme_settings': return '

    ' . t('These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.') . '

    '; + case 'system.modules_install': + $output = '

    ' . t('The modules listed below are available for installation. Download additional contributed modules to extend your site\'s functionality.', array('!modules' => 'https://www.drupal.org/project/modules')) . '

    '; + return $output; case 'system.modules_list': - $output = '

    ' . t('Download additional contributed modules to extend your site\'s functionality.', array('!modules' => 'https://www.drupal.org/project/modules')) . '

    '; + $output = '

    ' . t('The modules listed below are currently installed. Install new modules to extend your site\'s functionality.', array('!modules' => \Drupal::url('system.modules_install'))) . '

    '; if (\Drupal::moduleHandler()->moduleExists('update')) { if (update_manager_access()) { $output .= '

    ' . t('Regularly review and install available updates to maintain a secure and current site. Always run the update script each time a module is updated.', array('!update-php' => \Drupal::url('system.db_update'), '!updates' => \Drupal::url('update.status'))) . '

    '; diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index 12e7d9a..8e19c0e 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -265,23 +265,31 @@ entity.date_format.delete_form: requirements: _entity_access: 'date_format.delete' -system.modules_list: +system.modules_install: path: '/admin/modules' defaults: _title: 'Extend' _title_context: 'With components' - _form: 'Drupal\system\Form\ModulesListForm' + _form: 'Drupal\system\Form\ModulesInstallForm' requirements: _permission: 'administer modules' -system.modules_list_confirm: - path: '/admin/modules/list/confirm' +system.modules_install_confirm: + path: '/admin/modules/install/confirm' defaults: - _form: 'Drupal\system\Form\ModulesListConfirmForm' + _form: 'Drupal\system\Form\ModulesInstallConfirmForm' _title: 'Some required modules must be enabled' requirements: _permission: 'administer modules' +system.modules_list: + path: '/admin/modules/list' + defaults: + _title: 'List' + _controller: 'Drupal\system\Controller\ModulesListController::listModules' + requirements: + _permission: 'administer modules' + system.theme_uninstall: path: '/admin/appearance/uninstall' defaults: diff --git a/core/modules/toolbar/css/toolbar.icons.theme.css b/core/modules/toolbar/css/toolbar.icons.theme.css index 65aff35..1a7d506 100644 --- a/core/modules/toolbar/css/toolbar.icons.theme.css +++ b/core/modules/toolbar/css/toolbar.icons.theme.css @@ -117,11 +117,11 @@ .toolbar-icon-entity-user-collection.is-active:before { background-image: url(../../../misc/icons/000000/people.svg); } -.toolbar-icon-system-modules-list:before { +.toolbar-icon-system-modules-install:before { background-image: url(../../../misc/icons/787878/puzzlepiece.svg); } -.toolbar-icon-system-modules-list:active:before, -.toolbar-icon-system-modules-list.is-active:before { +.toolbar-icon-system-modules-install:active:before, +.toolbar-icon-system-modules-install.is-active:before { background-image: url(../../../misc/icons/000000/puzzlepiece.svg); } .toolbar-icon-system-admin-config:before { diff --git a/core/modules/update/src/UpdateManager.php b/core/modules/update/src/UpdateManager.php index 007b040..f103e44 100644 --- a/core/modules/update/src/UpdateManager.php +++ b/core/modules/update/src/UpdateManager.php @@ -161,7 +161,7 @@ public function projectStorage($key) { // update status of the site to avoid presenting stale information. $route_names = array( 'update.theme_update', - 'system.modules_list', + 'system.modules_install', 'system.theme_install', 'update.module_update', 'update.module_install', diff --git a/core/modules/update/update.links.action.yml b/core/modules/update/update.links.action.yml index d6f6b8d..94cc4cf 100644 --- a/core/modules/update/update.links.action.yml +++ b/core/modules/update/update.links.action.yml @@ -10,7 +10,7 @@ update.module_install: title: 'Install new module' weight: 25 appears_on: - - system.modules_list + - system.modules_install update.theme_install: route_name: update.theme_install diff --git a/core/modules/update/update.links.task.yml b/core/modules/update/update.links.task.yml index d831bf0..bcf07e7 100644 --- a/core/modules/update/update.links.task.yml +++ b/core/modules/update/update.links.task.yml @@ -15,7 +15,7 @@ update.report_update: update.module_update: route_name: update.module_update - base_route: system.modules_list + base_route: system.modules_install title: Update weight: 10 diff --git a/core/modules/update/update.module b/core/modules/update/update.module index 4aed1ef..a00770a 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -73,7 +73,7 @@ function update_help($route_name, RouteMatchInterface $route_match) { case 'help.page.update': $output = ''; $output .= '

    ' . t('About') . '

    '; - $output .= '

    ' . t('The Update Manager module periodically checks for new versions of your site\'s software (including contributed modules and themes), and alerts administrators to available updates. The Update Manager system is also used by some other modules to manage updates and downloads; for example, the Interface Translation module uses the Update Manager to download translations from the localization server. Note that whenever the Update Manager system is used, anonymous usage statistics are sent to Drupal.org. If desired, you may disable the Update Manager module from the Extend page; if you do so, functionality that depends on the Update Manager system will not work. For more information, see the online documentation for the Update Manager module.', array('!update' => 'https://www.drupal.org/documentation/modules/update', '!modules' => \Drupal::url('system.modules_list'))) . '

    '; + $output .= '

    ' . t('The Update Manager module periodically checks for new versions of your site\'s software (including contributed modules and themes), and alerts administrators to available updates. The Update Manager system is also used by some other modules to manage updates and downloads; for example, the Interface Translation module uses the Update Manager to download translations from the localization server. Note that whenever the Update Manager system is used, anonymous usage statistics are sent to Drupal.org. If desired, you may disable the Update Manager module from the Extend page; if you do so, functionality that depends on the Update Manager system will not work. For more information, see the online documentation for the Update Manager module.', array('!update' => 'https://www.drupal.org/documentation/modules/update', '!modules' => \Drupal::url('system.modules_install'))) . '

    '; // Only explain the Update manager if it has not been disabled. if (update_manager_access()) { $output .= '

    ' . t('The Update Manager also allows administrators to update and install modules and themes through the administration interface.') . '

    '; @@ -85,9 +85,9 @@ function update_help($route_name, RouteMatchInterface $route_match) { // Only explain the Update manager if it has not been disabled. if (update_manager_access()) { $output .= '
    ' . t('Performing updates through the Update page') . '
    '; - $output .= '
    ' . t('The Update Manager module allows administrators to perform updates directly from the Update page. It lists all available updates, and you can confirm whether you want to download them. If you don\'t have sufficient access rights to your web server, you could be prompted for your FTP/SSH password. Afterwards the files are transferred into your site installation, overwriting your old files. Direct links to the Update page are also displayed on the Extend page and the Appearance page.', array('!modules_page' => \Drupal::url('system.modules_list'), '!themes_page' => \Drupal::url('system.themes_page'), '!update-page' => \Drupal::url('update.report_update'))) . '
    '; + $output .= '
    ' . t('The Update Manager module allows administrators to perform updates directly from the Update page. It lists all available updates, and you can confirm whether you want to download them. If you don\'t have sufficient access rights to your web server, you could be prompted for your FTP/SSH password. Afterwards the files are transferred into your site installation, overwriting your old files. Direct links to the Update page are also displayed on the Extend page and the Appearance page.', array('!modules_page' => \Drupal::url('system.modules_install'), '!themes_page' => \Drupal::url('system.themes_page'), '!update-page' => \Drupal::url('update.report_update'))) . '
    '; $output .= '
    ' . t('Installing new modules and themes through the Install page') . '
    '; - $output .= '
    ' . t('You can also install new modules and themes in the same fashion, through the Install page, or by clicking the Install new module/theme links at the top of the Extend page and the Appearance page. In this case, you are prompted to provide either the URL to the download, or to upload a packaged release file from your local computer.', array('!modules_page' => \Drupal::url('system.modules_list'), '!themes_page' => \Drupal::url('system.themes_page'), '!install' => \Drupal::url('update.report_install'))) . '
    '; + $output .= '
    ' . t('You can also install new modules and themes in the same fashion, through the Install page, or by clicking the Install new module/theme links at the top of the Extend page and the Appearance page. In this case, you are prompted to provide either the URL to the download, or to upload a packaged release file from your local computer.', array('!modules_page' => \Drupal::url('system.modules_install'), '!themes_page' => \Drupal::url('system.themes_page'), '!install' => \Drupal::url('update.report_install'))) . '
    '; } $output .= '
    '; return $output; diff --git a/core/themes/seven/css/components/modules-page.css b/core/themes/seven/css/components/modules-page.css index bc9c1e5..18c4000 100644 --- a/core/themes/seven/css/components/modules-page.css +++ b/core/themes/seven/css/components/modules-page.css @@ -45,3 +45,12 @@ .locale-translation-status-form .sticky-header th { border: 0; } + +.system-modules__list tr td:first-child { + padding-left: 0.5em; /* LTR */ +} + +[dir=rtl] .system-modules__list tr td:first-child { + padding-left: 0; + padding-right: 0.5em; +}