eva.module 6.65 KiB
<?php
/**
* @file
* Module implementing EVA extra field and views display
*/
use Drupal\views\Views;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Component\Utility\Xss;
use Drupal\Component\Utility\Html;
/**
* Implements hook_entity_extra_field_info() to add the view fields to relevant entities
*/
function eva_entity_extra_field_info() {
$extra = array();
$views = eva_get_views();
foreach ($views as $entity => $data) {
foreach ($data as $view) {
// 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) {
$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 ($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,
);
}
}
}
}
return $extra;
}
/**
* Get a list of views and displays attached to speficic entities.
*
* This function will cache its results into the views cache, so it gets
* cleared by Views appropriately.
*
* @param $type
* The entity type we want to retrieve views for. If NULL is
* specified, views for all entity types will be returned.
* @param $reset
* Force a rebuild of the data.
* @return
* An array of view name/display name values, or an empty array().
*/
function eva_get_views($type = NULL, $reset = FALSE) {
// Build and cache the data, both in the DB and statically.
$views = Views::getApplicableViews('uses_hook_entity_view');
$used_views = array();
foreach ($views as $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();
$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('label') . ' - ' . $view->storage->getDisplay($display_id)['display_title'],
'display' => $display_id,
'bundles' => $display->getOption('bundles'),
'uses exposed' => $display->usesExposed(),
);
$view->destroy();
}
if (!is_null($type)) {
return isset($used_views[$type]) ? $used_views[$type] : array();
}
return $used_views;
}
/**
* Implements hook_entity_view()
*/
function eva_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
$type = $entity->getEntityTypeId();
$views = eva_get_views($type);
foreach ($views as $info) {
$longname = $info['name'] .'_'. $info['display'];
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->buildRenderable($info['display']);
if (!empty($element)) {
$build[$longname][] = $element;
}
}
}
}
}
}
/**
* Get view arguments array from string that contains tokens
*
* @param $string
* The token string defined by the view.
* @param $type
* The token type.
* @param $object
* The object being used for replacement data (typically a node).
* @return
* An array of argument values.
*/
function eva_get_arguments_from_token_string($string, $type, $object) {
$args = trim($string);
if (empty($args)) {
return array();
}
$args = \Drupal::token()->replace($args, array($type => $object), array('sanitize' => FALSE));
return explode('/', $args);
}
/**
* Implements hook_modules_enabled().
*/
function eva_modules_enabled($modules) {
_eva_reset();
}
/**
* Implements hook_modules_disabled().
*/
function eva_modules_disabled($modules) {
_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');
\Drupal::cache('render')->deleteAll();
}
/**
* 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_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');
$id = $view->storage->id();
$variables['css_name'] = Html::cleanCssIdentifier($id);
$variables['id'] = $id;
$variables['display_id'] = $view->current_display;
$variables['dom_id'] = $view->dom_id;
// pull in the display class
$css_class = $view->display_handler->getOption('css_class');
if (!empty($css_class)) {
$variables['css_class'] = preg_replace('/[^a-zA-Z0-9- ]/', '-', $css_class);
$variables['attributes']['class'][] = $variables['css_class'];
}
$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());
}