diff --git a/core/includes/common.inc b/core/includes/common.inc index 0f252cacfd62728a080deaace023a7ce2bf4b3aa..092ac111ae449fbb6dd533dfdff2c12a6545f176 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -6557,7 +6557,7 @@ function drupal_array_nested_key_exists(array $array, array $parents) { * - description: Brief description. * - screenshot: Path to screenshot relative to the theme's .info file. * - engine: Theme engine; typically phptemplate. - * - base: Name of a base theme, if applicable; e.g., base = zen. + * - base theme: Name of a base theme, if applicable; e.g., base theme = zen. * - regions: Listed regions; e.g., region[left] = Left sidebar. * - features: Features available; e.g., features[] = logo. * - stylesheets: Theme stylesheets; e.g., stylesheets[all][] = my-style.css. diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index da3909793590f1ad49a767c71813e941b148e4bf..bdbc9d793aaa8432b7c66ec90f2096282029e01a 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1497,8 +1497,8 @@ function install_profile_modules(&$install_state) { $files[$install_state['parameters']['profile']]->info['required'] = FALSE; // Add modules that other modules depend on. foreach ($modules as $module) { - if ($files[$module]->requires) { - $modules = array_merge($modules, array_keys($files[$module]->requires)); + if ($files[$module]->requires['modules']) { + $modules = array_merge($modules, array_keys($files[$module]->requires['modules'])); } } $modules = array_unique($modules); diff --git a/core/includes/module.inc b/core/includes/module.inc index c1d99f238ffecbfd50a941d9833cb4e841f46dfd..b7721249890c01aec50e227c74cd0dc614bc6693 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -282,17 +282,19 @@ function system_list_reset() { } /** - * Determines which modules require and are required by each module. + * Determines which modules require and are required by each file. + * + * Required modules are declared in an info file with "dependencies[] = foo". * * @param $files * The array of filesystem objects used to rebuild the cache. * * @return - * The same array with the new keys for each module: - * - requires: An array with the keys being the modules that this module + * The same array with the new keys for each file: + * - requires: An array with the keys being the modules that this file * requires. * - required_by: An array with the keys being the modules that will not work - * without this module. + * without this file. */ function _module_build_dependencies($files) { foreach ($files as $filename => $file) { @@ -307,8 +309,8 @@ function _module_build_dependencies($files) { $graph_object = new Graph($graph); $graph = $graph_object->searchAndSort(); foreach ($graph as $module => $data) { - $files[$module]->required_by = isset($data['reverse_paths']) ? $data['reverse_paths'] : array(); - $files[$module]->requires = isset($data['paths']) ? $data['paths'] : array(); + $files[$module]->required_by['modules'] = isset($data['reverse_paths']) ? $data['reverse_paths'] : array(); + $files[$module]->requires['modules'] = isset($data['paths']) ? $data['paths'] : array(); $files[$module]->sort = $data['weight']; } return $files; @@ -453,7 +455,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) { // Add dependencies to the list, with a placeholder weight. // The new modules will be processed as the while loop continues. - foreach (array_keys($module_data[$module]->requires) as $dependency) { + foreach (array_keys($module_data[$module]->requires['modules']) as $dependency) { if (!isset($module_list[$dependency])) { $module_list[$dependency] = 0; } @@ -592,7 +594,7 @@ function module_disable($module_list, $disable_dependents = TRUE) { // Add dependent modules to the list, with a placeholder weight. // The new modules will be processed as the while loop continues. - foreach ($module_data[$module]->required_by as $dependent => $dependent_data) { + foreach ($module_data[$module]->required_by['modules'] as $dependent => $dependent_data) { if (!isset($module_list[$dependent]) && $dependent != $profile) { $module_list[$dependent] = 0; } @@ -673,7 +675,7 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE) // not included in the passed-in list, abort. It is not safe to uninstall // them automatically because uninstalling a module is a destructive // operation. - foreach (array_keys($module_data[$module]->required_by) as $dependent) { + foreach (array_keys($module_data[$module]->required_by['modules']) as $dependent) { if (!isset($module_list[$dependent]) && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED && $dependent != $profile) { return FALSE; } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 3c4576ae07a36866963a57fc588881511ef0d1e2..3c2259677ac92332ce8c071ed3faae4f932016bc 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -11,6 +11,9 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Template\Attribute; use Drupal\Core\Utility\ThemeRegistry; +use Drupal\Component\Graph\Graph; +use Drupal\Core\Config\DatabaseStorage; + /** * @defgroup content_flags Content markers @@ -2893,6 +2896,39 @@ function template_preprocess_region(&$variables) { } /** + * Determines which themes require and are required by each file. + * + * Required themes are declared in an info file with "base theme = foo". + * + * @param $files + * The array of filesystem objects used to rebuild the cache. + * + * @return + * The same array with the new keys for each file: + * - requires: An array with the keys being the themes that this file + * requires. + * - required_by: An array with the keys being the themes that will not work + * without this file. + */ +function _theme_build_dependencies($files) { + foreach ($files as $filename => $file) { + $graph[$file->name]['edges'] = array(); + if (isset($file->info['base theme']) && is_string($file->info['base theme'])) { + $dependency_data = drupal_parse_dependency($file->info['base theme']); + $graph[$file->name]['edges'][$dependency_data['name']] = $dependency_data; + } + } + $graph_object = new Graph($graph); + $graph = $graph_object->searchAndSort(); + foreach ($graph as $theme => $data) { + $files[$theme]->required_by['themes'] = isset($data['reverse_paths']) ? $data['reverse_paths'] : array(); + $files[$theme]->requires['themes'] = isset($data['paths']) ? $data['paths'] : array(); + $files[$theme]->sort = $data['weight']; + } + return $files; +} + +/** * Provides theme registration for themes across .inc files. */ function drupal_common_theme() { diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php index f691e7a2e81c8edecb4656383973df858afe1866..66b726b9be1b55192840b470aca154ca0b3b1e83 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Module/EnableDisableTest.php @@ -72,7 +72,7 @@ function testEnableDisable() { // Find out if the module has any dependencies that aren't enabled yet; // if so, add them to the list of modules we expect to be automatically // enabled. - foreach (array_keys($module->requires) as $dependency) { + foreach (array_keys($module->requires['modules']) as $dependency) { if (isset($modules[$dependency]) && empty($automatically_enabled[$dependency])) { $modules_to_enable[] = $dependency; $automatically_enabled[$dependency] = TRUE; diff --git a/core/modules/system/system.admin.css b/core/modules/system/system.admin.css index 957d3e08d981f894e9524ddd632f232d80d72021..de49499d05e9e5e708ebdb5773fa6c83651477cd 100644 --- a/core/modules/system/system.admin.css +++ b/core/modules/system/system.admin.css @@ -207,6 +207,9 @@ table.screenshot { .system-themes-list-disabled .theme-info { min-height: 170px; } +.theme-selector .theme-requires { + margin-bottom: 10px; +} .theme-selector .incompatible { margin-top: 10px; font-weight: bold; diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index c55289c366c3ab44df3d0d680e12e067bf982cec..a9b4d62d492d0fbe5d2a6fa8c7f273ddcd3914a4 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -221,7 +221,7 @@ function system_themes_page() { } // Sort enabled and disabled themes into their own groups. - $theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme; + $theme_groups[$theme->status ? 'enabled' : 'disabled'][$theme->name] = $theme; } // There are two possible theme groups. @@ -282,16 +282,37 @@ function system_theme_enable() { $theme = $_REQUEST['theme']; // Get current list of themes. $themes = list_themes(); + $theme_deps = _theme_build_dependencies($themes); // Check if the specified theme is one recognized by the system. if (!empty($themes[$theme])) { - theme_enable(array($theme)); - drupal_set_message(t('The %theme theme has been enabled.', array('%theme' => $themes[$theme]->info['name']))); + if ($theme_deps[$theme]->requires) { + + $modules = $theme_deps[$theme]->requires; + $required = '