diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index eeacd7a..e8808c2 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -249,16 +249,9 @@ function drupal_get_filename($type, $name, $filename = NULL) { if (!isset($files[$type][$name]) && \Drupal::hasService('state')) { $files[$type] += \Drupal::state()->get('system.' . $type . '.files', array()); } - // If still unknown, perform a filesystem scan. + // If still unknown, create a user-level error message. if (!isset($files[$type][$name])) { - $listing = new ExtensionDiscovery(DRUPAL_ROOT); - // Prevent an infinite recursion by this legacy function. - if ($original_type == 'profile') { - $listing->setProfileDirectories(array()); - } - foreach ($listing->scan($original_type) as $extension_name => $file) { - $files[$type][$extension_name] = $file->getPathname(); - } + trigger_error(SafeMarkup::format('The following @type is missing from the file system: @name', array('@type' => $type, '@name' => $name)), E_USER_WARNING); } } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index d858875..00c06d6 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -302,6 +302,11 @@ function install_begin_request($class_loader, &$install_state) { // Allow command line scripts to override server variables used by Drupal. require_once __DIR__ . '/bootstrap.inc'; + // Before having installed the system module and being able to do a module + // rebuild, prime the drupal_get_filename() static cache with the module's + // exact location. + drupal_get_filename('module', 'system', 'core/modules/system/system.info.yml'); + // If the hash salt leaks, it becomes possible to forge a valid testing user // agent, install a new copy of Drupal, and take over the original site. // The user agent header is used to pass a database prefix in the request when @@ -1029,6 +1034,9 @@ function install_base_system(&$install_state) { // system.module in order to work. file_ensure_htaccess(); + // Before installing the user module, perform a module rebuild so we know + // where the user module is located. + system_rebuild_module_data(); // Enable the user module so that sessions can be recorded during the // upcoming bootstrap step. \Drupal::service('module_installer')->install(array('user'), FALSE); diff --git a/core/includes/install.inc b/core/includes/install.inc index 7e0e32e..8d9ef23 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -556,7 +556,7 @@ function drupal_verify_profile($install_state) { $info = $install_state['profile_info']; // Get the list of available modules for the selected installation profile. - $listing = new ExtensionDiscovery(DRUPAL_ROOT); + $listing = new ExtensionDiscovery(\Drupal::root()); $present_modules = array(); foreach ($listing->scan('module') as $present_module) { $present_modules[] = $present_module->getName(); @@ -922,11 +922,19 @@ function drupal_check_profile($profile, array $install_state) { // Collect requirement testing results. $requirements = array(); + + // Performs an ExtensionDiscovery scan as the system module is unavailable and + // we don't yet know where all the modules are located. + $listing = new ExtensionDiscovery(\Drupal::root()); + $module_list = $listing->scan('module'); foreach ($info['dependencies'] as $module) { - module_load_install($module); + $file = \Drupal::root() . '/' . $module_list[$module]->getPath() . "/$module.install"; + if (is_file($file)) { + require_once $file; + } $function = $module . '_requirements'; - drupal_classloader_register($module, drupal_get_path('module', $module)); + drupal_classloader_register($module, $module_list[$module]->getPath()); if (function_exists($function)) { $requirements = array_merge($requirements, $function('install')); } diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index c109ea7..d87c142 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -157,17 +157,23 @@ public function installDefaultConfig($type, $name) { * {@inheritdoc} */ public function installOptionalConfig(StorageInterface $storage = NULL, $dependency = []) { + $profile = $this->drupalGetProfile(); if (!$storage) { // Search the install profile's optional configuration too. $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE); // The extension install storage ensures that overrides are used. $profile_storage = NULL; } - else { + elseif (isset($profile)) { // Creates a profile storage to search for overrides. - $profile_install_path = $this->drupalGetPath('module', $this->drupalGetProfile()) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY; + $profile_install_path = $this->drupalGetPath('module', $profile) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY; $profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION); } + else { + // Profile has not been set yet. For example during the first steps of the + // installer or during unit tests. + $profile_storage = NULL; + } $collection_info = $this->configManager->getConfigCollectionInfo(); $enabled_extensions = $this->getEnabledExtensions(); diff --git a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php index 15490b4..70f9737 100644 --- a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php +++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config; use Drupal\Core\Site\Settings; +use Drupal\Core\Extension\ExtensionDiscovery; /** * Storage to access configuration and schema in enabled extensions. @@ -80,26 +81,46 @@ public function createCollection($collection) { protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); - $this->folders += $this->getComponentNames('core', array('core')); + $this->folders += $this->getCoreNames(); $install_profile = Settings::get('install_profile'); $extensions = $this->configStorage->read('core.extension'); + $listing = new ExtensionDiscovery(\Drupal::root()); if (!empty($extensions['module'])) { $modules = $extensions['module']; // Remove the install profile as this is handled later. unset($modules[$install_profile]); - $this->folders += $this->getComponentNames('module', array_keys($modules)); + $module_list_scan = $listing->scan('module'); + $module_list = array(); + foreach (array_keys($modules) as $module) { + if (isset($module_list_scan[$module])) { + $module_list[$module] = $module_list_scan[$module]; + } + } + $this->folders += $this->getComponentNames($module_list); } if (!empty($extensions['theme'])) { - $this->folders += $this->getComponentNames('theme', array_keys($extensions['theme'])); + $theme_list_scan = $listing->scan('theme'); + foreach (array_keys($extensions['theme']) as $theme) { + if (isset($theme_list_scan[$theme])) { + $theme_list[$theme] = $theme_list_scan[$theme]; + } + } + $this->folders += $this->getComponentNames($theme_list); } if ($this->includeProfile) { // The install profile can override module default configuration. We do // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. - $profile_folders = $this->getComponentNames('profile', array(drupal_get_profile())); - $this->folders = $profile_folders + $this->folders; + $profile = drupal_get_profile(); + if (isset($profile)) { + $profile_list = $listing->scan('profile'); + if (isset($profile_list[$profile])) { + $profile_folders = $this->getComponentNames(array($profile_list[$profile])); + $this->folders = $profile_folders + $this->folders; + } + } } } return $this->folders; diff --git a/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php index 06618d7..a8850da 100644 --- a/core/lib/Drupal/Core/Config/InstallStorage.php +++ b/core/lib/Drupal/Core/Config/InstallStorage.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config; use Drupal\Core\Extension\ExtensionDiscovery; +use Drupal\Core\Extension\Extension; /** * Storage used by the Drupal installer. @@ -157,14 +158,18 @@ public function listAll($prefix = '') { protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); - $this->folders += $this->getComponentNames('core', array('core')); - // @todo Refactor getComponentNames() to use the extension list directly. + $this->folders += $this->getCoreNames(); + // Perform an ExtensionDiscovery scan as we cannot use drupal_get_path() + // yet because the system module may not yet be enabled during install. + $listing = new ExtensionDiscovery(\Drupal::root()); if ($profile = drupal_get_profile()) { - $this->folders += $this->getComponentNames('profile', array($profile)); + $profile_list = $listing->scan('profile'); + if (isset($profile_list[$profile])) { + $this->folders += $this->getComponentNames(array($profile_list[$profile])); + } } - $listing = new ExtensionDiscovery(DRUPAL_ROOT); - $this->folders += $this->getComponentNames('module', array_keys($listing->scan('module'))); - $this->folders += $this->getComponentNames('theme', array_keys($listing->scan('theme'))); + $this->folders += $this->getComponentNames($listing->scan('module')); + $this->folders += $this->getComponentNames($listing->scan('theme')); } return $this->folders; } @@ -172,21 +177,21 @@ protected function getAllFolders() { /** * Get all configuration names and folders for a list of modules or themes. * - * @param string $type - * Type of components: 'module' | 'theme' | 'profile' - * @param array $list - * Array of theme or module names. + * @param \Drupal\Core\Extension\Extension[] $list + * An associative array of Extension objects, keyed by extension name. * * @return array * Folders indexed by configuration name. */ - public function getComponentNames($type, array $list) { + public function getComponentNames(array $list) { $extension = '.' . $this->getFileExtension(); $folders = array(); - foreach ($list as $name) { - $directory = $this->getComponentFolder($type, $name); + foreach ($list as $extension_object) { + // We don't have to use ExtensionDiscovery here because our list of + // extensions was already obtained through an ExtensionDiscovery scan. + $directory = $this->getComponentFolder($extension_object); if (file_exists($directory)) { - $files = new \GlobIterator(DRUPAL_ROOT . '/' . $directory . '/*' . $extension); + $files = new \GlobIterator(\Drupal::root() . '/' . $directory . '/*' . $extension); foreach ($files as $file) { $folders[$file->getBasename($extension)] = $directory; } @@ -196,18 +201,45 @@ public function getComponentNames($type, array $list) { } /** + * Get all configuration names and folders for Drupal core. + * + * @return array + * Folders indexed by configuration name. + */ + public function getCoreNames() { + $extension = '.' . $this->getFileExtension(); + $folders = array(); + $directory = $this->getCoreFolder(); + if (file_exists($directory)) { + $files = new \GlobIterator(\Drupal::root() . '/' . $directory . '/*' . $extension); + foreach ($files as $file) { + $folders[$file->getBasename($extension)] = $directory; + } + } + return $folders; + } + + /** * Get folder inside each component that contains the files. * - * @param string $type - * Component type: 'module' | 'theme' | 'profile' - * @param string $name - * Component name. + * @param \Drupal\Core\Extension\Extension $extension + * The Extension object for the component. * * @return string * The configuration folder name for this component. */ - protected function getComponentFolder($type, $name) { - return drupal_get_path($type, $name) . '/' . $this->getCollectionDirectory(); + protected function getComponentFolder(Extension $extension) { + return $extension->getPath() . '/' . $this->getCollectionDirectory(); + } + + /** + * Get folder inside Drupal core that contains the files. + * + * @return string + * The configuration folder name for core. + */ + protected function getCoreFolder() { + return drupal_get_path('core', 'core') . '/' . $this->getCollectionDirectory(); } /** diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php index fbd8f1b..bb4f201 100644 --- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php @@ -134,8 +134,9 @@ public function __construct($root) { */ public function scan($type, $include_tests = NULL) { // Determine the installation profile directories to scan for extensions, - // unless explicit profile directories have been set. - if (!isset($this->profileDirectories)) { + // unless explicit profile directories have been set. Exclude profiles + // as we can't have profiles within profiles. + if (!isset($this->profileDirectories) && $type != 'profile') { $this->setProfileDirectoriesFromSettings(); } diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php index caddbad..af53b82 100644 --- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php +++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php @@ -18,7 +18,7 @@ /** * Default implementation of the module installer. * - * It registers the module in config, install its own configuration, + * It registers the module in config, installs its own configuration, * installs the schema, updates the Drupal kernel and more. */ class ModuleInstaller implements ModuleInstallerInterface { diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index 57a317e..0b31c40 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -466,7 +466,8 @@ public function rebuildThemeData() { ); $sub_themes = array(); - $files = array(); + $files_theme = array(); + $files_theme_engine = array(); // Read info files for each theme. foreach ($themes as $key => $theme) { // @todo Remove all code that relies on the $status property. @@ -495,6 +496,7 @@ public function rebuildThemeData() { if (isset($engines[$engine])) { $theme->owner = $engines[$engine]->getExtensionPathname(); $theme->prefix = $engines[$engine]->getName(); + $files_theme_engine[$engine] = $engines[$engine]->getPathname(); } // Prefix screenshot with theme path. @@ -502,7 +504,7 @@ public function rebuildThemeData() { $theme->info['screenshot'] = $theme->getPath() . '/' . $theme->info['screenshot']; } - $files[$key] = $theme->getPathname(); + $files_theme[$key] = $theme->getPathname(); } // Build dependencies. // @todo Move into a generic ExtensionHandler base class. @@ -510,8 +512,10 @@ public function rebuildThemeData() { $themes = $this->moduleHandler->buildModuleDependencies($themes); // Store filenames to allow system_list() and drupal_get_filename() to - // retrieve them without having to scan the filesystem. - $this->state->set('system.theme.files', $files); + // retrieve them for themes and theme engines without having to scan the + // filesystem. + $this->state->set('system.theme.files', $files_theme); + $this->state->set('system.theme_engine.files', $files_theme_engine); // After establishing the full list of available themes, fill in data for // sub-themes. diff --git a/core/modules/ckeditor/ckeditor.module b/core/modules/ckeditor/ckeditor.module index 2c2a6a5..1520c5e 100644 --- a/core/modules/ckeditor/ckeditor.module +++ b/core/modules/ckeditor/ckeditor.module @@ -82,7 +82,7 @@ function _ckeditor_theme_css($theme = NULL) { if (!isset($theme)) { $theme = \Drupal::config('system.theme')->get('default'); } - if ($theme_path = drupal_get_path('theme', $theme)) { + if (isset($theme) && $theme_path = drupal_get_path('theme', $theme)) { $info = system_get_info('theme', $theme); if (isset($info['ckeditor_stylesheets'])) { $css = $info['ckeditor_stylesheets']; diff --git a/core/modules/comment/src/Tests/CommentStringIdEntitiesTest.php b/core/modules/comment/src/Tests/CommentStringIdEntitiesTest.php index 3cb8ab0..0285432 100644 --- a/core/modules/comment/src/Tests/CommentStringIdEntitiesTest.php +++ b/core/modules/comment/src/Tests/CommentStringIdEntitiesTest.php @@ -27,7 +27,6 @@ class CommentStringIdEntitiesTest extends KernelTestBase { 'user', 'field', 'field_ui', - 'entity', 'entity_test', 'text', ); diff --git a/core/modules/config/src/Tests/ConfigDependencyTest.php b/core/modules/config/src/Tests/ConfigDependencyTest.php index c78eaac..7bfb3aa 100644 --- a/core/modules/config/src/Tests/ConfigDependencyTest.php +++ b/core/modules/config/src/Tests/ConfigDependencyTest.php @@ -184,6 +184,9 @@ public function testConfigEntityUninstall() { ) ); $entity2->save(); + // Perform a module rebuild so we can know where the node module is located. + // and uninstall it. + system_rebuild_module_data(); // Test that doing a config uninstall of the node module deletes entity2 // since it is dependent on entity1 which is dependent on the node module. $config_manager->uninstall('module', 'node'); diff --git a/core/modules/config/tests/config_test/src/TestInstallStorage.php b/core/modules/config/tests/config_test/src/TestInstallStorage.php index e4b3864..c4ee57e 100644 --- a/core/modules/config/tests/config_test/src/TestInstallStorage.php +++ b/core/modules/config/tests/config_test/src/TestInstallStorage.php @@ -23,13 +23,12 @@ class TestInstallStorage extends InstallStorage { */ protected function getAllFolders() { if (!isset($this->folders)) { - $this->folders = $this->getComponentNames('core', array('core')); - // @todo Refactor getComponentNames() to use the extension list directly. + $this->folders = $this->getCoreNames(); $listing = new ExtensionDiscovery(\Drupal::root()); $listing->setProfileDirectories(array()); - $this->folders += $this->getComponentNames('profile', array_keys($listing->scan('profile'))); - $this->folders += $this->getComponentNames('module', array_keys($listing->scan('module'))); - $this->folders += $this->getComponentNames('theme', array_keys($listing->scan('theme'))); + $this->folders += $this->getComponentNames($listing->scan('profile')); + $this->folders += $this->getComponentNames($listing->scan('module')); + $this->folders += $this->getComponentNames($listing->scan('theme')); } return $this->folders; } diff --git a/core/modules/quickedit/quickedit.module b/core/modules/quickedit/quickedit.module index 6813fe4..38805a2 100644 --- a/core/modules/quickedit/quickedit.module +++ b/core/modules/quickedit/quickedit.module @@ -77,7 +77,7 @@ function quickedit_library_info_alter(&$libraries, $extension) { // First let the base theme modify the library, then the actual theme. $alter_library = function(&$library, $theme) use (&$alter_library) { - if ($theme_path = drupal_get_path('theme', $theme)) { + if (isset($theme) && $theme_path = drupal_get_path('theme', $theme)) { $info = system_get_info('theme', $theme); // Recurse to process base theme(s) first. if (isset($info['base theme'])) { diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index bd611f4..48518a7 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -13,6 +13,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DrupalKernel; use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; +use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; use Drupal\Core\Language\Language; use Drupal\Core\Site\Settings; @@ -483,6 +484,13 @@ protected function installEntitySchema($entity_type_id) { * The new modules are only added to the active module list and loaded. */ protected function enableModules(array $modules) { + // Perform an ExtensionDiscovery scan as this function may receive a + // profile that is not the current profile, and we don't yet have a cached + // way to receive inactive profile information. + $listing = new ExtensionDiscovery(\Drupal::root()); + $module_list = $listing->scan('module'); + // In ModuleHandlerTest we pass in a profile as if it were a module. + $module_list += $listing->scan('profile'); // Set the list of modules in the extension handler. $module_handler = $this->container->get('module_handler'); @@ -492,7 +500,7 @@ protected function enableModules(array $modules) { $extensions = $active_storage->read('core.extension'); foreach ($modules as $module) { - $module_handler->addModule($module, drupal_get_path('module', $module)); + $module_handler->addModule($module, $module_list[$module]->getPath()); // Maintain the list of enabled modules in configuration. $extensions['module'][$module] = 0; } diff --git a/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php b/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php index f867045..94802fd 100644 --- a/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php +++ b/core/modules/system/src/Tests/Bootstrap/GetFilenameUnitTest.php @@ -17,34 +17,6 @@ class GetFilenameUnitTest extends KernelTestBase { /** - * The container used by the test, moved out of the way. - * - * @var \Symfony\Component\DependencyInjection\ContainerInterface - */ - protected $previousContainer; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - // Store the previous container. - $this->previousContainer = $this->container; - $this->container = NULL; - \Drupal::unsetContainer(); - } - - /** - * {@inheritdoc} - */ - protected function tearDown() { - parent::tearDown(); - // Restore the previous container. - $this->container = $this->previousContainer; - \Drupal::setContainer($this->previousContainer); - } - - /** * Tests that drupal_get_filename() works when the file is not in database. */ function testDrupalGetFilename() { @@ -53,24 +25,40 @@ function testDrupalGetFilename() { global $install_state; $install_state['parameters']['profile'] = 'testing'; - // Assert that this test is meaningful. - $this->assertNull($this->container); - $this->assertFalse(\Drupal::hasContainer()); + // Rebuild system.module.files state data. + drupal_static_reset('system_rebuild_module_data'); + system_rebuild_module_data(); // Retrieving the location of a module. $this->assertIdentical(drupal_get_filename('module', 'system'), 'core/modules/system/system.info.yml'); // Retrieving the location of a theme. + \Drupal::service('theme_handler')->install(array('stark')); $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'core/themes/stark/stark.info.yml'); // Retrieving the location of a theme engine. - $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'core/themes/engines/phptemplate/phptemplate.info.yml'); + $this->assertIdentical(drupal_get_filename('theme_engine', 'twig'), 'core/themes/engines/twig/twig.info.yml'); // Retrieving the location of a profile. Profiles are a special case with // a fixed location and naming. - $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'core/profiles/standard/standard.info.yml'); + $this->assertIdentical(drupal_get_filename('profile', 'testing'), 'core/profiles/testing/testing.info.yml'); + + + // Generate a non-existing module name. + $non_existing_module = uniqid("", TRUE); - // Searching for an item that does not exist returns NULL. - $this->assertNull(drupal_get_filename('module', uniqid("", TRUE)), 'Searching for an item that does not exist returns NULL.'); + // Set a custom error handler so we can ignore the file not found error. + set_error_handler(function($severity, $message, $file, $line) { + // Skip error handling if this is a "file not found" error. + if (strstr($message, 'is missing from the file system:')) { + \Drupal::state()->set('get_filename_test_triggered_error', TRUE); + return; + } + throw new \ErrorException($message, 0, $severity, $file, $line); + }); + $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for an item that does not exist returns NULL.'); + $this->assertTrue(\Drupal::state()->get('get_filename_test_triggered_error'), 'Searching for an item that does not exist triggers an error.'); + // Restore the original error handler. + restore_error_handler(); } } diff --git a/core/modules/system/src/Tests/Common/AttachedAssetsTest.php b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php index 3251305..8c9c217 100644 --- a/core/modules/system/src/Tests/Common/AttachedAssetsTest.php +++ b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php @@ -74,7 +74,7 @@ function testDefault() { * Tests non-existing libraries. */ function testLibraryUnknown() { - $build['#attached']['library'][] = 'unknown/unknown'; + $build['#attached']['library'][] = 'core/unknown'; $assets = AttachedAssets::createFromRenderArray($build); $this->assertIdentical([], $this->assetResolver->getJsAssets($assets, FALSE)[0], 'Unknown library was not added to the page.'); diff --git a/core/modules/system/src/Tests/Entity/EntitySchemaTest.php b/core/modules/system/src/Tests/Entity/EntitySchemaTest.php index 6f6f39d..5ce61be 100644 --- a/core/modules/system/src/Tests/Entity/EntitySchemaTest.php +++ b/core/modules/system/src/Tests/Entity/EntitySchemaTest.php @@ -24,13 +24,6 @@ class EntitySchemaTest extends EntityUnitTestBase { protected $database; /** - * Modules to enable. - * - * @var array - */ - public static $modules = array('menu_link'); - - /** * {@inheritdoc} */ public function setUp() { diff --git a/core/modules/system/src/Tests/Extension/ModuleHandlerTest.php b/core/modules/system/src/Tests/Extension/ModuleHandlerTest.php index d2d6fed..c4eeddc 100644 --- a/core/modules/system/src/Tests/Extension/ModuleHandlerTest.php +++ b/core/modules/system/src/Tests/Extension/ModuleHandlerTest.php @@ -23,6 +23,13 @@ class ModuleHandlerTest extends KernelTestBase { */ public static $modules = array('system'); + public function setUp() { + parent::setUp(); + // Set up the state values so we know where to find the files when running + // drupal_get_filename(). + system_rebuild_module_data(); + } + /** * {@inheritdoc} */ @@ -37,6 +44,10 @@ public function containerBuild(ContainerBuilder $container) { * The basic functionality of retrieving enabled modules. */ function testModuleList() { + // Prime the drupal_get_filename() static cache with the location of the + // testing profile as it is not the currently active profile and we don't + // yet have any cached way to retrieve its location. + drupal_get_filename('profile', 'testing', 'core/profiles/testing/testing.info.yml'); // Build a list of modules, sorted alphabetically. $profile_info = install_profile_info('testing', 'en'); $module_list = $profile_info['dependencies']; @@ -184,6 +195,10 @@ function testUninstallProfileDependency() { $profile = 'minimal'; $dependency = 'dblog'; $this->settingsSet('install_profile', $profile); + // Prime the drupal_get_filename() static cache with the location of the + // minimal profile as it is not the currently active profile and we don't + // yet have any cached way to retrieve its location. + drupal_get_filename('profile', 'minimal', 'core/profiles/' . $profile . '/' . $profile . '.info.yml'); $this->enableModules(array('module_test', $profile)); drupal_static_reset('system_rebuild_module_data'); diff --git a/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php b/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php index 165c52f..d3dec11 100644 --- a/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php +++ b/core/modules/system/src/Tests/Extension/ThemeHandlerTest.php @@ -316,6 +316,8 @@ function testThemeInfoAlter() { $themes = $this->themeHandler()->listInfo(); $this->assertFalse(isset($themes[$name]->info['regions']['test_region'])); + // Rebuild module data so we know where module_test is located. + system_rebuild_module_data(); $this->moduleInstaller()->install(array('module_test'), FALSE); $this->assertTrue($this->moduleHandler()->moduleExists('module_test')); diff --git a/core/modules/system/src/Tests/File/ScanDirectoryTest.php b/core/modules/system/src/Tests/File/ScanDirectoryTest.php index 8e631d3..1eee62e 100644 --- a/core/modules/system/src/Tests/File/ScanDirectoryTest.php +++ b/core/modules/system/src/Tests/File/ScanDirectoryTest.php @@ -28,7 +28,10 @@ class ScanDirectoryTest extends FileTestBase { protected function setUp() { parent::setUp(); - $this->path = drupal_get_path('module', 'simpletest') . '/files'; + // Hardcode the location of the simpletest files as it is already known + // and shouldn't change, and we don't yet have a way to retreive their + // location from drupal_get_filename() in a cached way. + $this->path = 'core/modules/simpletest/files'; } /** @@ -123,10 +126,10 @@ function testOptionKey() { * Check that the recurse option descends into subdirectories. */ function testOptionRecurse() { - $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => FALSE)); + $files = file_scan_directory($this->path . '/..', '/^javascript-/', array('recurse' => FALSE)); $this->assertTrue(empty($files), "Without recursion couldn't find javascript files."); - $files = file_scan_directory(drupal_get_path('module', 'simpletest'), '/^javascript-/', array('recurse' => TRUE)); + $files = file_scan_directory($this->path . '/..', '/^javascript-/', array('recurse' => TRUE)); $this->assertEqual(2, count($files), 'With recursion we found the expected javascript files.'); } diff --git a/core/modules/system/src/Tests/Installer/InstallerLanguageTest.php b/core/modules/system/src/Tests/Installer/InstallerLanguageTest.php index a025b35..f7be5e6 100644 --- a/core/modules/system/src/Tests/Installer/InstallerLanguageTest.php +++ b/core/modules/system/src/Tests/Installer/InstallerLanguageTest.php @@ -30,7 +30,7 @@ function testInstallerTranslationFiles() { 'it' => array(), ); - $file_translation = new FileTranslation(drupal_get_path('module', 'simpletest') . '/files/translations'); + $file_translation = new FileTranslation('core/modules/simpletest/files/translations'); foreach ($expected_translation_files as $langcode => $files_expected) { $files_found = $file_translation->findTranslationFiles($langcode); $this->assertTrue(count($files_found) == count($files_expected), format_string('@count installer languages found.', array('@count' => count($files_expected)))); diff --git a/core/modules/system/src/Tests/Path/UrlAliasFixtures.php b/core/modules/system/src/Tests/Path/UrlAliasFixtures.php index 777ffb1..1d0fd9b 100644 --- a/core/modules/system/src/Tests/Path/UrlAliasFixtures.php +++ b/core/modules/system/src/Tests/Path/UrlAliasFixtures.php @@ -80,6 +80,9 @@ public function sampleUrlAliases() { public function tableDefinition() { $tables = array(); + // Prime the drupal_get_filename() cache with the location of the system + // module as its location is known and shouldn't change. + drupal_get_filename('module', 'system', 'core/modules/system/system.info.yml'); module_load_install('system'); $schema = system_schema(); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index f2dcc7c..204d0e3 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -883,14 +883,23 @@ function system_get_info($type, $name = NULL) { */ function _system_rebuild_module_data() { $listing = new ExtensionDiscovery(\Drupal::root()); - // Find modules - $modules = $listing->scan('module'); - // Find installation profiles. + // Find installation profiles. This needs to happen before + // performing a module scan as the module scan requires knowing + // what the active profile is. $profiles = $listing->scan('profile'); + $profile = drupal_get_profile(); + if ($profile && isset($profiles[$profile])) { + // Prime the drupal_get_filename() static cache with the profile info file + // location so we can use drupal_get_path() on the active profile during + // the module scan. + drupal_get_filename('profile', $profile, $profiles[$profile]->getPathname()); + } + // Find modules. + $modules = $listing->scan('module'); // Include the installation profile in modules that are loaded. - if ($profile = drupal_get_profile()) { + if ($profile) { $modules[$profile] = $profiles[$profile]; // Installation profile hooks are always executed last. $modules[$profile]->weight = 1000; diff --git a/core/modules/taxonomy/src/Tests/TermKernelTest.php b/core/modules/taxonomy/src/Tests/TermKernelTest.php index 6692775..3d08826 100644 --- a/core/modules/taxonomy/src/Tests/TermKernelTest.php +++ b/core/modules/taxonomy/src/Tests/TermKernelTest.php @@ -23,7 +23,7 @@ class TermKernelTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = array( 'filter', 'taxonomy', 'taxonomy_term', 'text', 'user' ); + public static $modules = array( 'filter', 'taxonomy', 'text', 'user' ); /** * {@inheritdoc} diff --git a/core/modules/views/src/Tests/Plugin/RowEntityTest.php b/core/modules/views/src/Tests/Plugin/RowEntityTest.php index 35bd1e2..7de0305 100644 --- a/core/modules/views/src/Tests/Plugin/RowEntityTest.php +++ b/core/modules/views/src/Tests/Plugin/RowEntityTest.php @@ -24,7 +24,7 @@ class RowEntityTest extends ViewUnitTestBase { * * @var array */ - public static $modules = ['taxonomy', 'text', 'filter', 'field', 'entity', 'system', 'node', 'user']; + public static $modules = ['taxonomy', 'text', 'filter', 'field', 'system', 'node', 'user']; /** * Views used by this test.