Skip to content
Snippets Groups Projects
Unverified Commit 4a70ba37 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3109480 by longwave, catch, bnjmnm, xjm, lauriii, Gábor Hojtsy:...

Issue #3109480 by longwave, catch, bnjmnm, xjm, lauriii, Gábor Hojtsy: Properly deprecate theme functions for Drupal 10
parent 6ae9811c
No related branches found
No related tags found
No related merge requests found
Showing
with 324 additions and 220 deletions
......@@ -495,6 +495,7 @@ protected function processExtension(array &$cache, $name, $type, $theme, $path)
// if the theme hook specifies a function callback instead, check to
// ensure the function actually exists.
if (isset($info['function'])) {
@trigger_error('Theme functions are deprecated in drupal:8.0.0 and are removed from drupal:10.0.0. Use Twig templates instead. See https://www.drupal.org/node/1831138', E_USER_DEPRECATED);
if (!function_exists($info['function'])) {
throw new \BadFunctionCallException(sprintf(
'Theme hook "%s" refers to a theme function callback that does not exist: "%s"',
......
......@@ -121,27 +121,9 @@ function common_test_theme() {
'common_test_render_element' => [
'render element' => 'foo',
],
'common_test_empty' => [
'variables' => ['foo' => 'foo'],
'function' => 'theme_common_test_empty',
],
];
}
/**
* Provides a theme function for drupal_render().
*/
function theme_common_test_foo($variables) {
return $variables['foo'] . $variables['bar'];
}
/**
* Always returns an empty string.
*/
function theme_common_test_empty($variables) {
return '';
}
/**
* Implements MODULE_preprocess().
*
......
......@@ -2,7 +2,7 @@
/**
* @file
* Include file for testing theme suggestion hooks.
* Include file for testing theme suggestion hooks for legacy theme functions.
*/
/**
......
name: 'Legacy theme functions suggestions test'
type: module
description: 'Support module for testing theme suggestions for legacy theme functions.'
package: Testing
version: VERSION
<?php
/**
* @file
* Support module for testing theme suggestions.
*
* @todo Remove in https://www.drupal.org/project/drupal/issues/3097889
*/
/**
* Implements hook_theme().
*/
function theme_legacy_suggestions_test_theme() {
$items['theme_suggestions_test_include'] = [
'file' => 'theme_legacy_suggestions_test.inc',
'function' => 'theme_theme_suggestions_test_include',
];
return $items;
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_legacy_suggestions_test_theme_suggestions_theme_test_function_suggestions_alter(array &$suggestions, array $variables) {
$suggestions[] = 'theme_test_function_suggestions__module_override';
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_legacy_suggestions_test_theme_suggestions_theme_test_suggestions_include_alter(array &$suggestions, array $variables, $hook) {
$suggestions[] = 'theme_suggestions_test_include';
}
<?php
namespace Drupal\theme_legacy_test;
use Drupal\Core\Controller\ControllerBase;
/**
* Controller routines for test routes for legacy theme functions.
*
* @todo Remove in https://www.drupal.org/project/drupal/issues/3097889
*/
class ThemeTestController extends ControllerBase {
/**
* A theme template that overrides a theme function.
*
* @return array
* Render array containing a theme.
*/
public function functionTemplateOverridden() {
return [
'#theme' => 'theme_test_function_template_override',
];
}
/**
* Menu callback for testing suggestion alter hooks with theme functions.
*/
public function functionSuggestionAlter() {
return ['#theme' => 'theme_test_function_suggestions'];
}
/**
* Menu callback for testing includes with suggestion alter hooks.
*/
public function suggestionAlterInclude() {
return ['#theme' => 'theme_test_suggestions_include'];
}
}
<?php
/**
* @file
* Include file for testing legacy theme functions.
*/
/**
* Returns HTML for the 'theme_test' theme hook used by tests.
*/
function theme_theme_test($variables) {
return 'Theme hook implementor=theme_theme_test(). Foo=' . $variables['foo'];
}
name: 'Legacy theme functions test'
type: module
description: 'Support module for testing legacy theme functions.'
package: Testing
version: VERSION
<?php
/**
* @file
* Test module for legacy theme functions.
*
* @todo Remove in https://www.drupal.org/project/drupal/issues/3097889
*/
/**
* Implements hook_theme().
*/
function theme_legacy_test_theme($existing, $type, $theme, $path) {
$items['theme_test'] = [
'file' => 'theme_legacy_test.inc',
'variables' => ['foo' => ''],
'function' => 'theme_theme_test',
];
$items['theme_test_function_suggestions'] = [
'variables' => [],
'function' => 'theme_theme_test_function_suggestions',
];
$items['theme_test_suggestions_include'] = [
'variables' => [],
'function' => 'theme_theme_test_suggestions_include',
];
$items['theme_test_foo'] = [
'variables' => ['foo' => NULL],
'function' => 'theme_theme_test_foo',
];
$items['theme_test_render_element_children'] = [
'render element' => 'element',
'function' => 'theme_theme_test_render_element_children',
];
$items['theme_test_function_template_override'] = [
'variables' => [],
'function' => 'theme_theme_test_function_template_override',
];
$info['test_theme_not_existing_function'] = [
'function' => 'test_theme_not_existing_function',
];
return $items;
}
/**
* Implements template_preprocess_HOOK() for theme_test_function_suggestions theme functions.
*/
function template_preprocess_theme_test_function_suggestions(&$variables) {
}
/**
* Theme function for hook theme_test_foo.
*/
function theme_theme_test_foo($variables) {
return $variables['foo'];
}
/**
* Theme function for hook theme_test_function_template_override.
*/
function theme_theme_test_function_template_override($variables) {
return 'theme_test_function_template_override test failed.';
}
/**
* Theme function for testing rendering of child elements via drupal_render().
*
* Theme hooks defining a 'render element' add an internal '#render_children'
* property. When this property is found, drupal_render() avoids calling
* the 'theme.manager' service 'render' method on the top-level element to
* prevent infinite recursion.
*
* @param array $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
*/
function theme_theme_test_render_element_children($variables) {
return \Drupal::service('renderer')->render($variables['element']);
}
/**
* Returns HTML for a theme function suggestion test.
*/
function theme_theme_test_function_suggestions($variables) {
return 'Original theme function.';
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function theme_legacy_test_theme_suggestions_theme_test_suggestion_provided(array $variables) {
return ['theme_test_suggestion_provided__foo'];
}
/**
* Implements hook_theme_suggestions_alter().
*/
function theme_legacy_test_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
\Drupal::messenger()
->addStatus(__FUNCTION__ . '() executed for ' . $hook . '.');
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_legacy_test_theme_suggestions_theme_test_suggestions_alter(array &$suggestions, array $variables) {
\Drupal::messenger()->addStatus(__FUNCTION__ . '() executed.');
}
/**
* Returns HTML for a theme function include test.
*/
function theme_theme_test_suggestions_include($variables) {
return 'Original function before altering theme suggestions.';
}
theme_test.function_template_override:
path: '/theme-test/function-template-overridden'
options:
_custom_theme: 'test_theme'
defaults:
_controller: '\Drupal\theme_legacy_test\ThemeTestController::functionTemplateOverridden'
requirements:
_access: 'TRUE'
function_suggestion_alter:
path: '/theme-test/function-suggestion-alter'
defaults:
_controller: '\Drupal\theme_legacy_test\ThemeTestController::functionSuggestionAlter'
requirements:
_access: 'TRUE'
suggestion_alter_include:
path: '/theme-test/suggestion-alter-include'
defaults:
_controller: '\Drupal\theme_legacy_test\ThemeTestController::suggestionAlterInclude'
requirements:
_access: 'TRUE'
......@@ -5,18 +5,6 @@
* Support module for testing theme suggestions.
*/
/**
* Implements hook_theme().
*/
function theme_suggestions_test_theme() {
$items['theme_suggestions_test_include'] = [
'file' => 'theme_suggestions_test.inc',
'variables' => [],
'function' => 'theme_theme_suggestions_test_include',
];
return $items;
}
/**
* Implements hook_theme_suggestions_alter().
*/
......@@ -35,23 +23,9 @@ function theme_suggestions_test_theme_suggestions_theme_test_suggestions_alter(a
$suggestions[] = 'theme_test_suggestions__module_override';
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_suggestions_test_theme_suggestions_theme_test_function_suggestions_alter(array &$suggestions, array $variables) {
$suggestions[] = 'theme_test_function_suggestions__module_override';
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_suggestions_test_theme_suggestions_theme_test_specific_suggestions_alter(array &$suggestions, array $variables) {
$suggestions[] = 'theme_test_specific_suggestions__variant__foo';
}
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function theme_suggestions_test_theme_suggestions_theme_test_suggestions_include_alter(array &$suggestions, array $variables, $hook) {
$suggestions[] = 'theme_suggestions_test_include';
}
......@@ -10,18 +10,6 @@
*/
class ThemeTestController extends ControllerBase {
/**
* A theme template that overrides a theme function.
*
* @return array
* Render array containing a theme.
*/
public function functionTemplateOverridden() {
return [
'#theme' => 'theme_test_function_template_override',
];
}
/**
* Adds stylesheets to test theme .info.yml property processing.
*
......@@ -112,20 +100,6 @@ public function specificSuggestionAlter() {
return ['#theme' => 'theme_test_specific_suggestions__variant'];
}
/**
* Menu callback for testing suggestion alter hooks with theme functions.
*/
public function functionSuggestionAlter() {
return ['#theme' => 'theme_test_function_suggestions'];
}
/**
* Menu callback for testing includes with suggestion alter hooks.
*/
public function suggestionAlterInclude() {
return ['#theme' => 'theme_test_suggestions_include'];
}
/**
* Controller to ensure that no theme is initialized.
*
......
{# Output for Theme API test #}
{{ foo -}}
{# Output for Theme API test #}
{{ element -}}
......@@ -5,13 +5,6 @@
* Include file for test module.
*/
/**
* Returns HTML for the 'theme_test' theme hook used by tests.
*/
function theme_theme_test($variables) {
return 'Theme hook implementor=theme_theme_test(). Foo=' . $variables['foo'];
}
/**
* Preprocesses variables for theme_theme_test().
*/
......
......@@ -14,7 +14,6 @@ function theme_test_theme($existing, $type, $theme, $path) {
$items['theme_test'] = [
'file' => 'theme_test.inc',
'variables' => ['foo' => ''],
'function' => 'theme_theme_test',
];
$items['theme_test_template_test'] = [
'template' => 'theme_test.template_test',
......@@ -34,31 +33,14 @@ function theme_test_theme($existing, $type, $theme, $path) {
$items['theme_test_general_suggestions'] = [
'variables' => [],
];
$items['theme_test_function_suggestions'] = [
'variables' => [],
'function' => 'theme_theme_test_function_suggestions',
];
$items['theme_test_suggestions_include'] = [
'variables' => [],
'function' => 'theme_theme_test_suggestions_include',
];
$items['theme_test_foo'] = [
'variables' => ['foo' => NULL],
'function' => 'theme_theme_test_foo',
];
$items['theme_test_render_element'] = [
'render element' => 'elements',
];
$items['theme_test_render_element_children'] = [
'render element' => 'element',
'function' => 'theme_theme_test_render_element_children',
];
$items['theme_test_function_template_override'] = [
'variables' => [],
'function' => 'theme_theme_test_function_template_override',
];
$info['test_theme_not_existing_function'] = [
'function' => 'test_theme_not_existing_function',
];
$items['theme_test_preprocess_suggestions'] = [
'variables' => [
......@@ -95,26 +77,6 @@ function theme_test_page_bottom(array &$page_bottom) {
$page_bottom['theme_test_page_bottom'] = ['#markup' => 'theme test page bottom markup'];
}
/**
* Implements template_preprocess_HOOK() for theme_test_function_suggestions theme functions.
*/
function template_preprocess_theme_test_function_suggestions(&$variables) {
}
/**
* Theme function for hook theme_test_foo.
*/
function theme_theme_test_foo($variables) {
return $variables['foo'];
}
/**
* Theme function for hook theme_test_function_template_override.
*/
function theme_theme_test_function_template_override($variables) {
return 'theme_test_function_template_override test failed.';
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
......@@ -149,29 +111,6 @@ function template_preprocess_theme_test_render_element(&$variables) {
$variables['attributes']['data-variables-are-preprocessed'] = TRUE;
}
/**
* Theme function for testing rendering of child elements via drupal_render().
*
* Theme hooks defining a 'render element' add an internal '#render_children'
* property. When this property is found, drupal_render() avoids calling
* the 'theme.manager' service 'render' method on the top-level element to
* prevent infinite recursion.
*
* @param array $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
*/
function theme_theme_test_render_element_children($variables) {
return \Drupal::service('renderer')->render($variables['element']);
}
/**
* Returns HTML for a theme function suggestion test.
*/
function theme_theme_test_function_suggestions($variables) {
return 'Original theme function.';
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
......@@ -193,13 +132,6 @@ function theme_test_theme_suggestions_theme_test_suggestions_alter(array &$sugge
\Drupal::messenger()->addStatus(__FUNCTION__ . '() executed.');
}
/**
* Returns HTML for a theme function include test.
*/
function theme_theme_test_suggestions_include($variables) {
return 'Original function before altering theme suggestions.';
}
/**
* Implements hook_system_info_alter().
*
......
theme_test.function_template_override:
path: '/theme-test/function-template-overridden'
options:
_custom_theme: 'test_theme'
defaults:
_controller: '\Drupal\theme_test\ThemeTestController::functionTemplateOverridden'
requirements:
_access: 'TRUE'
theme_test.info_stylesheets:
path: '/theme-test/info/stylesheets'
defaults:
......@@ -83,20 +74,6 @@ specific_suggestion_alter:
requirements:
_access: 'TRUE'
function_suggestion_alter:
path: '/theme-test/function-suggestion-alter'
defaults:
_controller: '\Drupal\theme_test\ThemeTestController::functionSuggestionAlter'
requirements:
_access: 'TRUE'
suggestion_alter_include:
path: '/theme-test/suggestion-alter-include'
defaults:
_controller: '\Drupal\theme_test\ThemeTestController::suggestionAlterInclude'
requirements:
_access: 'TRUE'
theme_test.non_html:
path: '/theme-test/non-html'
defaults:
......
<?php
namespace Drupal\Tests\system\Functional\Theme;
use Drupal\Tests\BrowserTestBase;
/**
* Tests legacy theme functions.
*
* @group Theme
* @group legacy
*
* @todo Remove in https://www.drupal.org/project/drupal/issues/3097889
*/
class ThemeLegacyTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['theme_test', 'theme_legacy_test'];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
protected function setUp() {
parent::setUp();
\Drupal::service('theme_installer')->install(['test_legacy_theme']);
}
/**
* Ensures a theme template can override a theme function.
*/
public function testFunctionOverride() {
$this->drupalGet('theme-test/function-template-overridden');
$this->assertText('Success: Template overrides theme function.', 'Theme function overridden by test_theme template.');
}
/**
* Tests that theme suggestion alter hooks work for theme functions.
*/
public function testThemeFunctionSuggestionsAlter() {
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Original theme function.');
// Install test_theme and test that themes can alter theme suggestions.
$this->config('system.theme')
->set('default', 'test_legacy_theme')
->save();
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Theme function overridden based on new theme suggestion provided by the test_legacy_theme theme.');
// Enable the theme_suggestions_test module to test modules implementing
// suggestions alter hooks.
\Drupal::service('module_installer')->install(['theme_legacy_suggestions_test']);
$this->resetAll();
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Theme function overridden based on new theme suggestion provided by a module.');
}
/**
* Tests that theme suggestion alter hooks work with theme hook includes.
*/
public function testSuggestionsAlterInclude() {
// Check the original theme output.
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Original function before altering theme suggestions.');
// Enable theme_suggestions_test module and make two requests to make sure
// the include file is always loaded. The file will always be included for
// the first request because the theme registry is being rebuilt.
\Drupal::service('module_installer')->install(['theme_legacy_suggestions_test']);
$this->resetAll();
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Function suggested via suggestion alter hook found in include file.', 'Include file loaded for initial request.');
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Function suggested via suggestion alter hook found in include file.', 'Include file loaded for second request.');
}
}
......@@ -116,47 +116,6 @@ public function testSpecificSuggestionsAlter() {
$this->assertTrue(strpos($raw_content, 'theme_test_specific_suggestions__variant') < strpos($raw_content, 'theme_test_specific_suggestions__variant__foo'), 'Specific theme call is added to the suggestions array before the suggestions alter hook.');
}
/**
* Tests that theme suggestion alter hooks work for theme functions.
*/
public function testThemeFunctionSuggestionsAlter() {
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Original theme function.');
// Install test_theme and test that themes can alter theme suggestions.
$this->config('system.theme')
->set('default', 'test_theme')
->save();
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Theme function overridden based on new theme suggestion provided by the test_theme theme.');
// Enable the theme_suggestions_test module to test modules implementing
// suggestions alter hooks.
\Drupal::service('module_installer')->install(['theme_suggestions_test']);
$this->resetAll();
$this->drupalGet('theme-test/function-suggestion-alter');
$this->assertText('Theme function overridden based on new theme suggestion provided by a module.');
}
/**
* Tests that theme suggestion alter hooks work with theme hook includes.
*/
public function testSuggestionsAlterInclude() {
// Check the original theme output.
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Original function before altering theme suggestions.');
// Enable theme_suggestions_test module and make two requests to make sure
// the include file is always loaded. The file will always be included for
// the first request because the theme registry is being rebuilt.
\Drupal::service('module_installer')->install(['theme_suggestions_test']);
$this->resetAll();
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Function suggested via suggestion alter hook found in include file.', 'Include file loaded for initial request.');
$this->drupalGet('theme-test/suggestion-alter-include');
$this->assertText('Function suggested via suggestion alter hook found in include file.', 'Include file loaded for second request.');
}
/**
* Tests execution order of theme suggestion alter hooks.
*
......
......@@ -45,7 +45,7 @@ public function testPreprocessForSuggestions() {
drupal_theme_rebuild();
for ($i = 0; $i < 2; $i++) {
$this->drupalGet('theme-test/suggestion');
$this->assertText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
$this->assertText('Theme hook implementor=theme-test--suggestion.html.twig. Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
}
}
......@@ -56,7 +56,7 @@ public function testNegotiatorPriorities() {
$this->drupalGet('theme-test/priority');
// Ensure that the custom theme negotiator was not able to set the theme.
$this->assertNoText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
$this->assertNoText('Theme hook implementor=theme-test--suggestion.html.twig. Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.');
}
/**
......@@ -141,14 +141,6 @@ public function testTemplateOverride() {
$this->assertText('Success: Template overridden.', 'Template overridden by defined \'template\' filename.');
}
/**
* Ensures a theme template can override a theme function.
*/
public function testFunctionOverride() {
$this->drupalGet('theme-test/function-template-overridden');
$this->assertText('Success: Template overrides theme function.', 'Theme function overridden by test_theme template.');
}
/**
* Tests that the page variable is not prematurely flattened.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment