10

I have a large vocabulary, and admin views does not yet work for taxonomy. Taxonomy Manager does not do this as well.

Are there other options for bulk-deleting taxonomy terms?

0

21 Answers 21

15

Taxonomy manager does have bulk delete functionality, just select all the terms in your vocabulary and click the 'Delete' button:

enter image description here

If you want to do it using code something like the following should help:

$vocabulary = taxonomy_vocabulary_machine_name_load('my_custom_vocabulary');
foreach (taxonomy_get_tree($vocabulary->vid) as $term) {
  taxonomy_term_delete($term->tid);
}
5
  • Ok thanks, although Taxo Manager does not have a bulk select option, and if you have hundreds of terms you would have to check each one by one.
    – giorgio79
    Jul 27, 2012 at 9:09
  • Yeah that's kind of annoying actually, I might put in a feature request for that
    – Clive
    Jul 27, 2012 at 9:13
  • 2
    Thanks for adding both the UI and code methods! Always very useful +1 Oct 25, 2013 at 10:00
  • 5
    @giorgio79 most modern browsers support Shift+Click on checkboxes. If you click a checkbox, then Shift+Click on another checkbox in the same group, all checkboxes between those 2 will be selected/unselected.
    – Elin Y.
    May 19, 2014 at 13:55
  • I use this to check all checkboxes in Taxonomy Manager from devTools console: jQuery('.fancytree-checkbox').click();
    – zsd
    May 26, 2022 at 7:53
28

A favorite method of bulk-deleting content by content type, taxonomy vocabulary, etc utilizes the http://drupal.org/project/devel module. For deleting all terms in a vocabulary:

  1. Enable the Devel and Devel Generate modules
  2. Go to Development > Generate Terms
  3. Select the Vocabulary from which you wish to delete terms
  4. Enter "0" for number of Terms to generate
  5. Check "Delete existing terms before generating new ones"
  6. Click Submit

Voila-- empty vocabulary, otherwise untouched.

2
  • Module is called: Devel Generate
    – kenorb
    Sep 28, 2013 at 14:04
  • Some solutions make me smile. This is one of them. <3
    – apotek
    Aug 2, 2023 at 18:16
8

Untested; use for inspiration and test:

<?php

$vid = 17;

$tree = taxonomy_get_tree($vid);

if (count($tree) == 0) {
  print "Nothing to delete.\n";
}
else {
  $tree = array_slice($tree, 0, 1000);

  foreach ($tree as $term) {
    print 'Deleting tid ' . $term->tid . "\n";
    taxonomy_term_delete($term->tid);
  }
}

Put this in its own file, and execute as

drush -u 1 scr nuke_vid_18.php

Keep running it until it doesn't show anything as deleted. The array_slice is there to limit things so you don't run out of memory. You can potentially save some memory by querying directly, but taxonomy_get_tree() isn't terribly inefficient as long as you aren't doing full term loads.

Backup your database with drush sql-dump as a precaution before you do anything like this.

8

You can use the following command.

drush -v eval 'foreach(taxonomy_get_tree(123) as $term) { taxonomy_term_delete($term->tid); }'

If it doesn't work, make sure that you clear your cache (e.g. memcached).

A faster way is using the following dirty SQL query, where 123 is the ID of the vocabulary you should change.

drush sqlq "DELETE FROM taxonomy_term_data WHERE vid = 123"

You can get the vid from the vocabulary name with the following command.

drush sqlq "SELECT name, vid FROM taxonomy_vocabulary WHERE name = 'vocabulary_name'"
0
7

I've these modules: Drush and Devel For exclude all terms of taxonomy, use the generate-terms command:

drush generate-terms you_vocabulary_name 0 --kill

Change your_vocabulary_name to name of vocabulary you need delete terms

1
  • quite easy solution. thanks. why the --kill ?
    – xaa
    Apr 14, 2016 at 8:59
3

On Drupal 8 and 9 with Drush, just run :

drush entity:delete taxonomy_term --bundle=VOCABULARY_ID

Replace VOCABULARY_ID with the vocabulary machine name.

0
2

Admin views just provides preconfigured VBO views.

VBO itself works fine with terms (or any other entity type). Install VBO, create the view that you want, then use VBO to delete the terms.

2

You can also use the Taxonomy Multi-delete Terms module to delete taxonomy terms.

This module makes it possible to delete multiple terms at one time. You need to select terms and click on delete button. All selected terms will be deleted. You can also delete all terms at one time.

The module has been developed for Drupal 7 and Drupal 8. It's also covered by the security advisory policy.

0
2

To bulk delete all taxonomy terms within a vocabulary in Drupal 7, use taxonomy_term_delete() and loop through all terms.

Consider the following example.

// Get metadata about the vocabulary from its machine name.
$vocab = taxonomy_vocabulary_machine_name_load('TAXONOMY_MACHINE_NAME');

// Get a hierarchical representation of all terms.
$terms = taxonomy_get_tree($vocab->vid);

// Loop through all terms in the taxonomy, deleting each one.
if (!empty($terms)) {
  foreach ($terms as $term) {
    taxonomy_term_delete($term->tid);
  }
}

Even easier, if you have Drush and the Devel module installed, you can use the following command to bulk delete all terms in a taxonomy* from the comfort of your shell.

drush generate-terms TAXONOMY_MACHINE_NAME 0 --kill

This assumes you have the Devel Generate module enabled, which can be installed with drush en -y devel && drush en -y devel_generate.

0
2

I’m using the jQuery Easy Confirm Dialog plugin for this. First download the library from here and put this in your themes js folder.

We can then add a “Delete All Terms” button with a little code in a custom module:

function hook_form_alter(&$form, &$form_state, $form_id) {
    switch($form_id) {
        case 'taxonomy_overview_terms':
 
            if($form['#total_entries']) {
                drupal_add_library('system', 'ui.dialog');
                drupal_add_js(drupal_get_path('theme', 'YOUR_THEME_NAME').'/js/jquery.easy-confirm-dialog.js');         
                $js = 'jQuery(document).ready(function($){$(".confirm").easyconfirm({locale: { title: \'Delete all '.$form['#vocabulary']->name.' terms\', button: [\'No\',\'Yes\']}});});';
                drupal_add_js($js, array('type'=>'inline'));
                $form['actions']['delete_all'] = array(
                    '#markup' => '<a href="/admin/structure/taxonomy/'.$form['#vocabulary']->vid.'/delete-all" class="button confirm" title="Are you sure you want to delete all terms from the '.$form['#vocabulary']->name.' vocabulary?">Delete All Terms</a>',
                    '#weight' => 10,
                    '#attributes' => array('class' => array('button'))
                );
            }
 
            break;
    }
}

Now we need to define the path to our function to delete the terms:

function hook_menu() {
    $items = array();
    $items['admin/structure/taxonomy/%/delete-all'] = array(
        'title' => 'Delete all taxonomy terms',
        'type' => MENU_CALLBACK,
        'page callback' => 'delete_all_taxonomy_terms',
        'page arguments'    =>  array(3),
        'access arguments'  =>  array('administer taxonomy'),
    );
    return $items;
}

And finally add the functionality to actually delete the terms:

function delete_all_taxonomy_terms($vid) {
    $vocabulary = taxonomy_vocabulary_load($vid);
    $query = new EntityFieldQuery();
    $result = $query
        ->entityCondition('entity_type', 'taxonomy_term')
        ->propertyCondition('vid', $vid)
        ->execute();
    foreach($result['taxonomy_term'] as $term) {
        taxonomy_term_delete($term->tid);
    }
    drupal_set_message('All terms have been deleted from the '.$vocabulary->name.' vocabulary');
    drupal_goto('admin/structure/taxonomy/'.$vocabulary->machine_name);
}
1

I would recommend using Admin Views with VBO to get a view to replace the default display of Taxonomy terms.

What you have to do is the following:

  1. Enable those modules of course
  2. Enable the view called "Administration: Taxonomy terms"
  3. Add a column into the view called "Bulk operations: Taxonomy term"
  4. FLUSH CACHES - then go to Admin > Structure > Taxonomy > Specific Vocab

Views Bulk Operations and Admin Views

1

In addition to @mpdonadio code, I just added the snippet to load vid by the vocabulary's name. I hope it might help someone to save time.

$voca = "forums";
$vobj=taxonomy_vocabulary_machine_name_load("forums");
$vid = $vobj->vid;

$tree = taxonomy_get_tree($vid);

if (count($tree) == 0) {
    print "Nothing to delete.\n";
}
else {
   $tree = array_slice($tree, 0, 1000);

   foreach ($tree as $term) {
    print 'Deleting tid ' . $term->tid . "\n";
    taxonomy_term_delete($term->tid);
   }
}
1

Assuming Entity API is installed we can use entity_delete_multiple which should be faster than deleting one every time.

define("MY_VOCAB", "tags");

function _custom_zap_vocab() {
  $vocab = taxonomy_vocabulary_machine_name_load(MY_VOCAB);

  $tree = taxonomy_get_tree($vocab->vid);

  $tids = array_map(function($term){
    return $term->tid;
  }, $tree);

  entity_delete_multiple('taxonomy_term', $tids);
}
1

With Drupal 8 and Drush, just run a command like the following one.

drush php-eval 'foreach (Drupal::entityTypeManager()->getStorage("taxonomy_term")->loadByProperties(["vid" => ["department", "region"]]) as $c) {$c->delete();}'

In this example, I delete all terms in two vocabularies: department and region.

0

My answer is tangentially-related to the original question. Building on kenorb's answer, if you wish to clean ALL vocabularies at your site, you can run the following:

drush -v eval '$vocabularies = taxonomy_get_vocabularies(); foreach($vocabularies as $vocabulary) { foreach(taxonomy_get_tree($vocabulary->vid) as $term) { taxonomy_term_delete($term->tid);}}'
0

You can create a drush command named vocabulary-clean. Create a module named drush_taxonomy, inside the drush_taxonomy.drush.inc file put this code:

<?php
/**
 * @file
 * Drush commands related to taxonomy.
 */

/**
* Implements hook_drush_command().
*/
function drush_taxonomy_drush_command() {
  $items['vocabulary-clean'] = array(
    'description' => dt("Delete all terms in a vocabulary."),
    'aliases' => array('vc'),
    'arguments' => array(
      'name' => dt('The vocabulary names to clean.'),
    ),
    'examples' => array(
      'drush vocabulary-clean tags' => dt('Delete all the terms in tags vocabulary'),
      'drush vocabulary-clean tags test' => dt('Delete all the terms in tags and test vocabularies'),

    ),
  );
  return $items;
}

/**
 * Callback for the vocabulary clean command.
 */
function drush_drush_taxonomy_vocabulary_clean() {
  $names = func_get_args();

  if (!empty($names)) {
    // Check for duplicate ids.
    $test_names = array_unique($names);
    if (count($test_names) != count($names)) {
      drush_set_error('DRUSH_VOCABULARY_CLEAN_ERROR', dt('You have duplicate vocabulary names.'));
      return;
    }
    //Searching the vocabularies in the site
    $vocabulary_in_db = array_column(taxonomy_get_vocabularies(), 'machine_name');
    $vocabulary_non_existent = array_diff($names, $vocabulary_in_db);
    $vocabulary_existent = array_diff($names, $vocabulary_non_existent);

    if(count($vocabulary_existent) == 0) {
      drush_set_error('DRUSH_VOCABULARY_CLEAN_ERROR', dt("The desired vocabularies to clean doesn't exists."));
      return;
    }

    if(count($vocabulary_non_existent)) {
      drush_print(dt("Non-existent vocabularies:"));
      drush_print(implode(' ', $vocabulary_non_existent));
    }

    foreach ($vocabulary_existent as $name) {
      $vid = taxonomy_vocabulary_machine_name_load($name)->vid;
      foreach(taxonomy_get_tree($vid) as $term) {
        taxonomy_term_delete($term->tid);
      }
    }

    drush_print(dt("Vocabularies cleaned:"));
    drush_print(implode(' ', $vocabulary_existent));
  }
  else {
    drush_set_error('DRUSH_VOCABULARY_CLEAN_ERROR', dt("You must enter at least one vocabulary name."));
  }
}

Install the module, run drush cc drush to clear the drush cache and use the command like this:

drush vc tags

or

drush vocabulary-clean tags

If you want add another alias to the command add elements to the aliases array like this:

'aliases' => array('vc', 'voc-clean', 'clean'),

And you can use this commands:

drush vc tags
drush voc-clean tags
drush clean tags

Always the output will be:

Vocabularies cleaned:
tags
0
0

Today, it is also easy to do this with Drupal Console. For example, to delete all the taxonomy terms from the Tags vocabulary, it's sufficient to run drupal taxonomy:term:delete tags.

0

As was said by @texas_bronius, if you have devel generate enabled, you can use that but taking it one step further, if you also have Drush installed, I would use drush generate-terms [vocabulary_machine_name] 0 --kill.

Replace [vocabulary_machine_name] with the machine name of the vocabulary to delete. 0 is the number of taxonomy terms to add and --kill is to remove the existing taxonomy terms.

0

Just to complete the answers, there is a module doing exactly this: the Taxonomy delete all terms module. I have used it and it works.

For sites with very large Taxonomy vocabularies, deleting vocabularies may become impossible due to the term deletion request timing out. When that happens before the deletion transaction is complete, the transaction is rolled back, causing no terms at all to be deleted.

The module isn't covered by by the security advisory policy, and it has only a development snapshot for Drupal 7. There aren't branches/releases for Drupal 8 or 9.

0

Today, within Drupal 8|9, taxonomy_bulk_actions contrib module can do that for you.

0

In Drupal 8+ you can use this:

 * Delete terms of chosen vocabulary.
 *
 * @param string $vocabulary
 *   Machine name of the vocabulary.
 *
 * @command module_name:delete-terms-of
 * @aliases delete-terms-of
 */
public function deleteChosenTerms(string $vocabulary) {
  try {
    $taxonomy_storage = $this->entityTypeManager->getStorage('taxonomy_term');
    $terms = $taxonomy_storage->loadByProperties(['vid' => $vocabulary]);

    if (!empty($terms)) {
      foreach ($terms as $term) {
        $term->delete();
      }
    }
  }
  catch (InvalidPluginDefinitionException | PluginNotFoundException | EntityStorageException $e) {
    $this->loggerFactory->error($e->getMessage());
  }
}

Then you can run drush command e.g: drush delete-terms-of taxonomy_name

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.