Backup of db before drupal security update
[yaffs-website] / web / core / modules / taxonomy / taxonomy.module
1 <?php
2
3 /**
4  * @file
5  * Enables the organization of content into categories.
6  */
7
8 use Drupal\Component\Utility\Tags;
9 use Drupal\Component\Utility\Unicode;
10 use Drupal\Core\Entity\EntityInterface;
11 use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
12 use Drupal\Core\Render\Element;
13 use Drupal\Core\Routing\RouteMatchInterface;
14 use Drupal\Core\Url;
15 use Drupal\taxonomy\Entity\Term;
16 use Drupal\taxonomy\Entity\Vocabulary;
17 use Drupal\taxonomy\TermInterface;
18 use Drupal\taxonomy\VocabularyInterface;
19
20 /**
21  * Denotes that no term in the vocabulary has a parent.
22  *
23  * @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
24  *   \Drupal\taxonomy\VocabularyInterface::HIERARCHY_DISABLED instead.
25  */
26 const TAXONOMY_HIERARCHY_DISABLED = 0;
27
28 /**
29  * Denotes that one or more terms in the vocabulary has a single parent.
30  *
31  * @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
32  *   \Drupal\taxonomy\VocabularyInterface::HIERARCHY_SINGLE instead.
33  */
34 const TAXONOMY_HIERARCHY_SINGLE = 1;
35
36 /**
37  * Denotes that one or more terms in the vocabulary have multiple parents.
38  *
39  * @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
40  *   \Drupal\taxonomy\VocabularyInterface::HIERARCHY_MULTIPLE instead.
41  */
42 const TAXONOMY_HIERARCHY_MULTIPLE = 2;
43
44 /**
45  * Implements hook_help().
46  */
47 function taxonomy_help($route_name, RouteMatchInterface $route_match) {
48   switch ($route_name) {
49     case 'help.page.taxonomy':
50       $field_ui_url = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#';
51       $output = '';
52       $output .= '<h3>' . t('About') . '</h3>';
53       $output .= '<p>' . t('The Taxonomy module allows users who have permission to create and edit content to categorize (tag) content of that type. Users who have the <em>Administer vocabularies and terms</em> <a href=":permissions" title="Taxonomy module permissions">permission</a> can add <em>vocabularies</em> that contain a set of related <em>terms</em>. The terms in a vocabulary can either be pre-set by an administrator or built gradually as content is added and edited. Terms may be organized hierarchically if desired.', [':permissions' => \Drupal::url('user.admin_permissions', [], ['fragment' => 'module-taxonomy'])]) . '</p>';
54       $output .= '<p>' . t('For more information, see the <a href=":taxonomy">online documentation for the Taxonomy module</a>.', [':taxonomy' => 'https://www.drupal.org/documentation/modules/taxonomy/']) . '</p>';
55       $output .= '<h3>' . t('Uses') . '</h3>';
56       $output .= '<dl>';
57       $output .= '<dt>' . t('Managing vocabularies') . '</dt>';
58       $output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission can add and edit vocabularies from the <a href=":taxonomy_admin">Taxonomy administration page</a>. Vocabularies can be deleted from their <em>Edit vocabulary</em> page. Users with the <em>Taxonomy term: Administer fields</em> permission may add additional fields for terms in that vocabulary using the <a href=":field_ui">Field UI module</a>.', [':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection'), ':field_ui' => $field_ui_url]) . '</dd>';
59       $output .= '<dt>' . t('Managing terms') . '</dt>';
60       $output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission or the <em>Edit terms</em> permission for a particular vocabulary can add, edit, and organize the terms in a vocabulary from a vocabulary\'s term listing page, which can be accessed by going to the <a href=":taxonomy_admin">Taxonomy administration page</a> and clicking <em>List terms</em> in the <em>Operations</em> column. Users must have the <em>Administer vocabularies and terms</em> permission or the <em>Delete terms</em> permission for a particular vocabulary to delete terms.', [':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection')]) . ' </dd>';
61       $output .= '<dt>' . t('Classifying entity content') . '</dt>';
62       $output .= '<dd>' . t('A user with the <em>Administer fields</em> permission for a certain entity type may add <em>Taxonomy term</em> reference fields to the entity type, which will allow entities to be classified using taxonomy terms. See the <a href=":entity_reference">Entity Reference help</a> for more information about reference fields. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for general information on fields and how to create and manage them.', [':field_ui' => $field_ui_url, ':field' => \Drupal::url('help.page', ['name' => 'field']), ':entity_reference' => \Drupal::url('help.page', ['name' => 'entity_reference'])]) . '</dd>';
63       $output .= '<dt>' . t('Adding new terms during content creation') . '</dt>';
64       $output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if either of the two <em>Autocomplete</em> widgets is chosen for the Taxonomy term reference field in the <em>Manage form display</em> page for the field. You will also need to enable the <em>Create referenced entities if they don\'t already exist</em> option, and restrict the field to one vocabulary.') . '</dd>';
65       $output .= '<dt>' . t('Configuring displays and form displays') . '</dt>';
66       $output .= '<dd>' . t('See the <a href=":entity_reference">Entity Reference help</a> page for the field widgets and formatters that can be configured for any reference field on the <em>Manage display</em> and <em>Manage form display</em> pages. Taxonomy additionally provides an <em>RSS category</em> formatter that displays nothing when the entity item is displayed as HTML, but displays an RSS category instead of a list when the entity item is displayed in an RSS feed.', [':entity_reference' => \Drupal::url('help.page', ['name' => 'entity_reference'])]) . '</li>';
67       $output .= '</ul>';
68       $output .= '</dd>';
69       $output .= '</dl>';
70       return $output;
71
72     case 'entity.taxonomy_vocabulary.collection':
73       $output = '<p>' . t('Taxonomy is for categorizing content. Terms are grouped into vocabularies. For example, a vocabulary called "Fruit" would contain the terms "Apple" and "Banana".') . '</p>';
74       return $output;
75
76     case 'entity.taxonomy_vocabulary.overview_form':
77       $vocabulary = $route_match->getParameter('taxonomy_vocabulary');
78       switch ($vocabulary->getHierarchy()) {
79         case VocabularyInterface::HIERARCHY_DISABLED:
80           return '<p>' . t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
81         case VocabularyInterface::HIERARCHY_SINGLE:
82           return '<p>' . t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
83         case VocabularyInterface::HIERARCHY_MULTIPLE:
84           return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label())]) . '</p>';
85       }
86   }
87 }
88
89 /**
90  * Entity URI callback.
91  */
92 function taxonomy_term_uri($term) {
93   return new Url('entity.taxonomy_term.canonical', [
94     'taxonomy_term' => $term->id(),
95   ]);
96 }
97
98 /**
99  * Implements hook_page_attachments_alter().
100  */
101 function taxonomy_page_attachments_alter(array &$page) {
102   $route_match = \Drupal::routeMatch();
103   if ($route_match->getRouteName() == 'entity.taxonomy_term.canonical' && ($term = $route_match->getParameter('taxonomy_term')) && $term instanceof TermInterface) {
104     foreach ($term->uriRelationships() as $rel) {
105       // Set the URI relationships, like canonical.
106       $page['#attached']['html_head_link'][] = [
107         [
108           'rel' => $rel,
109           'href' => $term->url($rel),
110         ],
111         TRUE,
112       ];
113
114       // Set the term path as the canonical URL to prevent duplicate content.
115       if ($rel == 'canonical') {
116         // Set the non-aliased canonical path as a default shortlink.
117         $page['#attached']['html_head_link'][] = [
118           [
119             'rel' => 'shortlink',
120             'href' => $term->url($rel, ['alias' => TRUE]),
121           ],
122           TRUE,
123         ];
124       }
125     }
126   }
127 }
128
129 /**
130  * Implements hook_theme().
131  */
132 function taxonomy_theme() {
133   return [
134     'taxonomy_term' => [
135       'render element' => 'elements',
136     ],
137   ];
138 }
139
140 /**
141  * Checks and updates the hierarchy flag of a vocabulary.
142  *
143  * Checks the current parents of all terms in a vocabulary and updates the
144  * vocabulary's hierarchy setting to the lowest possible level. If no term
145  * has parent terms then the vocabulary will be given a hierarchy of
146  * VocabularyInterface::HIERARCHY_DISABLED. If any term has a single parent then
147  * the vocabulary will be given a hierarchy of
148  * VocabularyInterface::HIERARCHY_SINGLE. If any term has multiple parents then
149  * the vocabulary will be given a hierarchy of
150  * VocabularyInterface::HIERARCHY_MULTIPLE.
151  *
152  * @param \Drupal\taxonomy\VocabularyInterface $vocabulary
153  *   A taxonomy vocabulary entity.
154  * @param $changed_term
155  *   An array of the term structure that was updated.
156  *
157  * @return
158  *   An integer that represents the level of the vocabulary's hierarchy.
159  */
160 function taxonomy_check_vocabulary_hierarchy(VocabularyInterface $vocabulary, $changed_term) {
161   $tree = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($vocabulary->id());
162   $hierarchy = VocabularyInterface::HIERARCHY_DISABLED;
163   foreach ($tree as $term) {
164     // Update the changed term with the new parent value before comparison.
165     if ($term->tid == $changed_term['tid']) {
166       $term = (object) $changed_term;
167       $term->parents = $term->parent;
168     }
169     // Check this term's parent count.
170     if (count($term->parents) > 1) {
171       $hierarchy = VocabularyInterface::HIERARCHY_MULTIPLE;
172       break;
173     }
174     elseif (count($term->parents) == 1 && !isset($term->parents[0])) {
175       $hierarchy = VocabularyInterface::HIERARCHY_SINGLE;
176     }
177   }
178   if ($hierarchy != $vocabulary->getHierarchy()) {
179     $vocabulary->setHierarchy($hierarchy);
180     $vocabulary->save();
181   }
182
183   return $hierarchy;
184 }
185
186 /**
187  * Generates an array which displays a term detail page.
188  *
189  * @param \Drupal\taxonomy\Entity\Term $term
190  *   A taxonomy term object.
191  * @param string $view_mode
192  *   View mode; e.g., 'full', 'teaser', etc.
193  * @param string $langcode
194  *   (optional) A language code to use for rendering. Defaults to the global
195  *   content language of the current request.
196  *
197  * @return array
198  *   A $page element suitable for use by drupal_render().
199  */
200 function taxonomy_term_view(Term $term, $view_mode = 'full', $langcode = NULL) {
201   return entity_view($term, $view_mode, $langcode);
202 }
203
204 /**
205  * Constructs a drupal_render() style array from an array of loaded terms.
206  *
207  * @param array $terms
208  *   An array of taxonomy terms as returned by Term::loadMultiple().
209  * @param string $view_mode
210  *   View mode; e.g., 'full', 'teaser', etc.
211  * @param string $langcode
212  *   (optional) A language code to use for rendering. Defaults to the global
213  *   content language of the current request.
214  *
215  * @return array
216  *   An array in the format expected by drupal_render().
217  */
218 function taxonomy_term_view_multiple(array $terms, $view_mode = 'full', $langcode = NULL) {
219   return entity_view_multiple($terms, $view_mode, $langcode);
220 }
221
222 /**
223  * Implements hook_theme_suggestions_HOOK().
224  */
225 function taxonomy_theme_suggestions_taxonomy_term(array $variables) {
226   $suggestions = [];
227
228   /** @var \Drupal\taxonomy\TermInterface $term */
229   $term = $variables['elements']['#taxonomy_term'];
230
231   $suggestions[] = 'taxonomy_term__' . $term->bundle();
232   $suggestions[] = 'taxonomy_term__' . $term->id();
233
234   return $suggestions;
235 }
236
237 /**
238  * Prepares variables for taxonomy term templates.
239  *
240  * Default template: taxonomy-term.html.twig.
241  *
242  * @param array $variables
243  *   An associative array containing:
244  *   - elements: An associative array containing the taxonomy term and any
245  *     fields attached to the term. Properties used:
246  *     - #taxonomy_term: A \Drupal\taxonomy\TermInterface object.
247  *     - #view_mode: The current view mode for this taxonomy term, e.g.
248  *       'full' or 'teaser'.
249  *   - attributes: HTML attributes for the containing element.
250  */
251 function template_preprocess_taxonomy_term(&$variables) {
252   $variables['view_mode'] = $variables['elements']['#view_mode'];
253   $variables['term'] = $variables['elements']['#taxonomy_term'];
254   /** @var \Drupal\taxonomy\TermInterface $term */
255   $term = $variables['term'];
256
257   $variables['url'] = $term->url();
258   // We use name here because that is what appears in the UI.
259   $variables['name'] = $variables['elements']['name'];
260   unset($variables['elements']['name']);
261   $variables['page'] = $variables['view_mode'] == 'full' && taxonomy_term_is_page($term);
262
263   // Helpful $content variable for templates.
264   $variables['content'] = [];
265   foreach (Element::children($variables['elements']) as $key) {
266     $variables['content'][$key] = $variables['elements'][$key];
267   }
268 }
269
270 /**
271  * Returns whether the current page is the page of the passed-in term.
272  *
273  * @param \Drupal\taxonomy\Entity\Term $term
274  *   A taxonomy term entity.
275  */
276 function taxonomy_term_is_page(Term $term) {
277   if (\Drupal::routeMatch()->getRouteName() == 'entity.taxonomy_term.canonical' && $page_term_id = \Drupal::routeMatch()->getRawParameter('taxonomy_term')) {
278     return $page_term_id == $term->id();
279   }
280   return FALSE;
281 }
282
283 /**
284  * Clear all static cache variables for terms.
285  */
286 function taxonomy_terms_static_reset() {
287   \Drupal::entityManager()->getStorage('taxonomy_term')->resetCache();
288 }
289
290 /**
291  * Clear all static cache variables for vocabularies.
292  *
293  * @param $ids
294  *   An array of ids to reset in the entity cache.
295  */
296 function taxonomy_vocabulary_static_reset(array $ids = NULL) {
297   \Drupal::entityManager()->getStorage('taxonomy_vocabulary')->resetCache($ids);
298 }
299
300 /**
301  * Get names for all taxonomy vocabularies.
302  *
303  * @return array
304  *   A list of existing vocabulary IDs.
305  */
306 function taxonomy_vocabulary_get_names() {
307   $names = &drupal_static(__FUNCTION__);
308
309   if (!isset($names)) {
310     $names = [];
311     $config_names = \Drupal::configFactory()->listAll('taxonomy.vocabulary.');
312     foreach ($config_names as $config_name) {
313       $id = substr($config_name, strlen('taxonomy.vocabulary.'));
314       $names[$id] = $id;
315     }
316   }
317
318   return $names;
319 }
320
321 /**
322  * Try to map a string to an existing term, as for glossary use.
323  *
324  * Provides a case-insensitive and trimmed mapping, to maximize the
325  * likelihood of a successful match.
326  *
327  * @param $name
328  *   Name of the term to search for.
329  * @param $vocabulary
330  *   (optional) Vocabulary machine name to limit the search. Defaults to NULL.
331  *
332  * @return
333  *   An array of matching term objects.
334  */
335 function taxonomy_term_load_multiple_by_name($name, $vocabulary = NULL) {
336   $values = ['name' => trim($name)];
337   if (isset($vocabulary)) {
338     $vocabularies = taxonomy_vocabulary_get_names();
339     if (isset($vocabularies[$vocabulary])) {
340       $values['vid'] = $vocabulary;
341     }
342     else {
343       // Return an empty array when filtering by a non-existing vocabulary.
344       return [];
345     }
346   }
347   return entity_load_multiple_by_properties('taxonomy_term', $values);
348 }
349
350 /**
351  * Load multiple taxonomy terms based on certain conditions.
352  *
353  * This function should be used whenever you need to load more than one term
354  * from the database. Terms are loaded into memory and will not require
355  * database access if loaded again during the same page request.
356  *
357  * @see entity_load_multiple()
358  * @see \Drupal\Core\Entity\Query\EntityQueryInterface
359  *
360  * @deprecated in Drupal 8.x, will be removed before Drupal 9.0.
361  *   Use \Drupal\taxonomy\Entity\Term::loadMultiple().
362  *
363  * @param array $tids
364  *   (optional) An array of entity IDs. If omitted, all entities are loaded.
365  *
366  * @return array
367  *   An array of taxonomy term entities, indexed by tid. When no results are
368  *   found, an empty array is returned.
369  */
370 function taxonomy_term_load_multiple(array $tids = NULL) {
371   return Term::loadMultiple($tids);
372 }
373
374 /**
375  * Loads multiple taxonomy vocabularies based on certain conditions.
376  *
377  * This function should be used whenever you need to load more than one
378  * vocabulary from the database. Terms are loaded into memory and will not
379  * require database access if loaded again during the same page request.
380  *
381  * @see entity_load_multiple()
382  *
383  * @deprecated in Drupal 8.x, will be removed before Drupal 9.0.
384  *   Use \Drupal\taxonomy\Entity\Vocabulary::loadMultiple().
385  *
386  * @param array $vids
387  *   (optional) An array of entity IDs. If omitted, all entities are loaded.
388  *
389  * @return array
390  *   An array of vocabulary objects, indexed by vid.
391  */
392 function taxonomy_vocabulary_load_multiple(array $vids = NULL) {
393   return Vocabulary::loadMultiple($vids);
394 }
395
396 /**
397  * Return the taxonomy vocabulary entity matching a vocabulary ID.
398  *
399  * @deprecated in Drupal 8.x, will be removed before Drupal 9.0.
400  *   Use \Drupal\taxonomy\Entity\Vocabulary::load().
401  *
402  * @param int $vid
403  *   The vocabulary's ID.
404  *
405  * @return \Drupal\taxonomy\Entity\Vocabulary|null
406  *   The taxonomy vocabulary entity, if exists, NULL otherwise. Results are
407  *   statically cached.
408  */
409 function taxonomy_vocabulary_load($vid) {
410   return Vocabulary::load($vid);
411 }
412
413 /**
414  * Return the taxonomy term entity matching a term ID.
415  *
416  * @deprecated in Drupal 8.x, will be removed before Drupal 9.0.
417  *   Use \Drupal\taxonomy\Entity\Term::load().
418  *
419  * @param $tid
420  *   A term's ID
421  *
422  * @return \Drupal\taxonomy\Entity\Term|null
423  *   A taxonomy term entity, or NULL if the term was not found. Results are
424  *   statically cached.
425  */
426 function taxonomy_term_load($tid) {
427   if (!is_numeric($tid)) {
428     return NULL;
429   }
430   return Term::load($tid);
431 }
432
433 /**
434  * Implodes a list of tags of a certain vocabulary into a string.
435  *
436  * @see \Drupal\Component\Utility\Tags::explode()
437  */
438 function taxonomy_implode_tags($tags, $vid = NULL) {
439   $typed_tags = [];
440   foreach ($tags as $tag) {
441     // Extract terms belonging to the vocabulary in question.
442     if (!isset($vid) || $tag->bundle() == $vid) {
443       // Make sure we have a completed loaded taxonomy term.
444       if ($tag instanceof EntityInterface && $label = $tag->label()) {
445         // Commas and quotes in tag names are special cases, so encode 'em.
446         $typed_tags[] = Tags::encode($label);
447       }
448     }
449   }
450   return implode(', ', $typed_tags);
451 }
452
453 /**
454  * Title callback for term pages.
455  *
456  * @param \Drupal\taxonomy\Entity\Term $term
457  *   A taxonomy term entity.
458  *
459  * @return
460  *   The term name to be used as the page title.
461  */
462 function taxonomy_term_title(Term $term) {
463   return $term->getName();
464 }
465
466 /**
467  * @defgroup taxonomy_index Taxonomy indexing
468  * @{
469  * Functions to maintain taxonomy indexing.
470  *
471  * Taxonomy uses default field storage to store canonical relationships
472  * between terms and fieldable entities. However its most common use case
473  * requires listing all content associated with a term or group of terms
474  * sorted by creation date. To avoid slow queries due to joining across
475  * multiple node and field tables with various conditions and order by criteria,
476  * we maintain a denormalized table with all relationships between terms,
477  * published nodes and common sort criteria such as status, sticky and created.
478  * When using other field storage engines or alternative methods of
479  * denormalizing this data you should set the
480  * taxonomy.settings:maintain_index_table to '0' to avoid unnecessary writes in
481  * SQL.
482  */
483
484 /**
485  * Implements hook_ENTITY_TYPE_insert() for node entities.
486  */
487 function taxonomy_node_insert(EntityInterface $node) {
488   // Add taxonomy index entries for the node.
489   taxonomy_build_node_index($node);
490 }
491
492 /**
493  * Builds and inserts taxonomy index entries for a given node.
494  *
495  * The index lists all terms that are related to a given node entity, and is
496  * therefore maintained at the entity level.
497  *
498  * @param \Drupal\node\Entity\Node $node
499  *   The node entity.
500  */
501 function taxonomy_build_node_index($node) {
502   // We maintain a denormalized table of term/node relationships, containing
503   // only data for current, published nodes.
504   if (!\Drupal::config('taxonomy.settings')->get('maintain_index_table') || !(\Drupal::entityManager()->getStorage('node') instanceof SqlContentEntityStorage)) {
505     return;
506   }
507
508   $status = $node->isPublished();
509   $sticky = (int) $node->isSticky();
510   // We only maintain the taxonomy index for published nodes.
511   if ($status && $node->isDefaultRevision()) {
512     // Collect a unique list of all the term IDs from all node fields.
513     $tid_all = [];
514     $entity_reference_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
515     foreach ($node->getFieldDefinitions() as $field) {
516       $field_name = $field->getName();
517       $class = $field->getItemDefinition()->getClass();
518       $is_entity_reference_class = ($class === $entity_reference_class) || is_subclass_of($class, $entity_reference_class);
519       if ($is_entity_reference_class && $field->getSetting('target_type') == 'taxonomy_term') {
520         foreach ($node->getTranslationLanguages() as $language) {
521           foreach ($node->getTranslation($language->getId())->$field_name as $item) {
522             if (!$item->isEmpty()) {
523               $tid_all[$item->target_id] = $item->target_id;
524             }
525           }
526         }
527       }
528     }
529     // Insert index entries for all the node's terms.
530     if (!empty($tid_all)) {
531       foreach ($tid_all as $tid) {
532         db_merge('taxonomy_index')
533           ->key(['nid' => $node->id(), 'tid' => $tid, 'status' => $node->isPublished()])
534           ->fields(['sticky' => $sticky, 'created' => $node->getCreatedTime()])
535           ->execute();
536       }
537     }
538   }
539 }
540
541 /**
542  * Implements hook_ENTITY_TYPE_update() for node entities.
543  */
544 function taxonomy_node_update(EntityInterface $node) {
545   // If we're not dealing with the default revision of the node, do not make any
546   // change to the taxonomy index.
547   if (!$node->isDefaultRevision()) {
548     return;
549   }
550   taxonomy_delete_node_index($node);
551   taxonomy_build_node_index($node);
552 }
553
554 /**
555  * Implements hook_ENTITY_TYPE_predelete() for node entities.
556  */
557 function taxonomy_node_predelete(EntityInterface $node) {
558   // Clean up the {taxonomy_index} table when nodes are deleted.
559   taxonomy_delete_node_index($node);
560 }
561
562 /**
563  * Deletes taxonomy index entries for a given node.
564  *
565  * @param \Drupal\Core\Entity\EntityInterface $node
566  *   The node entity.
567  */
568 function taxonomy_delete_node_index(EntityInterface $node) {
569   if (\Drupal::config('taxonomy.settings')->get('maintain_index_table')) {
570     db_delete('taxonomy_index')->condition('nid', $node->id())->execute();
571   }
572 }
573
574 /**
575  * Implements hook_ENTITY_TYPE_delete() for taxonomy_term entities.
576  */
577 function taxonomy_taxonomy_term_delete(Term $term) {
578   if (\Drupal::config('taxonomy.settings')->get('maintain_index_table')) {
579     // Clean up the {taxonomy_index} table when terms are deleted.
580     db_delete('taxonomy_index')->condition('tid', $term->id())->execute();
581   }
582 }
583
584 /**
585  * @} End of "defgroup taxonomy_index".
586  */