entity_language_fallback.module in Entity Language Fallback 8
Add fallback languages to entities.
File
entity_language_fallback.moduleView source
<?php
/**
* @file
* Add fallback languages to entities.
*/
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\entity_language_fallback\Plugin\search_api\datasource\ContentEntityFallback;
use Drupal\language\ConfigurableLanguageInterface;
/**
* Implements hook_language_fallback_candidates_alter()
*/
function entity_language_fallback_language_fallback_candidates_alter(array &$candidates, array $context) {
$operation = $context['operation'];
if ($operation == 'entity_upcast' || $operation == 'entity_view') {
/* @var $fallback_controller \Drupal\entity_language_fallback\FallbackController */
$fallback_controller = \Drupal::service('language_fallback.controller');
if ($new_candidates = $fallback_controller
->getEntityFallbackCandidates($context['data'], $context['langcode'])) {
$candidates = $new_candidates;
}
}
}
/**
* Implements hook_form_FORM_ID_alter()
*/
function entity_language_fallback_form_language_admin_edit_form_alter(&$form, FormStateInterface $form_state) {
/** @var Drupal\language\Entity\ConfigurableLanguage $this_language */
$this_language = $form_state
->getFormObject()
->getEntity();
$languages = Drupal::languageManager()
->getLanguages();
$options = [];
foreach ($languages as $language) {
// Only include this language if its not itself.
if ($language
->getId() != $this_language
->getId()) {
$options[$language
->getId()] = $language
->getName();
}
}
$form['entity_language_fallback'] = [
'#title' => t('Entity fallback language'),
'#description' => t('Choose one or more fallback languages in prioritized order. The languages are used as fallback in entity view.'),
'#type' => 'details',
'#open' => TRUE,
'#tree' => TRUE,
];
// Creating one priority field per available language.
$default_values = $this_language
->getThirdPartySetting('entity_language_fallback', 'fallback_langcodes', []);
for ($i = 0; $i < count($options); $i++) {
$form['entity_language_fallback'][$i] = [
'#type' => 'select',
'#title' => t('Priority @priority', [
'@priority' => $i + 1,
]),
'#description' => t('Choose the language used as priority @priority fallback language.', [
'@priority' => $i + 1,
]),
'#options' => $options,
'#default_value' => !empty($default_values[$i]) ? $default_values[$i] : '',
'#empty_option' => t('-None-'),
'#tree' => TRUE,
];
}
$form['#entity_builders'][] = 'entity_language_fallback_form_language_admin_edit_form_builder';
}
/**
* Entity builder for the language form entity_language_fallback options.
*
* @see entity_language_fallback_form_language_admin_edit_form_alter()
*/
function entity_language_fallback_form_language_admin_edit_form_builder($entity_type, ConfigurableLanguageInterface $this_language, &$form, FormStateInterface $form_state) {
$this_language
->setThirdPartySetting('entity_language_fallback', 'fallback_langcodes', $form_state
->getValue('entity_language_fallback'));
}
/**
* Implements hook_entity_insert().
*
* Modified version of search_api_entity_insert().
* @see search_api_entity_insert()
*/
function entity_language_fallback_entity_insert(EntityInterface $entity) {
if (!\Drupal::moduleHandler()
->moduleExists('search_api')) {
return;
}
// Check if the entity is a content entity.
if (!$entity instanceof ContentEntityInterface || $entity->search_api_skip_tracking) {
return;
}
$indexes = ContentEntityFallback::getIndexesForEntity($entity);
if (!$indexes) {
return;
}
// Compute the item IDs for all languages set up on the language fallback chain.
$item_ids = [];
$entity_id = $entity
->id();
$fallback_controller = \Drupal::service('language_fallback.controller');
$fallback_languages = array_keys($fallback_controller
->getTranslations($entity));
foreach ($fallback_languages as $langcode) {
$item_ids[] = $entity_id . ':' . $langcode;
}
$datasource_id = 'entity_language_fallback:' . $entity
->getEntityTypeId();
foreach ($indexes as $index) {
$filtered_item_ids = ContentEntityFallback::filterValidItemIds($index, $datasource_id, $item_ids);
$index
->trackItemsInserted($datasource_id, $filtered_item_ids);
}
}
/**
* Implements hook_entity_update().
*
* search_api_entity_update() can only update items that are in ContentEntity
* datasources.
*
* @see search_api_entity_update().
*/
function entity_language_fallback_entity_update(EntityInterface $entity) {
if (!\Drupal::moduleHandler()
->moduleExists('search_api')) {
return;
}
// Check if the entity is a content entity.
if (!$entity instanceof ContentEntityInterface || $entity->search_api_skip_tracking) {
return;
}
$indexes = ContentEntityFallback::getIndexesForEntity($entity);
if (!$indexes) {
return;
}
/** @var \Drupal\entity_language_fallback\FallbackControllerInterface $fallback_controller */
static $fallback_controller;
if (!isset($fallback_controller)) {
$fallback_controller = \Drupal::service('language_fallback.controller');
}
// Compare old and new languages for the entity to identify inserted,
// updated and deleted translations (and, therefore, search items).
$entity_id = $entity
->id();
$inserted_item_ids = [];
$updated_item_ids = $fallback_controller
->getTranslations($entity);
$deleted_item_ids = [];
$old_translations = $fallback_controller
->getTranslations($entity->original);
foreach ($old_translations as $langcode => $language) {
if (!isset($updated_item_ids[$langcode])) {
$deleted_item_ids[] = $langcode;
}
}
foreach ($updated_item_ids as $langcode => $language) {
if (!isset($old_translations[$langcode])) {
unset($updated_item_ids[$langcode]);
$inserted_item_ids[] = $langcode;
}
}
$datasource_id = 'entity_language_fallback:' . $entity
->getEntityTypeId();
$combine_id = function ($langcode) use ($entity_id) {
return $entity_id . ':' . $langcode;
};
$inserted_item_ids = array_map($combine_id, $inserted_item_ids);
$updated_item_ids = array_map($combine_id, array_keys($updated_item_ids));
$deleted_item_ids = array_map($combine_id, $deleted_item_ids);
foreach ($indexes as $index) {
if ($inserted_item_ids) {
$filtered_item_ids = ContentEntityFallback::filterValidItemIds($index, $datasource_id, $inserted_item_ids);
$index
->trackItemsInserted($datasource_id, $filtered_item_ids);
}
if ($updated_item_ids) {
$index
->trackItemsUpdated($datasource_id, $updated_item_ids);
}
if ($deleted_item_ids) {
$index
->trackItemsDeleted($datasource_id, $deleted_item_ids);
}
}
}
/**
* Implements hook_entity_delete().
*
* Deletes all entries for this entity from the tracking table for each index
* that tracks this entity type.
*
* By setting the $entity->search_api_skip_tracking property to a true-like
* value before this hook is invoked, you can prevent this behavior and make the
* Search API ignore this deletion. (Note that this might lead to stale data in
* the tracking table or on the server, since the item will not removed from
* there (if it has been added before).)
*
* Note that this function implements tracking only on behalf of the "Content
* Entity" datasource defined in this module, not for entity-based datasources
* in general. Datasources defined by other modules still have to implement
* their own mechanism for tracking new/updated/deleted entities.
*
* @see \Drupal\search_api\Plugin\search_api\datasource\ContentEntity
*/
function entity_language_fallback_entity_delete(EntityInterface $entity) {
if (!\Drupal::moduleHandler()
->moduleExists('search_api')) {
return;
}
// Check if the entity is a content entity.
if (!$entity instanceof ContentEntityInterface || $entity->search_api_skip_tracking) {
return;
}
$indexes = ContentEntityFallback::getIndexesForEntity($entity);
if (!$indexes) {
return;
}
// Remove the search items for all the entity's translations.
$item_ids = [];
$entity_id = $entity
->id();
foreach (array_keys($entity
->getTranslationLanguages()) as $langcode) {
$item_ids[] = $entity_id . ':' . $langcode;
}
$datasource_id = 'entity:' . $entity
->getEntityTypeId();
foreach ($indexes as $index) {
$index
->trackItemsDeleted($datasource_id, $item_ids);
}
}
/**
* Implements hook_search_api_index_items_alter().
*/
function entity_language_fallback_search_api_index_items_alter(\Drupal\search_api\IndexInterface $index, array &$items) {
/** @var Drupal\search_api\Item\Item $item */
foreach ($items as &$item) {
$object = $item
->getOriginalObject(TRUE);
$lang = isset($object->language) ? $object->language : $object
->getValue()->langcode->value;
if ($lang) {
$item
->setLanguage($lang);
}
}
}
Functions
Name | Description |
---|---|
entity_language_fallback_entity_delete | Implements hook_entity_delete(). |
entity_language_fallback_entity_insert | Implements hook_entity_insert(). |
entity_language_fallback_entity_update | Implements hook_entity_update(). |
entity_language_fallback_form_language_admin_edit_form_alter | Implements hook_form_FORM_ID_alter() |
entity_language_fallback_form_language_admin_edit_form_builder | Entity builder for the language form entity_language_fallback options. |
entity_language_fallback_language_fallback_candidates_alter | Implements hook_language_fallback_candidates_alter() |
entity_language_fallback_search_api_index_items_alter | Implements hook_search_api_index_items_alter(). |