Есть ли способ отключить термин, а не удалять его?


У меня возникла ситуация, когда мне нужно удалить термин из таксономии. Однако есть элементы, которые связаны с этой таксономией. Иногда эти удаления являются временными (т. Е. Мы прекращаем доставку в страну, но хотели бы, чтобы товары оставались связанными с этими странами, если мы когда-нибудь снова начнем отправлять их в эту страну).

Есть ли какой-либо способ "отключить" термин, а не wp_delete_term? Спасибо!

Author: jsanc623, 2017-02-23

2 answers

Не напрямую, но мне также нужна эта функциональность, как часть плагина, который я пишу для клиента, и у меня есть то, что я считаю довольно хорошим началом реализации.

Подход, который я использую, заключается в том, чтобы сохранить мета-термин, когда термин отключен, а затем подключиться к фильтру get_terms_defaults, чтобы удалить отключенные термины, которые будут возвращены вызовами WP Core в get_terms(), get_the_terms(), и т.д.

Мой плагин инкапсулирует все это в класс, который служит оболочкой вокруг register_taxonomy(). Ниже приведена урезанная версия этого класса (для плагина, который я пишу, эта оболочка делает намного больше с пользовательскими таксономиями).

Смотрите Custom_Taxonomy::enable_term() и Custom_Taxonmy::disable_term() для кода, который добавляет/удаляет соответствующий термин meta; и смотрите 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) ;
    }
}

Мой вариант использования

У меня есть 2 пользовательские типы записей, type_a и type_b. type_b имеет пользовательскую таксономию taxonomy_b, условиями которой являются заголовки всех сообщений типа type_a.

Только для тех сообщений type_a, post_status которых publish, должны быть включены соответствующие термины в taxonomy_b. Я добиваюсь этого, подключаясь к save_post_type_a, чтобы вставить термины (если они еще не существуют) и включить/отключить их, а также подключаясь к delete_post, чтобы удалить их.

Если ваш вариант использования для отключенных терминов вообще похож, они выше должно, по крайней мере, указывать вам в одном возможном направлении.

Вопросы, которые у меня все еще есть

Я все еще работаю над этим плагином, и есть несколько открытых проблем, связанных с его реализацией.

  1. Является ли фильтр get_terms_defaults, к которому я подключаюсь, чтобы добавить мета_запрос в WP_Term_Query, лучшим для использования? Я пробовал get_terms_args, но, похоже, это вызывается слишком поздно в процессе создания запроса wp_term_, используемого get_terms() и т. Д. чтобы правильно обработать мета_запрос, добавленный Custom_taxonomy::strip_disabled_terms().

  2. Я не уверен, как это взаимодействует с кэшированием объектов WP Core. Например, если термин отключен, когда вызов get_terms() кэширует термины в таксономии, и для них термин включен в том же выполнении wp(), будет ли последующий вызов get_terms() включать термин или он вернет кэшированные термины...что не включало бы этот термин. Но, похоже, это работает в тестах, которые я проводил до сих пор.

Если у кого-нибудь, читающего это, есть какие-либо предложения для улучшения этого класса, особенно в аспекте кэширования объектов, пожалуйста, свяжитесь с нами!

 3
Author: Paul 'Sparrow Hawk' Biron, 2017-02-23 23:07:23

Вы можете временно исключить свои условия из запросов. Это означает, что вы скрываете их на некоторых страницах со списком и т. Д. Все исключенные условия не будут удалены, а ссылки на товары останутся нетронутыми.

Получить все страны, кроме Атлантиды, Эльдорадо и Лемурии:

<?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
Author: Max Yudin, 2017-02-25 10:53:05