问题描述

我试图用 metabox 的标签来替换 metabox 的类别,因为有太多的层次结构和滚动来检查适当的类别,而 sub-categories 不是一个选项。所以在我的情况下,标签的 metabox 更好。

这就是我这样做:

/*
 * Non-hierarchal metabox for categories
 * (like the tags metabox)
 *
 * SOURCES:
 * http://wordpress.stackexchange.com/a/50098
 * http://wordpress.stackexchange.com/a/49048
 * http://wordpress.stackexchange.com/a/48816
 *
 */

// De-register categories metabox
add_action( 'admin_menu', 'flatsy_remove_meta_box' );
function flatsy_remove_meta_box() {
    remove_meta_box( 'categorydiv', 'post', 'normal' );
}

// Add new taxonomy meta box
add_action( 'add_meta_boxes', 'flatsy_add_custom_cat_meta_box' );
function flatsy_add_custom_cat_meta_box() {
    add_meta_box( 'flatsy_categorydiv', 'Categories', 'flatsy_custom_cat_metabox', 'post', 'side', 'core' );
}

// This function determines what displays in your metabox
function flatsy_custom_cat_metabox( $post ) {
    $defaults = array('taxonomy' => 'category');
    if ( !isset($box['args']) || !is_array($box['args']) )
        $args = array();
    else
        $args = $box['args'];
    extract( wp_parse_args($args, $defaults), EXTR_SKIP );
    $tax_name = esc_attr($taxonomy);
    $taxonomy = get_taxonomy($taxonomy);
    $disabled = !current_user_can($taxonomy->cap->assign_terms) ? 'disabled="disabled"' : '';
?>
<div class="tagsdiv" id="<?php echo $tax_name; ?>">
    <div class="jaxtag">
    <div class="nojs-tags hide-if-js">
    <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p>
    <textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php echo $disabled; ?>><?php echo get_terms_to_edit( $post->ID, $tax_name ); // textarea_escaped by esc_attr() ?></textarea></div>
    <?php if ( current_user_can($taxonomy->cap->assign_terms) ) : ?>
    <div class="ajaxtag hide-if-no-js">
        <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $box['title']; ?></label>
        <div class="taghint"><?php echo $taxonomy->labels->add_new_item; ?></div>
        <p><input type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" value="" />
        <input type="button" class="button tagadd" value="<?php esc_attr_e('Add'); ?>" tabindex="3" /></p>
    </div>
    <p class="howto"><?php echo esc_attr( $taxonomy->labels->separate_items_with_commas ); ?></p>
    <?php endif; ?>
    </div>
    <div class="tagchecklist"></div>
</div>
<?php if ( current_user_can($taxonomy->cap->assign_terms) ) : ?>
<p class="hide-if-no-js"><a href="#titlediv" class="tagcloud-link" id="link-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->choose_from_most_used; ?></a></p>
<?php endif; ?>
<?php
}

这段代码的工作原理应该是… 看…

… 除了在保存帖子时不保存类别元数据。有一点搜索显示我一定是在做某事 like this

<?php
add_action( 'save_post', 'cd_meta_box_save' );
function cd_meta_box_save( $post_id )
{
    // Bail if we're doing an auto save
    if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

    // if our nonce isn't there, or we can't verify it, bail
    if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;

    // if our current user can't edit this post, bail
    if( !current_user_can( 'edit_post' ) ) return;

    // now we can actually save the data
    $allowed = array(
        'a' => array( // on allow a tags
            'href' => array() // and those anchors can only have href attribute
        )
    );

    // Make sure your data is set before trying to save it
    if( isset( $_POST['my_meta_box_text'] ) )
        update_post_meta( $post_id, 'my_meta_box_text', wp_kses( $_POST['my_meta_box_text'], $allowed ) );

    if( isset( $_POST['my_meta_box_select'] ) )
        update_post_meta( $post_id, 'my_meta_box_select', esc_attr( $_POST['my_meta_box_select'] ) );

    // This is purely my personal preference for saving check-boxes
    $chk = isset( $_POST['my_meta_box_check'] ) && $_POST['my_meta_box_select'] ? 'on' : 'off';
    update_post_meta( $post_id, 'my_meta_box_check', $chk );
}
?>

但是,由于我正在处理默认功能 (即使用标签 metabox 已经具有多少/什么 wordpress),所以我想知道 save_post 对于’category’ 和’tag’ 元框有什么检查,以及 WordPress 默认情况下是如何进行的。

// Save post metadata when a post is saved.
add_action( 'save_post', 'flatsy_save_cat_meta' );
function flatsy_save_cat_meta( $post_id, $post, $update ) {

    return 'WHAT DO I DO HERE? HOW DOES WORDPRESS DO IT FOR THE TAGS METABOX?';

}

如果不是这样做,那么当我将类别 metabox 转换成一个标签 metabox 和 vice-versa(两种情况) 时,代码如何?


澄清:我不想将分类从分层更改为 non-hierarchical 。我只想要一个 tags-like metabox 类别。如果我想要一个 non-hierarchical 分类法,我只需要注册一个自定义分类法。

最佳解决方案

检查出/wp-admin/post.php 文件,其中包含 edit_post()函数,edit_post()函数调用 wp_update_post(),它是一个 wp_insert_post()包装器。

这是保存分配的类别术语的骨架:

/**
 * Saving assigned category terms (skeleton)
 */
add_action( 'admin_action_editpost', function()
{
    add_filter( 'wp_insert_post_data',  function( $data, $parr )
    {
        add_action( 'save_post_post', function( $post_ID, $post ) use ( $parr )
        {
            if(
                    isset( $parr['_wpnonce'] )
                &&  wp_verify_nonce( $parr['_wpnonce'], 'update-post_' . absint( $post_ID ) )
                &&  current_user_can( 'manage_categories' )
                && function_exists( 'wpse_save_assigned_cats' )
                && ! did_action( 'wpse_save_assigned_cats' )
            ) {
                wpse_save_assigned_cats( $post_ID, $parr );
                do_action( 'wpse_save_assigned_cats' );
            }
        }, 10, 2 );
        return $data;
    }, 10, 2 );
} );

我们的帮助函数 wpse_save_assigned_cats()基于 edit_post()功能:

/**
 * Helper function based on the cat/tax handling of the edit_post() functions
 */
function wpse_save_assigned_cats( $post_ID, $parr )
{
    if( ! empty( $parr['tax_input']['category'] ) && $post_ID > 0 )
    {
        // Change the comma seperated string of category names,
        // in $parr['tax_input']['category'], to an array of cats id
        $input_cats = explode( ',',  trim( $parr['tax_input']['category'], " ntrx0B," ) );
        $clean_cats = array();
        foreach ( $input_cats as $cat_name )
        {
            // Don't allow empty categories
            if ( empty( $cat_name ) )
                continue;

            // Check if there already exists such a category
            $_cat = get_terms( 'category', array(
                'name'          => $cat_name,
                'fields'        => 'ids',
                'hide_empty'    => false,
            ) );

            // The category name already exists
            if ( ! empty( $_cat ) )
            {
                // Collect the (first) category id
                $clean_cats[] = intval( $_cat[0] );
            }
            else
            {
                // Create the category, since it doesn't exists
                $cat_id = wp_create_category( $cat_name );

                // Collect the category id
                if( $cat_id > 0 )
                    $clean_cats[] = $cat_id;
            }
        }
        // Current post's category IDs
        $cats = (array) wp_get_post_categories( $post_ID, array( 'fields' => 'ids' ) );

        // Unique array of category IDs
        $post_categories = array_unique( array_merge( $cats, $clean_cats ) );

        // Assign the categories to the current post
        wp_set_post_categories( $post_ID, $post_categories );
    }
}

上一个答案:

这是我的星期五答案,所以可能需要一些测试;-)

我只是 re-registered 的 category 分类法作为 non-hierarchical 与:

        'hierarchical' => false,

那么类别框出现如下:

并保存条款按预期工作。

这是我的测试代码片段,所以您可以进一步尝试:

add_action( 'init', function()
{
    global $wp_rewrite;
    register_taxonomy( 'category', 'post', array(
        'hierarchical' => false,
        'query_var' => 'category_name',
        'rewrite' =>  array(
            'hierarchical' => true,
            'slug'         => get_option('category_base') ? get_option('category_base') : 'category',
            'with_front'   => ! get_option('category_base') || $wp_rewrite->using_index_permalinks(),
            'ep_mask'      => EP_CATEGORIES,
        ),
        'public' => true,
        'show_ui' => true,
        'show_admin_column' => true,
        '_builtin' => true,
        'labels' => array(
            'name'                          => __( 'Categories' ),
            'singular_name'                 => __( 'Category' ),
            'search_items'                  => __( 'Search Categories' ),
            'popular_items'                 => null,
            'all_items'                     => __( 'All Categories' ),
            'edit_item'                     => __( 'Edit Category' ),
            'update_item'                   => __( 'Update Category' ),
            'add_new_item'                  => __( 'Add New Category' ),
            'new_item_name'                 => __( 'New Category Name' ),
            'separate_items_with_commas'    => null,
            'add_or_remove_items'           => null,
            'choose_from_most_used'         => null,
        ),
        'capabilities' => array(
            'manage_terms' => 'manage_categories',
            'edit_terms'   => 'manage_categories',
            'delete_terms' => 'manage_categories',
            'assign_terms' => 'edit_posts',
        ),
    ) );
} );

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。