From 07298d66e40f0ade1d63e05129826d710f228773 Mon Sep 17 00:00:00 2001 From: Dries <dries@buytaert.net> Date: Fri, 16 Aug 2013 14:49:18 -0500 Subject: [PATCH] Issue #1911492 by jibran, Manuel Garcia, derhasi, pcambra, dawehner, damiankloip: Fixed Views try to find Custom StylePlugin template in core/modules/views/templates. --- .../block/Plugin/views/display/Block.php | 1 + .../Drupal/comment/Plugin/views/row/Rss.php | 1 + .../Plugin/views/display/EntityReference.php | 1 + .../Plugin/views/row/EntityReference.php | 1 + .../Plugin/views/style/EntityReference.php | 1 + .../lib/Drupal/node/Plugin/views/row/Rss.php | 1 + .../Drupal/views/Plugin/views/PluginBase.php | 23 ++++++++ .../lib/Drupal/views/Tests/ModuleTest.php | 2 +- .../Drupal/views/Tests/ViewsTemplateTest.php | 55 +++++++++++++++++++ .../views.view.test_view_display_template.yml | 46 ++++++++++++++++ .../views/display/DisplayNoAreaTest.php | 1 + .../Plugin/views/display/DisplayTest.php | 1 + .../Plugin/views/row/RowTest.php | 1 + .../Plugin/views/style/MappingTest.php | 1 + .../Plugin/views/style/StyleTemplateTest.php | 37 +++++++++++++ .../Plugin/views/style/StyleTest.php | 1 + .../views-view-mapping-test.html.twig | 17 ++++++ .../views-view-style-template-test.html.twig | 7 +++ core/modules/views/views.module | 45 +++++++++++---- 19 files changed, 230 insertions(+), 13 deletions(-) create mode 100644 core/modules/views/lib/Drupal/views/Tests/ViewsTemplateTest.php create mode 100644 core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_display_template.yml create mode 100644 core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTemplateTest.php create mode 100644 core/modules/views/tests/modules/views_test_data/templates/views-view-mapping-test.html.twig create mode 100644 core/modules/views/tests/modules/views_test_data/templates/views-view-style-template-test.html.twig diff --git a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php index 43198783660a..bf3dca4b1c3d 100644 --- a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php +++ b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php @@ -24,6 +24,7 @@ * title = @Translation("Block"), * help = @Translation("Display the view as a block."), * theme = "views_view", + * register_theme = FALSE, * uses_hook_block = TRUE, * contextual_links_locations = {"block"}, * admin = @Translation("Block") diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/row/Rss.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/row/Rss.php index 6cc187c52eec..ffd4968e61ab 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/row/Rss.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/row/Rss.php @@ -20,6 +20,7 @@ * title = @Translation("Comment"), * help = @Translation("Display the comment as RSS."), * theme = "views_view_row_rss", + * register_theme = FALSE, * base = {"comment"}, * display_types = {"feed"} * ) diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php index fc46aa60897a..0bd74943c2eb 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php @@ -26,6 +26,7 @@ * admin = @Translation("Entity Reference Source"), * help = @Translation("Selects referenceable entities for an entity reference field."), * theme = "views_view", + * register_theme = FALSE, * uses_hook_menu = FALSE, * entity_reference_display = TRUE * ) diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php index 069689604325..f2d7aa9d4de9 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php @@ -21,6 +21,7 @@ * title = @Translation("Entity Reference inline fields"), * help = @Translation("Displays the fields with an optional template."), * theme = "views_view_fields", + * register_theme = FALSE, * display_types = {"entity_reference"} * ) */ diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php index c6068562a0a9..75f6877d3881 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php @@ -21,6 +21,7 @@ * title = @Translation("Entity Reference list"), * help = @Translation("Returns results as a PHP array of labels and rendered rows."), * theme = "views_view_unformatted", + * register_theme = FALSE, * display_types = {"entity_reference"} * ) */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php b/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php index 9d73565c8f31..124f0bb7337c 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php @@ -20,6 +20,7 @@ * title = @Translation("Content"), * help = @Translation("Display the content with standard node view."), * theme = "views_view_row_rss", + * register_theme = FALSE, * base = {"node"}, * display_types = {"feed"}, * module = "node" diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php index 285f53a60a9c..df65cc5e25e0 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php @@ -13,6 +13,29 @@ use Drupal\views\ViewExecutable; use Symfony\Component\DependencyInjection\ContainerInterface; +/** + * Base class for any views plugin types. + * + * Via the @Plugin definition the plugin may specify a theme function or + * template to be used for the plugin. It also can auto-register the theme + * implementation for that file or function. + * - theme: the theme implementation to use in the plugin. This may be the name + * of the function (without theme_ prefix) or the template file (without + * template engine extension). + * If a template file should be used, the file has to be placed in the + * module's templates folder. + * Example: theme = "mymodule_row" of module "mymodule" will implement either + * theme_mymodule_row() or mymodule-row.tpl.php in the + * [..]/modules/mymodule/templates folder. + * - register_theme: (optional) When set to TRUE (default) the theme is + * registered automatically. When set to FALSE the plugin reuses an existing + * theme implementation, defined by another module or views plugin. + * - theme_file: (optional) the location of an include file that may hold the + * theme or preprocess function. The location has to be relative to module's + * root directory. + * - module: machine name of the module. It must be present for any plugin that + * wants to register a theme. + */ abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php index 925294c17049..87dc3a59cf61 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php @@ -247,7 +247,7 @@ public function testViewsFetchPluginNames() { // Test using the 'test' style plugin type only returns the test_style and // mapping_test plugins. $plugins = views_fetch_plugin_names('style', 'test'); - $this->assertIdentical(array_keys($plugins), array('mapping_test', 'test_style')); + $this->assertIdentical(array_keys($plugins), array('mapping_test', 'test_style', 'test_template_style')); // Test a non existent style plugin type returns no plugins. $plugins = views_fetch_plugin_names('style', $this->randomString()); diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewsTemplateTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewsTemplateTest.php new file mode 100644 index 000000000000..f6be8770bfab --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Tests/ViewsTemplateTest.php @@ -0,0 +1,55 @@ +<?php + +/** + * @file + * Contains \Drupal\views\Tests\ViewsTemplateTest. + */ + +namespace Drupal\views\Tests; + +use Drupal\views\Tests\ViewTestBase; +use Drupal\views\Views; + +/** + * Tests the views custom templates. + * + * @see Drupal\views_test_data\Plugin\views\style\StyleTemplateTest + */ +class ViewsTemplateTest extends ViewTestBase { + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = array('test_view_display_template'); + + public static function getInfo() { + return array( + 'name' => 'View template tests', + 'description' => 'Tests the template retrieval of views.', + 'group' => 'Views' + ); + } + + protected function setUp() { + parent::setUp(); + + $this->enableViewsTestModule(); + } + + /** + * Tests render functionality. + */ + public function testTemplate() { + + // Make sure that the rendering just calls the preprocess function once. + $view = Views::getView('test_view_display_template'); + $output = $view->preview(); + + // Check if we got the rendered output of our template file. + $this->assertTrue(strpos(drupal_render($output), 'This module defines its own display template.') !== FALSE, 'Display plugin DisplayTemplateTest defines its own template.'); + + } + +} diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_display_template.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_display_template.yml new file mode 100644 index 000000000000..f005f0075297 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_display_template.yml @@ -0,0 +1,46 @@ +base_field: id +base_table: views_test_data +core: 8.x +description: '' +status: '1' +display: + default: + display_plugin: default + id: default + display_title: Master + position: '1' + display_options: + access: { } + cache: { } + query: { } + pager: { } + style: + type: test_template_style + row: + type: fields + options: { } + fields: + id: + id: id + table: views_test_data + field: id + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '0' + alter: { } + provider: views_test_config + filters: { } + sorts: { } + header: { } + footer: { } + empty: { } + relationships: { } + arguments: { } +label: test_view_display_template +module: views +id: test_view_display_template +tag: '' +uuid: a8e37ebf-573e-4cb9-83f5-a259f12bdc7a +langcode: en diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayNoAreaTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayNoAreaTest.php index bc208497c85f..1adab692faf1 100644 --- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayNoAreaTest.php +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayNoAreaTest.php @@ -17,6 +17,7 @@ * id = "display_no_area_test", * title = @Translation("Display test no area"), * theme = "views_view", + * register_theme = FALSE, * contextual_links_locations = {"view"} * ) */ diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayTest.php index 83a4336af42e..7f35dafb17e8 100644 --- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayTest.php +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/display/DisplayTest.php @@ -18,6 +18,7 @@ * id = "display_test", * title = @Translation("Display test"), * theme = "views_view", + * register_theme = FALSE, * contextual_links_locations = {"view"} * ) */ diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/row/RowTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/row/RowTest.php index d6dedf9dcad0..400ccc32464d 100644 --- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/row/RowTest.php +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/row/RowTest.php @@ -21,6 +21,7 @@ * title = @Translation("Test row plugin"), * help = @Translation("Provides a generic row test plugin."), * theme = "views_view_row_test", + * module = "views_test_data", * display_types = {"normal", "test"} * ) */ diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/MappingTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/MappingTest.php index 3a4e4865fadd..4dc3ea85f51c 100644 --- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/MappingTest.php +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/MappingTest.php @@ -22,6 +22,7 @@ * title = @Translation("Field mapping"), * help = @Translation("Maps specific fields to specific purposes."), * theme = "views_view_mapping_test", + * module = "views_test_data", * display_types = {"normal", "test"} * ) */ diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTemplateTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTemplateTest.php new file mode 100644 index 000000000000..df7547acebfa --- /dev/null +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTemplateTest.php @@ -0,0 +1,37 @@ +<?php + +/** + * @file + * Definition of Drupal\views_test_data\Plugin\views\style\StyleTemplateTest. + */ + +namespace Drupal\views_test_data\Plugin\views\style; + +use Drupal\Component\Annotation\Plugin; +use Drupal\Core\Annotation\Translation; +use Drupal\views\Plugin\views\style\StylePluginBase; + +/** + * Provides a general test style template plugin. + * + * @ingroup views_style_plugins + * + * @Plugin( + * id = "test_template_style", + * module = "views_test_data", + * title = @Translation("Test style template plugin"), + * help = @Translation("Provides a generic style template test plugin."), + * theme = "views_view_style_template_test", + * display_types = {"normal", "test"} + * ) + */ +class StyleTemplateTest extends StylePluginBase { + + /** + * Can the style plugin use row plugins. + * + * @var bool + */ + protected $usesRowPlugin = TRUE; + +} diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php index 26a31121057d..b6fc20a83542 100644 --- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php +++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php @@ -21,6 +21,7 @@ * title = @Translation("Test style plugin"), * help = @Translation("Provides a generic style test plugin."), * theme = "views_view_style_test", + * register_theme = FALSE, * display_types = {"normal", "test"} * ) */ diff --git a/core/modules/views/tests/modules/views_test_data/templates/views-view-mapping-test.html.twig b/core/modules/views/tests/modules/views_test_data/templates/views-view-mapping-test.html.twig new file mode 100644 index 000000000000..8d30f81e93ea --- /dev/null +++ b/core/modules/views/tests/modules/views_test_data/templates/views-view-mapping-test.html.twig @@ -0,0 +1,17 @@ +{# +/** + * @file + * Default theme implementation to display a view of mapping_test rows. + * + * Available variables: + * - rows: A list of view rows. + * - options: Various view options, including the row style mapping. + * - view: The view object. + * - element: Render array of views rows. + * + * @see template_preprocess_views_view_mapping_test() + * + * @ingroup themeable + */ +#} +{{ element }} diff --git a/core/modules/views/tests/modules/views_test_data/templates/views-view-style-template-test.html.twig b/core/modules/views/tests/modules/views_test_data/templates/views-view-style-template-test.html.twig new file mode 100644 index 000000000000..f065ee1a8c43 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_data/templates/views-view-style-template-test.html.twig @@ -0,0 +1,7 @@ +{# +/** + * @file + * Views template test template to test the module defined templates. + */ +#} +This module defines its own display template. diff --git a/core/modules/views/views.module b/core/modules/views/views.module index cbb04b26952c..81b3e5962f45 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -78,7 +78,10 @@ function views_pre_render_view_element($element) { } /** - * Implement hook_theme(). Register views theming functions. + * Implements hook_theme(). + * + * Register views theming functions and those that are defined via views plugin + * definitions. */ function views_theme($existing, $type, $theme, $path) { Drupal::moduleHandler()->loadInclude('views', 'inc', 'views.theme'); @@ -118,7 +121,10 @@ function views_theme($existing, $type, $theme, $path) { $plugins = views_get_plugin_definitions(); - // Register theme functions for all style plugins + // Register theme functions for all style plugins. It provides a basic auto + // implementation of theme functions or template files by using the plugin + // definitions (theme, theme_file, module, register_theme). Template files are + // assumed to be located in the templates folder. foreach ($plugins as $type => $info) { foreach ($info as $def) { // Not all plugins have theme functions, and they can also explicitly @@ -126,32 +132,47 @@ function views_theme($existing, $type, $theme, $path) { if (!isset($def['theme']) || empty($def['register_theme'])) { continue; } + // For each theme registration we a base directory to look for the + // templates folder. This will be in any case the root of the given module + // so we always need a module definition. + // @todo: watchdog or exception? + if (!isset($def['provider'])) { + continue; + } $hooks[$def['theme']] = array( 'variables' => $variables[$type], ); - if ($def['module'] == 'views') { + // For the views module we ensure views.theme.inc is included. + if ($def['provider'] == 'views') { $def['theme_file'] = 'views.theme.inc'; } - elseif (isset($def['theme_file'])) { - $def['theme_path'] = drupal_get_path('module', $def['module']); - } + // We always use the module directory as base dir. + $module_dir = drupal_get_path('module', $def['provider']); - if (isset($def['theme_path'])) { - $hooks[$def['theme']]['path'] = $def['theme_path']; - } + // The theme_file definition is always relative to the modules directory. if (isset($def['theme_file'])) { + $hooks[$def['theme']]['path'] = $module_dir; $hooks[$def['theme']]['file'] = $def['theme_file']; } - if (isset($def['theme_path']) && isset($def['theme_file'])) { - $include = DRUPAL_ROOT . '/' . $def['theme_path'] . '/' . $def['theme_file']; + // Whenever we got a theme file, we include it directly so we can + // auto-detect the theme function. + if (isset($def['theme_file'])) { + $include = DRUPAL_ROOT . '/' . $module_dir. '/' . $def['theme_file']; if (is_file($include)) { require_once $include; } } + // If there is no theme function for the given theme definition, we assume + // a template file shall be used. By default this file is located in the + // /templates directory of the module's folder. + // If a module wants to define its own location it has to set + // register_theme of the plugin to FALSE and implement hook_theme() by + // itself. if (!function_exists('theme_' . $def['theme'])) { - $hooks[$def['theme']]['template'] = drupal_clean_css_identifier($def['theme']); + $hooks[$def['theme']]['path'] = $module_dir; + $hooks[$def['theme']]['template'] = 'templates/' . drupal_clean_css_identifier($def['theme']); } } } -- GitLab