diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index 001650a..ca2506f 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -120,6 +120,10 @@ action_configuration_default: sequence: - type: string +# Theme settings schema is automatically applied to a theme's *.settings +# configuration unless the theme provides its own schema. Static analysis of +# configuration objects using schema will have to duplicate the +# system_config_schema_info_alter() to determine a theme's *.settings schema. theme_settings: type: mapping mapping: @@ -177,6 +181,11 @@ theme_settings: use_default: type: boolean label: 'Use default' + third_party_settings: + type: sequence + label: 'Third party settings' + sequence: + - type: theme_settings.third_party.[%key] theme_breakpoints_default: type: sequence diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 34dbdc2..7bbd4ff 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -323,9 +323,6 @@ function drupal_find_theme_templates($cache, $extension, $path) { * * The final setting is obtained from the last value found in the following * sources: - * - the default theme-specific settings defined in any base theme's .info.yml - * file - * - the default theme-specific settings defined in the theme's .info.yml file * - the saved values from the global theme settings form * - the saved values from the theme's settings form * To only retrieve the default global theme setting, an empty string should be @@ -340,6 +337,7 @@ function drupal_find_theme_templates($cache, $extension, $path) { * The value of the requested setting, NULL if the setting does not exist. */ function theme_get_setting($setting_name, $theme = NULL) { + /** @var \Drupal\Core\Theme\ThemeSettings[] $cache */ $cache = &drupal_static(__FUNCTION__, array()); // If no key is given, use the current theme if we can determine it. @@ -350,33 +348,13 @@ function theme_get_setting($setting_name, $theme = NULL) { if (empty($cache[$theme])) { // Create a theme settings object. $cache[$theme] = new ThemeSettings($theme); + // Get the global settings from configuration. + $cache[$theme]->setData(\Drupal::config('system.theme.global')->get()); - // Get the values for the theme-specific settings from the .info.yml files - // of the theme and all its base themes. - $themes = list_themes(); - if ($theme && isset($themes[$theme])) { + $themes = \Drupal::service('theme_handler')->listInfo(); + if (isset($themes[$theme])) { $theme_object = $themes[$theme]; - // Create a list which includes the current theme and all its base themes. - if (isset($theme_object->base_themes)) { - $theme_keys = array_keys($theme_object->base_themes); - $theme_keys[] = $theme; - } - else { - $theme_keys = array($theme); - } - // Read hard-coded default settings from the theme info files. - foreach ($theme_keys as $theme_key) { - if (!empty($themes[$theme_key]->info['settings'])) { - $cache[$theme]->merge($themes[$theme_key]->info['settings']); - } - } - } - - // Get the global settings from configuration. - $cache[$theme]->merge(\Drupal::config('system.theme.global')->get()); - - if ($theme && isset($themes[$theme])) { // Retrieve configured theme-specific settings, if any. try { if ($theme_settings = \Drupal::config($theme . '.settings')->get()) { diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index e99397e..17d3a07 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -90,8 +90,9 @@ public function __construct(ConfigFactoryInterface $config_factory, StorageInter */ public function installDefaultConfig($type, $name) { $extension_path = drupal_get_path($type, $name); - // If the extension provides configuration schema clear the definitions. - if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY)) { + // If the extension provides configuration schema or is a theme clear the + // definitions. + if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY) || $type == 'theme') { // Refresh the schema cache if installing default configuration and the // extension has a configuration schema directory. $this->typedConfig->clearCachedDefinitions(); diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php index 4d448cd..b868d35 100644 --- a/core/modules/config/src/Tests/ConfigImportUITest.php +++ b/core/modules/config/src/Tests/ConfigImportUITest.php @@ -84,7 +84,6 @@ function testImport() { $system_theme = \Drupal::config('system.theme')->get(); $system_theme['default'] = 'bartik'; $staging->write('system.theme', $system_theme); - $staging->write('bartik.settings', $install_storage->read('bartik.settings')); // Read the action config from module default config folder. $action_settings = $install_storage->read('action.settings'); @@ -108,7 +107,6 @@ function testImport() { $this->assertText('core.extension'); $this->assertText('system.theme'); $this->assertText('action.settings'); - $this->assertText('bartik.settings'); $this->assertFieldById('edit-submit', t('Import all')); // Import and verify that both do not appear anymore. @@ -118,7 +116,6 @@ function testImport() { $this->assertNoText('core.extension'); $this->assertNoText('system.theme'); $this->assertNoText('action.settings'); - $this->assertNoText('bartik.settings'); $this->assertNoFieldById('edit-submit', t('Import all')); diff --git a/core/modules/config/src/Tests/DefaultConfigTest.php b/core/modules/config/src/Tests/DefaultConfigTest.php index 4880561..99ff07a 100644 --- a/core/modules/config/src/Tests/DefaultConfigTest.php +++ b/core/modules/config/src/Tests/DefaultConfigTest.php @@ -10,7 +10,9 @@ use Drupal\config_test\TestInstallStorage; use Drupal\Core\Config\InstallStorage; use Drupal\Core\Config\TypedConfigManager; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\simpletest\KernelTestBase; +use Symfony\Component\DependencyInjection\Reference; /** * Tests that default configuration provided by all modules matches schema. @@ -24,23 +26,46 @@ class DefaultConfigTest extends KernelTestBase { /** * Modules to enable. * + * Enable the system module so that system_config_schema_info_alter() fires. + * + * @var array + */ + public static $modules = array('system', 'config_test'); + + /** + * Themes which provide default configuration and need enabling. + * + * If a theme provides default configuration but does not have a schema + * because it can rely on schemas added by system_config_schema_info_alter() + * then this test needs to enable it. + * * @var array */ - public static $modules = array('config_test'); + protected $themes = ['seven']; + + protected function setUp() { + parent::setUp(); + \Drupal::service('theme_handler')->install($this->themes); + } + + /** + * {@inheritdoc} + */ + public function containerBuild(ContainerBuilder $container) { + parent::containerBuild($container); + $container->register('DefaultConfigTest.schema_storage') + ->setClass('\Drupal\config_test\TestInstallStorage') + ->addArgument(InstallStorage::CONFIG_SCHEMA_DIRECTORY); + + $definition = $container->getDefinition('config.typed'); + $definition->replaceArgument(1, new Reference('DefaultConfigTest.schema_storage')); + } /** * Tests default configuration data type. */ public function testDefaultConfig() { - // Create a typed config manager with access to configuration schema in - // every module, profile and theme. - $typed_config = new TypedConfigManager( - \Drupal::service('config.storage'), - new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY), - \Drupal::service('cache.discovery'), - \Drupal::service('module_handler') - ); - + $typed_config = \Drupal::service('config.typed'); // Create a configuration storage with access to default configuration in // every module, profile and theme. $default_config_storage = new TestInstallStorage(); diff --git a/core/modules/shortcut/config/schema/shortcut.schema.yml b/core/modules/shortcut/config/schema/shortcut.schema.yml index 9332699..014b67c 100644 --- a/core/modules/shortcut/config/schema/shortcut.schema.yml +++ b/core/modules/shortcut/config/schema/shortcut.schema.yml @@ -10,3 +10,12 @@ shortcut.set.*: label: type: label label: 'Label' + +# Schema for theme settings. +theme_settings.third_party.shortcut: + type: mapping + label: 'Shortcut settings' + mapping: + module_link: + type: boolean + label: 'Add link' diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 601a149..db98882 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -330,7 +330,7 @@ function shortcut_preprocess_page(&$variables) { $route_parameters = array('shortcut' => $shortcut_id); } - if (theme_get_setting('shortcut_module_link')) { + if (theme_get_setting('third_party_settings.shortcut.module_link')) { $variables['title_suffix']['add_or_remove_shortcut'] = array( '#attached' => array( 'library' => array( diff --git a/core/modules/system/src/Tests/Theme/ThemeTest.php b/core/modules/system/src/Tests/Theme/ThemeTest.php index dfe249c..7f3587f 100644 --- a/core/modules/system/src/Tests/Theme/ThemeTest.php +++ b/core/modules/system/src/Tests/Theme/ThemeTest.php @@ -219,17 +219,6 @@ function testListThemes() { } /** - * Test the theme_get_setting() function. - */ - function testThemeGetSetting() { - $this->container->get('theme_handler')->install(array('test_subtheme')); - \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('test_theme')); - $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', 'theme_get_setting() uses the default theme automatically.'); - $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), 'Base theme\'s default settings values can be overridden by subtheme.'); - $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', 'Base theme\'s default settings values are inherited by subtheme.'); - } - - /** * Tests child element rendering for 'render element' theme hooks. */ function testDrupalRenderChildren() { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 9334a88..e084a5a 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1344,3 +1344,20 @@ function system_path_insert() { function system_path_delete($path) { \Drupal::service('path.alias_manager')->cacheClear(); } + +/** + * Implements hook_config_schema_info_alter(). + */ +function system_config_schema_info_alter(&$definitions) { + // Provide a default schema for all theme settings files if the theme does + // provide its own schema already.. + foreach (\Drupal::service('theme_handler')->listInfo(TRUE) as $name => $theme) { + $config_name = $name . '.settings'; + if (!isset($definitions[$config_name])) { + $definitions[$config_name] = array( + 'type' => 'theme_settings', + 'label' => $name . ' settings', + ); + } + } +} diff --git a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml index 2edc823..7fb29fc 100644 --- a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml +++ b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml @@ -14,6 +14,3 @@ stylesheets-override: stylesheets-remove: - base-remove.css - base-remove.sub-override.css -settings: - basetheme_only: 'base theme value' - subtheme_override: 'base theme value' diff --git a/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml b/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml index cdcd8f0..eea7443 100644 --- a/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml +++ b/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml @@ -15,5 +15,3 @@ stylesheets-remove: - sub-remove.css - base-add.sub-remove.css - base-override.sub-remove.css -settings: - subtheme_override: 'subtheme value' diff --git a/core/modules/system/tests/themes/test_theme/test_theme.info.yml b/core/modules/system/tests/themes/test_theme/test_theme.info.yml index fd5aae5..9eebc90 100644 --- a/core/modules/system/tests/themes/test_theme/test_theme.info.yml +++ b/core/modules/system/tests/themes/test_theme/test_theme.info.yml @@ -16,8 +16,6 @@ base theme: classy core: 8.x stylesheets-remove: - system.module.css -settings: - theme_test_setting: 'default value' regions: content: Content left: Left diff --git a/core/themes/bartik/bartik.info.yml b/core/themes/bartik/bartik.info.yml index 22e62b4..a330800 100644 --- a/core/themes/bartik/bartik.info.yml +++ b/core/themes/bartik/bartik.info.yml @@ -29,6 +29,3 @@ regions: footer_thirdcolumn: 'Footer third column' footer_fourthcolumn: 'Footer fourth column' footer: Footer - -settings: - shortcut_module_link: false diff --git a/core/themes/bartik/config/install/bartik.settings.yml b/core/themes/bartik/config/install/bartik.settings.yml deleted file mode 100644 index 48877a3..0000000 --- a/core/themes/bartik/config/install/bartik.settings.yml +++ /dev/null @@ -1,4 +0,0 @@ -# @todo There is no UI yet for configuring this, but the setting is included -# here, because ConfigImportUITest requires a non-empty bartik.settings.yml -# file: https://drupal.org/node/2235901. -shortcut_module_link: false diff --git a/core/themes/bartik/config/schema/bartik.schema.yml b/core/themes/bartik/config/schema/bartik.schema.yml deleted file mode 100644 index bebcfc1..0000000 --- a/core/themes/bartik/config/schema/bartik.schema.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Schema for the configuration files of the Bartik theme. - -bartik.settings: - type: theme_settings - label: 'Bartik settings' - mapping: - # @todo Module-specific settings should be defined by the module: - # https://drupal.org/node/2235901. - shortcut_module_link: - type: boolean - label: 'Shortcut module link' diff --git a/core/themes/seven/config/install/seven.settings.yml b/core/themes/seven/config/install/seven.settings.yml new file mode 100644 index 0000000..6bba58b --- /dev/null +++ b/core/themes/seven/config/install/seven.settings.yml @@ -0,0 +1,3 @@ +third_party_settings: + shortcut: + module_link: true diff --git a/core/themes/seven/config/schema/seven.schema.yml b/core/themes/seven/config/schema/seven.schema.yml deleted file mode 100644 index 6d4c86e..0000000 --- a/core/themes/seven/config/schema/seven.schema.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Schema for the configuration files of the Seven theme. - -seven.settings: - type: theme_settings - label: 'Seven settings' - -seven.breakpoints: - type: theme_breakpoints_default - label: 'Seven breakpoints' diff --git a/core/themes/seven/seven.info.yml b/core/themes/seven/seven.info.yml index 1277db9..c957bf7 100644 --- a/core/themes/seven/seven.info.yml +++ b/core/themes/seven/seven.info.yml @@ -56,6 +56,3 @@ regions: sidebar_first: 'First sidebar' regions_hidden: - sidebar_first - -settings: - shortcut_module_link: true