From 18a39f8c03631799ac05735c9bc1afaf08a6caa8 Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Fri, 3 Jan 2025 13:42:46 +1000
Subject: [PATCH] Issue #3495508 by nicxvan: Mark Media and Media Library
 modules' procedural hooks as converted

---
 core/.phpstan-baseline.php                    |  6 --
 core/modules/media/media.install              | 74 ++++++++++---------
 core/modules/media/media.module               | 45 +----------
 .../src/Hook/MediaThemeSuggestionsHooks.php   | 56 ++++++++++++++
 .../media_library/media_library.module        | 23 ------
 .../media_library/media_library.services.yml  |  3 +
 .../src/Hook/MediaLibraryHooks.php            | 22 ++++++
 7 files changed, 121 insertions(+), 108 deletions(-)
 create mode 100644 core/modules/media/src/Hook/MediaThemeSuggestionsHooks.php

diff --git a/core/.phpstan-baseline.php b/core/.phpstan-baseline.php
index 0d897d182157..5e76e8752801 100644
--- a/core/.phpstan-baseline.php
+++ b/core/.phpstan-baseline.php
@@ -25777,12 +25777,6 @@
 	'count' => 1,
 	'path' => __DIR__ . '/modules/media/media.module',
 ];
-$ignoreErrors[] = [
-	'message' => '#^Function media_theme_suggestions_media\\(\\) has no return type specified\\.$#',
-	'identifier' => 'missingType.return',
-	'count' => 1,
-	'path' => __DIR__ . '/modules/media/media.module',
-];
 $ignoreErrors[] = [
 	'message' => '#^Method Drupal\\\\media\\\\Controller\\\\MediaFilterController\\:\\:checkCsrf\\(\\) has no return type specified\\.$#',
 	'identifier' => 'missingType.return',
diff --git a/core/modules/media/media.install b/core/modules/media/media.install
index 4cda7d359391..db6e3563ad11 100644
--- a/core/modules/media/media.install
+++ b/core/modules/media/media.install
@@ -8,48 +8,13 @@
 use Drupal\Core\File\Exception\FileException;
 use Drupal\Core\File\FileExists;
 use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\Hook\Attribute\StopProceduralHookScan;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Url;
 use Drupal\image\Plugin\Field\FieldType\ImageItem;
 use Drupal\media\Entity\MediaType;
 use Drupal\user\RoleInterface;
 
-/**
- * Implements hook_install().
- */
-function media_install(): void {
-  $source = \Drupal::service('extension.list.module')->getPath('media') . '/images/icons';
-  $destination = \Drupal::config('media.settings')->get('icon_base_uri');
-  /** @var \Drupal\Core\File\FileSystemInterface $file_system */
-  $file_system = \Drupal::service('file_system');
-  $file_system->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
-
-  $files = $file_system->scanDirectory($source, '/.*\.(svg|png|jpg|jpeg|gif)$/');
-  foreach ($files as $file) {
-    // When reinstalling the media module we don't want to copy the icons when
-    // they already exist. The icons could be replaced (by a contrib module or
-    // manually), so we don't want to replace the existing files. Removing the
-    // files when we uninstall could also be a problem if the files are
-    // referenced somewhere else. Since showing an error that it was not
-    // possible to copy the files is also confusing, we silently do nothing.
-    if (!file_exists($destination . DIRECTORY_SEPARATOR . $file->filename)) {
-      try {
-        $file_system->copy($file->uri, $destination, FileExists::Error);
-      }
-      catch (FileException) {
-        // Ignore and continue.
-      }
-
-    }
-  }
-
-  // Grant the "view media" permission to all users by default.
-  if (\Drupal::moduleHandler()->moduleExists('user')) {
-    user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, ['view media']);
-    user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['view media']);
-  }
-}
-
 /**
  * Implements hook_requirements().
  */
@@ -144,6 +109,43 @@ function media_requirements($phase) {
   return $requirements;
 }
 
+/**
+ * Implements hook_install().
+ */
+#[StopProceduralHookScan]
+function media_install(): void {
+  $source = \Drupal::service('extension.list.module')->getPath('media') . '/images/icons';
+  $destination = \Drupal::config('media.settings')->get('icon_base_uri');
+  /** @var \Drupal\Core\File\FileSystemInterface $file_system */
+  $file_system = \Drupal::service('file_system');
+  $file_system->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
+
+  $files = $file_system->scanDirectory($source, '/.*\.(svg|png|jpg|jpeg|gif)$/');
+  foreach ($files as $file) {
+    // When reinstalling the media module we don't want to copy the icons when
+    // they already exist. The icons could be replaced (by a contrib module or
+    // manually), so we don't want to replace the existing files. Removing the
+    // files when we uninstall could also be a problem if the files are
+    // referenced somewhere else. Since showing an error that it was not
+    // possible to copy the files is also confusing, we silently do nothing.
+    if (!file_exists($destination . DIRECTORY_SEPARATOR . $file->filename)) {
+      try {
+        $file_system->copy($file->uri, $destination, FileExists::Error);
+      }
+      catch (FileException) {
+        // Ignore and continue.
+      }
+
+    }
+  }
+
+  // Grant the "view media" permission to all users by default.
+  if (\Drupal::moduleHandler()->moduleExists('user')) {
+    user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, ['view media']);
+    user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['view media']);
+  }
+}
+
 /**
  * Implements hook_update_last_removed().
  */
diff --git a/core/modules/media/media.module b/core/modules/media/media.module
index b23be0e5f5c4..5e14e6867d11 100644
--- a/core/modules/media/media.module
+++ b/core/modules/media/media.module
@@ -4,54 +4,12 @@
  * @file
  */
 
-use Drupal\Component\Plugin\DerivativeInspectionInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Hook\Attribute\StopProceduralHookScan;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\RenderElementBase;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Url;
-use Drupal\media\Plugin\media\Source\OEmbedInterface;
-
-/**
- * Implements hook_theme_suggestions_HOOK().
- */
-function media_theme_suggestions_media(array $variables) {
-  $suggestions = [];
-  /** @var \Drupal\media\MediaInterface $media */
-  $media = $variables['elements']['#media'];
-  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
-
-  $suggestions[] = 'media__' . $sanitized_view_mode;
-  $suggestions[] = 'media__' . $media->bundle();
-  $suggestions[] = 'media__' . $media->bundle() . '__' . $sanitized_view_mode;
-
-  // Add suggestions based on the source plugin ID.
-  $source = $media->getSource();
-  if ($source instanceof DerivativeInspectionInterface) {
-    $source_id = $source->getBaseId();
-    $derivative_id = $source->getDerivativeId();
-    if ($derivative_id) {
-      $source_id .= '__derivative_' . $derivative_id;
-    }
-  }
-  else {
-    $source_id = $source->getPluginId();
-  }
-  $suggestions[] = "media__source_$source_id";
-
-  // If the source plugin uses oEmbed, add a suggestion based on the provider
-  // name, if available.
-  if ($source instanceof OEmbedInterface) {
-    $provider_id = $source->getMetadata($media, 'provider_name');
-    if ($provider_id) {
-      $provider_id = \Drupal::transliteration()->transliterate($provider_id);
-      $provider_id = preg_replace('/[^a-z0-9_]+/', '_', mb_strtolower($provider_id));
-      $suggestions[] = end($suggestions) . "__provider_$provider_id";
-    }
-  }
-
-  return $suggestions;
-}
 
 /**
  * Prepares variables for media templates.
@@ -65,6 +23,7 @@ function media_theme_suggestions_media(array $variables) {
  *   - name: The label for the media item.
  *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
  */
+#[StopProceduralHookScan]
 function template_preprocess_media(array &$variables): void {
   $variables['media'] = $variables['elements']['#media'];
   $variables['view_mode'] = $variables['elements']['#view_mode'];
diff --git a/core/modules/media/src/Hook/MediaThemeSuggestionsHooks.php b/core/modules/media/src/Hook/MediaThemeSuggestionsHooks.php
new file mode 100644
index 000000000000..8bdfc5824c38
--- /dev/null
+++ b/core/modules/media/src/Hook/MediaThemeSuggestionsHooks.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\media\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Component\Plugin\DerivativeInspectionInterface;
+use Drupal\media\Plugin\media\Source\OEmbedInterface;
+
+/**
+ * Theme suggestions for media.
+ */
+class MediaThemeSuggestionsHooks {
+
+  /**
+   * Implements hook_theme_suggestions_HOOK().
+   */
+  #[Hook('theme_suggestions_media')]
+  public function themeSuggestionsMedia(array $variables): array {
+    $suggestions = [];
+    /** @var \Drupal\media\MediaInterface $media */
+    $media = $variables['elements']['#media'];
+    $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
+
+    $suggestions[] = 'media__' . $sanitized_view_mode;
+    $suggestions[] = 'media__' . $media->bundle();
+    $suggestions[] = 'media__' . $media->bundle() . '__' . $sanitized_view_mode;
+
+    // Add suggestions based on the source plugin ID.
+    $source = $media->getSource();
+    if ($source instanceof DerivativeInspectionInterface) {
+      $source_id = $source->getBaseId();
+      $derivative_id = $source->getDerivativeId();
+      if ($derivative_id) {
+        $source_id .= '__derivative_' . $derivative_id;
+      }
+    }
+    else {
+      $source_id = $source->getPluginId();
+    }
+    $suggestions[] = "media__source_$source_id";
+
+    // If the source plugin uses oEmbed, add a suggestion based on the provider
+    // name, if available.
+    if ($source instanceof OEmbedInterface) {
+      $provider_id = $source->getMetadata($media, 'provider_name');
+      if ($provider_id) {
+        $provider_id = \Drupal::transliteration()->transliterate($provider_id);
+        $provider_id = preg_replace('/[^a-z0-9_]+/', '_', mb_strtolower($provider_id));
+        $suggestions[] = end($suggestions) . "__provider_$provider_id";
+      }
+    }
+
+    return $suggestions;
+  }
+
+}
diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module
index 0e12f0311178..11c359007c9f 100644
--- a/core/modules/media_library/media_library.module
+++ b/core/modules/media_library/media_library.module
@@ -85,29 +85,6 @@ function media_library_preprocess_views_view_fields(&$variables): void {
   }
 }
 
-/**
- * Alter the bulk form to add a more accessible label.
- *
- * @param array $form
- *   An associative array containing the structure of the form.
- * @param \Drupal\Core\Form\FormStateInterface $form_state
- *   The current state of the form.
- *
- * @todo Remove in https://www.drupal.org/node/2983454
- */
-function media_library_form_views_form_media_library_page_alter(array &$form, FormStateInterface $form_state): void {
-  if (isset($form['media_bulk_form']) && isset($form['output'])) {
-    /** @var \Drupal\views\ViewExecutable $view */
-    $view = $form['output'][0]['#view'];
-    foreach (Element::getVisibleChildren($form['media_bulk_form']) as $key) {
-      if (isset($view->result[$key])) {
-        $media = $view->field['media_bulk_form']->getEntity($view->result[$key]);
-        $form['media_bulk_form'][$key]['#title'] = $media ? t('Select @label', ['@label' => $media->label()]) : '';
-      }
-    }
-  }
-}
-
 /**
  * Form #after_build callback for media_library view's exposed filters form.
  */
diff --git a/core/modules/media_library/media_library.services.yml b/core/modules/media_library/media_library.services.yml
index 9a0253f15798..510769de9d6d 100644
--- a/core/modules/media_library/media_library.services.yml
+++ b/core/modules/media_library/media_library.services.yml
@@ -1,3 +1,6 @@
+parameters:
+  media_library.hooks_converted: true
+
 services:
   _defaults:
     autoconfigure: true
diff --git a/core/modules/media_library/src/Hook/MediaLibraryHooks.php b/core/modules/media_library/src/Hook/MediaLibraryHooks.php
index 0bf9fdf9a2a5..62ca5efffca8 100644
--- a/core/modules/media_library/src/Hook/MediaLibraryHooks.php
+++ b/core/modules/media_library/src/Hook/MediaLibraryHooks.php
@@ -18,6 +18,7 @@
 use Drupal\Core\Url;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\Render\Element;
 
 /**
  * Hook implementations for media_library.
@@ -207,6 +208,27 @@ public function formAlter(array &$form, FormStateInterface $form_state, $form_id
     }
   }
 
+  /**
+   * Implements hook_form_FORM_ID_alter().
+   *
+   * Alter the bulk form to add a more accessible label.
+   *
+   * @todo Remove in https://www.drupal.org/node/2983454
+   */
+  #[Hook('form_views_form_media_library_page_alter')]
+  public function formViewsFormMediaLibraryPageAlter(array &$form, FormStateInterface $form_state, $form_id) : void {
+    if (isset($form['media_bulk_form']) && isset($form['output'])) {
+      /** @var \Drupal\views\ViewExecutable $view */
+      $view = $form['output'][0]['#view'];
+      foreach (Element::getVisibleChildren($form['media_bulk_form']) as $key) {
+        if (isset($view->result[$key])) {
+          $media = $view->field['media_bulk_form']->getEntity($view->result[$key]);
+          $form['media_bulk_form'][$key]['#title'] = $media ? t('Select @label', ['@label' => $media->label()]) : '';
+        }
+      }
+    }
+  }
+
   /**
    * Implements hook_field_ui_preconfigured_options_alter().
    */
-- 
GitLab