Utilizzare il filtro 'parse_query' per mostrare post con criteri multipli

26 gen 2015, 03:40:47
Visualizzazioni: 14.9K
Voti: 1

Sto cercando di filtrare la pagina dei Post nell'admin di WordPress per mostrare i post che soddisfano i criteri per "A" -oppure- i criteri per "B". Ho esaminato la documentazione ma non ho trovato un modo efficace per farlo.

Dettagli: Ho limitato i ruoli utente in modo che gli autori possano modificare solo i propri post. Tuttavia, ho aggiunto un campo personalizzato che permette agli autori di selezionare altri autori per consentire anche a loro di modificare il post. Questa funzionalità funziona perfettamente se uso uno o l'altro nel mio filtro 'parse_query', ma se provo ad abilitarli entrambi la query pensa che voglia mostrare post che soddisfino TUTTI i criteri (e quindi nessuno).

Per riferimento, ecco il mio codice (si trova in functions.php):

add_filter('parse_query', 'show_appropriate_posts');
function show_appropriate_posts($query) {
    if ( strpos($_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php') !== false ) {
        if ( !current_user_can('manage_options') ) {
            global $current_user;

            //Mostra solo i post di questo utente (A).
            $query->set('author', $current_user->id);

            //Mostra i post in cui questo utente è "segnato" (B).
            $query->set('meta_key', 'add_editing_permission_for');
            $query->set('meta_value', $current_user->id);
            $query->set('meta_compare', 'LIKE');

            //@TODO: Bisogna mostrare i post che soddisfano (A) -oppure- (B).
        }
    }
}

Ripeto, sia (A) che (B) funzionano correttamente quando vengono eseguiti singolarmente.

3
Commenti

Dopo ulteriori ricerche, penso che potrei aver bisogno di una query SQL personalizzata. Se è così, apprezzerei qualsiasi aiuto per integrarla con il filtro sopra menzionato.

GreatBlakes GreatBlakes
26 gen 2015 07:38:44

Dai un'occhiata a meta_query (per sostituire meta_key, meta_value e meta_compare), potresti essere in grado di fare qualcosa con questo.

David Gard David Gard
26 gen 2015 16:53:34

In realtà, ignora il mio commento precedente, non credo che si possa fare in quel modo. Spero comunque di averti fornito una risposta :)

David Gard David Gard
26 gen 2015 17:34:26
Tutte le risposte alla domanda 1
8

Ignora il mio commento su meta_query. Non solo non funziona con $query->set(), ma non saresti in grado di controllare il requisito critico "A O B" della query.

Invece, credo che ciò di cui hai bisogno sia possibile attraverso una combinazione dell'hook di azione pre_get_posts e dell'hook di filtro posts_where come segue.

add_action('pre_get_posts', 'my_show_appropriate_posts');
function my_show_appropriate_posts($query){

    if(strpos($_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php') !== false) :

        if(!current_user_can('manage_options')) :

            /** Annulla per poter controllare esattamente dove questa parte della query viene inclusa */
            $query->set('author', null);

            /** Assicurati che le tabelle rilevanti necessarie per una meta query siano incluse */
            $query->set('meta_query', array(
                array(
                    'key'       => 'add_editing_permission_for',
                    'value'     => 'dummy', // Questo non può essere vuoto a causa di un bug in WordPress
                    'compare'   => '='
                )
            ));

            /** Chiama il filtro per modificare la porzione '$where' della query */
            add_filter('posts_where', 'my_custom_posts_where');

        endif;

    endif;

}

function my_custom_posts_where( $where = '' ){

    global $wpdb;

    /** Aggiungi le nostre condizioni richieste alla porzione '$where' della query */
    $where.= sprintf(
        ' AND ( %1$s.post_author = %2$s OR ( %3$s.meta_key = "add_editing_permission_for" AND %3$s.meta_value = %2$s ) )',
        $wpdb->posts,
        get_current_user_id(),
        $wpdb->postmeta
    );

    /** Rimuovi il filtro per chiamare questa funzione, poiché non lo vogliamo più */
    remove_filter('posts_where', 'my_custom_posts_where');

    return $where;

}

Letture consigliate

26 gen 2015 17:33:48
Commenti

Grazie per questo - con alcune piccole modifiche ha fatto esattamente ciò di cui avevo bisogno (ho cambiato il primo AND nella tua sprintf in OR e ho modificato il meta_query). Grazie ancora!

GreatBlakes GreatBlakes
26 gen 2015 21:05:54

Nessun problema. Sono però curioso del perché hai dovuto cambiare AND in OR? L'idea è che stai dicendo alla query "(soddisfa tutte le condizioni precedenti) AND (assicura che l'autore del post sia l'utente corrente OR assicura che l'utente corrente sia autorizzato a modificare il post)". Cambiandolo in OR stai ignorando tutte le altre condizioni, come il tipo di post - quindi, ad esempio, potresti scoprire che gli utenti che hanno creato pagine le vedono nell'elenco, non solo i post.

David Gard David Gard
27 gen 2015 12:43:26

Inoltre, vedo che qualcun altro ha rifiutato la tua modifica alla mia risposta. Il motivo è che non "corregge" davvero nulla. Ad esempio, il meta_query non fa alcuna differenza (per quanto ne sappia), devi solo passarne uno a $query->set() per assicurarti che vengano effettuati i join rilevanti. E riguardo al cambiamento da AND a OR, se potessi spiegare perché l'hai fatto nei commenti per gli altri utenti sarebbe fantastico, e da lì posso modificare la risposta se necessario. Grazie.

David Gard David Gard
27 gen 2015 12:53:52

Ad essere sincero, pensavo di averlo risolto, ma era solo l'illusione che funzionasse - haha. L'OR faceva apparire tutto, il che sembrava fosse sistemato. In realtà sono ancora bloccato su questo - sono certo che il tuo codice funzionerà, ma non sono ancora riuscito a capire i dettagli specifici. Per qualche motivo il resto dell'SQL non funziona correttamente (e non so perché perché sembra esattamente quello che voglio). Sono contento che la mia modifica sia stata respinta, in realtà, perché avrebbe portato altre persone sulla strada sbagliata (dove mi trovo ora).

GreatBlakes GreatBlakes
27 gen 2015 20:58:39

C'entra qualcosa con il lato meta_key della query SQL. Anche se provo a interrogare solo quello, non ottengo alcun risultato. Il $query->set della prima funzione sembra avere a che fare con questo - ho la sensazione che forse non stia preparando quelle chiavi nel modo giusto? Oh - dovrai rimuovere la seconda chiamata a add_filter('posts_where', 'my_custom_posts_where'); nella tua risposta - altrimenti si attiva su tutti i post (anche sul frontend) - quella riga dovrebbe apparire solo all'interno della prima funzione.

GreatBlakes GreatBlakes
27 gen 2015 21:03:23

Perché stai aggiungendo il filtro due volte (una dentro il callback e una nello scope globale)? A una prima occhiata, verrà eseguito su ogni query. +1 per il resto della risposta :)

kaiser kaiser
28 gen 2015 02:22:30

Ottima osservazione, ho rimosso quello dall'ambito globale.

David Gard David Gard
28 gen 2015 11:28:24

Ok ora funziona. È imbarazzante, ma l'unica modifica aggiuntiva necessaria nella tua risposta è che il '=' dopo 'dummy' deve diventare un '!='. È stato un modo indiretto per trovarlo usando phpmyadmin per testare query SQL, ma almeno ora è tutto a posto.

GreatBlakes GreatBlakes
29 gen 2015 21:55:49
Mostra i restanti 3 commenti