Verified Commit 62c7178d authored by Lee Rowlands's avatar Lee Rowlands
Browse files

task: #3581218 Deprecate .theme file extension

By: nicxvan
By: berdir
By: catch
By: quietone
By: alexpott
By: smustgrave
By: larowlan
parent 9e4409d6
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ class Theme extends Extension {
   *   The info array parsed from the theme's .info.yml file.
   * @param string|null $filename
   *   (optional) The filename of the main extension file; e.g., olivero.theme.
   *   This is deprecated and will be removed in Drupal 13.0.0.
   */
  public function __construct(string $root, string $pathname, array $info, ?string $filename = NULL) {
    parent::__construct($root, 'theme', $pathname, $filename);
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ public function getThemeDirectories();
   * Determines whether a given theme is installed.
   *
   * @param string $theme
   *   The name of the theme (without the .theme extension).
   *   The machine name of the theme.
   *
   * @return bool
   *   TRUE if the theme is installed.
+20 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\Hook\Attribute;

/**
 * Defines a ExtensionFileIsConverted attribute object.
 *
 * This prevents deprecation messages for .theme files to allow legacy tests or
 * supporting multiple versions of core. It must be on a function in the .theme
 * file. This must only be used for legacy support, the extension must fully
 * work without the file in versions >=11.3.0. If the minimum supported version
 * of core is 11.3.0 then this attribute must not be used.
 *
 * @see https://www.drupal.org/node/3581222
 * @see https://www.drupal.org/node/3551652
 */
#[\Attribute(\Attribute::TARGET_FUNCTION)]
class ExtensionFileIsConverted {}
+29 −3
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
use Drupal\Core\Hook\Attribute\ProceduralHookScanStop;
use Drupal\Core\Hook\Attribute\ReorderHook;
use Drupal\Core\Site\Settings;
use Drupal\Core\Hook\Attribute\ExtensionFileIsConverted;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

@@ -61,6 +62,15 @@ class ThemeHookCollectorPass implements CompilerPassInterface {
   */
  protected array $preprocessForSuggestions;

  /**
   * Deprecated .theme files.
   *
   * These are stored to allow emitting deprecation messages.
   *
   * @var array<string, true>
   */
  protected array $deprecatedThemeFiles = [];

  /**
   * Constructor.
   *
@@ -98,6 +108,10 @@ protected function writeToContainer(ContainerBuilder $container): void {
      'theme_hook_list' => $this->sortByTheme($implementationsByHook),
      'theme_preprocess_for_suggestions' => $this->preprocessForSuggestions ?? [],
    ]);

    foreach ($this->deprecatedThemeFiles as $deprecatedThemeFile => $v) {
      @trigger_error('Using ' . $deprecatedThemeFile . '.theme is deprecated in drupal:12.0.0 and is removed from drupal:13.0.0. Use classes instead. See https://www.drupal.org/node/3581222', E_USER_DEPRECATED);
    }
  }

  /**
@@ -225,6 +239,10 @@ protected function collectThemeHookImplementations($dir, $theme, $currentThemePr

      $isThemeSettings = str_ends_with($filename, 'theme-settings.php');

      if ($fileExtension === 'theme') {
        $this->deprecatedThemeFiles[pathinfo($filename, PATHINFO_FILENAME)] = TRUE;
      }

      if ($fileExtension === 'php' && !$isThemeSettings) {
        $cached = $hookFileCache->get($filename);
        if ($cached) {
@@ -268,19 +286,27 @@ protected function collectThemeHookImplementations($dir, $theme, $currentThemePr
        if ($implementations === NULL) {
          $finder = MockFileFinder::create($filename);
          $parser = new StaticReflectionParser('', $finder);
          $implementations = [];
          $implementations = [
            'hooks' => [],
          ];
          foreach ($parser->getMethodAttributes() as $function => $attributes) {
            if (StaticReflectionParser::hasAttribute($attributes, ExtensionFileIsConverted::class)) {
              $implementations['@skip_theme_file_deprecation'] = TRUE;
            }
            if (StaticReflectionParser::hasAttribute($attributes, ProceduralHookScanStop::class)) {
              break;
            }
            if (!StaticReflectionParser::hasAttribute($attributes, LegacyHook::class) && (preg_match($currentThemePreg, $function, $matches) || preg_match($allThemesPreg, $function, $matches))) {
              assert($function === $matches['theme'] . '_' . $matches['hook']);
              $implementations[] = ['theme' => $matches['theme'], 'hook' => $matches['hook']];
              $implementations['hooks'][] = ['theme' => $matches['theme'], 'hook' => $matches['hook']];
            }
          }
          $proceduralHookFileCache->set($filename, $implementations);
        }
        foreach ($implementations as $implementation) {
        if (isset($implementations['@skip_theme_file_deprecation'])) {
          unset($this->deprecatedThemeFiles[pathinfo($filename, PATHINFO_FILENAME)]);
        }
        foreach ($implementations['hooks'] as $implementation) {
          $this->proceduralImplementations[$implementation['hook']][] = $implementation['theme'];
        }
      }
+4 −6
Original line number Diff line number Diff line
@@ -630,9 +630,8 @@ function hook_preprocess_HOOK(&$variables): void {
 * hook called (in this case 'node__article') is available in
 * $variables['theme_hook_original'].
 *
 * Implementations of this hook must be placed in *.module or *.theme files, or
 * must otherwise make sure that the hook implementation is available at
 * any given time.
 * Implementations of this hook must be placed in src/Hook and tagged with the
 * #[Hook('theme_suggestions_HOOK')] attribute.
 *
 * Suggestions must begin with the value of HOOK, followed by two underscores to
 * be discoverable.
@@ -749,9 +748,8 @@ function hook_theme_suggestions_alter(array &$suggestions, array &$variables, $h
 *   - node--article is invalid
 *   - article__custom_template is invalid
 *
 * Implementations of this hook must be placed in *.module or *.theme files, or
 * must otherwise make sure that the hook implementation is available at
 * any given time.
 * Implementations of this hook must be placed in src/Hook and tagged with the
 * #[Hook('theme_suggestions_HOOK_alter')] attribute.
 *
 * In the following example, we provide an alternative template suggestion to
 * node templates based on the user being logged in.
Loading