From e1e072ff0a15297ff0ce8ed33d392cdd055793b2 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 10 Jan 2025 14:58:44 +0000
Subject: [PATCH] Issue #3494921 by nicxvan, smustgrave: Convert profile hooks

---
 core/.phpstan-baseline.php                    |  30 -----
 core/profiles/demo_umami/demo_umami.profile   | 106 ----------------
 .../demo_umami/src/Hook/DemoUmamiHooks.php    | 120 ++++++++++++++++++
 .../standard/src/Hook/StandardHooks.php       |  37 ++++++
 core/profiles/standard/standard.profile       |  26 ----
 5 files changed, 157 insertions(+), 162 deletions(-)
 delete mode 100644 core/profiles/demo_umami/demo_umami.profile
 create mode 100644 core/profiles/demo_umami/src/Hook/DemoUmamiHooks.php
 create mode 100644 core/profiles/standard/src/Hook/StandardHooks.php
 delete mode 100644 core/profiles/standard/standard.profile

diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php
index 4d20a0a706f3..a4b7ee050fb0 100644
--- a/core/.phpstan-baseline.php
+++ b/core/.phpstan-baseline.php
@@ -54477,30 +54477,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/profiles/demo_umami/demo_umami.install',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Function demo_umami_form_install_configure_submit\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/profiles/demo_umami/demo_umami.profile',
-];
-$ignoreErrors[] = [
-	'message' => '#^Function demo_umami_help\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/profiles/demo_umami/demo_umami.profile',
-];
-$ignoreErrors[] = [
-	'message' => '#^Function demo_umami_set_users_passwords\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/profiles/demo_umami/demo_umami.profile',
-];
-$ignoreErrors[] = [
-	'message' => '#^Function demo_umami_toolbar\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/profiles/demo_umami/demo_umami.profile',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\demo_umami_content\\\\InstallHelper\\:\\:create\\(\\) has no return type specified\\.$#',
 	'identifier' => 'missingType.return',
@@ -54627,12 +54603,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/profiles/minimal/tests/src/Functional/MinimalTest.php',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Function standard_form_install_configure_submit\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/profiles/standard/standard.profile',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\Tests\\\\standard\\\\Functional\\\\StandardTest\\:\\:assertConfigSchema\\(\\) has no return type specified\\.$#',
 	'identifier' => 'missingType.return',
diff --git a/core/profiles/demo_umami/demo_umami.profile b/core/profiles/demo_umami/demo_umami.profile
deleted file mode 100644
index 64b4cc3a40b6..000000000000
--- a/core/profiles/demo_umami/demo_umami.profile
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-
-/**
- * @file
- * Enables modules and site configuration for a demo_umami site installation.
- */
-
-use Drupal\contact\Entity\ContactForm;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Url;
-
-/**
- * Implements hook_help().
- */
-function demo_umami_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    case 'help.page.demo_umami':
-      $output = '';
-      $output .= '<h2>' . t('About') . '</h2>';
-      $output .= '<p>' . t('Umami is an example food magazine website that demonstrates some of the features of Drupal core. It is intended to be used as an example site, rather than as a foundation for building your own site. For more information, see the <a href=":demo_umami">online documentation for the Umami installation profile</a>.', [':demo_umami' => 'https://www.drupal.org/node/2941833']) . '</p>';
-      $output .= '<h2>' . t('Uses') . '</h2>';
-      $output .= '<h3>' . t('Demonstrating Drupal core functionality') . '</h3>';
-      $output .= '<p>' . t('You can look around the site to get ideas for what kinds of features Drupal is capable of, and to see how an actual site can be built using Drupal core.') . '</p>';
-      $output .= '<h3>' . t('Sample content') . '</h3>';
-      $output .= '<p>' . t('The Umami profile is very handy if you are developing a feature and need some sample content.') . '</p>';
-      $output .= '<h2>' . t('What to do when you are ready to build your Drupal website') . '</h2>';
-      $output .= '<p>' . t("Once you've tried Drupal using Umami and want to build your own site, simply reinstall Drupal and select a different installation profile (such as Standard) from the install screen.") . '</p>';
-      return $output;
-  }
-}
-
-/**
- * Implements hook_form_FORM_ID_alter() for install_configure_form().
- *
- * Allows the profile to alter the site configuration form.
- */
-function demo_umami_form_install_configure_form_alter(&$form, FormStateInterface $form_state): void {
-  $form['site_information']['site_name']['#default_value'] = 'Umami Food Magazine';
-  $form['#submit'][] = 'demo_umami_form_install_configure_submit';
-}
-
-/**
- * Submission handler to sync the contact.form.feedback recipient.
- */
-function demo_umami_form_install_configure_submit($form, FormStateInterface $form_state) {
-  $site_mail = $form_state->getValue('site_mail');
-  ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save();
-
-  $password = $form_state->getValue('account')['pass'];
-  demo_umami_set_users_passwords($password);
-}
-
-/**
- * Sets the password of admin to be the password for all users.
- */
-function demo_umami_set_users_passwords(#[\SensitiveParameter] $admin_password) {
-  // Collect the IDs of all users with roles editor or author.
-  $ids = \Drupal::entityQuery('user')
-    ->accessCheck(FALSE)
-    ->condition('roles', ['author', 'editor'], 'IN')
-    ->execute();
-
-  $users = \Drupal::entityTypeManager()->getStorage('user')->loadMultiple($ids);
-
-  foreach ($users as $user) {
-    $user->setPassword($admin_password);
-    $user->save();
-  }
-}
-
-/**
- * Implements hook_toolbar().
- */
-function demo_umami_toolbar() {
-  // Add a warning about using an experimental profile.
-  // @todo This can be removed once a generic warning for experimental profiles
-  //   has been introduced. https://www.drupal.org/project/drupal/issues/2934374
-  $items['experimental-profile-warning'] = [
-    '#weight' => 3400,
-    '#cache' => [
-      'contexts' => ['route'],
-    ],
-  ];
-
-  // Show warning only on administration pages.
-  $admin_context = \Drupal::service('router.admin_context');
-  if ($admin_context->isAdminRoute()) {
-    $link_to_help_page = \Drupal::moduleHandler()->moduleExists('help') && \Drupal::currentUser()->hasPermission('access help pages');
-    $items['experimental-profile-warning']['#type'] = 'toolbar_item';
-    $items['experimental-profile-warning']['tab'] = [
-      '#type' => 'inline_template',
-      '#template' => '<a class="toolbar-warning" href="{{ more_info_link }}">This site is intended for demonstration purposes.</a>',
-      '#context' => [
-        // Link directly to the drupal.org documentation if the help pages
-        // aren't available.
-        'more_info_link' => $link_to_help_page ? Url::fromRoute('help.page', ['name' => 'demo_umami'])
-          : 'https://www.drupal.org/node/2941833',
-      ],
-      '#attached' => [
-        'library' => ['demo_umami/toolbar-warning'],
-      ],
-    ];
-  }
-  return $items;
-}
diff --git a/core/profiles/demo_umami/src/Hook/DemoUmamiHooks.php b/core/profiles/demo_umami/src/Hook/DemoUmamiHooks.php
new file mode 100644
index 000000000000..261637733c46
--- /dev/null
+++ b/core/profiles/demo_umami/src/Hook/DemoUmamiHooks.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace Drupal\demo_umami\Hook;
+
+use Drupal\contact\Entity\ContactForm;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
+
+/**
+ * Hook implementations for demo_umami.
+ */
+class DemoUmamiHooks {
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match): string {
+    $output = '';
+    switch ($route_name) {
+      case 'help.page.demo_umami':
+        $output .= '<h2>' . t('About') . '</h2>';
+        $output .= '<p>' . t('Umami is an example food magazine website that demonstrates some of the features of Drupal core. It is intended to be used as an example site, rather than as a foundation for building your own site. For more information, see the <a href=":demo_umami">online documentation for the Umami installation profile</a>.', [':demo_umami' => 'https://www.drupal.org/node/2941833']) . '</p>';
+        $output .= '<h2>' . t('Uses') . '</h2>';
+        $output .= '<h3>' . t('Demonstrating Drupal core functionality') . '</h3>';
+        $output .= '<p>' . t('You can look around the site to get ideas for what kinds of features Drupal is capable of, and to see how an actual site can be built using Drupal core.') . '</p>';
+        $output .= '<h3>' . t('Sample content') . '</h3>';
+        $output .= '<p>' . t('The Umami profile is very handy if you are developing a feature and need some sample content.') . '</p>';
+        $output .= '<h2>' . t('What to do when you are ready to build your Drupal website') . '</h2>';
+        $output .= '<p>' . t("Once you've tried Drupal using Umami and want to build your own site, simply reinstall Drupal and select a different installation profile (such as Standard) from the install screen.") . '</p>';
+    }
+
+    return $output;
+  }
+
+  /**
+   * Implements hook_form_FORM_ID_alter() for install_configure_form().
+   *
+   * Allows the profile to alter the site configuration form.
+   */
+  #[Hook('form_install_configure_form_alter')]
+  public function formInstallConfigureFormAlter(&$form, FormStateInterface $form_state): void {
+    $form['site_information']['site_name']['#default_value'] = 'Umami Food Magazine';
+    $form['#submit'][] = [$this, 'installConfigureSubmit'];
+  }
+
+  /**
+   * Submission handler to sync the contact.form.feedback recipient.
+   *
+   * @param array $form
+   *   Form array.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current form state.
+   */
+  public function installConfigureSubmit(array $form, FormStateInterface $form_state): void {
+    $site_mail = $form_state->getValue('site_mail');
+    ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save();
+
+    $password = $form_state->getValue('account')['pass'];
+    $this->setUserPasswords($password);
+  }
+
+  /**
+   * Implements hook_toolbar().
+   */
+  #[Hook('toolbar')]
+  public function toolbar(): array {
+    // Add a warning about using an experimental profile.
+    // @todo This can be removed once a generic warning for experimental profiles
+    //   has been introduced. https://www.drupal.org/project/drupal/issues/2934374
+    $items['experimental-profile-warning'] = [
+      '#weight' => 3400,
+      '#cache' => [
+        'contexts' => ['route'],
+      ],
+    ];
+
+    // Show warning only on administration pages.
+    $admin_context = \Drupal::service('router.admin_context');
+    if ($admin_context->isAdminRoute()) {
+      $link_to_help_page = \Drupal::moduleHandler()->moduleExists('help') && \Drupal::currentUser()->hasPermission('access help pages');
+      $items['experimental-profile-warning']['#type'] = 'toolbar_item';
+      $items['experimental-profile-warning']['tab'] = [
+        '#type' => 'inline_template',
+        '#template' => '<a class="toolbar-warning" href="{{ more_info_link }}">This site is intended for demonstration purposes.</a>',
+        '#context' => [
+          // Link directly to the drupal.org documentation if the help pages
+          // aren't available.
+          'more_info_link' => $link_to_help_page ? Url::fromRoute('help.page', ['name' => 'demo_umami'])
+            : 'https://www.drupal.org/node/2941833',
+        ],
+        '#attached' => [
+          'library' => ['demo_umami/toolbar-warning'],
+        ],
+      ];
+    }
+    return $items;
+  }
+
+  /**
+   * Sets the password of admin to be the password for all users.
+   */
+  public function setUserPasswords(#[\SensitiveParameter] $admin_password): void {
+    // Collect the IDs of all users with roles editor or author.
+    $ids = \Drupal::entityQuery('user')
+      ->accessCheck(FALSE)
+      ->condition('roles', ['author', 'editor'], 'IN')
+      ->execute();
+
+    $users = \Drupal::entityTypeManager()->getStorage('user')->loadMultiple($ids);
+
+    foreach ($users as $user) {
+      $user->setPassword($admin_password);
+      $user->save();
+    }
+  }
+
+}
diff --git a/core/profiles/standard/src/Hook/StandardHooks.php b/core/profiles/standard/src/Hook/StandardHooks.php
new file mode 100644
index 000000000000..41e15eb840de
--- /dev/null
+++ b/core/profiles/standard/src/Hook/StandardHooks.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\standard\Hook;
+
+use Drupal\contact\Entity\ContactForm;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for standard.
+ */
+class StandardHooks {
+
+  /**
+   * Implements hook_form_FORM_ID_alter() for install_configure_form().
+   *
+   * Allows the profile to alter the site configuration form.
+   */
+  #[Hook('form_install_configure_form_alter')]
+  public function formInstallConfigureFormAlter(&$form, FormStateInterface $form_state): void {
+    $form['#submit'][] = [$this, 'installConfigureSubmit'];
+  }
+
+  /**
+   * Submission handler to sync the contact.form.feedback recipient.
+   *
+   * @param array $form
+   *   Form array.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current form state.
+   */
+  public function installConfigureSubmit(array $form, FormStateInterface $form_state): void {
+    $site_mail = $form_state->getValue('site_mail');
+    ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save();
+  }
+
+}
diff --git a/core/profiles/standard/standard.profile b/core/profiles/standard/standard.profile
deleted file mode 100644
index 00bb9af445f4..000000000000
--- a/core/profiles/standard/standard.profile
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * @file
- * Enables modules and site configuration for a standard site installation.
- */
-
-use Drupal\contact\Entity\ContactForm;
-use Drupal\Core\Form\FormStateInterface;
-
-/**
- * Implements hook_form_FORM_ID_alter() for install_configure_form().
- *
- * Allows the profile to alter the site configuration form.
- */
-function standard_form_install_configure_form_alter(&$form, FormStateInterface $form_state): void {
-  $form['#submit'][] = 'standard_form_install_configure_submit';
-}
-
-/**
- * Submission handler to sync the contact.form.feedback recipient.
- */
-function standard_form_install_configure_submit($form, FormStateInterface $form_state) {
-  $site_mail = $form_state->getValue('site_mail');
-  ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save();
-}
-- 
GitLab