Multisite – Protect categories from deletion?

Extending @Roman’s answer.


The following was developed and tested in a Multisite environment – local and live WP installs.


Looking at the source of wp_delete_term, there are some hooks that are triggered when the function is called.

I’m not sure if this is the best way of doing this, but it works.

add_action( 'delete_term_taxonomy', 'wpse_70758_del_tax', 10, 1 );

function wpse_70758_del_tax( $tt_id )
{
    $undeletable = array( 'undeletable', 'uncategorized', 'other-cat' );
    $term = get_term_by( 'id', $tt_id, 'category' );

    if( in_array( $term->slug, $undeletable ) ) 
        wp_die( 'cant delete' );
}

So, when trying to delete the “Undeletable” category (using the Quick Edit menu), it produces:

can't delete category

As the deletion happens via Ajax, we are breaking its execution and WP dumps that error message (modifying that text deserves a separate Question).

If we use the “Bulk actions“, that wp_die() is printed in the screen.


But that’s not all. Before the actual deletion (action hook delete_term_taxonomy), the child categories of the one we are blocking are “unparented”, line #1772:

// Update children to point to new parent

There’s another hook where this action happens and we can insert an early break to prevent the “unparenting”:

add_action( 'edit_term_taxonomies', 'wpse_70758_del_child_tax', 10, 1 );

function wpse_70758_del_child_tax( $arr_ids )
{
    $undeletable = array( 'undeletable', 'uncategorized', 'other-cat' );
    foreach( $arr_ids as $id )
    {
        $term   = get_term_by( 'id', $id, 'category' );
        $parent = get_term_by( 'id', $term->parent, 'category' );

        if( in_array( $parent->slug, $undeletable ) ) 
            wp_die( 'cant delete' );        
    }
}

Use this inside a Must Use Plugin and it will be automatically active in the network.


The snapshot above has a custom ID column in the category listing. That’s done with the following code (an here with an extra column marking the “undeletable” categories with a big red bullet):

add_filter( 'manage_edit-category_columns', 'wpse_70758_cat_edit_columns' );
add_filter( 'manage_category_custom_column', 'wpse_70758_cat_custom_columns', 10, 3 );

function wpse_70758_cat_edit_columns( $columns )
{
    $columns['tt_id'] = 'ID';   
    $columns['undeletable'] = 'Undeletable';   
    return $columns;
}   

function wpse_70758_cat_custom_columns( $value, $name, $tt_id )
{
    if( 'tt_id' == $name ) 
        echo $tt_id;

    $term = get_term_by( 'id', $tt_id, 'category' );
    $undeletable = array( 'undeletable', 'uncategorized', 'other-cat' );

    if( 'undeletable' == $name && in_array( $term->slug, $undeletable ) )
        echo '<span style="color:#f00;font-size:5em;line-height:.5em">&#149;</span>';
}

Full working plugin: https://gist.github.com/4110831

Leave a Comment