Skip to content

Instantly share code, notes, and snippets.

@ahebrank
Created December 7, 2016 17:50
Show Gist options
  • Save ahebrank/e6af5f525677f56434e81f5167004952 to your computer and use it in GitHub Desktop.
Save ahebrank/e6af5f525677f56434e81f5167004952 to your computer and use it in GitHub Desktop.
Bring d.o eva 8.x branch up to working head
diff --git a/README.txt b/README.txt
old mode 100755
new mode 100644
index d2bdcba..27e73b6
--- a/README.txt
+++ b/README.txt
@@ -39,8 +39,7 @@ ourselves.
REQUIREMENTS
-- Drupal 7
-- Views 3
+- Drupal 8
AUTHOR AND CREDIT
@@ -49,4 +48,6 @@ Original development: Jeff Eaton "eaton" (http://drupal.org/user/16496)
Actual D6 release, and version 2.0: Larry Garfield "Crell"
(http://drupal.org/user/26398)
-D7 port and tomfoolery: Jeff Eaton "eaton" (http://drupal.org/user/16496)
\ No newline at end of file
+D7 port and tomfoolery: Jeff Eaton "eaton" (http://drupal.org/user/16496)
+
+D8 port started by Mike Kadin "mkadin" (https://www.drupal.org/u/mkadin) and rounded out by Andy Hebrank "ahebrank" (https://www.drupal.org/u/ahebrank)
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..8bb6230
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+ "name": "drupal/eva",
+ "type": "drupal-module",
+ "description": "Attach a view to an entity"
+}
diff --git a/eva-display-entity-view.tpl.php b/eva-display-entity-view.tpl.php
deleted file mode 100755
index e661ad1..0000000
--- a/eva-display-entity-view.tpl.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * @file eva-display-entity-view.tpl.php
- * Entity content view template
- *
- * Variables available:
- * - $classes_array: An array of classes determined in
- * template_preprocess_views_view(). Default classes are:
- * .view
- * .view-[css_name]
- * .view-id-[view_name]
- * .view-display-id-[display_name]
- * .view-dom-id-[dom_id]
- * - $classes: A string version of $classes_array for use in the class attribute
- * - $css_name: A css-safe version of the view name.
- * - $css_class: The user-specified classes names, if any
- * - $header: The view header
- * - $footer: The view footer
- * - $rows: The results of the view query, if any
- * - $empty: The empty text to display if the view is empty
- * - $pager: The pager next/prev links to display, if any
- * - $exposed: Exposed widget form/info to display
- * - $feed_icon: Feed icon to display, if any
- * - $more: A link to view more, if any
- *
- * @ingroup views_templates
- */
-?>
-<div class="<?php print $classes; ?>">
- <?php print render($title_prefix); ?>
- <?php if ($title): ?>
- <h2 class="title"><?php print $title; ?></h2>
- <?php endif; ?>
- <?php print render($title_suffix); ?>
-
- <?php if ($header): ?>
- <div class="view-header">
- <?php print $header; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($exposed && !$exposed_form_as_field): ?>
- <div class="view-filters">
- <?php print $exposed; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($attachment_before): ?>
- <div class="attachment attachment-before">
- <?php print $attachment_before; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($rows): ?>
- <div class="view-content">
- <?php print $rows; ?>
- </div>
- <?php elseif ($empty): ?>
- <div class="view-empty">
- <?php print $empty; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($pager): ?>
- <?php print $pager; ?>
- <?php endif; ?>
-
- <?php if ($attachment_after): ?>
- <div class="attachment attachment-after">
- <?php print $attachment_after; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($more): ?>
- <?php print $more; ?>
- <?php endif; ?>
-
- <?php if ($footer): ?>
- <div class="view-footer">
- <?php print $footer; ?>
- </div>
- <?php endif; ?>
-
- <?php if ($feed_icon): ?>
- <div class="feed-icon">
- <?php print $feed_icon; ?>
- </div>
- <?php endif; ?>
-
-</div> <?php /* class view */ ?>
diff --git a/eva.info.yml b/eva.info.yml
old mode 100755
new mode 100644
index eda4dd5..bc65d48
--- a/eva.info.yml
+++ b/eva.info.yml
@@ -1,8 +1,7 @@
name: Eva
description: Provides a Views display type that can be attached to entities.
core: 8.x
+type: module
dependencies:
- views
package: Views
-files:
- - eva_plugin_display_entity.inc
diff --git a/eva.module b/eva.module
old mode 100755
new mode 100644
index ac8a55e..c2cf08d
--- a/eva.module
+++ b/eva.module
@@ -1,44 +1,37 @@
<?php
-// Load theme functions
-module_load_include('inc', 'eva', 'eva.theme');
-
/**
- * Implements hook_views_api().
+ * @file
+ * Module implementing EVA extra field and views display
*/
-function eva_views_api() {
- return array(
- 'api' => 3,
- );
-}
+
+use Drupal\views\Views;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Component\Utility\Xss;
/**
- * Implements hook_field_extra_fields().
+ * Implements hook_entity_extra_field_info() to add the view fields to relevant entities
*/
-function eva_field_extra_fields() {
- $extras = array();
+function eva_entity_extra_field_info() {
+ $extra = array();
$views = eva_get_views();
-
- //exit("<pre>" . var_export($views, TRUE) . "</pre>");
-
+
foreach ($views as $entity => $data) {
foreach ($data as $view) {
- if ($view['bundles']) {
- $bundles = $view['bundles'];
- }
- else { // If no bundles are set, apply to all bundles.
- $bundles = array_keys(entity_get_bundles($entity));
- }
+ // if no bundles are set, apply to all bundles
+ // per current 7.x behavior (http://cgit.drupalcode.org/eva/tree/eva.module#n25)
+ $bundles = !empty($view['bundles'])? $view['bundles'] : array_keys(\Drupal::service('entity_type.bundle.info')->getBundleInfo($entity));
foreach ($bundles as $bundle) {
- $extras[$entity][$bundle]['display'][$view['id'] . '_' . $view['display']] = array(
- 'label' => (empty($view['title'])) ? $view['id'] : $view['title'],
- 'description' => $view['title'],
+ $extra[$entity][$bundle]['display'][$view['name'] . '_' . $view['display']] = array(
+ 'label' => (empty($view['title'])) ? $view['name'] : $view['title'],
+ 'description' => $view['title'],
'weight' => 10,
);
// Provide a separate extra field for the exposed form if there is any.
- if (!empty($view['exposed form']) && !empty($view['exposed form split'])) {
- $extras[$entity][$bundle]['display'][$view['name'] . '_' . $view['display'] . '_' . 'form'] = array(
- 'label' => ((empty($view['title'])) ? $view['name'] : $view['title']) . ' (' . t('Exposed form') . ')',
+ if ($view['uses exposed']) {
+ $extra[$entity][$bundle]['display'][$view['name'] . '_' . $view['display'] . '_' . 'form'] = array(
+ 'label' => ((empty($view['title'])) ? $view['name'] : $view['title']) . ' (' . t('Exposed form') . ')',
'description' => t('The exposed filter form of the view.'),
'weight' => 9,
);
@@ -47,57 +40,9 @@ function eva_field_extra_fields() {
}
}
- return $extras;
+ return $extra;
}
-/**
- * Implements hook_entity_view_alter().
- *
- * This is a terrible, terrible hack that should not be necessary; taxonomy and
- * some other entity types use fields, but don't implement hook_entity_view().
- * We have to ALTER those entity types after they're built. For the time being,
- * we'll use a list of special cases to trigger this special handling.
- */
-function eva_entity_view_alter(&$build, $type) {
- $view_mode = $build['#view_mode'];
- $language = $build['#language'];
-
- $entity_data = entity_get_info($type);
- $entity = _eva_extract_entity_from_build($build);
-
- $entity_ids = entity_extract_ids($type, $entity);
- $settings = field_view_mode_settings($type, $entity_ids[2]);
- $fields = field_extra_fields_get_display($type, $entity_ids[2], $view_mode);
- $views = eva_get_views($type);
-
- foreach ($views as $info) {
- $longname = $info['name'] . '_' . $info['display'];
- if (isset($fields[$longname]) && $fields[$longname]['visible']) {
- if ($view = views_get_view($info['name'])) {
- $view->set_display($info['display']);
- if ($view->access($info['display'])) {
- $view->current_entity = $entity;
-
- if (isset($fields[$longname . '_form']) && $fields[$longname . '_form']['visible']) {
- $view->init_handlers();
- $exposed_form = $view->display_handler->get_plugin('exposed_form');
-
- $build[$longname . '_form'] = array(
- '#markup' => $exposed_form->render_exposed_form(TRUE),
- );
- }
- $result = $view->execute_display($info['display']);
- if (!empty($result)) {
- $build[$longname] = array(
- '#markup' => $result,
- '#weight' => $fields[$longname]['weight'],
- );
- }
- }
- }
- }
- }
-}
/**
* Get a list of views and displays attached to speficic entities.
@@ -114,71 +59,73 @@ function eva_entity_view_alter(&$build, $type) {
* An array of view name/display name values, or an empty array().
*/
function eva_get_views($type = NULL, $reset = FALSE) {
- $used_views = &drupal_static(__FUNCTION__);
-
// Build and cache the data, both in the DB and statically.
- $views = views_get_applicable_views('uses_hook_entity_view');
+ $views = Views::getApplicableViews('uses_hook_entity_view');
+
+ $used_views = array();
foreach ($views as $data) {
- list($view, $display_id) = $data;
+ list($view_name, $display_id) = $data;
+ $view = Views::getView($view_name);
+
// Initialize handlers, to determine if the view uses exposed filters.
+ $view->setDisplay($display_id);
$view->initHandlers();
- $view_entity = $view->display_handler->getOption('entity_type');
- debug($view->display_handler->getOption('entity_type'));
+ $display = $view->display_handler;
+
+ $view_entity = $display->getOption('entity_type');
$used_views[$view_entity][] = array(
+ 'name' => $view_name,
'id' => $view->storage->get('id'),
- 'title' => 'EVA: ' . $view->storage->get('human_name') . ' - ',
+ 'title' => 'EVA: ' . $view->storage->get('label') . ' - ' . $view->storage->getDisplay($display_id)['display_title'],
'display' => $display_id,
- 'bundles' => $view->display_handler->getOption('bundles'),
- 'exposed form' => $view->display_handler->usesExposed(),
- 'exposed form split' => $view->display_handler->getOption('exposed_form_as_field'),
+ 'bundles' => $display->getOption('bundles'),
+ 'uses exposed' => $display->usesExposed(),
);
$view->destroy();
}
- // Now spit back the data.
- if (isset($type) & isset($used_views)) {
+
+ if (!is_null($type)) {
return isset($used_views[$type]) ? $used_views[$type] : array();
}
- else {
- return isset($used_views) ? $used_views : array();
- }
+ return $used_views;
}
/**
- * Extract an actual entity object from its $build array.
- *
- * This is a bit more complicated than it should be, since core entities, contrib
- * entities, and contrib entities based on EntityAPI all store their junk in
- * different slots of the build array. See http://drupal.org/node/1170198.
- *
- * @param $build
- * The token string defined by the view.
- * @param $entity_data
- * The token type.
- *
- * I hate you, Milkman Dan.
+ * Implements hook_entity_view()
*/
-function _eva_extract_entity_from_build($build) {
- // EntityAPI often sticks stuff in here.
- if (!empty($build['#entity'])) {
- return $build['#entity'];
- }
+function eva_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
+ $type = $entity->getEntityTypeId();
+ $views = eva_get_views($type);
- // Other entities stick them here!
- elseif (!empty($build['#' . $build['#entity_type']])) {
- return $build['#' . $build['#entity_type']];
- }
+ foreach ($views as $info) {
+ $longname = $info['name'] .'_'. $info['display'];
- // Some entities are naughty.
- elseif ($build['#entity_type'] == 'user') {
- return $build['#account'];
- }
- elseif ($build['#entity_type'] == 'taxonomy_term') {
- return $build['#term'];
- }
+ if ($display->getComponent($longname)) {
+ if ($view = Views::getView($info['name'])) {
+ $view->setDisplay($info['display']);
+ if ($view->access($info['display'])) {
+ // no parent for current_entity; it's used by the display's preExecute
+ $view->current_entity = $entity;
+
+ // exposed form
+ if ($info['uses exposed']) {
+ $view->initHandlers();
+ $exposed_form = $view->display_handler->getPlugin('exposed_form');
+ $build[$longname . '_form'] = $exposed_form->renderExposedForm(TRUE);
+ }
+
+ $element = $view->executeDisplay($info['display']);
- return FALSE;
+ if (!empty($element)) {
+ $build[$longname][] = $element;
+ }
+ }
+ }
+ }
+ }
}
+
/**
* Get view arguments array from string that contains tokens
*
@@ -190,15 +137,13 @@ function _eva_extract_entity_from_build($build) {
* The object being used for replacement data (typically a node).
* @return
* An array of argument values.
- *
- * @todo: security?
*/
function eva_get_arguments_from_token_string($string, $type, $object) {
$args = trim($string);
if (empty($args)) {
return array();
}
- $args = token_replace($args, array($type => $object), array('sanitize' => FALSE));
+ $args = \Drupal::token()->replace($args, array($type => $object), array('sanitize' => FALSE));
return explode('/', $args);
}
@@ -206,27 +151,50 @@ function eva_get_arguments_from_token_string($string, $type, $object) {
* Implements hook_modules_enabled().
*/
function eva_modules_enabled($modules) {
- // Reset the static cache in case any of the enabled modules
- // implement an eva view
- drupal_static_reset('eva_get_views');
- cache_clear_all('*', 'cache_views', TRUE);
+ _eva_reset();
}
/**
* Implements hook_modules_disabled().
*/
function eva_modules_disabled($modules) {
- // Reset the static cache in case any of the disabled modules
- // implemented an eva view
+ _eva_reset();
+}
+
+/**
+ * Cache clearing helper function
+ * Reset the static cache in case any of the disabled modules
+ * implemented an eva view
+ */
+function _eva_reset() {
drupal_static_reset('eva_get_views');
- cache_clear_all('*', 'cache_views', TRUE);
+ \Drupal::cache('render')->deleteAll();
}
/**
- * Implements hook_form_FORM_ID_alter().
+ * Clear the field cache when view cache clears
+ * this is intended to fire when a View is saved
+ * hopefully it won't kick off an endless cache clearing loop
*/
-function eva_form_views_ui_edit_form_alter(&$form, &$form_state, $form_id) {
- // Clear the field cache when views are saved. This will make sure newly
- // created EVA views and/or exposed filters will appear.
- $form['actions']['save']["#submit"][] = 'field_cache_clear';
-}
\ No newline at end of file
+function eva_views_invalidate_cache() {
+ // see https://www.drupal.org/node/2281897
+ \Drupal::entityManager()->clearCachedFieldDefinitions();
+}
+
+/**
+ * templating preprocessing
+ * figure out the title and whether there's an exposed form
+ */
+function template_preprocess_eva_display_entity_view(&$variables) {
+ $view = $variables['view'];
+ $display = $view->display_handler;
+ $variables['title'] = $display->getOption('show_title') ? Xss::filterAdmin($view->getTitle()) : '';
+ $variables['exposed_form_as_field'] = $display->getOption('exposed_form_as_field');
+ // inject the dom ID since this isn't done automatically
+ $variables['dom_id'] = $view->dom_id;
+
+ $variables['view_array']['#view_id'] = $view->storage->id();
+ $variables['view_array']['#view_display_show_admin_links'] = $view->getShowAdminLinks();
+ $variables['view_array']['#view_display_plugin_id'] = $display->getPluginId();
+ views_add_contextual_links($variables['view_array'], 'view', $display->getLinkDisplay());
+}
diff --git a/eva.theme.inc b/eva.theme.inc
deleted file mode 100755
index b64c0db..0000000
--- a/eva.theme.inc
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-/**
- * @file
- * Preprocess handlers for theme functions
- */
-
-function template_preprocess_eva_display_entity_view(&$vars) {
- template_preprocess_views_view($vars);
- $view = $vars['view'];
- $display = $view->display_handler;
- $vars['title'] = $display->get_option('show_title') ? filter_xss_admin($view->get_title()) : '';
- $vars['exposed_form_as_field'] = $display->get_option('exposed_form_as_field');
-}
-
-function template_process_eva_display_entity_view(&$vars) {
- template_process_views_view($vars);
-}
-
diff --git a/eva.views.inc b/eva.views.inc
deleted file mode 100755
index 51994e9..0000000
--- a/eva.views.inc
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * Implements hook_views_plugins().
- */
-function eva_views_plugins() {
- return array(
- 'display' => array(
- 'entity_view' => array(
- 'title' => t('EVA Field'),
- 'help' => t("Display the view as a part of an entity's content."),
- 'handler' => 'eva_plugin_display_entity',
- 'theme' => 'eva_display_entity_view',
- 'uses hook entity view' => TRUE,
- 'use ajax' => TRUE,
- 'use pager' => TRUE,
- 'use more' => TRUE,
- 'accept attachments' => TRUE,
- 'admin' => t('Entity content'),
- 'help topic' => 'display-entity',
- ),
- ),
- );
-}
diff --git a/eva_plugin_display_entity.inc b/eva_plugin_display_entity.inc
deleted file mode 100755
index 449a65b..0000000
--- a/eva_plugin_display_entity.inc
+++ /dev/null
@@ -1,305 +0,0 @@
-<?php
-
-/**
- * The plugin that handles entity-attached views.
- */
-class eva_plugin_display_entity extends views_plugin_display {
- function option_definition() {
- $options = parent::option_definition();
-
- $options['entity_type'] = array('default' => '');
- $options['bundles'] = array('default' => array());
- $options['argument_mode'] = array('default' => 'id');
- $options['default_argument'] = array('default' => '');
- $options['show_title'] = 0;
- $options['exposed_form_as_field'] = 0;
-
- return $options;
- }
-
- /**
- * Provide the summary for page options in the views UI.
- *
- * This output is returned as an array.
- */
- function options_summary(&$categories, &$options) {
- // It is very important to call the parent function here:
- parent::options_summary($categories, $options);
-
- $categories['entity_view'] = array(
- 'title' => t('Entity content settings'),
- 'column' => 'second',
- 'build' => array(
- '#weight' => -10,
- ),
- );
-
- if ($entity_type = $this->get_option('entity_type')) {
- $entity_info = entity_get_info($entity_type);
- $type_name = $entity_info['label'];
- $bundle_names = array();
- foreach ($this->get_option('bundles') as $bundle) {
- $bundle_names[] = $entity_info['bundles'][$bundle]['label'];
- }
- }
-
- $options['entity_type'] = array(
- 'category' => 'entity_view',
- 'title' => t('Entity type'),
- 'value' => empty($type_name) ? t('None') : $type_name,
- );
-
- $options['bundles'] = array(
- 'category' => 'entity_view',
- 'title' => t('Bundles'),
- 'value' => empty($bundle_names) ? t('All') : implode(', ', $bundle_names),
- );
-
- $argument_mode = $this->get_option('argument_mode');
- $options['arguments'] = array(
- 'category' => 'entity_view',
- 'title' => t('Arguments'),
- 'value' => empty($argument_mode) ? t('None') : check_plain($argument_mode),
- );
-
- $options['show_title'] = array(
- 'category' => 'entity_view',
- 'title' => t('Show title'),
- 'value' => $this->get_option('show_title') ? t('Yes') : t('No'),
- );
-
- $options['exposed_form_as_field'] = array(
- 'category' => 'entity_view',
- 'title' => t('Exposed Form as Field'),
- 'value' => $this->get_option('exposed_form_as_field') ? t('Yes') : t('No'),
- );
-
- if (module_exists('token')) {
- // We must load token values here to show them on the options form.
- drupal_add_js(drupal_get_path('module', 'token') . '/token.js');
- drupal_add_css(drupal_get_path('module', 'token') . '/token.css');
- drupal_add_library('token', 'treeTable');
- }
- }
-
- /**
- * Provide the default form for setting options.
- */
- function options_form(&$form, &$form_state) {
- // It is very important to call the parent function here:
- parent::options_form($form, $form_state);
-
- $entity_info = entity_get_info();
- $entity_type = $this->get_option('entity_type');
-
- switch ($form_state['section']) {
- case 'entity_type':
- foreach ($entity_info as $type => $info) {
- if (!empty($info['view modes'])) {
- $entity_names[$type] = $info['label'];
- }
- }
-
- $form['#title'] .= t('Entity type');
- $form['entity_type'] = array(
- '#type' => 'radios',
- '#required' => TRUE,
- '#title' => t("Attach this display to the following entity type"),
- '#options' => $entity_names,
- '#default_value' => $this->get_option('entity_type'),
- );
- break;
-
- case 'bundles':
- foreach ($entity_info[$entity_type]['bundles'] as $bundle => $info) {
- $options[$bundle] = $info['label'];
- }
- $form['#title'] .= t('Bundles');
- $form['bundles'] = array(
- '#type' => 'checkboxes',
- '#title' => t("Attach this display to the following bundles. If no bundles are selected, the display will be attached to all."),
- '#options' => $options,
- '#default_value' => $this->get_option('bundles'),
- );
- break;
-
- case 'arguments':
- $form['#title'] .= t('Arguments');
- $default = $this->get_option('argument_mode');
- $options = array(
- 'none' => t("No special handling"),
- 'id' => t("Use the ID of the entity the view is attached to"),
- 'token' => t("Use tokens from the entity the view is attached to"),
- );
-
- $form['argument_mode'] = array(
- '#type' => 'radios',
- '#title' => t("How should this display populate the view's arguments?"),
- '#options' => $options,
- '#default_value' => $default,
- );
-
- $form['token'] = array(
- '#type' => 'fieldset',
- '#title' => t('Token replacement'),
- '#collapsible' => TRUE,
- '#states' => array(
- 'visible' => array(
- 'input:[name=argument_mode]' => array('value' => 'token'),
- ),
- ),
- );
-
- $form['token']['default_argument'] = array(
- '#title' => t('Arguments'),
- '#type' => 'textfield',
- '#default_value' => $this->get_option('default_argument'),
- '#description' => t('You may use token replacement to provide arguments based on the current entity. Separate arguments with "/".'),
- );
-
- if (module_exists('token')) {
- $form['token']['tokens'] = array(
- '#theme' => 'token_tree',
- '#token_types' => array(token_get_entity_mapping('entity', $entity_type)),
- );
- }
- break;
-
- case 'show_title':
- $form['#title'] .= t('Show title');
- $form['show_title'] = array(
- '#type' => 'checkbox',
- '#title' => t('Show the title of the view above the attached view.'),
- '#default_value' => $this->get_option('show_title'),
- );
- break;
- case 'exposed_form_as_field':
- $form['#title'] .= t('Exposed Form as Field');
- $form['exposed_form_as_field'] = array(
- '#type' => 'checkbox',
- '#title' => t('Split off Exposed Form as Separate Field'),
- '#default_value' => $this->get_option('exposed_form_as_field'),
- '#description' => t('Check this box to have a separate field for this view\'s exposed form on the "Manage Display" tab'),
- );
- }
-
- }
-
- function options_submit(&$form, &$form_state) {
- // It is very important to call the parent function here:
- parent::options_submit($form, $form_state);
-
- switch ($form_state['section']) {
- case 'entity_type':
- $new_entity = $form_state['values']['entity_type'];
- $old_entity = $this->get_option('entity_type');
-
- $this->set_option('entity_type', $new_entity);
- if ($new_entity != $old_entity) {
- // Each entity has its own list of bundles and view modes. If there's
- // only one on the new type, we can select it automatically. Otherwise
- // we need to wipe the options and start over.
- $new_entity_info = entity_get_info($new_entity);
-
- $new_bundle_keys = array_keys($new_entity_info['bundles']);
- $new_bundles = array();
- if (count($new_bundle_keys) == 1) {
- $new_bundles[] = $new_bundle_keys[0];
- }
- $this->set_option('bundles', $new_bundles);
- }
- break;
- case 'bundles':
- $this->set_option('bundles', array_values(array_filter($form_state['values']['bundles'])));
- break;
- case 'arguments':
- $this->set_option('argument_mode', $form_state['values']['argument_mode']);
- if ($form_state['values']['argument_mode'] == 'token') {
- $this->set_option('default_argument', $form_state['values']['default_argument']);
- }
- else {
- $this->set_option('default_argument', NULL);
- }
- break;
- case 'show_title':
- $this->set_option('show_title', $form_state['values']['show_title']);
- break;
- case 'exposed_form_as_field':
- $this->set_option('exposed_form_as_field', $form_state['values']['exposed_form_as_field']);
- break;
-
- }
- }
-
- function validate() {
- $errors = parent::validate();
-
- $entity_type = $this->get_option('entity_type');
- if (empty($entity_type)) {
- $errors[] = t('Display @display must have an entity type selected.', array('@display' => $this->display->display_title));
- }
- return $errors;
- }
-
- /**
- * We have to run token replacement before the arguments are used.
- */
- function pre_execute() {
- // Call the parent setup function so we do not lose data.
- parent::pre_execute();
-
- if (isset($this->view->current_entity)) {
- $entity = $this->view->current_entity;
- $entity_type = $this->view->display_handler->get_option('entity_type');
- $entity_info = entity_get_info($entity_type);
-
- $arg_mode = $this->view->display_handler->get_option('argument_mode');
- if ($arg_mode == 'token') {
- if ($token_string = $this->view->display_handler->get_option('default_argument')) {
- // Now do the token replacement.
- $token_values = eva_get_arguments_from_token_string($token_string, $entity_type, $entity);
- $new_args = array();
- // We have to be careful to only replace arguments that have tokens.
- foreach ($token_values as $key => $value) {
- $new_args[$key] = $value;
- }
-
- $this->view->args = $new_args;
- }
- }
- elseif ($arg_mode == 'id') {
- $this->view->args = array($entity->{$entity_info['entity keys']['id']});
- }
- }
- }
-
- /**
- * Specify the path of the entity.
- */
- function get_path() {
- if (isset($this->view->current_entity)) {
- $uri = entity_uri($this->view->display_handler->get_option('entity_type'), $this->view->current_entity);
- if ($uri) {
- $uri['options']['absolute'] = TRUE;
- return url($uri['path'], $uri['options']);
- }
- }
- return parent::get_path();
- }
-
- /**
- * The display block handler returns the structure necessary for a block.
- */
- function execute() {
- // Prior to this being called, the $view should already be set to this
- // display, and arguments should be set on the view.
- if (!isset($this->view->override_path)) {
- $this->view->override_path = $_GET['q'];
- }
-
- $data = $this->view->render();
- if (!empty($this->view->result) || $this->get_option('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
- return $data;
- }
- }
-}
diff --git a/lib/Drupal/eva/Plugin/views/display/EvaDisplayPlugin.php b/lib/Drupal/eva/Plugin/views/display/EvaDisplayPlugin.php
deleted file mode 100644
index b4156c1..0000000
--- a/lib/Drupal/eva/Plugin/views/display/EvaDisplayPlugin.php
+++ /dev/null
@@ -1,302 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\eva\Plugin\views\display\EvaDisplayPlugin.
- */
-
-namespace Drupal\eva\Plugin\views\display;
-
-use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\Component\Annotation\Plugin;
-use Drupal\Core\Annotation\Translation;
-use Drupal\Core\Entity\EntityManager;
-
-/**
- * A plugin to handle defaults on a view.
- *
- * @ingroup views_display_plugins
- *
- * @Plugin(
- * id = "eva",
- * title = @Translation("EVA Field"),
- * help = @Translation("View to be attached to any entity."),
- * theme = "views_view",
- * uses_hook_entity_view = TRUE
- * )
- */
-class EvaDisplayPlugin extends DisplayPluginBase {
-
- /**
- * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::defineOptions().
- */
- protected function defineOptions() {
- $options = parent::defineOptions();
-
- $options['entity_type'] = array('default' => '');
- $options['bundles'] = array('default' => array());
- $options['argument_mode'] = array('default' => 'id');
- $options['default_argument'] = array('default' => '');
- $options['show_title'] = 0;
- $options['exposed_form_as_field'] = 0;
-
- return $options;
- }
-
- /**
- * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary().
- */
- public function optionsSummary(&$categories, &$options) {
- parent::optionsSummary($categories, $options);
-
- $categories['entity_view'] = array(
- 'title' => t('Entity content settings'),
- 'column' => 'second',
- 'build' => array(
- '#weight' => -10,
- ),
- );
-
- if ($entity_type = $this->getOption('entity_type')) {
- $entity_info = entity_get_info($entity_type);
- $type_name = $entity_info['label'];
- $bundle_names = array();
- $bundle_info = entity_get_bundles($entity_type);
- foreach ($this->getOption('bundles') as $bundle) {
- $bundle_names[] = $bundle_info[$bundle]['label'];
- }
- }
-
- $options['entity_type'] = array(
- 'category' => 'entity_view',
- 'title' => t('Entity type'),
- 'value' => empty($type_name) ? t('None') : $type_name,
- );
-
- $options['bundles'] = array(
- 'category' => 'entity_view',
- 'title' => t('Bundles'),
- 'value' => empty($bundle_names) ? t('All') : implode(', ', $bundle_names),
- );
-
- $argument_mode = $this->getOption('argument_mode');
- $options['arguments'] = array(
- 'category' => 'entity_view',
- 'title' => t('Arguments'),
- 'value' => empty($argument_mode) ? t('None') : check_plain($argument_mode),
- );
-
- $options['show_title'] = array(
- 'category' => 'entity_view',
- 'title' => t('Show title'),
- 'value' => $this->getOption('show_title') ? t('Yes') : t('No'),
- );
-
- $options['exposed_form_as_field'] = array(
- 'category' => 'entity_view',
- 'title' => t('Exposed Form as Field'),
- 'value' => $this->getOption('exposed_form_as_field') ? t('Yes') : t('No'),
- );
- }
-
- /**
- * Overrides \Drupal\views\Plugin\views\display\callbackPluginBase::buildOptionsForm().
- */
- public function buildOptionsForm(&$form, &$form_state) {
- parent::buildOptionsForm($form, $form_state);
-
- $entity_info = drupal_container()->get('plugin.manager.entity')->getDefinitions();
- $entity_type = $this->getOption('entity_type');
-
- switch ($form_state['section']) {
- case 'entity_type':
- foreach ($entity_info as $type => $info) {
- if (!empty($info['render_controller_class'])) {
- $entity_names[$type] = $info['label'];
- }
- }
-
- $form['#title'] .= t('Entity type');
- $form['entity_type'] = array(
- '#type' => 'radios',
- '#required' => TRUE,
- '#title' => t("Attach this display to the following entity type"),
- '#options' => $entity_names,
- '#default_value' => $this->getOption('entity_type'),
- );
- break;
-
- case 'bundles':
- foreach (entity_get_bundles($entity_type) as $bundle => $info) {
- $options[$bundle] = $info['label'];
- }
- $form['#title'] .= t('Bundles');
- $form['bundles'] = array(
- '#type' => 'checkboxes',
- '#title' => t("Attach this display to the following bundles. If no bundles are selected, the display will be attached to all."),
- '#options' => $options,
- '#default_value' => $this->getOption('bundles'),
- );
- break;
-
- case 'arguments':
- $form['#title'] .= t('Arguments');
- $default = $this->getOption('argument_mode');
- $options = array(
- 'none' => t("No special handling"),
- 'id' => t("Use the ID of the entity the view is attached to"),
- 'token' => t("Use tokens from the entity the view is attached to"),
- );
-
- $form['argument_mode'] = array(
- '#type' => 'radios',
- '#title' => t("How should this display populate the view's arguments?"),
- '#options' => $options,
- '#default_value' => $default,
- );
-
- $form['token'] = array(
- '#type' => 'fieldset',
- '#title' => t('Token replacement'),
- '#collapsible' => TRUE,
- '#states' => array(
- 'visible' => array(
- ':input[name=argument_mode]' => array('value' => 'token'),
- ),
- ),
- );
-
- $form['token']['default_argument'] = array(
- '#title' => t('Arguments'),
- '#type' => 'textfield',
- '#default_value' => $this->getOption('default_argument'),
- '#description' => t('You may use token replacement to provide arguments based on the current entity. Separate arguments with "/".'),
- );
- break;
-
- case 'show_title':
- $form['#title'] .= t('Show title');
- $form['show_title'] = array(
- '#type' => 'checkbox',
- '#title' => t('Show the title of the view above the attached view.'),
- '#default_value' => $this->getOption('show_title'),
- );
- break;
- case 'exposed_form_as_field':
- $form['#title'] .= t('Exposed Form as Field');
- $form['exposed_form_as_field'] = array(
- '#type' => 'checkbox',
- '#title' => t('Split off Exposed Form as Separate Field'),
- '#default_value' => $this->getOption('exposed_form_as_field'),
- '#description' => t('Check this box to have a separate field for this view\'s exposed form on the "Manage Display" tab'),
- );
- }
- }
-
- public function validateOptionsForm(&$form, &$form_state) {
- $errors = parent::validateOptionsForm($form, $form_state);
-
- $entity_type = $this->getOption('entity_type');
- if (empty($entity_type)) {
- $errors[] = t('Display @display must have an entity type selected.', array('@display' => $this->display->display_title));
- }
- return $errors;
- }
-
- public function submitOptionsForm(&$form, &$form_state) {
- parent::submitOptionsForm($form, $form_state);
-
- switch ($form_state['section']) {
- case 'entity_type':
- $new_entity = $form_state['values']['entity_type'];
- $old_entity = $this->getOption('entity_type');
-
- $this->setOption('entity_type', $new_entity);
- if ($new_entity != $old_entity) {
- // Each entity has its own list of bundles and view modes. If there's
- // only one on the new type, we can select it automatically. Otherwise
- // we need to wipe the options and start over.
- $new_entity_info = drupal_container()->get('plugin.manager.entity')->getDefinition($new_entity);
- $new_bundles_keys = entity_get_bundles($new_entity);
- $new_bundles = array();
- if (count($new_bundle_keys) == 1) {
- $new_bundles[] = $new_bundle_keys[0];
- }
- $this->setOption('bundles', $new_bundles);
- }
- break;
- case 'bundles':
- $this->setOption('bundles', array_values(array_filter($form_state['values']['bundles'])));
- break;
- case 'arguments':
- $this->setOption('argument_mode', $form_state['values']['argument_mode']);
- if ($form_state['values']['argument_mode'] == 'token') {
- $this->setOption('default_argument', $form_state['values']['default_argument']);
- }
- else {
- $this->setOption('default_argument', NULL);
- }
- break;
- case 'show_title':
- $this->setOption('show_title', $form_state['values']['show_title']);
- break;
- case 'exposed_form_as_field':
- $this->setOption('exposed_form_as_field', $form_state['values']['exposed_form_as_field']);
- break;
- }
- }
-
- public function preExecute() {
- parent::preExecute();
-
- if (isset($this->view->current_entity)) {
- $entity = $this->view->current_entity;
- $entity_type = $this->view->display_handler->getOption('entity_type');
- $entity_info = drupal_container()->get('plugin.manager.entity')->getDefinition($entity_type);
-
- $arg_mode = $this->view->display_handler->getOption('argument_mode');
- if ($arg_mode == 'token') {
- if ($token_string = $this->view->display_handler->getOption('default_argument')) {
- // Now do the token replacement.
- $token_values = eva_get_arguments_from_token_string($token_string, $entity_type, $entity);
- $new_args = array();
- // We have to be careful to only replace arguments that have tokens.
- foreach ($token_values as $key => $value) {
- $new_args[$key] = $value;
- }
-
- $this->view->args = $new_args;
- }
- }
- elseif ($arg_mode == 'id') {
- $this->view->args = array($entity->{$entity_info['entity keys']['id']});
- }
- }
- }
-
- public function getPath() {
- if (isset($this->view->current_entity)) {
- $uri = $this->view->current_entity->uri();
- if ($uri) {
- $uri['options']['absolute'] = TRUE;
- return url($uri['path'], $uri['options']);
- }
- }
- return parent::get_path();
- }
-
- function execute() {
- // Prior to this being called, the $view should already be set to this
- // display, and arguments should be set on the view.
- if (!isset($this->view->override_path)) {
- $this->view->override_path = $_GET['q'];
- }
-
- $data = $this->view->render();
- if (!empty($this->view->result) || $this->getOption('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
- return $data;
- }
- }
-}
-
-
diff --git a/src/Plugin/views/display/Eva.php b/src/Plugin/views/display/Eva.php
new file mode 100644
index 0000000..83e4dbb
--- /dev/null
+++ b/src/Plugin/views/display/Eva.php
@@ -0,0 +1,304 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\eva\Plugin\views\display\Eva.
+ */
+
+namespace Drupal\eva\Plugin\views\display;
+
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Url;
+
+/**
+ * The plugin that handles an EVA display in views.
+ *
+ *
+ * @ingroup views_display_plugins
+ *
+ * @ViewsDisplay(
+ * id = "entity_view",
+ * title = @Translation("EVA"),
+ * admin = @Translation("EVA"),
+ * help = @Translation("Attach a view to an entity"),
+ * theme = "eva_display_entity_view",
+ * uses_menu_links = FALSE,
+ * uses_hook_entity_view = TRUE,
+ * )
+ */
+
+class Eva extends DisplayPluginBase {
+
+ /**
+ * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::defineOptions().
+ */
+ protected function defineOptions() {
+ $options = parent::defineOptions();
+
+ $options['entity_type']['default'] = '';
+ $options['bundles']['default'] = array();
+ $options['argument_mode']['default'] = 'id';
+ $options['default_argument']['default'] = '';
+
+
+ $options['title']['default'] = '';
+ $options['defaults']['default']['title'] = FALSE;
+
+ return $options;
+ }
+
+ /**
+ * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary().
+ */
+ public function optionsSummary(&$categories, &$options) {
+ parent::optionsSummary($categories, $options);
+
+ $categories['entity_view'] = array(
+ 'title' => t('Entity content settings'),
+ 'column' => 'second',
+ 'build' => array(
+ '#weight' => -10,
+ ),
+ );
+
+ if ($entity_type = $this->getOption('entity_type')) {
+ $entity_info = \Drupal::entityManager()->getDefinition($entity_type);
+ $type_name = $entity_info->get('label');
+
+ $bundle_names = array();
+ $bundle_info = \Drupal::entityManager()->getBundleInfo($entity_type);
+ foreach ($this->getOption('bundles') as $bundle) {
+ $bundle_names[] = $bundle_info[$bundle]['label'];
+ }
+ }
+
+ $options['entity_type'] = array(
+ 'category' => 'entity_view',
+ 'title' => $this->t('Entity type'),
+ 'value' => empty($type_name) ? $this->t('None') : $type_name,
+ );
+
+ $options['bundles'] = array(
+ 'category' => 'entity_view',
+ 'title' => $this->t('Bundles'),
+ 'value' => empty($bundle_names) ? $this->t('All') : implode(', ', $bundle_names),
+ );
+
+ $argument_mode = $this->getOption('argument_mode');
+ $options['arguments'] = array(
+ 'category' => 'entity_view',
+ 'title' => $this->t('Arguments'),
+ 'value' => empty($argument_mode) ? $this->t('None') : SafeMarkup::checkPlain($argument_mode),
+ );
+
+ $options['show_title'] = array(
+ 'category' => 'entity_view',
+ 'title' => $this->t('Show title'),
+ 'value' => $this->getOption('show_title') ? $this->t('Yes') : $this->t('No'),
+ );
+ }
+
+ /**
+ * Overrides \Drupal\views\Plugin\views\display\callbackPluginBase::buildOptionsForm().
+ */
+ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+ parent::buildOptionsForm($form, $form_state);
+
+ $entity_info = \Drupal::entityManager()->getDefinitions();
+ $entity_type = $this->getOption('entity_type');
+
+ switch ($form_state->get('section')) {
+ case 'entity_type':
+ foreach ($entity_info as $type => $info) {
+ // is this a content/front-facing entity?
+ if ($info instanceof \Drupal\Core\Entity\ContentEntityType) {
+ $entity_names[$type] = $info->get('label');
+ }
+ }
+
+ $form['#title'] .= t('Entity type');
+ $form['entity_type'] = array(
+ '#type' => 'radios',
+ '#required' => TRUE,
+ '#validated' => TRUE,
+ '#title' => $this->t('Attach this display to the following entity type'),
+ '#options' => $entity_names,
+ '#default_value' => $this->getOption('entity_type'),
+ );
+ break;
+
+ case 'bundles':
+ $options = array();
+ foreach (\Drupal::entityManager()->getBundleInfo($entity_type) as $bundle => $info) {
+ $options[$bundle] = $info['label'];
+ }
+ $form['#title'] .= $this->t('Bundles');
+ $form['bundles'] = array(
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Attach this display to the following bundles. If no bundles are selected, the display will be attached to all.'),
+ '#options' => $options,
+ '#default_value' => $this->getOption('bundles'),
+ );
+ break;
+
+ case 'arguments':
+ $form['#title'] .= $this->t('Arguments');
+ $default = $this->getOption('argument_mode');
+ $options = array(
+ 'None' => $this->t("No special handling"),
+ 'id' => $this->t("Use the ID of the entity the view is attached to"),
+ 'token' => $this->t("Use tokens from the entity the view is attached to"),
+ );
+
+ $form['argument_mode'] = array(
+ '#type' => 'radios',
+ '#title' => $this->t("How should this display populate the view's arguments?"),
+ '#options' => $options,
+ '#default_value' => $default,
+ );
+
+ $form['token'] = array(
+ '#type' => 'fieldset',
+ '#title' => $this->t('Token replacement'),
+ '#collapsible' => TRUE,
+ '#states' => array(
+ 'visible' => array(
+ ':input[name=argument_mode]' => array('value' => 'token'),
+ ),
+ ),
+ );
+
+ $form['token']['default_argument'] = array(
+ '#title' => t('Arguments'),
+ '#type' => 'textfield',
+ '#default_value' => $this->getOption('default_argument'),
+ '#description' => $this->t('You may use token replacement to provide arguments based on the current entity. Separate arguments with "/".'),
+ );
+ break;
+
+ case 'show_title':
+ $form['#title'] .= t('Show title');
+ $form['show_title'] = array(
+ '#type' => 'checkbox',
+ '#title' => $this->t('Show the title of the view above the attached view.'),
+ '#default_value' => $this->getOption('show_title'),
+ );
+ break;
+ }
+ }
+
+ public function validateOptionsForm(&$form, FormStateInterface $form_state) {
+ switch ($form_state->get('section')) {
+ case 'entity_type':
+ if (empty($form_state->getValue('entity_type'))) {
+ $form_state->setError($form['entity_type'], $this->t('Must select an entity'));
+ }
+ break;
+ }
+ }
+
+ public function validate() {
+ $errors = array();
+ if (empty($this->getOption('entity_type'))) {
+ $errors[] = $this->t('Display "@display" must be attached to an entity.', array('@display' => $this->display['display_title']));
+ }
+ return $errors;
+ }
+
+ public function submitOptionsForm(&$form, FormStateInterface $form_state) {
+ parent::submitOptionsForm($form, $form_state);
+
+ switch ($form_state->get('section')) {
+ case 'entity_type':
+ $new_entity = $form_state->getValue('entity_type');
+ $old_entity = $this->getOption('entity_type');
+ $this->setOption('entity_type', $new_entity);
+
+ if ($new_entity != $old_entity) {
+ // Each entity has its own list of bundles and view modes. If there's
+ // only one on the new type, we can select it automatically. Otherwise
+ // we need to wipe the options and start over.
+ $new_entity_info = \Drupal::entityManager()->getDefinition($new_entity);
+ $new_bundles_keys = \Drupal::entityManager()->getBundleInfo($new_entity);
+ $new_bundles = array();
+ if (count($new_bundles_keys) == 1) {
+ $new_bundles[] = $new_bundles_keys[0];
+ }
+ $this->setOption('bundles', $new_bundles);
+ }
+ break;
+ case 'bundles':
+ $this->setOption('bundles', array_values(array_filter($form_state->getValue('bundles'))));
+ break;
+ case 'arguments':
+ $this->setOption('argument_mode', $form_state->getValue('argument_mode'));
+ if ($form_state->getValue('argument_mode') == 'token') {
+ $this->setOption('default_argument', $form_state->getValue('default_argument'));
+ }
+ else {
+ $this->setOption('default_argument', NULL);
+ }
+ break;
+ case 'show_title':
+ $this->setOption('show_title', $form_state->getValue('show_title'));
+ break;
+ }
+ }
+
+ public function preExecute() {
+ parent::preExecute();
+
+ if (isset($this->view->current_entity)) {
+ $entity = $this->view->current_entity;
+ $entity_type = $this->view->display_handler->getOption('entity_type');
+ $entity_info = \Drupal::entityManager()->getDefinition($entity_type);
+
+ $arg_mode = $this->view->display_handler->getOption('argument_mode');
+ if ($arg_mode == 'token') {
+ if ($token_string = $this->view->display_handler->getOption('default_argument')) {
+ // Now do the token replacement.
+ $token_values = eva_get_arguments_from_token_string($token_string, $entity_type, $entity);
+ $new_args = array();
+ // We have to be careful to only replace arguments that have tokens.
+ foreach ($token_values as $key => $value) {
+ $new_args[Html::escape($key)] = Html::escape($value);
+ }
+
+ $this->view->args = $new_args;
+ }
+ }
+ elseif ($arg_mode == 'id') {
+ $this->view->args = array($entity->id());
+ }
+ }
+ }
+
+ public function getPath() {
+ if (isset($this->view->current_entity)) {
+ $uri = $this->view->current_entity->url();
+ if ($uri) {
+ $uri['options']['absolute'] = TRUE;
+ return url($uri['path'], $uri['options']);
+ }
+ }
+ return parent::getPath();
+ }
+
+ function execute() {
+ // Prior to this being called, the $view should already be set to this
+ // display, and arguments should be set on the view.
+ if (!isset($this->view->override_path)) {
+ $this->view->override_path = \Drupal::service('path.current')->getPath();
+ }
+
+ $element = $this->view->render();
+ if (!empty($this->view->result) || $this->getOption('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
+ return $element;
+ }
+ }
+}
+
+
diff --git a/templates/eva-display-entity-view.html.twig b/templates/eva-display-entity-view.html.twig
new file mode 100644
index 0000000..e8fba0b
--- /dev/null
+++ b/templates/eva-display-entity-view.html.twig
@@ -0,0 +1,75 @@
+{#
+/**
+ * @file
+ * eva theme implementation for main view template.
+ *
+ * the main difference between this and the canonical template
+ * is the exposed form is removed (because it is displayed as
+ * a separate field)
+ *
+ * Available variables:
+ * - attributes: Remaining HTML attributes for the element.
+ * - css_name: A css-safe version of the view name.
+ * - css_class: The user-specified classes names, if any.
+ * - header: The optional header.
+ * - footer: The optional footer.
+ * - rows: The results of the view query, if any.
+ * - empty: The content to display if there are no rows.
+ * - pager: The optional pager next/prev links to display.
+ * - exposed: Exposed widget form/info to display.
+ * - feed_icons: Optional feed icons to display.
+ * - more: An optional link to the next page of results.
+ * - title: Title of the view, only used when displaying in the admin preview.
+ * - title_prefix: Additional output populated by modules, intended to be
+ * displayed in front of the view title.
+ * - title_suffix: Additional output populated by modules, intended to be
+ * displayed after the view title.
+ * - attachment_before: An optional attachment view to be displayed before the
+ * view content.
+ * - attachment_after: An optional attachment view to be displayed after the
+ * view content.
+ * - dom_id: Unique id for every view being printed to give unique class for
+ * Javascript.
+ *
+ * @see template_preprocess_views_view()
+ *
+ * @ingroup themeable
+ */
+#}
+{%
+ set classes = [
+ dom_id ? 'js-view-dom-id-' ~ dom_id,
+ ]
+%}
+<div{{ attributes.addClass(classes) }}>
+ {{ title_prefix }}
+ {% if title %}
+ {{ title }}
+ {% endif %}
+ {{ title_suffix }}
+
+ {% if header %}
+ <header>
+ {{ header }}
+ </header>
+ {% endif %}
+
+ {{ attachment_before }}
+
+ {{ rows }}
+ {{ empty }}
+ {{ pager }}
+
+ {{ attachment_after }}
+ {{ more }}
+
+ {% if footer %}
+ <footer>
+ {{ footer }}
+ </footer>
+ {% endif %}
+
+ {% if feed_icons %}
+ {{ feed_icons }}
+ {% endif %}
+</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment