entity_generic-8.x-3.x-dev/entity_generic.module
entity_generic.module
<?php
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Link;
use Drupal\entity_generic\Entity\BasicInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\ContentEntityTypeInterface;
/**
* Implements hook_theme().
*/
function entity_generic_theme() {
return array(
'entity_generic' => array(
'render element' => 'elements',
),
);
}
/**
* Implements hook_entity_type_build().
* @param array $entity_types
*/
function entity_generic_entity_type_build(array &$entity_types) {
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
foreach ($entity_types as $entity_type_id => &$entity_type) {
// Check if the entity type has an 'entity_generic' mark.
if (isset($entity_type->get('additional')['entity_generic']) && $entity_type instanceof ContentEntityTypeInterface) {
$handlers = $entity_type->getHandlerClasses();
$links = $entity_type->getLinkTemplates();
// Add multiple delete possibility.
if (!isset($handlers['form']['delete-multiple-confirm'])) {
$handlers['form']['delete-multiple-confirm'] = 'Drupal\entity_generic\Form\GenericDeleteMultipleForm';
}
if (!isset($links['delete-multiple-form']) && isset($links['collection'])) {
$entity_type->setLinkTemplate('delete-multiple-form', $links['collection'] . '/delete');
}
// Add multiple merge possibility.
if (!isset($handlers['form']['merge-multiple-confirm'])) {
$handlers['form']['merge-multiple-confirm'] = 'Drupal\entity_generic\Form\GenericMergeMultipleForm';
}
if (!isset($links['merge-multiple-form']) && isset($links['collection'])) {
$entity_type->setLinkTemplate('merge-multiple-form', $links['collection'] . '/merge');
}
$entity_type->setHandlerClass('form', $handlers['form']);
}
}
}
/**
* Helper function returns all "entity_generic" entity types.
*/
function entity_generic_types() {
$entity_generic_types = &drupal_static(__FUNCTION__, []);
if (!$entity_generic_types) {
$entity_generic_types = [];
$cid = 'entity_generic:types';
if ($cache = \Drupal::cache()->get($cid)) {
$entity_generic_types = $cache->data;
}
else {
$types = \Drupal::entityTypeManager()->getDefinitions();
foreach($types as $type) {
if (isset($type->get('additional')['entity_generic'])) {
$entity_generic_types[$type->id()] = $type;
}
}
\Drupal::cache()->set($cid, $entity_generic_types, Cache::PERMANENT, ['entity_generic', 'entity_generic_types']);
}
}
return $entity_generic_types;
}
/**
* Checks whether the current page is the full page view of the passed-in entity.
*
* @param \Drupal\entity_generic\Entity\BasicInterface $entity
* An entity.
*
* @return int|false
* The ID of the entity if this is a full page view, otherwise FALSE.
*/
function entity_generic_is_page(BasicInterface $entity) {
$route_match = \Drupal::routeMatch();
if ($route_match->getRouteName() == 'entity.'.$entity->getEntityTypeId().'.canonical') {
$page_entity = $route_match->getParameter($entity->getEntityTypeId());
}
return (!empty($page_entity) ? $page_entity->id() == $entity->id() : FALSE);
}
/**
* Helper function to check if the entity is generic.
*
* @param $entity
*
* @return bool
*/
function entity_generic_is_generic(EntityInterface $entity) {
return array_key_exists($entity->getEntityTypeId(), entity_generic_types());
}
/**
* Implements hook_entity_view_alter().
*
* @param array $build
* @param \Drupal\Core\Entity\EntityInterface $entity
* @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
*/
function entity_generic_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
// Generalize the entity-type-specific defaults for easier default theming.
if ($entity instanceof BasicInterface) {
$app_root = \Drupal::getContainer()->getParameter('app.root');
$file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($entity->getEntityType()->getProvider()) . '/templates/entity-generic--' . strtr($entity->getEntityTypeId(), '_', '-') . '.html.twig';
if (file_exists($file_path)) {
$build['#theme'] = 'entity_generic__' . $entity->getEntityTypeId();
}
$build['#entity_generic'] = $entity;
}
}
/**
* Alters suggestions for generic entities to add additional variants of templates.
* Implements hook_theme_suggestions_HOOK_alter().
*
* @param array $suggestions
* @param array $variables
*/
function entity_generic_theme_suggestions_entity_generic_alter(array &$suggestions, array $variables) {
/** @var \Drupal\entity_generic\Entity\BasicInterface $entity */
$entity = $variables['elements']['#entity_generic'];
$sanitized_view_mode = 'vm-' . strtr($variables['elements']['#view_mode'], '.', '_');
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId();
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId() . '__' . $sanitized_view_mode;
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId() . '__' . $entity->bundle();
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId() . '__' . $entity->bundle() . '__' . $sanitized_view_mode;
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId() . '__' . $entity->id();
$suggestions[] = 'entity_generic__' . $entity->getEntityTypeId() . '__' . $entity->id() . '__' . $sanitized_view_mode;
}
/**
* Alter the theme registry to add templates for existing generic entities.
* Implements hook_theme_registry_alter().
*
* @see hook_theme()
* @see \Drupal\Core\Theme\Registry::processExtension()
*/
function entity_generic_theme_registry_alter(&$theme_registry) {
$app_root = \Drupal::getContainer()->getParameter('app.root');
foreach (entity_generic_types() as $type => $definition) {
$file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($definition->getProvider()) . '/templates/entity-generic--' . strtr($type, '_', '-') . '.html.twig';
if (file_exists($file_path)) {
$theme_registry['entity_generic__' . $type] = [
'path' => \Drupal::service('extension.list.module')->getPath($definition->getProvider()) . '/templates',
'preprocess functions' => [
'template_preprocess',
'template_preprocess_entity_generic',
'template_preprocess_entity_generic__' . $type,
],
'render element' => 'elements',
'template' => 'entity-generic--' . strtr($type, '_', '-'),
'theme path' => \Drupal::service('extension.list.module')->getPath($definition->getProvider()),
'type' => 'module',
];
}
}
}
/**
* Prepares variables for list of available entity type templates.
*
* Default template: entity-generic-add-list.html.twig.
*
* @param array $variables
* An associative array containing:
* - content: An array of entity types.
*/
function template_preprocess_entity_generic_add_list(&$variables) {
$variables['types'] = array();
if (!empty($variables['bundles'])) {
foreach ($variables['bundles'] as $bundle) {
$variables['types'][$bundle->id()] = array(
'label' => $bundle->id(),
'add_link' => Link::fromTextAndUrl($bundle->label(), new Url('entity.' .$variables['entity_type'] . '.add_form', array($bundle->getEntityTypeId() => $bundle->id()))),
'description' => array(
'#markup' => $bundle->getDescription(),
),
);
}
}
}
/**
* Prepares variables for entity templates.
* Default template: entity-generic.html.twig.
*
* @param array $variables
* An associative array containing:
* - elements: An array of elements to display in view mode.
* - entity: The entity object.
* - view_mode: View mode; e.g., 'full', 'teaser', etc.
*/
function template_preprocess_entity_generic(&$variables) {
// View mode.
$variables['view_mode'] = $variables['elements']['#view_mode'];
// Generic entity.
$variables['entity_generic'] = $variables['elements']['#entity_generic'];
// Entity type and bundle.
$variables['entity_type'] = $variables['entity_generic']->getEntityTypeId();
$variables['bundle'] = $variables['entity_generic']->bundle();
// The 'page' variable is set to TRUE in two occasions:
// - The view mode is 'full' or 'default' and we are on the 'entity.view' route.
$variables['page'] = entity_generic_is_page($variables['entity_generic']) && $variables['view_mode'] == 'full';
// Entity label.
if ($variables['page']) {
$variables['label'] = $variables['entity_generic']->label();
}
// Build the $content variable for templates.
$variables += ['content' => []];
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
// Add article ARIA role.
$variables['attributes']['role'] = 'article';
}
