Skip to content

Instantly share code, notes, and snippets.

@ahebrank
Created December 9, 2023 19:17
Show Gist options
  • Save ahebrank/0a66ed4abca03804f30d1882c3edbf69 to your computer and use it in GitHub Desktop.
Save ahebrank/0a66ed4abca03804f30d1882c3edbf69 to your computer and use it in GitHub Desktop.
diff --git a/README.md b/README.md
index 7ab5cfb..9e2f44e 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Select translation also provides an API following the same selection algorithm a
Based on the drupal 7 code by Alexandru Croitor (Placinta) which includes a much
better Views filter handler that uses left joins instead of correlated
(dependent) sub-queries, which should prove to work much faster when there are
-a lot of nodes in the database.
+a lot of entities in the database.
https://www.drupal.org/user/176134
Big thanks to Alice Heaton for the original D6 module.
diff --git a/select_translation.info.yml b/select_translation.info.yml
index 94e7222..756aa5b 100644
--- a/select_translation.info.yml
+++ b/select_translation.info.yml
@@ -1,6 +1,6 @@
name: 'Select Translation'
type: module
-description: 'Provides a Views filter to select which translation of a node should be displayed.'
+description: 'Provides a Views filter to select which translation of a entity should be displayed.'
package: Multilingual
core_version_requirement: ^9 || ^10
diff --git a/select_translation.module b/select_translation.module
index a99f825..d0aa4fe 100644
--- a/select_translation.module
+++ b/select_translation.module
@@ -6,7 +6,7 @@
*/
use Drupal\Core\Language\LanguageInterface;
-use Drupal\node\Entity\Node;
+use Drupal\Core\Entity\ContentEntityInterface;
/**
* Parse the mode argument.
@@ -52,42 +52,44 @@ function select_translation_parse_mode($mode) {
}
/**
- * Returns the selected translation of the given node.
+ * Returns the selected translation of the given entity.
*
* The value of the mode string can be:
*
- * - 'original', in which case the function will return a node following this
+ * - 'original', in which case the function will return a entity following this
* preference order:
- * + the node in the current language, if available;
- * + the node in the original language, otherwise.
+ * + the entity in the current language, if available;
+ * + the entity in the original language, otherwise.
*
- * - 'default', in which case the function will return a node following this
+ * - 'default', in which case the function will return a entity following this
* preference order:
- * + the node in the current language, if available;
- * + the node in the default language, if available;
- * + the node in the original language, otherwise.
+ * + the entity in the current language, if available;
+ * + the entity in the default language, if available;
+ * + the entity in the original language, otherwise.
*
* - a comma separated list of language codes, in which case it will return
- * the first available node translation.
+ * the first available entity translation.
*
* In that list, the special value 'current' refers to the current
* interface language, 'default' refers to the site default language, and
- * 'original' to the node original language. If no match is found the node
+ * 'original' to the entity original language. If no match is found the entity
* in the original language is returned.
*
- * @param int $nid
- * The node id.
+ * @param ContentEntityInterface $entity
+ * The entity
* @param string $mode
* The mode specifying how the translation should be selected.
*
- * @return \Drupal\node\Entity\Node
- * The Node entity in the selected translation, or the original translation
- * if one from $mode cannot be selected, or NULL if the node cannot be
+ * @return ContentEntityInterface
+ * The entity entity in the selected translation, or the original translation
+ * if one from $mode cannot be selected, or NULL if the entity cannot be
* found.
*/
-function select_translation_of_node($nid, $mode = 'default') {
- $node = Node::load($nid);
- if (!$node) {
+function select_translation_of_entity(ContentEntityInterface $entity, $mode = 'default') {
+ if (!$entity) {
+ return NULL;
+ }
+ if (!$entity->isTranslatable()) {
return NULL;
}
@@ -95,10 +97,10 @@ function select_translation_of_node($nid, $mode = 'default') {
foreach ($lang_list as $m) {
if ($m == 'original') {
- return $node->getUntranslated();
+ return $entity->getUntranslated();
}
- elseif ($node->hasTranslation($m)) {
- return $node->getTranslation($m);
+ elseif ($entity->hasTranslation($m)) {
+ return $entity->getTranslation($m);
}
}
diff --git a/select_translation.views.inc b/select_translation.views.inc
index 1fe3516..d27a24f 100644
--- a/select_translation.views.inc
+++ b/select_translation.views.inc
@@ -13,9 +13,18 @@ function select_translation_views_data_alter(array &$data) {
'title' => t('Select translation'),
'filter' => [
'title' => t('Select translation'),
- 'help' => t('Select which translation of a node should be displayed'),
+ 'help' => t('Select which translation of a entity should be displayed'),
'field' => 'nid',
'id' => 'select_translation_filter',
],
];
+ $data['taxonomy_term_field_data']['select_translation'] = [
+ 'title' => t('Select translation'),
+ 'filter' => [
+ 'title' => t('Select translation'),
+ 'help' => t('Select which translation of a term should be displayed'),
+ 'field' => 'tid',
+ 'id' => 'select_translation_filter',
+ ],
+ ];
}
diff --git a/src/Commands/SelectTranslationCommands.php b/src/Commands/SelectTranslationCommands.php
index 98b24e7..8bc4d6e 100644
--- a/src/Commands/SelectTranslationCommands.php
+++ b/src/Commands/SelectTranslationCommands.php
@@ -12,10 +12,10 @@ use Drush\Commands\DrushCommands;
class SelectTranslationCommands extends DrushCommands {
/**
- * Select which translation of a node should be displayed.
+ * Select which translation of an entity should be displayed.
*
- * @param int $nid
- * The Node ID.
+ * @param int $entity_id
+ * The entity ID.
*
* @command select_translation:translation
* @aliases select-translation
@@ -26,26 +26,26 @@ class SelectTranslationCommands extends DrushCommands {
* @usage select_translation:translation --mode default
*
*/
- public function translation($nid, array $options = ['mode' => NULL]) {
- $node_id = filter_var($nid, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
- if (!$node_id) {
+ public function translation($entity_id, array $options = ['mode' => NULL]) {
+ $entity_id = filter_var($entity_id, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
+ if (!$entity_id) {
throw new \Exception(dt("The 'nid' argument must be an integer >= 1."));
}
$mode = $options['mode'];
if ($mode) {
- $node = select_translation_of_node($node_id, $mode);
+ $entity = select_translation_of_entity($entity_id, $mode);
}
else {
- $node = select_translation_of_node($node_id);
+ $entity = select_translation_of_entity($entity_id);
}
- if (!$node) {
- throw new \Exception(dt("Node with 'nid' = $nid not available."));
+ if (!$entity) {
+ throw new \Exception(dt("Entity with 'id' = $entity_id not available."));
}
- \Drupal::logger('select_translation')->info("Selected translation for node $nid: " . $node->language()->getId());
- return $node;
+ \Drupal::logger('select_translation')->info("Selected translation for node $entity_id: " . $entity->language()->getId());
+ return $entity;
}
}
diff --git a/src/Plugin/views/filter/SelectTranslation.php b/src/Plugin/views/filter/SelectTranslation.php
index bc0e8f9..a099cea 100644
--- a/src/Plugin/views/filter/SelectTranslation.php
+++ b/src/Plugin/views/filter/SelectTranslation.php
@@ -5,7 +5,6 @@ namespace Drupal\select_translation\Plugin\views\filter;
use Drupal\Core\Database\Query\Condition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
-use Drupal\node\NodeInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Drupal\views\Views;
@@ -51,7 +50,7 @@ class SelectTranslation extends FilterPluginBase {
*/
public function adminSummary() {
$options = [
- 'original' => $this->t('Original node language fallback'),
+ 'original' => $this->t('Original entity language fallback'),
'default' => $this->t('Default site language fallback'),
'fallback' => $this->t('Language fallback candidates list'),
'list' => $this->t('Custom language priority'),
@@ -76,8 +75,8 @@ class SelectTranslation extends FilterPluginBase {
'#fieldset' => 'mode',
'#type' => 'radios',
'#options' => [
- 'original' => $this->t('Use the current interface language; if not available use the original node language'),
- 'default' => $this->t('Use the current interface language; if not available use the default site language; if not available use the original node language'),
+ 'original' => $this->t('Use the current interface language; if not available use the original entity language'),
+ 'default' => $this->t('Use the current interface language; if not available use the default site language; if not available use the original entity language'),
'fallback' => $this->t('Use the language fallback candidates list provided by the language manager service'),
'list' => $this->t('Custom language priorities'),
],
@@ -90,13 +89,13 @@ class SelectTranslation extends FilterPluginBase {
'#title' => $this->t('Language priorities'),
'#description' => $this->t('<p>If the selection mode is set to "Custom language priorities",
a comma separated list of language codes can be specified.<br/>
- The filter will then return the node in the first available language
- in that list; falling back to the original node language if no match was found.</p>
+ The filter will then return the entity in the first available language
+ in that list; falling back to the original entity language if no match was found.</p>
Some special values are recognized:
<ul>
<li>"<em>current</em>" will be replaced with the current interface language;</li>
<li>"<em>default</em>" will be replaced with the default site language;</li>
- <li>"<em>original</em>" will be replaced with the original node language.</li>
+ <li>"<em>original</em>" will be replaced with the original entity language.</li>
</ul>
Example:<br/><em>en,fr,current,default,original</em><br/>
This will return:
@@ -105,7 +104,7 @@ class SelectTranslation extends FilterPluginBase {
<li>if not, then the version in French, if available;</li>
<li>if not, then the version in the current interface language, if available;</li>
<li>if not, then the version in the default site language, if available;</li>
- <li>if none are available it will return the original node version.</li>
+ <li>if none are available it will return the original entity version.</li>
</ol>'),
'#default_value' => !empty($this->options['priorities']) ? $this->options['priorities'] : '',
'#states' => [
@@ -127,7 +126,7 @@ class SelectTranslation extends FilterPluginBase {
'#type' => 'checkbox',
'#title' => $this->t('Return content in the site default language when a translation for the current language *does* exist, but it is unpublished.'),
'#description' => $this->t('When you check this option, in addition to the order chosen above, content will be shown in the default site language in the event that the translation in the current language is unpublished.<br/>
- <strong>NOTE</strong>: This option assumes that the view is already filtering out unpublished content with the <code>Published (=Yes)</code> criterion, otherwise both the published and unpublished node will be displayed.'),
+ <strong>NOTE</strong>: This option assumes that the view is already filtering out unpublished content with the <code>Published (=Yes)</code> criterion, otherwise both the published and unpublished entity will be displayed.'),
'#default_value' => !empty($this->options['include_content_with_unpublished_translation']) ? $this->options['include_content_with_unpublished_translation'] : 0,
];
}
@@ -166,7 +165,7 @@ class SelectTranslation extends FilterPluginBase {
// Now build the query.
$query = $this->query;
- $alias = $query->ensureTable('node_field_data');
+ $alias = $query->ensureTable($this->table);
$condition_holder = new Condition('OR');
$i = 0;
@@ -178,13 +177,13 @@ class SelectTranslation extends FilterPluginBase {
// Before adding the currently processed language exclude the ones
// already processed in previous iterations.
foreach ($exclude as $e) {
- $and->isNull("$e.nid");
+ $and->isNull($e . "." . $this->realField);
}
if ($language != 'original') {
- // Create a Views join on the node table, and add it as a relationship.
+ // Create a Views join on the entity table, and add it as a relationship.
// This is used to find if there are translations of a certain language.
- $sub_query_alias = 'nt' . $i;
+ $sub_query_alias = 'et' . $i;
$exclude[] = $sub_query_alias;
++$i;
@@ -192,37 +191,37 @@ class SelectTranslation extends FilterPluginBase {
// exists clauses for each left joined node table (maybe specific to all
// node access modules), thus breaking the listing, we wrap the table in
// a sub-query, avoiding the exists clause.
- $join = $this->nodeAccessJoin($language, $alias, $sub_query_alias);
+ $join = $this->entityAccessJoin($current_language, $this->table, $sub_query_alias);
// Add the join as a relationship.
- $query->addRelationship($sub_query_alias, $join, 'node_field_data');
+ $query->addRelationship($sub_query_alias, $join, $this->table);
- // Include nodes of specified language.
+ // Include entities of specified language.
$and->condition("$alias.langcode", $language);
}
else {
- // Include nodes that are the base of a translation (aka original).
+ // Include entities that are the base of a translation (aka original).
$and->condition("$alias.default_langcode", 1);
}
$condition_holder->condition($and);
}
- // Include site default nodes in place of unpublished translations.
+ // Include site default entities in place of unpublished translations.
if ($this->options['include_content_with_unpublished_translation']) {
- $sub_query_alias = 'nt' . $i;
+ $sub_query_alias = 'et' . $i;
// Join with the currently selected language.
- $join = $this->nodeAccessJoin($current_language, 'node_field_data', $sub_query_alias);
+ $join = $this->entityAccessJoin($current_language, $this->table, $sub_query_alias);
// Add the join as a relationship.
- $query->addRelationship($sub_query_alias, $join, 'node_field_data');
+ $query->addRelationship($sub_query_alias, $join, $this->table);
- // The default language node will be selected, if the current language
- // (translated) node is unpublished.
+ // The default language entity will be selected, if the current language
+ // (translated) entity is unpublished.
$and = (new Condition('AND'))
->condition("$alias.langcode", $default_language)
- ->condition("$sub_query_alias.status", NodeInterface::NOT_PUBLISHED);
+ ->condition("$sub_query_alias.status", 0);
$condition_holder->condition($and);
}
@@ -232,27 +231,27 @@ class SelectTranslation extends FilterPluginBase {
}
/**
- * Join to the node table where the nodes have the given language.
+ * Join to the entity table where the entities have the given language.
*
* @param string $language
- * The language of the nodes that should be retrieved.
+ * The language of the entities that should be retrieved.
* @param string $alias
- * The alias of the main node table.
+ * The alias of the main entity table.
* @param string $sub_query_alias
- * The alias of the sub query node table.
+ * The alias of the sub query entity table.
*/
- private function nodeAccessJoin($language, $alias, $sub_query_alias) {
- $sub_query = \Drupal::database()->select('node_field_data', $sub_query_alias);
- $sub_query->addField($sub_query_alias, 'nid');
+ private function entityAccessJoin($language, $alias, $sub_query_alias) {
+ $sub_query = \Drupal::database()->select($this->table, $sub_query_alias);
+ $sub_query->addField($sub_query_alias, $this->realField);
$sub_query->addfield($sub_query_alias, 'status');
$sub_query->addField($sub_query_alias, 'langcode');
$sub_query->condition("$sub_query_alias.langcode", $language);
$configuration = [
'table' => $sub_query,
- 'field' => 'nid',
+ 'field' => $this->realField,
'left_table' => $alias,
- 'left_field' => 'nid',
+ 'left_field' => $this->realField,
'operator' => '=',
];
return Views::pluginManager('join')->createInstance('standard', $configuration);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment