是否挂接以在创建新的分类标记之前处理它?

时间:2016-04-29 作者:Joel

我正在一个网站上工作,那里有一个地方的自定义分类法,可以是城市或州。用户应该在每个帖子上标记一个城市和一个州。为了消除多个州中同名城市的歧义,这些城市标签附加了州名(例如,“迈阿密,佛罗里达”的名称为“迈阿密-佛罗里达”,而“迈阿密,俄亥俄”的名称为“迈阿密-俄亥俄”)。

尽管有自动完成功能,但用户无法掌握该系统,无法继续输入“Miami,Florida”,这将创建一个新的“Miami”标记以及现有的Florida标记。

我想在保存帖子并且即将创建新标签时截取用户输入,以查看城市-州组合是否已经存在(即,如果一个标签是Miami,另一个是Florida,“Miami Florida”是否已经存在)。然后我想阻止创建新标记,而是将现有标记应用于帖子。

我会使用什么钩子,我会如何更改帖子上的标签?

1 个回复
SO网友:Howdy_McGee

你要找的钩子是created_{$taxonomy} 但还有一个问题。我认为逻辑上最大的缺陷是把州和城市放在同一个分类法中。你永远无法区分这两个词(哪个是城市,哪个是州)。这将打开用户以执行以下部分操作,所有操作都不正确

输入无州城市我认为解决方法是将州和城市划分为两个不同的分类法。tax_statestag_cities. 这将确保每个帖子都有一个州,每个城市标签都以州为前缀。我将开始下面的代码,假设这两个分类法已注册。

首先,让我们添加一些jQuery以确保设置了状态—您可能需要考虑enqueueing 但由于它是一个小脚本,可能不是:

function post_type_custom_script() {
    global $post_type;

    if( \'post\' === $post_type ) {
      ?>

        <script type="text/javascript">
            /* Checks if cat is selected when publish button is clicked */
            jQuery( \'#submitdiv\' ).on( \'click\', \'#publish\', function( e ) {
                var $checked = jQuery( \'#category-all li input:checked\' );

                //Checks if cat is selected
                if( $checked.length <= 0 ) {
                    alert( "Please select a State" );
                    return false;
                } else { 
                    return true;
                }
            } );
        </script>

      <?php
    }
}
add_action( \'admin_footer\', \'post_type_custom_script\' );
上述脚本的最大问题是,它假设您的分类法是分层的(复选框),但由于理论上只应选择一个状态,因此分类法都不是最佳选择。相反,您可以创建一个术语选择列表并使用save_post 要保存术语或(我建议)将层次复选框更改为单选按钮(PHP Class, Radio Buttons for Taxonomies Plugin ).

现在我们应该有一个州的分类法,需要选择它才能发布,还有一个城市的标记框。下一步是在发布城市标记时将状态附加到城市标记。这是一个庞大的条件列表,所以我在必要时添加了注释。如果某个州没有被选中,我们会把帖子变成草稿,作为最后的结果:

/**
 * This function runs whenever a post is saved
 *
 * @param Int $post_id
 *
 * @return void
 */
function state_appended_tags( $post_id ) {
    global $post;

    if( ( defined( \'DOING_AUTOSAVE\' ) && DOING_AUTOSAVE ) || ( ! current_user_can( \'edit_post\', $post_id ) || ! is_object( $post ) ) ) {
        return $post_id;
    }

    if( \'post\' === $post->post_type ) {
        $state      = false;
        $set_draft  = false;

        if( isset( $_POST[\'tax_input\'] ) && ! empty( $_POST[\'tax_input\'] ) ) {

            // Grab State
            // If using the Radio Buttons Plugin linked above, use this conditional
                // if( isset( $_POST[\'radio_tax_input\'][\'tax_states\'] ) && ! empty( $_POST[\'radio_tax_input\'][\'tax_states\'] ) && 0 !== $_POST[\'radio_tax_input\'][\'tax_states\'][0] ) {
                    // $state_obj  = get_term_by( \'id\', $_POST[\'radio_tax_input\'][\'tax_states\'][0], \'tax_states\' ); // Grab Term Object
                    // $state_slug = $state_obj->slug;
            if( isset( $_POST[\'tax_input\'][\'tax_states\'] ) && ! empty( $_POST[\'tax_input\'][\'tax_states\'] ) && 0 !== $_POST[\'tax_input\'][\'tax_states\'][0] ) {
                $state_obj  = get_term_by( \'id\', $_POST[\'tax_input\'][\'tax_states\'][0], \'tax_states\' );  // Grab Term Object
                $state_slug = $state_obj->slug;
            } else {
                $set_draft = true;
            }

            // Prefix Cities
            if( ! empty( $state_slug ) && isset( $_POST[\'tax_input\'][\'tag_cities\'] ) && ! empty( $_POST[\'tax_input\'][\'tag_cities\'] ) ) {
                $new_tags = array();

                foreach( $_POST[\'tax_input\'][\'tag_cities\'] as $city ) {
                    $city_obj   = false;
                    $city_slug  = \'\';

                    // Post tags come in two forms - slugs and integers
                    if( is_numeric( $city ) ) {
                        $city_obj  = get_term_by( \'id\', $city, \'tag_cities\' );  // Grab Term Object
                        $city_slug = $city_obj->slug;
                    } else {
                        $city_obj  = get_term_by( \'slug\', $city, \'tag_cities\' );    // Grab Term Object
                        $city_slug = $city_obj->slug;
                    }

                    // If user has already entered the correct state-city formatted tag, skip it
                    // Otherwise we\'ll enter the conditional
                    if( 0 !== strcmp( "{$state_slug}-{$city_slug}", $city_slug ) ) {
                        $new_tags[] = "{$state_slug}-{$city_slug}";
                        wp_delete_term( $city_obj->term_id, \'tag_cities\' );     // Delete Term
                    }
                }

                // Set New State Appended Tags
                if( ! empty( $new_tags ) ) {
                    wp_set_object_terms( $post_id, $new_tags, \'tag_cities\', false );
                }
            }
        } else {
            $set_draft = true;
        }

        // Finally, should something have failed, don\'t publish the post and investigate
        if( $set_draft ) {
            remove_action( \'save_post\', \'state_appended_tags\' );
            wp_update_post( array(
                \'ID\'            => $post_id,
                \'post_status\'   => \'draft\',
            ) );
            add_action( \'save_post\', \'state_appended_tags\' );
        }
    }
}
add_action( \'save_post\', \'state_appended_tags\' );
你需要换掉tag_citiestax_states 使用实际的分类法,但这应该适合您。

相关推荐

Custom Taxonomy Page

我正在尝试创建一个显示特定类别的所有子类别的页面。所以在上下文中,我有一个标题为“目的地”的父类别。我希望能够点击目的地,并被引导到一个页面,显示子类别或国家的列表。下面是我试图实现的一个示例,减去顶部的地图-https://www.vagabrothers.com/destinations. 在理想情况下,类别页面的布局将与此页面相同。你可以从上面的例子中看出我的意思。它会使网站上的导航像这样:目的地>国家>个人帖子。我正在使用CPT UI,设置了一个名为“目的地”的自定义帖子类型和类别,然