web-dev-qa-db-fra.com

Autoriser une seule instance de chaque terme dans chaque taxonomie personnalisée

Je recherche une fonction qui limite la création de chaque terme à une seule instance dans chaque taxonomie personnalisée. Chaque taxonomie personnalisée peut avoir le même terme, mais ce terme ne peut apparaître qu'une seule fois dans chaque taxonomie personnalisée. Je suppose que cela nécessitera une fonction pour chaque taxonomie personnalisée.

2
Pete

Une question assez intéressante. Je ne peux pas vraiment trouver quelque chose de facile. La création de termes est gérée par la fonction wp_insert_term() . Si vous regardez le code source, vous verrez qu'il n'y a pas beaucoup de filtres ou d'actions que nous pouvons utiliser avant l'insertion du terme. pre_insert_term est à peu près le seul filtre qui se produit avant la validation et l’insertion de termes.

Par défaut, dans toute taxonomie hiérarchique, vous pouvez avoir des termes avec des noms en double si ces termes ne se trouvent pas dans la même hiérarchie. Il n’existe aucun filtre ni aucune action permettant de modifier ce comportement. Nous nous efforcerons donc d’arrêter ce comportement et de nous assurer que nous ne pouvons avoir qu’une seule instance d’un terme.

Les taxonomies non hiérarchiques, car il ne peut y avoir que des termes de premier niveau, n'auront pas ce problème. Il ne peut y avoir aucun autre terme du même nom.

Il existe toutefois une exception aux règles ci-dessus: chaque fois que nous définissons explicitement un slug unique, nous pouvons avoir des termes portant le même nom au même niveau. Nous allons toutefois ignorer tout cela ensemble et nous concentrer uniquement sur le nom fourni.

Il ne nous reste donc que le filtre pre_insert_term. Permet de regarder une solution possible

add_filter( 'pre_insert_term', function ( $term, $taxonomy )
{
    /**
     * Start by validating the term. The taxonomy is already validated
     * 
     * If the term is a numeric or int value, we will bail. We will let wp_insert_term
     * handle the process from here on. This is just a very loose check on our side
     */
    if ( is_numeric( $term ) )
        return $term;

    /**
     * $term is a valid non numeric string, so we most probably have a term name
     *
     * We will now basically use the same logic as `wp_insert_term` to validate the $term
     * name.
     */
    $term_name = strtolower( filter_var( $term, FILTER_SANITIZE_STRING ) );

    /**
     * Get all terms which matchings names like $term_name
     *
     * Getting terms by name is not an exact match, but a LIKE comparison, so
     * if you have names like 'Term A', 'term a' and 'term A', they all will match.
     * We will need to do an exact match later on
     */
    $name_matches = get_terms( 
        $taxonomy, 
        [
            'name'       => $term_name,
            'hide_empty' => false,
            'fields'     => 'names', // Only get term names
        ] 
    );
    // If $name_matches is empty, we do not have duplicates, bail
    if ( !$name_matches )
        return $term;

    // Convert all names into lowercase
    $names_array = array_map( 'strtolower', $name_matches );
    // Test to see if we have an exact term name match, if so, return WP_Error
    if ( in_array( $term_name, $names_array ) )
        return new WP_Error( 
            'term_exists',
            __( 'You cannot have a term with the same name, choose a unique name.' ),
            $term 
        );

    // OK we have a unique term name, let 'wp_insert_term' continue the rest of the process
    return $term;   
}, 10, 2 );

Ce que nous avons fait est d’obtenir tous les termes avec des noms tels que celui que nous aimerions insérer, de les convertir tous en minuscules, puis de vérifier si notre nom de terme figure dans le tableau de noms de termes. Si tel est le cas, nous renverrons un objet WP_Error afin d'arrêter tout le processus d'insertion du terme.

Évidemment, vous n'avez besoin d'aucun autre contrôle entre les taxonomies, car vous pouvez avoir un terme du même nom entre différentes taxonomies.

1
Pieter Goosen