web-dev-qa-db-fra.com

est-il possible d'ajouter un "extra" tableau de navigation aux écrans edit-tags.php?

WP_Posts_List_Table :: extra_tablenav () apply restrict_manage_posts , qui peut être utilisé par un plug-in pour générer des listes déroulantes supplémentaires (ou d'autres balises) permettant de filtrer les publications de la table par des critères arbitraires.

De même, WP_(Users|Comments)_List_Table a une action resttric_manage_(users|comment) à des fins similaires.

Cependant, pour autant que je sache, WP_Terms_List_Table does not . Est-ce correct?

J'écris un plugin qui s'appuie fortement sur termmeta sur diverses taxonomies personnalisées. Mon plugin ajoute à edit-tags.php?taxonomy=my_custom_tax des colonnes personnalisées qui affichent la ou les valeurs des différents termmeta pour chaque terme. Cela améliorerait grandement l'UX de mon plugin si les utilisateurs pouvaient filtrer la liste des termes en fonction des meta_value distincts pour mes meta_key '.

Avant d’ouvrir un ticket Trac proposant d’ajouter une méthode WP_Terms_List_Table::extra_tablenav() et un filtre restrict_manage_terms pour pouvoir faire ce que je veux faire, je voulais voir si quelqu'un ici sur WPSE savait:

  1. existe-t-il une solution de contournement viable (n'impliquant pas le piratage edit-tags.php?taxonomy=my_custom_tax pour rediriger vers une page personnalisée utilisant une sous-classe personnalisée de WP_Terms_List_Table)?
  2. existe-t-il une (bonne) raison pour laquelle WP_Terms_List_Table ne prend actuellement pas en charge cette fonctionnalité?
    1. Je réalise que pour core, il n’ya aucune (bonne) raison de filtrer l’une des colonnes standard WP_Term_List_Table, mais l’ajout de colonnes personnalisées est assez courant et je ne peux pas croire que je suis le seul à avoir jamais voulu filtrer par les valeurs. dans les colonnes personnalisées.

Modifier

Je dois noter que lors de l’affichage de meta_value dans la colonne personnalisée, je l’affiche sous forme de lien qui filtre efficacement la liste de termes en fonction de cette valeur. Si les utilisateurs pouvaient choisir parmi une liste déroulante (comme dans WP_Posts_List_Table), ce serait parce que toutes les valeurs de meta_value ne sont pas toujours visibles sur les pages de termes affichées dans la liste. PourI/ utiliser les liens pour filtrer par une valeur non affichée sur la page en cours, cliquez sur un lien aléatoire, puis modifiez l'URL résultante dans le champ d'adresse du navigateur pour obtenir le meta_value.Iveut filtrer par. Non seulement c'est une douleur, mais tous les utilisateurs ne sont pas assez savants pour se rendre compte qu'ils peuvent le faire.

J'ai cherché la même réponse à votre question et rencontré exactement les mêmes problèmes, et j'apprécie vraiment vos recherches approfondies. Je suis certainement +1 ici pour proposer cet ajout!

Pour tenter de répondre 2) - Je ne pense pas qu'il y ait une bonne raison de l'exclure. Je pense que les termes de taxonomie de WordPress manquent cruellement de fonctionnalités par rapport à la poste et aux entités utilisateurs (vu que le terme méta est venu beaucoup plus tard, après le méta poste et utilisateur), et aimerait voir ce changement.

Pour répondre 1) - Je ne sais pas combien meilleur ceci est votre solution, mais la solution de contournement que j'ai proposée implique de filtrer la liste de taxonomie via le filtre get_terms_args, puis d'insérer manuellement un élément de sélection menu déroulant + bouton de filtre dans JS côté client. Voici un exemple de ma configuration (modifiée pour ne pas utiliser mes classes ou constantes spécifiques), qui filtre en fonction du méta de certains termes:

PHP Logic

// @see https://developer.wordpress.org/reference/hooks/get_terms_args/
add_filter( 'get_terms_args', 'taxonomy_filter', 10, 2 );

function taxonomy_filter( $args, $taxonomies ) {
    global $pagenow;
    if ( 'edit-tags.php' !== $pagenow || ! in_array( 'taxonomy-name', $taxonomies, true ) ) { return $args; }

    // Sort by most recently added terms, instead of alphabetically
    $args['orderby'] = 'term_id';
    $args['order'] = 'desc';

    // Filter by term meta
    $meta_key = ( isset( $_GET['meta_key'] ) ) ? sanitize_text_field( $_GET['meta_key'] ) : null;
    $meta_value = ( isset( $_GET['meta_value'] ) ) ? sanitize_text_field( $_GET['meta_value'] ) : null;

    if ( 'meta-filter' === $meta_key && $meta_value ) {
        $args['meta_key'] = $meta_key;
        $args['meta_value'] = $meta_value;
    }

    // Note: for more complex filtering, use the $args['meta_query'] array.

    return $args;
}

À ce stade, vous devriez pouvoir voir cela fonctionner simplement en allant à (par exemple) yoursite.com/wp-admin/edit-tags.php?taxonomy=taxonomy-name&meta_key=meta-filter&meta_value=foobar.

Logique jQuery côté client

(Assurez-vous d'inclure ce fichier dans wp_enqueue_script(), mais uniquement lorsque $pagenow === 'edit-tags.php').

/**
 * Param helpers
 */

// Get params in a JS object
var params = {};
window.location.search.substr(1).split( '&' ).forEach(function(item) {
    params[ item.split( '=' )[0] ] = item.split( '=' )[1];
});

// Return param string based on the params object
function setParams() {
    var string = '?';

    for ( key in params ) {
        var value = params[ key ];
        string += key + '=' + value + '&';
    }

    return string.slice(0, -1); // Remove trailing &
}

/**
 * Add dropdown filters + functionality to term tables
 */

if ( 'taxonomy-name' === params.taxonomy ) {
    // Create the dropdown menu & HTML
    $( document.querySelector( '.tablenav .bulkactions' ) ).after( '\
        <div class="alignleft actions"> \
            <select id="js-filter-dropdown"> \
                <option value="">Term Meta Filter</option> \
                <option value="foo">Foo</option> \
                <option value="bar">Bar</option> \
                <option value="baz">Baz</option> \
            </select> \
            <button id="js-filter" class="button" type="button">Filter</button> \
        </div> \
    ' );

    // If we're already filtering the view, have the dropdown reflect that
    var value = decodeURIComponent( params.meta_value ).replace(/\+/g, ' ');
    $( '#js-filter-dropdown' ).find( 'option[value="' + value + '"]' ).prop( 'selected', true );

    // Set up the button action - see taxonomy_filter() for server-side filtering
    $( '#js-filter' ).click(function() {
        var value = $( '#js-filter-dropdown' ).val();

        if ( value ) {
            params.meta_key = 'meta-filter';
            params.meta_value = encodeURIComponent( value );
        } else {
            delete params.meta_key;
            delete params.meta_value;
        }

        window.location.search = setParams();
    });
}

Capture d'écran de l'interface utilisateur de filtrage

 Before 

Capture d'écran de la table filtrée

 After image 

4
constancecchen

En examinant rapidement la classe, il semble que nous pourrions détourner le filtre bulk_actions-{$this->screen->id} pour ajouter des menus déroulants supplémentaires au sommet de la table.

Exemple

Pour la taxonomie de la catégorie:

add_filter( 'bulk_actions-edit-category', function( $actions )
{
    echo '<select name="foo" ><option value="bar">Bar</option></select>';

    return $actions;
} );

Sinon, il n’est pas facile d’étendre la classe WP_Terms_List_Table qui est instanciée avec:

$wp_list_table = _get_list_table('WP_Terms_List_Table');

Mettre à jour:

Voici un autre hack des aventures, pour la edit category screen, qui a besoin de quelques tests :-)

add_filter( 'manage_edit-category_columns', function( $columns ) use ( &$wp_list_table )
{    
    // Include the WP_Terms_List_Table class
    require_once ( ABSPATH . 'wp-admin/includes/class-wp-terms-list-table.php' );

    // Extend the WP_Terms_List_Table class
    class WPSE_Terms_List_Table extends WP_Terms_List_Table
    {
        // Override this method
        protected function extra_tablenav( $which )
        {
            echo '<select name="foo" ><option value="bar">Bar</option></select>';
        }
    } 
    // end class

    $obj = new WPSE_Terms_List_Table;
    $obj->prepare_items(); 

    // Let's clone it to the global object
    $wp_list_table = clone $obj;

    return $columns;
} );

De plus, il faut filtrer avec get_terms_args comme mentionné par @winnietherpooh et ajuster l'emplacement avec le filtre redirect_term_location comme mentionné par @Paul 'Sparrow Hawk' Biron

3
birgire