我是否可以锁定父术语级别的自定义分类,而不是子术语级别的自定义分类?

时间:2014-09-04 作者:rugbert

我创建了一个名为“主题”的分类法,它有4个顶级术语:

科学、环境、技术记不住最后一个术语,每个术语都有子术语。我希望能够锁定顶级术语,但不能锁定子术语。

基本上,编辑应该能够为这些顶级术语中的每一个创建尽可能多的术语。。但这些顶级术语不能删除或修改。

这可能吗?

1 个回复
SO网友:Nicolai Grossherr

这不是一个完整且现成的答案,但以下内容应该可以帮助您开始。

首先要注意的是,删除和修改是不同的功能,因此不同的功能和挂钩与之相关。也就是我们所说的wp_delete_term() - sourcewp_update_term() - source - 关于功能。

让我们看看wp_delete_term(), 您必须至少考虑两个挂钩:edit_term_taxonomiesdelete_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;
    }
}
Thepre_insert_term 挂钩是wp_insert_term() 作用


一些注意事项:

parent 的值$args is 0, 未选择父项时。但我们无法访问动作中的内容,表单确实返回-1 对于$_POST[ \'parent\' ] 如果选择了»无«。所以<= \'0\' 无论如何都应该有效current_user_can() 函数,因为这只是wrong - 虽然你经常看到它,但它仍然很糟糕。相反capabilities 用于确定我们正在处理的用户类型

结束

相关推荐

如何从操作钩子‘set_Object_Terms’中获取Term_id?

我有以下代码,我想在该函数中使用term\\u id。我知道变量$terms包含术语;然而,我不知道如何从中获取术语id。add_action(\'set_object_terms\',\'wpse5123_set_object_terms\',10,4); function wpse5123_set_object_terms($object_id, $terms, $tt_ids, $taxonomy){ if($taxonomy == \'category\')