Folosește filtrul 'parse_query' pentru a afișa postări care îndeplinesc mai multe criterii

26 ian. 2015, 03:40:47
Vizualizări: 14.9K
Voturi: 1

Încerc să filtrez pagina de Postări în administrarea WordPress pentru a afișa postările care îndeplinesc criteriile pentru "A" -sau- criteriile pentru "B". Am căutat în documentație și nu am găsit o metodă bună pentru a face asta.

Detalii: Am configurat rolurile utilizatorilor astfel încât autorii să poată edita doar propriile postări. Totuși, am adăugat un câmp personalizat care permite autorilor să selecteze alți autori pentru a le permite să editeze postarea. Această funcționalitate funcționează perfect dacă folosesc unul sau celălalt criteriu în filtrul meu 'parse_query', dar dacă încerc să activez ambele, interogarea crede că vreau să afișez postări care îndeplinesc TOATE criteriile (ceea ce nu există).

Pentru referință, iată codul meu (acesta se află în 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;

            //Afisează doar postările acestui utilizator (A).
            $query->set('author', $current_user->id);

            //Afisează postările în care acest utilizator este "atribuit" (B).
            $query->set('meta_key', 'add_editing_permission_for');
            $query->set('meta_value', $current_user->id);
            $query->set('meta_compare', 'LIKE');

            //@TODO: Trebuie să afișez postări care îndeplinesc (A) -sau- (B).
        }
    }
}

Din nou, ambele condiții (A) și (B) funcționează atunci când sunt rulate separat.

3
Comentarii

După mai multă cercetare, cred că ar putea fi nevoie de o interogare SQL personalizată. Dacă este cazul, aș aprecia orice ajutor pentru a integra una cu filtrul menționat mai sus.

GreatBlakes GreatBlakes
26 ian. 2015 07:38:44

Aruncă o privire la meta_query (pentru a înlocui meta_key, meta_value și meta_compare), s-ar putea să poți face ceva cu asta.

David Gard David Gard
26 ian. 2015 16:53:34

De fapt, ignoră comentariul meu anterior, nu cred că poți face asta în acel fel. Sper totuși că ți-am oferit un răspuns :)

David Gard David Gard
26 ian. 2015 17:34:26
Toate răspunsurile la întrebare 1
8

Ignoră comentariul meu despre meta_query. Nu numai că nu funcționează cu $query->set(), dar nici nu ai putea controla cerința critică "A SAU B" a interogării.

În schimb, cred că ceea ce ai nevoie este posibil prin combinarea ambelor hook-uri de acțiune pre_get_posts și filtrul posts_where după cum urmează.

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')) :

            /** Anulează setarea pentru a putea controla exact unde este inclusă această parte a interogării */
            $query->set('author', null);

            /** Asigură-te că tabelele relevante necesare pentru o interogare meta sunt incluse */
            $query->set('meta_query', array(
                array(
                    'key'       => 'add_editing_permission_for',
                    'value'     => 'dummy', // Aceasta nu poate fi goală din cauza unui bug în WordPress
                    'compare'   => '='
                )
            ));

            /** Apelează filtrul pentru a modifica porțiunea '$where' a interogării */
            add_filter('posts_where', 'my_custom_posts_where');

        endif;

    endif;

}

function my_custom_posts_where( $where = '' ){

    global $wpdb;

    /** Adaugă condițiile noastre necesare la porțiunea '$where' a interogării */
    $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
    );

    /** Elimină filtrul pentru a nu mai apela această funcție, deoarece nu o mai dorim */
    remove_filter('posts_where', 'my_custom_posts_where');

    return $where;

}

Lectură recomandată

26 ian. 2015 17:33:48
Comentarii

Mulțumesc pentru asta - cu câteva modificări minore, acest lucru a făcut exact ce aveam nevoie (am schimbat primul AND din sprintf-ul tău în OR și am editat meta_query-ul). Mulțumesc din nou!

GreatBlakes GreatBlakes
26 ian. 2015 21:05:54

Nicio problemă. Sunt curios de ce a trebuit să schimbi AND în OR totuși? Ideea este că spui interogării "(îndeplinește toate condițiile anterioare) AND (asigură-te că autorul postării este utilizatorul curent OR asigură-te că utilizatorul curent este autorizat să editeze postarea)". Prin schimbarea în OR, ignori toate celelalte condiții, cum ar fi tipul de postare - așa că, de exemplu, poate găsi că utilizatorii care au creat pagini le văd în listă, nu doar postări.

David Gard David Gard
27 ian. 2015 12:43:26

De asemenea, văd că cineva a respins editarea ta a răspunsului meu. Motivul pentru asta este că nu 'repară' cu adevărat nimic. meta_query-ul, de exemplu, nu face nicio diferență (din câte știu eu), trebuie doar să treci unul la $query->set() pentru a te asigura că se fac join-urile relevante. Și referitor la schimbarea AND în OR, dacă ai putea explica de ce ai făcut asta în comentarii pentru alți utilizatori, ar fi minunat, și de acolo pot edita răspunsul dacă este necesar. Mulțumesc.

David Gard David Gard
27 ian. 2015 12:53:52

Să fiu sincer, am crezut că am rezolvat problema, dar era doar iluzia că funcționează - haha. Operatorul OR a făcut ca totul să apară, ceea ce părea că e rezolvat. De fapt, încă sunt blocat aici - sunt sigur că codul tău va funcționa, dar nu am reușit încă să înțeleg detaliile. Din nu știu ce motiv, restul interogării SQL nu merge corect (și nu înțeleg de ce, pentru că arată exact cum aș vrea). Mă bucur că edit-ul meu a fost respins, pentru că i-ar fi dus pe alți pe o cale greșită (acolo unde sunt eu acum).

GreatBlakes GreatBlakes
27 ian. 2015 20:58:39

Are legătură cu partea de meta_key din interogarea SQL. Chiar dacă încerc să interoghez doar asta, nu primesc niciun rezultat. $query->set din prima funcție pare să aibă legătură cu asta - am impresia că poate nu pregătește corect acele chei? A, și va trebui să elimini cel de-al doilea apel la add_filter('posts_where', 'my_custom_posts_where'); din răspunsul tău - altfel se activează pentru toate postările (chiar și pe frontend) - acea linie ar trebui să apară doar în interiorul primei funcții.

GreatBlakes GreatBlakes
27 ian. 2015 21:03:23

De ce adaugi filtrul de două ori (o dată în callback și o dată în scope-ul global)? La o privire rapidă, se va executa pentru fiecare interogare. +1 pentru restul răspunsului :)

kaiser kaiser
28 ian. 2015 02:22:30

Bună observație, am eliminat-o din domeniul global.

David Gard David Gard
28 ian. 2015 11:28:24

Ok, acum funcționează. E jenant, dar singura modificare suplimentară de care ai nevoie în răspunsul tău este ca '=' după 'dummy' să fie înlocuit cu '!='. A fost un mod ocolit de a găsi soluția folosind phpmyadmin pentru a testa interogările SQL, dar cel puțin acum totul funcționează corect.

GreatBlakes GreatBlakes
29 ian. 2015 21:55:49
Arată celelalte 3 comentarii