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:
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">•</span>';
}
Full working plugin: https://gist.github.com/4110831