web-dev-qa-db-ja.com

削除するのではなく、用語を無効にする方法はありますか?

分類から用語を削除しなければならない状況があります。ただし、その分類法にリンクされている項目があります。時々、これらの除去は一時的です(すなわち、我々は国への出荷を停止します、しかし、もし我々がその国への出荷を再開するならば、それらの国にリンクされたままのアイテムが欲しいです)。

Wp_delete_term以外の用語を「無効にする」方法はありますか?ありがとうございます。

4
jsanc623

直接ではありませんが、私はクライアントのために書いているプラ​​グインの一部として、この機能も同様に必要としています。そして私が実装のかなり良いスタートだと思うものを持っています。

私がとっているアプローチは、用語が無効になったときに用語メタを保存し、次にget_terms_defaultsフィルターにフックしてWP Coreのget_terms()get_the_terms()などへの呼び出しによって返される無効な用語を取り除くことです。

私のプラグインは、これらすべてをregister_taxonomy()のラッパーとして機能するクラスにカプセル化しています。以下はそのクラスのバージョンを簡略化したものです(私が書いているプラ​​グインでは、このラッパーはカスタム分類法でもっと多くのことができます)。

関連する用語metaを追加/削除するコードについてはCustom_Taxonomy::enable_term()Custom_Taxonmy::disable_term()を参照してください。無効化された用語を削除するコードについてはCustom_Taxonomy::strip_disabled_terms()を参照してください。

うまくいけば、この質問に当てはまらないものを取り除いたときに、このクラスの関連コードをすべて残しました。

/**
 * this class is a wrapper around register_taxonomy(), that adds additional functionality
 * to allow terms in the taxonomy so registered to be "disabled".
 *
 * Disabled terms will NOT be returned by the various WP Core functions like get_terms(),
 * get_the_terms(), etc.
 *
 * TODO: make sure that this works correctly given WP Core's object caching, see Custom_Taxonomy::strip_disabled_terms()
 */
class
Custom_Taxonomy
{
    const DISABLED_TERM_META_KEY = '_shc_disabled' ;

    public $name ;
    public $can_disable_terms = false ;

    /**
     * construct an instance of Custom_Taxonomy
     *
     * @param $taxonomy string Taxonomy key, must not exceed 32 characters
     * @param $post_types array|string post type or array of post types with which the taxonomy should be associated
     * @param $args array Array or query string of arguments for registering a taxonomy
     *
     * params are the same as WP's register_taxonomy() except that $args may have extra keys:
     *
     *  'can_disable_terms' => true|false
     */
    function
    __construct ($taxonomy, $post_types, $args)
    {
        $this->name = $taxonomy ;

        // modify args, if needed
        $default_args = array (
            'can_disable_terms' => false,
            ) ;
        $args = wp_parse_args ($args, $default_args) ;

        $this->can_disable_terms = $args['can_disable_terms'] ;
        unset ($args['can_disable_terms']) ;

        if ($this->can_disable_terms) {
            // TODO: is there a better filter to hook into than 'get_terms_defaults'?
            // I've tried 'get_terms_args', but that seems to be called too late
            // in the process of builing the WP_Term_Query used by get_terms(), etc
            // to have the meta_query that is added by $this->strip_disabled_terms()
            add_filter ('get_terms_defaults', array ($this, 'strip_disabled_terms'), 10, 2) ;
            }

        // register the taxonomy
        register_taxonomy ($taxonomy, $post_types, $args) ;

        return ;
    }

    /**
     * disable a term
     *
     * disabling a term will make it appear as if the term does not exist, without actually deleting it
     *
     * @param $term int|string|WP_Term the term to disable
     * @param $taxonomy string the taxonomy term is in
     * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies. False on failure
     */
    function
    disable_term ($term, $taxonomy = '', $field = 'name')
    {
        if (!$this->can_disable_terms) {
            return ;
            }

        $taxonomy = $taxonomy ? $taxonomy : $this->name ;
        if (is_string ($term)) {
            $term = get_term_by ($field, $term, $taxonomy) ;
            }
        else {
            $term = get_term ($term, $taxonomy) ;
            }

        return (add_term_meta ($term->term_id, self::DISABLED_TERM_META_KEY, true, true)) ;
    }

    /**
     * enable a term
     *
     * @param $term int|WP_Term the term to disable
     * @param $taxonomy string the taxonomy term is in
     * @return bool True on success, false on failure
     */
    function
    enable_term ($term, $taxonomy = '', $field = 'name')
    {
        if (!$this->can_disable_terms) {
            return ;
            }

        $taxonomy = $taxonomy ? $taxonomy : $this->name ;
        if (is_string ($term)) {
            $term = get_term_by ($field, $term, $taxonomy) ;
            }
        else {
            $term = get_term ($term, $taxonomy) ;
            }

        return (delete_term_meta ($term->term_id, self::DISABLED_TERM_META_KEY)) ;
    }

    /**
     * strip disabled terms from e.g., get_terms() and get_the_terms()
     *
     * TODO: make sure that this works correctly given WP Core's object caching
     *
     * @param $term int|WP_Term the term to disable
     * @param $taxonomy string the taxonomy term is in
     * @return bool True on success, false on failure
     */
    function
    strip_disabled_terms ($args, $taxonomies)
    {
        if (!$this->can_disable_terms) {
            return ($args) ;
            }

        // I *think* the count('taxonomy') check is necesary because get_terms_args() is
        // applied by the WP Core object_term caching infrastructure by
        // passing all taxonomies for a given post_type, and we only want to
        // add this restriction when we are getting the terms for just the
        // this taxonomy
        if (count ($args['taxonomy']) != 1 || !in_array ($this->name, $args['taxonomy'])) {
            return ($args) ;
            }

        $args['meta_query'] = array (
            array (
                'key' => self::DISABLED_TERM_META_KEY,
                'compare' => 'NOT EXISTS',
                )
            ) ;

        return ($args) ;
    }
}

私のユースケース

type_atype_bの2つのカスタム投稿タイプがあります。 type_bにはカスタム分類法taxonomy_bがあり、その用語はtype_a型のすべての投稿のpost_titleです。

type_apublishであるpost_statusの投稿のみ、対応するtaxonomy_bの用語を有効にする必要があります。これを実現するには、save_post_type_aにフックして(まだ存在していない場合は)用語を挿入し、それらを有効/無効にして、delete_postにフックしてそれらを削除します。

障害者用語のユースケースがまったく似ている場合は、上記の説明から少なくとも1つの可能性のある方向性が示されるはずです。

私がまだ持っている質問

私はまだこのプラグインに取り組んでいます、そしてその実装に関してはいくつかの未解決の問題があります。

  1. meta_queryをget_terms_defaultsに追加するためにフックするWP_Term_Queryフィルタは、最適なフックですか?私はget_terms_argsを試しましたが、Custom_taxonomy::strip_disabled_terms()によって追加されたmeta_queryを正しく処理するためにget_terms()などによって使用されるWP_Term_Queryを構築する過程で遅すぎるように呼ばれているようです。

  2. これがWP Coreのオブジェクトキャッシングとどのように相互作用するのかわかりません。例えば、get_terms()への呼び出しがタクソノミ内のタームをキャッシュするときにタームが無効にされ、それらがwp()の同じ実行で有効にされると、それに続くget_terms()への呼び出しはそのタームを含むか、キャッシュされたタームを返します。用語を含めないであろう。しかし、それは私がこれまでにやったテストで働いているようです。

これを読んでいる人がこのクラスの改善、特にオブジェクトキャッシングの側面についての提案があれば、チャイムインしてください。

クエリから一時的に自分の用語を除外することができます。一部のリスティングページなどでそれらを非表示にすることを意味します。除外されたすべての用語は削除されず、アイテムのリンクはそのまま残ります。

アトランティス、エルドラド、レムリアを除くすべての国を入手:

<?php
$args = array(
    'post_type'  => 'A_POST_TYPE', // change this
    'tax_query' => array(
        array(
            'taxonomy' => 'countries',
            'field'    => 'slug',
            'operator' => 'NOT IN', // operator to test
            'terms'    => array( // countries to exclude
                'atlantis',
                'el-dorado',
                'lemuria'
            ) 
        )
    )
);

$result = new WP_Query($args);

詳細はWP_Query()分類学パラメータ をご覧ください。

編集

4.4以降、term metaがあり、そこにあなたのやり方の印を付けることができます。 「無効」、「非表示」などです。

https://www.smashingmagazine.com/2015/12/how-to-use-term-meta-data-in-wordpress/

とにかくあなたはより良いあなたのクエリを再考する必要があります。

2
Max Yudin