Loading core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +18 −2 Original line number Diff line number Diff line Loading @@ -261,13 +261,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $update_status_module = $form_state->getValue('enable_update_status_module'); if (empty($install_state['config_install_path']) && $update_status_module) { $this->moduleInstaller->install(['update']); // After a module is installed, there is a new container, so all class // properties dependent on the container need to be reset. $this->resetPropertiesFromContainer(); // Add the site maintenance account's email address to the list of // addresses to be notified when updates are available, if selected. $email_update_status_emails = $form_state->getValue('enable_update_status_emails'); if ($email_update_status_emails) { // Reset the configuration factory so it is updated with the new module. $this->resetConfigFactory(); // Reset the configuration so it is updated with the new module. $this->config('update.settings')->set('notification.emails', [$account_values['mail']])->save(TRUE); } } Loading Loading @@ -315,4 +317,18 @@ protected function getAdminRoles(): array { return $this->entityTypeManager->getStorage('user_role')->loadByProperties(['is_admin' => TRUE]); } /** * Repopulate class properties from container. */ protected function resetPropertiesFromContainer(): void { $this->resetConfigFactory(); $container = \Drupal::getContainer(); $this->root = $container->getParameter('app.root'); $this->sitePath = $container->getParameter('site.path'); $this->entityTypeManager = $container->get('entity_type.manager'); $this->moduleInstaller = $container->get('module_installer'); $this->userNameValidator = $container->get('user.name_validator'); $this->superUserAccessPolicy = $container->getParameter('security.enable_super_user') ?? TRUE; } } core/profiles/tests/testing_site_config/src/Hook/TestingSiteConfigHooks.php 0 → 100644 +37 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\testing_site_config\Hook; use Drupal\Core\Hook\Attribute\Hook; use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Simulates a hook class with a dependency chain requiring the kernel. * * During an interactive site installation, if 'Check for updates automatically' * is checked, the update module will be installed in the submit handler of the * site configure form. After that, the user 1 entity is loaded to be populated * with values from the form. This leads to hook implementations (the user_load * hook in this instance) to be called. However, since the container was rebuilt * when the update module was installed, all the service properties in * SiteConfigureForm, such as entityTypeManager, need to re-populated from the * newly-built container, otherwise they will reference outdated objects and * cause exceptions. * * @see \Drupal\Core\Installer\Form\SiteConfigureForm::submitForm() */ class TestingSiteConfigHooks { public function __construct( #[Autowire(service: 'kernel')] protected $kernel, ) {} #[Hook('user_load')] public function userLoad(): void { assert(isset($this->kernel)); } } core/tests/Drupal/FunctionalTests/Installer/InstallerSiteConfigProfileTest.php +5 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ protected function installParameters() { // from our install profile. unset($parameters['forms']['install_configure_form']['site_mail']); // Set 'enable_update_status_module' flag to test that // SiteConfigureForm::submit() handles the container rebuild correctly after // the Update Status module is installed. $parameters['forms']['install_configure_form']['enable_update_status_module'] = TRUE; return $parameters; } Loading @@ -67,6 +71,7 @@ protected function setUpSite() { public function testInstaller(): void { $this->assertEquals(self::EXPECTED_SITE_MAIL, $this->config('system.site')->get('mail')); $this->assertEquals(self::EXPECTED_TIMEZONE, $this->config('system.date')->get('timezone.default')); $this->assertTrue(\Drupal::moduleHandler()->moduleExists('update')); } } Loading
core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +18 −2 Original line number Diff line number Diff line Loading @@ -261,13 +261,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $update_status_module = $form_state->getValue('enable_update_status_module'); if (empty($install_state['config_install_path']) && $update_status_module) { $this->moduleInstaller->install(['update']); // After a module is installed, there is a new container, so all class // properties dependent on the container need to be reset. $this->resetPropertiesFromContainer(); // Add the site maintenance account's email address to the list of // addresses to be notified when updates are available, if selected. $email_update_status_emails = $form_state->getValue('enable_update_status_emails'); if ($email_update_status_emails) { // Reset the configuration factory so it is updated with the new module. $this->resetConfigFactory(); // Reset the configuration so it is updated with the new module. $this->config('update.settings')->set('notification.emails', [$account_values['mail']])->save(TRUE); } } Loading Loading @@ -315,4 +317,18 @@ protected function getAdminRoles(): array { return $this->entityTypeManager->getStorage('user_role')->loadByProperties(['is_admin' => TRUE]); } /** * Repopulate class properties from container. */ protected function resetPropertiesFromContainer(): void { $this->resetConfigFactory(); $container = \Drupal::getContainer(); $this->root = $container->getParameter('app.root'); $this->sitePath = $container->getParameter('site.path'); $this->entityTypeManager = $container->get('entity_type.manager'); $this->moduleInstaller = $container->get('module_installer'); $this->userNameValidator = $container->get('user.name_validator'); $this->superUserAccessPolicy = $container->getParameter('security.enable_super_user') ?? TRUE; } }
core/profiles/tests/testing_site_config/src/Hook/TestingSiteConfigHooks.php 0 → 100644 +37 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\testing_site_config\Hook; use Drupal\Core\Hook\Attribute\Hook; use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Simulates a hook class with a dependency chain requiring the kernel. * * During an interactive site installation, if 'Check for updates automatically' * is checked, the update module will be installed in the submit handler of the * site configure form. After that, the user 1 entity is loaded to be populated * with values from the form. This leads to hook implementations (the user_load * hook in this instance) to be called. However, since the container was rebuilt * when the update module was installed, all the service properties in * SiteConfigureForm, such as entityTypeManager, need to re-populated from the * newly-built container, otherwise they will reference outdated objects and * cause exceptions. * * @see \Drupal\Core\Installer\Form\SiteConfigureForm::submitForm() */ class TestingSiteConfigHooks { public function __construct( #[Autowire(service: 'kernel')] protected $kernel, ) {} #[Hook('user_load')] public function userLoad(): void { assert(isset($this->kernel)); } }
core/tests/Drupal/FunctionalTests/Installer/InstallerSiteConfigProfileTest.php +5 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,10 @@ protected function installParameters() { // from our install profile. unset($parameters['forms']['install_configure_form']['site_mail']); // Set 'enable_update_status_module' flag to test that // SiteConfigureForm::submit() handles the container rebuild correctly after // the Update Status module is installed. $parameters['forms']['install_configure_form']['enable_update_status_module'] = TRUE; return $parameters; } Loading @@ -67,6 +71,7 @@ protected function setUpSite() { public function testInstaller(): void { $this->assertEquals(self::EXPECTED_SITE_MAIL, $this->config('system.site')->get('mail')); $this->assertEquals(self::EXPECTED_TIMEZONE, $this->config('system.date')->get('timezone.default')); $this->assertTrue(\Drupal::moduleHandler()->moduleExists('update')); } }