Есть ли способ отключить термин, а не удалять его?
У меня возникла ситуация, когда мне нужно удалить термин из таксономии. Однако есть элементы, которые связаны с этой таксономией. Иногда эти удаления являются временными (т. Е. Мы прекращаем доставку в страну, но хотели бы, чтобы товары оставались связанными с этими странами, если мы когда-нибудь снова начнем отправлять их в эту страну).
Есть ли какой-либо способ "отключить" термин, а не wp_delete_term? Спасибо!
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
, чтобы удалить их.
Если ваш вариант использования для отключенных терминов вообще похож, они выше должно, по крайней мере, указывать вам в одном возможном направлении.
Вопросы, которые у меня все еще есть
Я все еще работаю над этим плагином, и есть несколько открытых проблем, связанных с его реализацией.
Является ли фильтр
get_terms_defaults
, к которому я подключаюсь, чтобы добавить мета_запрос вWP_Term_Query
, лучшим для использования? Я пробовалget_terms_args
, но, похоже, это вызывается слишком поздно в процессе создания запроса wp_term_, используемого get_terms() и т. Д. чтобы правильно обработать мета_запрос, добавленныйCustom_taxonomy::strip_disabled_terms()
.Я не уверен, как это взаимодействует с кэшированием объектов 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/
В любом случае вам придется лучше переосмыслить свои запросы.