You are here

taxonomy_entity_index.module in Taxonomy Entity Index 8

Same filename and directory in other branches
  1. 7 taxonomy_entity_index.module

Module file for taxonomy_entity_index.

File

taxonomy_entity_index.module
View source
<?php

/**
 * @file
 * Module file for taxonomy_entity_index.
 */
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\taxonomy\TermInterface;

/**
 * Implements hook_field_config_delete().
 */
function taxonomy_entity_index_field_config_delete(FieldConfig $instance) {
  \Drupal::database()
    ->delete('taxonomy_entity_index')
    ->condition('field_name', $instance
    ->id())
    ->condition('entity_type', $instance
    ->getEntityTypeId())
    ->condition('bundle', $instance
    ->bundle())
    ->execute();
}

/**
 * Implements hook_entity_delete().
 */
function taxonomy_entity_index_entity_delete(EntityInterface $entity) {
  \Drupal::database()
    ->delete('taxonomy_entity_index')
    ->condition('entity_type', $entity
    ->getEntityTypeId())
    ->condition('entity_id', $entity
    ->id())
    ->execute();
}

/**
 * Implements hook_ENTITY_TYPE_delete().
 */
function taxonomy_entity_index_taxonomy_term_delete(TermInterface $term) {
  \Drupal::database()
    ->delete('taxonomy_entity_index')
    ->condition('tid', $term
    ->id())
    ->execute();
}

/**
 * Implements hook_entity_revision_delete().
 */
function taxonomy_entity_index_entity_revision_delete(EntityInterface $entity) {
  \Drupal::database()
    ->delete('taxonomy_entity_index')
    ->condition('entity_type', $entity
    ->getEntityTypeId())
    ->condition('entity_id', $entity
    ->id())
    ->condition('revision_id', $entity
    ->getRevisionId())
    ->execute();
}

/**
 * Implements hook_entity_insert().
 */
function taxonomy_entity_index_entity_insert(EntityInterface $entity) {
  taxonomy_entity_index_entity_update($entity);
}

/**
 * Implements hook_entity_update().
 */
function taxonomy_entity_index_entity_update(EntityInterface $entity) {
  $entity_type_id = $entity
    ->getEntityTypeId();
  $config = \Drupal::config('taxonomy_entity_index.settings');
  $entity_types_to_index = $config
    ->get('types');
  if (!in_array($entity_type_id, $entity_types_to_index)) {
    return;
  }
  $entity_id = $entity
    ->id();
  $bundle = $entity
    ->bundle();
  $revision_id = NULL;
  if ($entity
    ->getEntityType()
    ->isRevisionable() === TRUE) {
    $revision_id = $entity
      ->getRevisionId();
  }
  if (is_null($revision_id)) {
    $revision_id = $entity_id;
  }
  if (!empty($config
    ->get('index_revisions'))) {

    // Clear previous taxonomy index for the specific revision ID of the entity
    // since we want to keep track of previous revisions.
    \Drupal::database()
      ->delete('taxonomy_entity_index')
      ->condition('entity_type', $entity_type_id)
      ->condition('entity_id', $entity_id)
      ->condition('revision_id', $revision_id)
      ->execute();
  }
  else {

    // Clear all prior index records for this entity.
    \Drupal::database()
      ->delete('taxonomy_entity_index')
      ->condition('entity_type', $entity_type_id)
      ->condition('entity_id', $entity_id)
      ->execute();
  }
  $term_ref_field_names = taxonomy_entity_index_get_taxonomy_field_names($entity_type_id);
  if (empty($term_ref_field_names[$bundle])) {
    return;
  }
  $term_ref_field_names = $term_ref_field_names[$bundle];
  $terms = [];
  foreach ($term_ref_field_names as $field_name) {
    if ($items = $entity
      ->get($field_name)
      ->getValue()) {
      foreach ($items as $delta => $item) {

        // Check the terms array to see if this one is already there.
        $exists = array_search($item['target_id'], array_column($terms, 'tid'));

        // Check config to see if we are to index each field individually.
        if (!empty($config
          ->get('index_per_field')) || $exists === FALSE) {
          $terms[] = [
            'tid' => $item['target_id'],
            'field_name' => $field_name,
            'delta' => $delta,
          ];
        }
      }
    }
  }
  if (!empty($terms)) {
    $query = \Drupal::database()
      ->insert('taxonomy_entity_index');
    $query
      ->fields([
      'entity_type',
      'bundle',
      'entity_id',
      'revision_id',
      'field_name',
      'delta',
      'tid',
    ]);
    foreach ($terms as $term) {
      $query
        ->values([
        'entity_type' => $entity_type_id,
        'bundle' => $bundle,
        'entity_id' => $entity_id,
        'revision_id' => $revision_id,
        'field_name' => $term['field_name'],
        'delta' => $term['delta'],
        'tid' => $term['tid'],
      ]);
    }
    $query
      ->execute();
  }
}

/**
 * Return all the taxonomy entity reference field names for a given entity type.
 */
function taxonomy_entity_index_get_taxonomy_field_names($entity_type_id) {
  $cache_id = 'entity-taxonomy-fields_' . $entity_type_id;
  $entity_ref_fields =& drupal_static($cache_id);
  if (!isset($entity_ref_fields)) {
    if ($cache = \Drupal::cache()
      ->get($cache_id)) {
      $entity_ref_fields = $cache->data;
    }
    else {
      $entity_ref_fields = [];
      $entity_field_manager = \Drupal::service('entity_field.manager');
      $fieldmap = $entity_field_manager
        ->getFieldMapByFieldType('entity_reference');
      if (isset($fieldmap[$entity_type_id])) {
        foreach ($fieldmap[$entity_type_id] as $field_name => $field) {
          foreach ($field['bundles'] as $bundle) {
            $field_definitions =& drupal_static('entity-taxonomy-field-defs' . '_' . $entity_type_id . '_' . $bundle);
            if (!isset($field_definitions)) {
              $field_definitions = $entity_field_manager
                ->getFieldDefinitions($entity_type_id, $bundle);
            }
            $field_definition = $field_definitions[$field_name];
            $settings = $field_definition
              ->getSettings();
            if ($settings['target_type'] === 'taxonomy_term') {
              $entity_ref_fields[$bundle][] = $field_name;
            }
          }
        }
      }
      \Drupal::cache()
        ->set($cache_id, $entity_ref_fields, Cache::PERMANENT, [
        'entity_types',
        'entity_field_info',
      ]);
    }
  }
  return $entity_ref_fields;
}

/**
 * Batch callback; re-index all the terms for a given entity type.
 */
function taxonomy_entity_index_reindex_entity_type($entity_type_id, &$context) {
  $entity_type_manger = \Drupal::entityTypeManager();
  $entity_type = $entity_type_manger
    ->getDefinition($entity_type_id);
  $bundle_key = $entity_type
    ->getKey('bundle');
  if (empty($context['sandbox'])) {
    $context['sandbox'] = [];
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_id'] = 0;
    $context['sandbox']['bundles'] = array_keys(taxonomy_entity_index_get_taxonomy_field_names($entity_type_id));
    $context['sandbox']['entity_key_id'] = $entity_type
      ->getKey('id');

    // Clear out any records for this type.
    \Drupal::database()
      ->delete('taxonomy_entity_index')
      ->condition('entity_type', $entity_type_id)
      ->execute();

    // Calculate the maximum number of entities.
    if (!empty($context['sandbox']['bundles'])) {
      $query = \Drupal::entityQuery($entity_type_id);
      if ($bundle_key) {
        $query
          ->condition($bundle_key, $context['sandbox']['bundles'], 'IN');
      }
      $query
        ->condition($context['sandbox']['entity_key_id'], 0, '>');
      $query
        ->count();
      $context['sandbox']['max'] = (int) $query
        ->execute();
    }
    if (empty($context['sandbox']['max'])) {
      $context['finished'] = TRUE;
      return;
    }
  }
  $entity_id_key = $context['sandbox']['entity_key_id'];
  $limit = 25;
  $query = \Drupal::entityQuery($entity_type_id);
  if ($bundle_key) {
    $query
      ->condition($bundle_key, $context['sandbox']['bundles'], 'IN');
  }
  $query
    ->condition($entity_id_key, $context['sandbox']['current_id'], '>');
  $query
    ->sort($entity_id_key, 'ASC');
  $query
    ->range(0, $limit);
  $results = $query
    ->execute();
  $entities = $entity_type_manger
    ->getStorage($entity_type_id)
    ->loadMultiple($results);
  foreach ($entities as $id => $entity) {
    taxonomy_entity_index_entity_update($entity);
    $context['sandbox']['current_id'] = $id;
    $context['message'] = t('Updating taxonomy entity index data for @type @id.', [
      '@type' => $entity_type_id,
      '@id' => $id,
    ]);
  }

  // In case any of the entities fail to load, increase the progress by the
  // stub entity count.
  $context['sandbox']['progress'] += count($results);
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] >= $context['sandbox']['max'];
  }
}

/**
 * Batch 'finished' callback.
 *
 * @see taxonomy_entity_index_admin_form()
 * @see taxonomy_entity_index_reindex_entity_type()
 */
function taxonomy_entity_index_reindex_finished($success, $results, $operations) {
  if ($success) {
    \Drupal::messenger()
      ->addMessage(t('Taxonomy entity index rebuilt successfully.'));
  }
  else {

    // An error occurred.
    \Drupal::messenger()
      ->addError(t('An error occurred while processing the operation.'));
  }
}

/**
 * Get all entity types, which can be used in the views integration.
 *
 * Therefore both the entity type has to be fieldable and the base table
 * has already a views integration.
 *
 * @return \Drupal\Core\Entity\EntityTypeInterface[]
 *   An array of entity types.
 */
function taxonomy_entity_index_entity_views_integrable() {
  $entity_types = \Drupal::entityTypeManager()
    ->getDefinitions();
  foreach ($entity_types as $entity_type_id => $entity_type) {
    if (is_null($entity_type
      ->getBaseTable()) || !$entity_type
      ->entityClassImplements('\\Drupal\\Core\\Entity\\ContentEntityInterface')) {
      unset($entity_types[$entity_type_id]);
    }
  }
  return $entity_types;
}

/**
 * Determine if the views plugins should support revisions.
 *
 * @param array $entity_keys
 *   The entity keys for the type being checked.
 *
 * @return bool
 *   True indicates revisions should be supported.
 */
function taxonomy_entity_index_entity_views_revisionable(array $entity_keys) {

  // Return false if revision support isn't enabled.
  $config = \Drupal::config('taxonomy_entity_index.settings');
  if (empty($config
    ->get('index_revisions'))) {
    return FALSE;
  }

  // Does the entity support revisions?
  if (!empty($entity_keys['revision'])) {
    return TRUE;
  }

  // Default to false.
  return FALSE;
}

Functions

Namesort descending Description
taxonomy_entity_index_entity_delete Implements hook_entity_delete().
taxonomy_entity_index_entity_insert Implements hook_entity_insert().
taxonomy_entity_index_entity_revision_delete Implements hook_entity_revision_delete().
taxonomy_entity_index_entity_update Implements hook_entity_update().
taxonomy_entity_index_entity_views_integrable Get all entity types, which can be used in the views integration.
taxonomy_entity_index_entity_views_revisionable Determine if the views plugins should support revisions.
taxonomy_entity_index_field_config_delete Implements hook_field_config_delete().
taxonomy_entity_index_get_taxonomy_field_names Return all the taxonomy entity reference field names for a given entity type.
taxonomy_entity_index_reindex_entity_type Batch callback; re-index all the terms for a given entity type.
taxonomy_entity_index_reindex_finished Batch 'finished' callback.
taxonomy_entity_index_taxonomy_term_delete Implements hook_ENTITY_TYPE_delete().