Folosește filtrul 'parse_query' pentru a afișa postări care îndeplinesc mai multe criterii
Î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.
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ă
Hook-ul de acțiune
pre_get_posts
- http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_postsHook-ul de filtru
posts_where
- http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where

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!

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.

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.

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).

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.

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

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.
