web-dev-qa-db-fra.com

Existe-t-il un moyen de désactiver un terme plutôt que de le supprimer?

J'ai une situation où je dois supprimer un terme d'une taxonomie. Cependant, certains éléments sont liés à cette taxonomie. Parfois, ces déménagements sont temporaires (c’est-à-dire que nous arrêtons les envois vers un pays, mais nous aimerions que les articles restent liés à ces pays si jamais nous retournons dans ce pays).

Existe-t-il un moyen de "désactiver" un terme plutôt que wp_delete_term? Merci!

4
jsanc623

Pas directement, mais j'ai également besoin de cette fonctionnalité. Dans le cadre d'un plugin, j'écris pour un client et je pense que c'est un bon début pour une implémentation.

Mon approche consiste à stocker une méta de terme lorsque le terme est désactivé, puis à utiliser le filtre get_terms_defaults pour éliminer les termes désactivés qui seraient renvoyés par WP Les appels de Core à get_terms(), get_the_terms(), etc.

Mon plugin encapsule tout cela dans une classe qui sert de wrapper autour de register_taxonomy(). Ce qui suit est une version allégée de cette classe (pour le plugin que j'écris, ce wrapper en fait beaucoup plus avec les taxonomies personnalisées).

Voir Custom_Taxonomy::enable_term() et Custom_Taxonmy::disable_term() pour le code qui ajoute/supprime le terme méta pertinent; et voyez Custom_Taxonomy::strip_disabled_terms() pour le code qui supprime les termes désactivés.

J'espère que j'ai laissé tous les codes pertinents de cette classe lorsque j'ai enlevé tout ce qui ne s'applique pas à cette question :-)

/**
 * 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) ;
    }
}

Mon cas d'utilisation

J'ai 2 types de messages personnalisés, type_a et type_b. type_b a une taxonomie personnalisée, taxonomy_b, dont les termes sont les posts_title de tous les posts de type type_a.

Seules les publications de type_a dont post_status est publish devraient avoir les termes correspondants dans taxonomy_b activés. Pour ce faire, je m'accroche dans save_post_type_a pour insérer les termes (s'ils n'existent pas déjà) et les activer/les désactiver, puis dans delete_post pour les supprimer.

Si votre cas d'utilisation de termes désactivés est similaire, les opérations ci-dessus devraient au moins vous orienter dans une direction possible.

Questions que j'ai encore

Je travaille toujours sur ce plugin et il y a quelques problèmes en suspens concernant son implémentation.

  1. le filtre get_terms_defaults auquel je me connecte pour ajouter la méta_query à WP_Term_Query constitue-t-il le meilleur hook à utiliser? J'ai essayé get_terms_args, mais cela semble être appelé trop tard dans le processus de compilation du WP_Term_Query utilisé par get_terms (), etc. pour traiter correctement la méta_query ajoutée par Custom_taxonomy::strip_disabled_terms().

  2. Je ne suis pas sûr de savoir comment cela interagit avec la mise en cache des objets de WP Core. Par exemple, si un terme est désactivé lorsqu'un appel à get_terms() met en cache les termes de la taxonomie et que le terme est activé dans la même exécution de wp(), un appel ultérieur à get_terms() inclura le terme ou renverra les termes en cache. .qui n'inclurait pas le terme. Mais cela semble fonctionner dans les tests que j'ai effectués jusqu'à présent.

Si quelqu'un qui lit ceci a des suggestions d'amélioration à apporter à cette classe, notamment en ce qui concerne l'aspect de la mise en cache des objets, connectez-vous!

3

Vous pouvez exclure temporairement vos termes des requêtes. Cela signifie que vous les masquez sur certaines pages de liste, etc. Tous les termes exclus ne seront pas supprimés et les liens d’objet demeureront intacts.

Obtenez tous les pays sauf Atlantis, El Dorado et Lemuria:

<?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);

Voir WP_Query()Paramètres de taxonomie pour plus d'informations.

Modifier

Depuis 4.4, il y a term meta où vous pouvez, par exemple, le marquer à votre guise. "Désactivé", "Caché" ou autre.

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

Quoi qu'il en soit, vous devez mieux repenser vos requêtes.

2
Max Yudin