Merge branch '8.x' of git.drupal.org:project/drupal into 8.x

8.0.x
Dries 2012-02-03 16:16:15 -05:00
commit 87518a97db
16 changed files with 292 additions and 47 deletions

View File

@ -5344,9 +5344,24 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
// themes as provided by a distribution. It is pristine in the same way that
// the 'core/modules' directory is pristine for core; users should avoid
// any modification by using the sites/all or sites/<domain> directories.
$profiles = array();
$profile = drupal_get_profile();
if (file_exists("profiles/$profile/$directory")) {
$searchdir[] = "profiles/$profile/$directory";
// For SimpleTest to be able to test modules packaged together with a
// distribution we need to include the profile of the parent site (in which
// test runs are triggered).
if (drupal_valid_test_ua()) {
$testing_profile = variable_get('simpletest_parent_profile', FALSE);
if ($testing_profile && $testing_profile != $profile) {
$profiles[] = $testing_profile;
}
}
// In case both profile directories contain the same extension, the actual
// profile always has precedence.
$profiles[] = $profile;
foreach ($profiles as $profile) {
if (file_exists("profiles/$profile/$directory")) {
$searchdir[] = "profiles/$profile/$directory";
}
}
// Always search sites/all/* as well as the global directories.

View File

@ -178,6 +178,30 @@ function system_list($type) {
$lists['filepaths'][] = array('type' => $record->type, 'name' => $record->name, 'filepath' => $record->filename);
}
}
foreach ($lists['theme'] as $key => $theme) {
if (!empty($theme->info['base theme'])) {
// Make a list of the theme's base themes.
$lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
// Don't proceed if there was a problem with the root base theme.
if (!current($lists['theme'][$key]->base_themes)) {
continue;
}
// Determine the root base theme.
$base_key = key($lists['theme'][$key]->base_themes);
// Add to the list of sub-themes for each of the theme's base themes.
foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
$lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
}
// Add the base theme's theme engine info.
$lists['theme'][$key]->info['engine'] = $lists['theme'][$base_key]->info['engine'];
}
else {
// A plain theme is its own base theme.
$base_key = $key;
}
// Set the theme engine prefix.
$lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine'];
}
cache('bootstrap')->set('system_list', $lists);
}
// To avoid a separate database lookup for the filepath, prime the

View File

@ -723,7 +723,7 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
* names of the themes and the values are objects having the following
* properties:
* - 'filename': The name of the .info file.
* - 'name': The name of the theme.
* - 'name': The machine name of the theme.
* - 'status': 1 for enabled, 0 for disabled themes.
* - 'info': The contents of the .info file.
* - 'stylesheets': A two dimensional array, using the first key for the
@ -733,7 +733,10 @@ function _theme_build_registry($theme, $base_theme, $theme_engine) {
* - 'scripts': An associative array of JavaScripts, using the filename as key
* and the complete filepath as value.
* - 'engine': The name of the theme engine.
* - 'base theme': The name of the base theme.
* - 'base_theme': The name of the base theme.
* - 'base_themes': An ordered array of all the base themes. If the first item
* is NULL, a base theme is missing for this theme.
* - 'sub_themes': An unordered array of sub-themes of this theme.
*/
function list_themes($refresh = FALSE) {
$list = &drupal_static(__FUNCTION__, array());
@ -789,6 +792,47 @@ function list_themes($refresh = FALSE) {
return $list;
}
/**
* Find all the base themes for the specified theme.
*
* Themes can inherit templates and function implementations from earlier themes.
*
* @param $themes
* An array of available themes.
* @param $key
* The name of the theme whose base we are looking for.
* @param $used_keys
* A recursion parameter preventing endless loops.
* @return
* Returns an array of all of the theme's ancestors; the first element's value
* will be NULL if an error occurred.
*/
function drupal_find_base_themes($themes, $key, $used_keys = array()) {
$base_key = $themes[$key]->info['base theme'];
// Does the base theme exist?
if (!isset($themes[$base_key])) {
return array($base_key => NULL);
}
$current_base_theme = array($base_key => $themes[$base_key]->info['name']);
// Is the base theme itself a child of another theme?
if (isset($themes[$base_key]->info['base theme'])) {
// Do we already know the base themes of this theme?
if (isset($themes[$base_key]->base_themes)) {
return $themes[$base_key]->base_themes + $current_base_theme;
}
// Prevent loops.
if (!empty($used_keys[$base_key])) {
return array($base_key => NULL);
}
$used_keys[$base_key] = TRUE;
return drupal_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
}
// If we get here, then this is our parent theme.
return $current_base_theme;
}
/**
* Generates themed output.
*

View File

@ -101,6 +101,12 @@ function update_prepare_d8_bootstrap() {
),
);
if ($has_required_schema) {
// Bootstrap variables so we can update theme while preparing the update
// process.
drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
// Update the dynamic include paths that might be used before running the
// proper update functions.
update_prepare_stored_includes();
// Update the environment for the language bootstrap if needed.
update_prepare_d8_language();
@ -127,6 +133,22 @@ function update_prepare_d8_bootstrap() {
}
}
/**
* Fix stored include paths to match the "/core" migration.
*/
function update_prepare_stored_includes() {
// Update language negotiation settings.
foreach (language_types() as $language_type) {
$negotiation = variable_get("language_negotiation_$language_type", array());
foreach ($negotiation as $id => &$provider) {
if (isset($negotiation[$id]['file']) && $negotiation[$id]['file'] == 'includes/locale.inc') {
$negotiation[$id]['file'] = 'core/includes/locale.inc';
}
}
variable_set("language_negotiation_$language_type", $negotiation);
}
}
/**
* Prepare Drupal 8 language changes for the bootstrap if needed.
*/

View File

@ -1372,6 +1372,12 @@ class DrupalWebTestCase extends DrupalTestCase {
variable_set('file_private_path', $private_files_directory);
variable_set('file_temporary_path', $temp_files_directory);
// Set the 'simpletest_parent_profile' variable to add the parent profile's
// search path to the child site's search paths.
// @see drupal_system_listing()
// @todo This may need to be primed like 'install_profile' above.
variable_set('simpletest_parent_profile', $this->originalProfile);
// Include the testing profile.
variable_set('install_profile', $this->profile);
$profile_details = install_profile_info($this->profile, 'en');

View File

@ -616,3 +616,91 @@ class SimpleTestMissingCheckedRequirements extends DrupalWebTestCase {
}
}
}
/**
* Verifies that tests bundled with installation profile modules are found.
*/
class SimpleTestInstallationProfileModuleTestsTestCase extends DrupalWebTestCase {
/**
* Use the Testing profile.
*
* The Testing profile contains drupal_system_listing_compatible_test.test,
* which attempts to:
* - run tests using the Minimal profile (which does not contain the
* drupal_system_listing_compatible_test.module)
* - but still install the drupal_system_listing_compatible_test.module
* contained in the Testing profile.
*
* @see DrupalSystemListingCompatibleTestCase
*/
protected $profile = 'testing';
public static function getInfo() {
return array(
'name' => 'Installation profile module tests',
'description' => 'Verifies that tests bundled with installation profile modules are found.',
'group' => 'SimpleTest',
);
}
function setUp() {
parent::setUp(array('simpletest'));
$this->admin_user = $this->drupalCreateUser(array('administer unit tests'));
$this->drupalLogin($this->admin_user);
}
/**
* Tests existence of test case located in an installation profile module.
*/
function testInstallationProfileTests() {
$this->drupalGet('admin/config/development/testing');
$this->assertText('Installation profile module tests helper');
$edit = array(
'DrupalSystemListingCompatibleTestCase' => TRUE,
);
$this->drupalPost(NULL, $edit, t('Run tests'));
$this->assertText('DrupalSystemListingCompatibleTestCase test executed.');
}
}
/**
* Verifies that tests in other installation profiles are not found.
*
* @see SimpleTestInstallationProfileModuleTestsTestCase
*/
class SimpleTestOtherInstallationProfileModuleTestsTestCase extends DrupalWebTestCase {
/**
* Use the Minimal profile.
*
* The Testing profile contains drupal_system_listing_compatible_test.test,
* which should not be found.
*
* @see SimpleTestInstallationProfileModuleTestsTestCase
* @see DrupalSystemListingCompatibleTestCase
*/
protected $profile = 'minimal';
public static function getInfo() {
return array(
'name' => 'Other Installation profiles',
'description' => 'Verifies that tests in other installation profiles are not found.',
'group' => 'SimpleTest',
);
}
function setUp() {
parent::setUp(array('simpletest'));
$this->admin_user = $this->drupalCreateUser(array('administer unit tests'));
$this->drupalLogin($this->admin_user);
}
/**
* Tests that tests located in another installation profile do not appear.
*/
function testOtherInstallationProfile() {
$this->drupalGet('admin/config/development/testing');
$this->assertNoText('Installation profile module tests helper');
}
}

View File

@ -113,6 +113,37 @@ class ThemeUnitTest extends DrupalWebTestCase {
$this->drupalGet('theme-test/template-test');
$this->assertText('Success: Template overridden.', t('Template overridden by defined \'template\' filename.'));
}
/**
* Test the list_themes() function.
*/
function testListThemes() {
$themes = list_themes();
// Check if drupal_theme_access() retrieves enabled themes properly from list_themes().
$this->assertTrue(drupal_theme_access('test_theme'), t('Enabled theme detected'));
// Check if list_themes() returns disabled themes.
$this->assertTrue(array_key_exists('test_basetheme', $themes), t('Disabled theme detected'));
// Check for base theme and subtheme lists.
$base_theme_list = array('test_basetheme' => 'Theme test base theme');
$sub_theme_list = array('test_subtheme' => 'Theme test subtheme');
$this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, t('Base theme\'s object includes list of subthemes.'));
$this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, t('Subtheme\'s object includes list of base themes.'));
// Check for theme engine in subtheme.
$this->assertIdentical($themes['test_subtheme']->engine, 'phptemplate', t('Subtheme\'s object includes the theme engine.'));
// Check for theme engine prefix.
$this->assertIdentical($themes['test_basetheme']->prefix, 'phptemplate', t('Base theme\'s object includes the theme engine prefix.'));
$this->assertIdentical($themes['test_subtheme']->prefix, 'phptemplate', t('Subtheme\'s object includes the theme engine prefix.'));
}
/**
* Test the theme_get_setting() function.
*/
function testThemeGetSetting() {
$GLOBALS['theme_key'] = 'test_theme';
$this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', t('theme_get_setting() uses the default theme automatically.'));
$this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), t('Base theme\'s default settings values can be overridden by subtheme.'));
$this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', t('Base theme\'s default settings values are inherited by subtheme.'));
}
}
/**

View File

@ -19,6 +19,8 @@ function theme_test_theme($existing, $type, $theme, $path) {
*/
function theme_test_system_theme_info() {
$themes['test_theme'] = drupal_get_path('module', 'theme_test') . '/themes/test_theme/test_theme.info';
$themes['test_basetheme'] = drupal_get_path('module', 'theme_test') . '/themes/test_basetheme/test_basetheme.info';
$themes['test_subtheme'] = drupal_get_path('module', 'theme_test') . '/themes/test_subtheme/test_subtheme.info';
return $themes;
}

View File

@ -0,0 +1,7 @@
name = Theme test base theme
description = Test theme which acts as a base theme for other test subthemes.
core = 8.x
hidden = TRUE
settings[basetheme_only] = base theme value
settings[subtheme_override] = base theme value

View File

@ -0,0 +1,7 @@
name = Theme test subtheme
description = Test theme which uses test_basetheme as the base theme.
core = 8.x
base theme = test_basetheme
hidden = TRUE
settings[subtheme_override] = subtheme value

View File

@ -14,3 +14,5 @@ hidden = TRUE
; version from being loaded, and that errors aren't caused by the lack of this
; file within the theme folder.
stylesheets[all][] = system.base.css
settings[theme_test_setting] = default value

View File

@ -369,7 +369,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
// Default settings are defined in theme_get_setting() in includes/theme.inc
if ($key) {
$var = 'theme_' . $key . '_settings';
$themes = system_rebuild_theme_data();
$themes = list_themes();
$features = $themes[$key]->info['features'];
}
else {

View File

@ -2581,7 +2581,7 @@ function _system_rebuild_theme_data() {
// Now that we've established all our master themes, go back and fill in data
// for subthemes.
foreach ($sub_themes as $key) {
$themes[$key]->base_themes = system_find_base_themes($themes, $key);
$themes[$key]->base_themes = drupal_find_base_themes($themes, $key);
// Don't proceed if there was a problem with the root base theme.
if (!current($themes[$key]->base_themes)) {
continue;
@ -2673,47 +2673,6 @@ function _system_default_theme_features() {
);
}
/**
* Find all the base themes for the specified theme.
*
* Themes can inherit templates and function implementations from earlier themes.
*
* @param $themes
* An array of available themes.
* @param $key
* The name of the theme whose base we are looking for.
* @param $used_keys
* A recursion parameter preventing endless loops.
* @return
* Returns an array of all of the theme's ancestors; the first element's value
* will be NULL if an error occurred.
*/
function system_find_base_themes($themes, $key, $used_keys = array()) {
$base_key = $themes[$key]->info['base theme'];
// Does the base theme exist?
if (!isset($themes[$base_key])) {
return array($base_key => NULL);
}
$current_base_theme = array($base_key => $themes[$base_key]->info['name']);
// Is the base theme itself a child of another theme?
if (isset($themes[$base_key]->info['base theme'])) {
// Do we already know the base themes of this theme?
if (isset($themes[$base_key]->base_themes)) {
return $themes[$base_key]->base_themes + $current_base_theme;
}
// Prevent loops.
if (!empty($used_keys[$base_key])) {
return array($base_key => NULL);
}
$used_keys[$base_key] = TRUE;
return system_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
}
// If we get here, then this is our parent theme.
return $current_base_theme;
}
/**
* Get a list of available regions from a specified theme.
*

View File

@ -4,3 +4,4 @@ package = Testing
version = VERSION
core = 8.x
hidden = TRUE
files[] = drupal_system_listing_compatible_test.test

View File

@ -0,0 +1,37 @@
<?php
/**
* Helper to verify tests in installation profile modules.
*/
class DrupalSystemListingCompatibleTestCase extends DrupalWebTestCase {
/**
* Use the Minimal profile.
*
* This test needs to use a different installation profile than the test which
* asserts that this test is found.
*
* @see SimpleTestInstallationProfileModuleTestsTestCase
*/
protected $profile = 'minimal';
public static function getInfo() {
return array(
'name' => 'Installation profile module tests helper',
'description' => 'Verifies that tests in installation profile modules are found and may use another profile for running tests.',
'group' => 'Installation profile',
);
}
function setUp() {
// Attempt to install a module in Testing profile, while this test runs with
// a different profile.
parent::setUp(array('drupal_system_listing_compatible_test'));
}
/**
* Non-empty test* method required to executed the test case class.
*/
function testDrupalSystemListing() {
$this->pass(__CLASS__ . ' test executed.');
}
}