这不是一个完整且现成的答案,但以下内容应该可以帮助您开始。
首先要注意的是,删除和修改是不同的功能,因此不同的功能和挂钩与之相关。也就是我们所说的wp_delete_term()
- source 和wp_update_term()
- source - 关于功能。
让我们看看wp_delete_term()
, 您必须至少考虑两个挂钩:edit_term_taxonomies 和delete_term_taxonomy. 由于批量操作和层次分类的处理,它们都是相关的。
下面是一些示例性代码,介绍如何实现这一点。我试图解释代码中最重要的东西。剩下的你得自己读一读。
首先edit_term_taxonomies 挂钩:
add_action(
\'edit_term_taxonomies\',
\'wpse160191_top_level_lock_down_edit_term_taxonomies\',
10,
1
);
function wpse160191_top_level_lock_down_edit_term_taxonomies(
$edit_tt_ids
) {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if(
// these are the conditions we are checking against
// is this a tag edit page
$base == \'edit-tags\'
// we want this only for a specific taxonomy
&& $taxonomy == \'category\'
// not super and/or admin
&& ! current_user_can( \'manage_options\' )
// a least an editor
&& current_user_can( \'manage_categories\' )
) {
// these are the terms up for deletion
$terms_queue_for_deletion = $_POST[\'delete_tags\'];
$term_parents_ids = array();
// we need information if or not one of the terms is a top level one
foreach ( $terms_queue_for_deletion as $term_id ) {
$term_obj = get_term_by( \'id\', $term_id, \'category\' );
$term_parent = $term_obj->parent;
$term_parents_ids[] = $term_parent;
}
if( empty( $edit_tt_ids ) ) {
return;
}
if( ! empty( $edit_tt_ids ) ) {
if ( in_array( 0, $term_parents_ids ) ) {
$msg = new WP_Error(
\'parent_terms_are_forever\',
__(\'Sorry, you are not allowed to delete top level terms.\')
);
wp_die( $msg );
} else {
return;
}
}
}
}
第二个
delete_term_taxonomy 挂钩:
add_action(
\'delete_term_taxonomy\',
\'wpse160191_top_level_lock_down_delete_term_taxonomy\',
10,
1
);
function wpse160191_top_level_lock_down_delete_term_taxonomy(
$tt_id
) {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if (
// these are the conditions we are checking against
// is this a tag edit page
$base == \'edit-tags\'
// we want this only for a specific taxonomy
&& $taxonomy == \'category\'
// not super and/or admin
&& ! current_user_can( \'manage_options\' )
// a least an editor
&& current_user_can( \'manage_categories\' )
) {
$term_obj = get_term_by( \'term_taxonomy_id\', $tt_id, \'category\' );
$parent_id = $term_obj->parent;
if (
// this applies only to top level terms
$parent_id == 0
) {
$msg = new WP_Error(
\'parent_terms_are_forever\',
__(\'s:Sorry, you are not allowed to delete top level terms.\')
);
wp_die( $msg );
}
}
}
如上所述,它变得有点复杂,主要是因为AJAX操作。如果您正在考虑使用众所周知的简单检查进行此操作:
if ( defined(\'DOING_AJAX\') && DOING_AJAX ) {
// code
}
我现在可以告诉你,我很确定这还不够。主要是因为你无法完成所有需要的检查。如果您只需要禁用或准确地说,删除指向AJAX操作的链接就可以了,您可以这样做:
add_action(
\'admin_head\' ,
\'wpse160191_remove_ajax_delete_link\'
);
function wpse160191_remove_ajax_delete_link() {
$screen_obj = get_current_screen();
$base = $screen_obj->base;
$taxonomy = $screen_obj->taxonomy;
if(
// lets just remove the link on that one page and not everywhere
$base == \'edit-tags\'
&& $taxonomy == \'category\'
) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
var element = \'span.delete\';
$(element).each(function(){
$(element).css(\'opacity\', \'0\');
$(element).css(\'pointer-events\', \'none\');
$(element).remove();
});
});
</script>
<?php
}
}
当然,您不应该内联这样做,但您可以优化自己。这当然不是很令人满意,因为我们刚刚删除了功能。
我设想处理AJAX操作的一种方法是使用debug_backtrace()
. 这将提供一种正确确定和处理AJAX操作的方法。它可以实现到上面显示的代码中。当然需要注意的是debug_backtrace()
性能方面是否昂贵,而且在更大范围内肯定不推荐使用
另一种方法是实现自己的AJAX操作,以替代wp_ajax_delete_tag()
, 但要做到这一点,您必须另外扩展WP_Terms_List_Table
或者使用一些挂钩来实现这一点。目前还不能完全确定,所以你必须自己进一步检查。
的程序wp_update_term()
不允许更新/修改类似于上面所示。对于AJAX部分也有同样的考虑,特别是因为可以进行内联快速编辑。
起初,我完全误解了这个问题,并给出了答案<保留它,因为它可能对其他人有用
你能做的就是pre_insert_term
进行所需的检查。
Code:
add_action( \'pre_insert_term\', \'wpse160191_restrict_top_level_term_creation\', 10, 2 );
function wpse160191_restrict_top_level_term_creation( $term, $taxonomy ) {
if(
// these are the conditions we are checking against
// we want this only for a specific taxonomy
$taxonomy == \'topics\'
// a value of 0 or -1 does indicate the top level
&& $_POST[ \'parent\' ] <= \'0\'
// not super and/or admin
&& ! current_user_can( \'manage_options\' )
// a least an editor
&& current_user_can( \'manage_categories\' )
) {
// the user is an editor and not allowed to add parent terms
// so return a friendly message so the user at least knows
return new WP_Error(
\'parent_terms_not_allowed_for_editors\',
__(\'Sorry, you are not allowed to add parent terms.\')
);
} else {
// a super and/or admin, s|he is allowed to do what s|he wants
return $term;
}
}
The
pre_insert_term
挂钩是
wp_insert_term()
作用
一些注意事项:
在parent
的值$args
is 0
, 未选择父项时。但我们无法访问动作中的内容,表单确实返回-1
对于$_POST[ \'parent\' ]
如果选择了»无«。所以<= \'0\'
无论如何都应该有效我们没有将用户角色传递给current_user_can()
函数,因为这只是wrong - 虽然你经常看到它,但它仍然很糟糕。相反capabilities 用于确定我们正在处理的用户类型