diff --git a/core/authorize.php b/core/authorize.php index d812f2e..2587c46 100644 --- a/core/authorize.php +++ b/core/authorize.php @@ -65,9 +65,8 @@ function authorize_access_allowed() { // We have to enable the user and system modules, even to check access and // display errors via the maintenance theme. -$module_list['system'] = 'core/modules/system/system.module'; -$module_list['user'] = 'core/modules/user/user.module'; -\Drupal::moduleHandler()->setModuleList($module_list); +\Drupal::moduleHandler()->add('system', 'core/modules/system'); +\Drupal::moduleHandler()->add('user', 'core/modules/user'); \Drupal::moduleHandler()->load('system'); \Drupal::moduleHandler()->load('user'); diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 222ac0c..33ee8f1 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -628,9 +628,9 @@ function _drupal_request_initialize() { * configuration. For example, a module 'foo' may legally be located * in any of these three places: * - * core/modules/foo/foo.module - * modules/foo/foo.module - * sites/example.com/modules/foo/foo.module + * core/modules/foo/foo.info.yml + * modules/foo/foo.info.yml + * sites/example.com/modules/foo/foo.info.yml * * Calling drupal_get_filename('module', 'foo') will give you one of * the above, depending on where the module is located. @@ -670,7 +670,9 @@ function drupal_get_filename($type, $name, $filename = NULL) { // providers first. // Retrieve the current module list (derived from the service container). if ($type == 'module' && \Drupal::hasService('module_handler')) { - $files[$type] += \Drupal::moduleHandler()->getModuleList(); + foreach (\Drupal::moduleHandler()->getModuleList() as $module_name => $module) { + $files[$type][$module_name] = $module->getPathname(); + } } // If still unknown, retrieve the file list prepared in state by // system_rebuild_module_data() and system_rebuild_theme_data(). @@ -685,7 +687,7 @@ function drupal_get_filename($type, $name, $filename = NULL) { $listing->setProfileDirectories(array()); } foreach ($listing->scan($original_type) as $extension_name => $file) { - $files[$type][$extension_name] = $file->uri; + $files[$type][$extension_name] = $file->getPathname(); } } } diff --git a/core/includes/common.inc b/core/includes/common.inc index 57095f7..578f584 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -4957,9 +4957,9 @@ function drupal_flush_all_caches() { // sufficient, since the list of enabled modules might have been adjusted // above due to changed code. $files = array(); - foreach ($module_data as $module => $data) { - if (isset($data->uri) && $data->status) { - $files[$module] = $data->uri; + foreach ($module_data as $name => $extension) { + if ($extension->status) { + $files[$name] = $extension; } } \Drupal::service('kernel')->updateModules($module_handler->getModuleList(), $files); diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index f0e74e3..80349e3 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -492,7 +492,7 @@ function install_begin_request(&$install_state) { $module_handler = \Drupal::moduleHandler(); if (!$module_handler->moduleExists('system')) { // Override the module list with a minimal set of modules. - $module_handler->setModuleList(array('system' => 'core/modules/system/system.module')); + $module_handler->add('system', 'core/modules/system'); } // After setting up a custom and finite module list in a custom low-level // bootstrap like here, ensure to use ModuleHandler::loadAll() so that @@ -507,7 +507,7 @@ function install_begin_request(&$install_state) { // Prime drupal_get_filename()'s static cache. foreach ($install_state['profiles'] as $name => $profile) { - drupal_get_filename('profile', $name, $profile->uri); + drupal_get_filename('profile', $name, $profile->getPathname()); } // Prepare for themed output. We need to run this at the beginning of the @@ -870,9 +870,7 @@ function install_tasks($install_state) { // Allow the installation profile to modify the full list of tasks. if (!empty($install_state['parameters']['profile'])) { $profile = $install_state['parameters']['profile']; - $profile_file = $install_state['profiles'][$profile]->uri; - if (file_exists($profile_file)) { - include_once DRUPAL_ROOT . '/' . $profile_file; + if ($install_state['profiles'][$profile]->load()) { $function = $install_state['parameters']['profile'] . '_install_tasks_alter'; if (function_exists($function)) { $function($tasks, $install_state); @@ -1895,19 +1893,12 @@ function install_already_done_error() { * * @param $install_state * An array of information about the current installation state. The loaded - * profile information will be added here, or an exception will be thrown if - * the profile cannot be loaded. + * profile information will be added here. */ function install_load_profile(&$install_state) { $profile = $install_state['parameters']['profile']; - $profile_file = $install_state['profiles'][$profile]->uri; - if (file_exists($profile_file)) { - include_once DRUPAL_ROOT . '/' . $profile_file; - $install_state['profile_info'] = install_profile_info($install_state['parameters']['profile'], $install_state['parameters']['langcode']); - } - else { - throw new Exception(t('Sorry, the profile you have chosen cannot be loaded.')); - } + $install_state['profiles'][$profile]->load(); + $install_state['profile_info'] = install_profile_info($profile, $install_state['parameters']['langcode']); } /** diff --git a/core/includes/install.inc b/core/includes/install.inc index 3630e07..651228b 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -659,8 +659,9 @@ function drupal_install_system($install_state) { ->save(); // Update the module list to include it. Reboot the kernel too. - \Drupal::moduleHandler()->setModuleList(array('system' => $system_path . '/system.module')); - $kernel->updateModules(array('system' => $system_path . '/system.module')); + \Drupal::moduleHandler()->add('system', 'core/modules/system'); + $module_list = \Drupal::moduleHandler()->getModuleList(); + $kernel->updateModules($module_list); \Drupal::service('config.installer')->installDefaultConfig('module', 'system'); diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc index 21c8d07..a0155e0 100644 --- a/core/includes/theme.maintenance.inc +++ b/core/includes/theme.maintenance.inc @@ -67,9 +67,8 @@ function _drupal_maintenance_theme() { // Ensure that system.module is loaded. if (!function_exists('_system_rebuild_theme_data')) { - $module_list['system'] = 'core/modules/system/system.module'; $module_handler = \Drupal::moduleHandler(); - $module_handler->setModuleList($module_list); + $module_handler->add('system', 'core/modules/system'); $module_handler->load('system'); } diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 218e7da..054fa0c 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -81,12 +81,9 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { protected $newModuleList; /** - * An array of module data objects. + * List of available modules and installation profiles. * - * The data objects have the same data structure as returned by - * ExtensionDiscovery but only the uri property is used. - * - * @var array + * @var \Drupal\Core\Extension\Extension[] */ protected $moduleData = array(); @@ -330,8 +327,8 @@ protected function moduleData($module) { */ public function updateModules(array $module_list, array $module_filenames = array()) { $this->newModuleList = $module_list; - foreach ($module_filenames as $module => $filename) { - $this->moduleData[$module] = (object) array('uri' => $filename); + foreach ($module_filenames as $name => $extension) { + $this->moduleData[$name] = $extension; } // If we haven't yet booted, we don't need to do anything: the new module // list will take effect when boot() is called. If we have already booted, @@ -414,7 +411,7 @@ protected function initializeContainer() { // from the container. $container_modules = $this->container->getParameter('container.modules'); $namespaces_before = $this->classLoader->getPrefixes(); - $this->registerNamespaces($this->getModuleNamespaces($container_modules)); + $this->registerNamespaces($this->container->getParameter('container.namespaces')); // If 'container.modules' is wrong, the container must be rebuilt. if (!isset($this->moduleList)) { @@ -502,7 +499,7 @@ protected function buildContainer() { $container = $this->getContainerBuilder(); $container->set('kernel', $this); $container->setParameter('container.service_providers', $this->serviceProviderClasses); - $container->setParameter('container.modules', $this->getModuleFileNames()); + $container->setParameter('container.modules', $this->getModulesParameter()); // Get a list of namespaces and put it onto the container. $namespaces = $this->getModuleNamespaces($this->getModuleFileNames()); @@ -646,13 +643,32 @@ protected function storage() { } /** + * Returns an array of Extension class parameters for all enabled modules. + * + * @return array + */ + protected function getModulesParameter() { + $extensions = array(); + foreach ($this->moduleList as $name => $weight) { + if ($data = $this->moduleData($name)) { + $extensions[$name] = array( + 'type' => $data->getType(), + 'pathname' => $data->getPathname(), + 'filename' => $data->getExtensionFilename(), + ); + } + } + return $extensions; + } + + /** * Returns the file name for each enabled module. */ protected function getModuleFileNames() { $filenames = array(); foreach ($this->moduleList as $module => $weight) { if ($data = $this->moduleData($module)) { - $filenames[$module] = $data->uri; + $filenames[$module] = $data->getPathname(); } } return $filenames; diff --git a/core/lib/Drupal/Core/Extension/Extension.php b/core/lib/Drupal/Core/Extension/Extension.php index 97f3fa3..cc21c53 100644 --- a/core/lib/Drupal/Core/Extension/Extension.php +++ b/core/lib/Drupal/Core/Extension/Extension.php @@ -27,19 +27,9 @@ class Extension implements \Serializable { protected $pathname; /** - * The relative pathname of the main extension file (e.g., 'core/modules/node/node.module'). - * - * @todo Remove this property and do not require .module/.profile files. - * @see https://drupal.org/node/340723 - * - * @var string - */ - public $uri; - - /** * The filename of the main extension file (e.g., 'node.module'). * - * @var string + * @var string|null */ protected $filename; @@ -61,14 +51,12 @@ class Extension implements \Serializable { * The relative path and filename of the extension's info file; e.g., * 'core/modules/node/node.info.yml'. * @param string $filename - * The filename of the main extension file; e.g., 'node.module'. + * (optional) The filename of the main extension file; e.g., 'node.module'. */ - public function __construct($type, $pathname, $filename) { + public function __construct($type, $pathname, $filename = NULL) { $this->type = $type; $this->pathname = $pathname; - // Set legacy public properties. $this->filename = $filename; - $this->uri = dirname($pathname) . '/' . $filename; } /** @@ -117,6 +105,40 @@ public function getFilename() { } /** + * Returns the relative path of the main extension file, if any. + * + * @return string|null + */ + public function getExtensionPathname() { + if ($this->filename) { + return $this->getPath() . '/' . $this->filename; + } + } + + /** + * Returns the name of the main extension file, if any. + * + * @return string|null + */ + public function getExtensionFilename() { + return $this->filename; + } + + /** + * Loads the main extension file, if any. + * + * @return bool + * TRUE if this extension has a main extension file, FALSE otherwise. + */ + public function load() { + if ($this->filename) { + include_once DRUPAL_ROOT . '/' . $this->getPath() . '/' . $this->filename; + return TRUE; + } + return FALSE; + } + + /** * Re-routes method calls to SplFileInfo. * * Offers all SplFileInfo methods to consumers; e.g., $extension->getMTime(). @@ -153,14 +175,9 @@ public function serialize() { $data = array( 'type' => $this->type, 'pathname' => $this->pathname, + 'filename' => $this->filename, ); - // Include legacy public properties. - // @todo Remove this property and do not require .module/.profile files. - // @see https://drupal.org/node/340723 - // @see Extension::$filename - $data['filename'] = basename($this->uri); - // @todo ThemeHandler::listInfo(), ThemeHandler::rebuildThemeData(), and // system_list() are adding custom properties to the Extension object. $info = new \ReflectionObject($this); @@ -178,12 +195,6 @@ public function unserialize($data) { $data = unserialize($data); $this->type = $data['type']; $this->pathname = $data['pathname']; - - // Restore legacy public properties. - // @todo Remove these properties and do not require .module/.profile files. - // @see https://drupal.org/node/340723 - // @see Extension::$filename - $this->uri = dirname($data['pathname']) . '/' . $data['filename']; $this->filename = $data['filename']; // @todo ThemeHandler::listInfo(), ThemeHandler::rebuildThemeData(), and diff --git a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php index aba0c2f..e9cfefa 100644 --- a/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php +++ b/core/lib/Drupal/Core/Extension/ExtensionDiscovery.php @@ -375,6 +375,9 @@ protected function scanDirectory($dir, $include_tests) { else { $filename = $name . '.' . $type; } + if (!file_exists(dirname($pathname) . '/' . $filename)) { + $filename = NULL; + } $extension = new Extension($type, $pathname, $filename); // Inject the existing RecursiveDirectoryIterator object to avoid diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index 89cd73e..003486f 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -30,9 +30,7 @@ class ModuleHandler implements ModuleHandlerInterface { /** * List of installed modules. * - * @var array - * An associative array whose keys are the names of the modules and whose - * values are the module filenames. + * @var \Drupal\Core\Extension\Extension[] */ protected $moduleList; @@ -69,14 +67,17 @@ class ModuleHandler implements ModuleHandlerInterface { * * @param array $module_list * An associative array whose keys are the names of installed modules and - * whose values are the module filenames. This is normally the + * whose values are Extension class parameters. This is normally the * %container.modules% parameter being set up by DrupalKernel. * * @see \Drupal\Core\DrupalKernel * @see \Drupal\Core\CoreServiceProvider */ public function __construct(array $module_list = array()) { - $this->moduleList = $module_list; + $this->moduleList = array(); + foreach ($module_list as $name => $module) { + $this->moduleList[$name] = new Extension($module['type'], $module['pathname'], $module['filename']); + } } /** @@ -88,8 +89,7 @@ public function load($name) { } if (isset($this->moduleList[$name])) { - $filename = $this->moduleList[$name]; - include_once DRUPAL_ROOT . '/' . $filename; + $this->moduleList[$name]->load(); $this->loadedFiles[$name] = TRUE; return TRUE; } @@ -101,8 +101,8 @@ public function load($name) { */ public function loadAll() { if (!$this->loaded) { - foreach ($this->moduleList as $module => $filename) { - $this->load($module); + foreach ($this->moduleList as $name => $module) { + $this->load($name); } $this->loaded = TRUE; } @@ -140,6 +140,13 @@ public function setModuleList(array $module_list = array()) { $this->resetImplementations(); } + public function add($name, $path) { + $pathname = "$path/$name.info.yml"; + $filename = file_exists($path . "/$name.module") ? "$name.module" : NULL; + $this->moduleList[$name] = new Extension('module', $pathname, $filename); + $this->resetImplementations(); + } + /** * Implements \Drupal\Core\Extension\ModuleHandlerInterface::buildModuleDependencies(). */ @@ -190,7 +197,7 @@ public function loadInclude($module, $type, $name = NULL) { $name = $name ?: $module; if (isset($this->moduleList[$module])) { - $file = DRUPAL_ROOT . '/' . dirname($this->moduleList[$module]) . "/$name.$type"; + $file = DRUPAL_ROOT . '/' . $this->moduleList[$module]->getPath() . "/$name.$type"; if (is_file($file)) { require_once $file; return $file; @@ -586,7 +593,10 @@ public function install(array $module_list, $enable_dependencies = TRUE) { $module_filenames[$name] = $current_module_filenames[$name]; } else { - $module_filenames[$name] = drupal_get_filename('module', $name); + $module_path = drupal_get_path('module', $name); + $pathname = "$module_path/$name.info.yml"; + $filename = file_exists($module_path . "/$name.module") ? "$name.module" : NULL; + $module_filenames[$name] = new Extension('module', $pathname, $filename); } } @@ -819,8 +829,8 @@ protected function removeCacheBins($module) { */ public function getModuleDirectories() { $dirs = array(); - foreach ($this->getModuleList() as $module => $filename) { - $dirs[$module] = DRUPAL_ROOT . '/' . dirname($filename); + foreach ($this->getModuleList() as $name => $module) { + $dirs[$name] = DRUPAL_ROOT . '/' . $module->getPath(); } return $dirs; } diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index 060d796..db22e5f 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -290,7 +290,7 @@ public function rebuildThemeData() { // Defaults to 'twig' (see $defaults above). $engine = $theme->info['engine']; if (isset($engines[$engine])) { - $theme->owner = $engines[$engine]->uri; + $theme->owner = $engines[$engine]->getExtensionPathname(); $theme->prefix = $engines[$engine]->getName(); } diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index 06a8dcc..2fed4e4 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -40,8 +40,8 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, $options = arr // Set twig path namespace for themes and modules. $namespaces = array(); - foreach ($module_handler->getModuleList() as $name => $filename) { - $namespaces[$name] = dirname($filename); + foreach ($module_handler->getModuleList() as $name => $extension) { + $namespaces[$name] = $extension->getPath(); } foreach ($theme_handler->listInfo() as $name => $extension) { $namespaces[$name] = $extension->getPath(); diff --git a/core/modules/action/tests/action_bulk_test/action_bulk_test.module b/core/modules/action/tests/action_bulk_test/action_bulk_test.module deleted file mode 100644 index b3d9bbc..0000000 --- a/core/modules/action/tests/action_bulk_test/action_bulk_test.module +++ /dev/null @@ -1 +0,0 @@ -getModuleList() as $module => $filename) { - $directories[$module] = dirname($filename); + foreach ($module_handler->getModuleList() as $name => $module) { + $directories[$name] = $module->getPath(); } foreach ($theme_handler->listInfo() as $theme) { $directories[$theme->getName()] = $theme->getPath(); diff --git a/core/modules/contact/tests/modules/contact_test_views/contact_test_views.module b/core/modules/contact/tests/modules/contact_test_views/contact_test_views.module deleted file mode 100644 index b3d9bbc..0000000 --- a/core/modules/contact/tests/modules/contact_test_views/contact_test_views.module +++ /dev/null @@ -1 +0,0 @@ -container->get('module_handler'); - $module_filenames = $module_handler->getModuleList(); // Write directly to active storage to avoid early instantiation of // the event dispatcher which can prevent modules from registering events. $active_storage = \Drupal::service('config.storage'); $system_config = $active_storage->read('system.module'); foreach ($modules as $module) { - $module_filenames[$module] = drupal_get_filename('module', $module); + $module_handler->add($module, drupal_get_path('module', $module)); // Maintain the list of enabled modules in configuration. $system_config['enabled'][$module] = 0; } $active_storage->write('system.module', $system_config); - $module_handler->setModuleList($module_filenames); - $module_handler->resetImplementations(); + $module_filenames = $module_handler->getModuleList(); // Update the kernel to make their services available. $this->kernel->updateModules($module_filenames, $module_filenames); diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 8da7e4c..9b6e9cc 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -552,7 +552,7 @@ function simpletest_classloader_register() { $extensions = array(); foreach ($types as $type) { foreach ($listing->scan($type, TRUE) as $name => $file) { - $extensions[$type][$name] = $file->uri; + $extensions[$type][$name] = $file->getPathname(); } } \Drupal::cache()->set($cid, $extensions); diff --git a/core/modules/statistics/tests/modules/statistics_test_views/statistics_test_views.module b/core/modules/statistics/tests/modules/statistics_test_views/statistics_test_views.module deleted file mode 100644 index e69de29..0000000 diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 60c7c4e..e58c1cf 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1463,7 +1463,7 @@ function system_rebuild_module_data() { $module->weight = isset($installed_modules[$name]) ? $installed_modules[$name] : 0; $module->status = (int) isset($installed_modules[$name]); $module->schema_version = SCHEMA_UNINSTALLED; - $files[$name] = $module->uri; + $files[$name] = $module->getPathname(); } $modules = \Drupal::moduleHandler()->buildModuleDependencies($modules); $modules_cache = $modules; @@ -1510,7 +1510,7 @@ function system_rebuild_theme_data() { $files = array(); foreach ($themes as $name => $theme) { $theme->status = (int) isset($enabled_themes[$name]); - $files[$name] = $theme->uri; + $files[$name] = $theme->getPathname(); } // Replace last known theme data state. // @todo Obsolete with proper installation status for themes. diff --git a/core/modules/system/tests/modules/action_test/action_test.module b/core/modules/system/tests/modules/action_test/action_test.module deleted file mode 100644 index b3d9bbc..0000000 --- a/core/modules/system/tests/modules/action_test/action_test.module +++ /dev/null @@ -1 +0,0 @@ -assertInstanceOf('Drupal\Core\Extension\Extension', $info); $this->assertEquals('seven', $info->getName()); $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.info.yml', $info->getPathname()); - $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.theme', $info->uri); + $this->assertEquals(DRUPAL_ROOT . '/core/themes/seven/seven.theme', $info->getExtensionPathname()); $this->assertEquals(DRUPAL_ROOT . '/core/themes/engines/twig/twig.engine', $info->owner); $this->assertEquals('twig', $info->prefix); diff --git a/core/themes/engines/phptemplate/phptemplate.engine b/core/themes/engines/phptemplate/phptemplate.engine index cab86fd..0521092 100644 --- a/core/themes/engines/phptemplate/phptemplate.engine +++ b/core/themes/engines/phptemplate/phptemplate.engine @@ -11,9 +11,7 @@ * Implements hook_init(). */ function phptemplate_init(Extension $theme) { - if (file_exists($theme->uri)) { - include_once DRUPAL_ROOT . '/' . $theme->uri; - } + $theme->load(); } /** diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index 2985ddc..fd988da 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -28,9 +28,7 @@ function twig_extension() { * Implements hook_init(). */ function twig_init(Extension $theme) { - if (file_exists($theme->uri)) { - include_once DRUPAL_ROOT . '/' . $theme->uri; - } + $theme->load(); } /** diff --git a/core/update.php b/core/update.php index 433d5cf..1adf244 100644 --- a/core/update.php +++ b/core/update.php @@ -252,9 +252,8 @@ function update_access_allowed() { // so we fall back on requiring that the user be logged in as user #1. try { $module_handler = \Drupal::moduleHandler(); + $module_handler->add('user', 'core/modules/user'); $module_filenames = $module_handler->getModuleList(); - $module_filenames['user'] = 'core/modules/user/user.module'; - $module_handler->setModuleList($module_filenames); $module_handler->reload(); \Drupal::service('kernel')->updateModules($module_filenames, $module_filenames); return user_access('administer software updates');