Cum să fac o postare draft accesibilă tuturor în WordPress?
Am mai multe postări nepublicate pe site-ul meu WordPress și încerc să le fac accesibile pentru utilizatorii normali (care nu sunt autentificați) folosind slug-urile normale ale postărilor (site.com/post-here
). Înțeleg că poate nu este cea mai bună practică, dar pentru scopul meu special, acest lucru trebuie făcut.
Am încercat să adaug următorul fragment de cod în fișierul meu functions.php
:
function enable_view_drafts() {
$role = get_role( 'subscriber' );
$role->add_cap( 'read_private_posts' );
$role->add_cap( 'edit_posts' );
}
add_action( 'after_setup_theme', 'enable_view_drafts');
Am încercat și cu hook-ul init
în loc de after_setup_theme
. Fără succes.
Din câte înțeleg, modificările la roluri sunt salvate în baza de date, așa că trebuie făcute doar o singură dată. De aceea folosesc hook-ul after_setup_theme
pentru a apela funcția.
Dar când încerc să accesez pagina ca utilizator normal, primesc în schimb o pagină 404 în loc să văd conținutul postării. Am încercat și cu URL-ul de previzualizare (site.com/?p=212&preview=true
), dar nici asta nu a funcționat.
Acestea sunt presupunerile mele:
- utilizatorul normal nu are suficiente
capabilități
pentru a citi postările draft. - testarea și vizualizarea postărilor draft pe front-end nu este posibilă pentru niciun utilizator (inclusiv administratori).
Ce modificări trebuie să fac pentru a realiza ceea ce încerc să fac? Dacă nu este posibil, ce soluții alternative sugerezi?
Notă: Nu caut soluții bazate pe plugin-uri.

Nu poți atribui capabilități utilizatorilor necunoscuți. Dacă vrei să faci un articol vizibil pentru toată lumea, creează un URL separat pentru aceste articole și adaugă un element de control în editorul de articole pentru a activa previzualizarea doar pe articolele selectate.
Când un astfel de URL este accesat, verifică dacă previzualizarea este permisă pentru articol și dacă articolul nu a fost deja publicat. De asemenea, asigură-te că motoarele de căutare ignoră acest URL.
Pentru URL aș folosi un endpoint:
add_rewrite_endpoint( 'post-preview', EP_ROOT );
Acum poți crea URL-uri precum...
http://example.com/post-preview/123
... unde 123
este ID-ul articolului.
Apoi folosește un handler de callback pentru a inspecta ID-ul articolului, verifică dacă este valid și suprascrie interogarea principală. Acesta este probabil singurul caz de utilizare acceptabil pentru query_posts()
. :)
Să presupunem că endpoint-ul este o clasă T5_Endpoint
(un model), iar handler-ul de ieșire este o clasă T5_Render_Endpoint
(o vizualizare) care primește modelul transmis anterior. Atunci probabil există o metodă render()
apelată pe template_redirect
:
public function render()
{
$post_id = $this->endpoint->get_value();
if ( ! $post_id )
return;
if ( 1 !== $this->meta->get_value( $post_id )
or 'publish' === get_post_status( $post_id )
)
{
wp_redirect( get_permalink( $post_id ) );
exit;
}
$query = array (
'suppress_filters' => TRUE,
'p' => $post_id,
'post_type' => 'any'
);
query_posts( $query );
add_action( 'wp_head', 'wp_no_robots' );
}
$this->meta
este un alt model (clasa T5_Post_Meta
) pentru valoarea meta a articolului care controlează dacă o previzualizare este permisă. Controlul este setat în caseta Publicare (acțiunea post_submitbox_misc_actions
), randată de o altă vizualizare care primește aceeași clasă meta.
Deci T5_Post_Meta
știe unde și când să stocheze valoarea meta, vizualizările fac ceva cu ea.
De asemenea, folosește hook-ul transition_post_status
pentru a șterge câmpul meta al articolului când acesta este publicat. Nu vrem să irosim resurse, nu-i așa?
Acesta este doar un schiță. Există multe detalii de acoperit... Am scris un mic plugin care arată cum să implementezi acest lucru: T5 Public Preview.

Am rezolvat această problemă într-un mod pe care l-am considerat mai simplu decât răspunsul lui @toscho de mai sus.
Cazul meu de utilizare este că folosesc aceeași bază de date atât pentru un site de staging intranet intern, cât și pentru un site public, iar fluxul de lucru este că autorii scriu drafturi și le împărtășesc cu alți utilizatori care le vizualizează pe site-ul intranet, înainte de publicare. Am vrut în mod special să evit necesitatea ca reviewerii să se autentifice pentru a vedea drafturile, așa că mă bazez doar pe o constantă, ENV_PRODUCTION
care este setată în fișierul wp-config pe baza numelui gazdei din $_SERVER['SERVER_NAME']
. Aceasta este ceea ce fac verificările pentru ENV_PRODUCTION
aici; doar scurtcircuitează toate aceste filtre dacă este vizualizat site-ul de producție.
Acest lucru este puțin ciudat, deoarece trebuie să te conectezi după ce WP_Query elimină toate articolele din array-ul $wp_query->posts, dar mi se pare stabil și sigur.
/*
* Pe site-ul de staging, pe paginile de acasă și arhive, drafturile ar trebui să fie vizibile.
*/
function show_drafts_in_staging_archives( $query ) {
if ( ENV_PRODUCTION )
return;
if ( is_admin() || is_feed() )
return;
$query->set( 'post_status', array( 'publish', 'draft' ) );
}
add_action( 'pre_get_posts', 'show_drafts_in_staging_archives' );
/*
* Face drafturile vizibile pe vizualizările individuale de pe site-ul de staging.
*
* (Deoarece pe vizualizările individuale, WP_Query trece prin logica de a se asigura că
* utilizatorul curent poate edita articolul înainte de a afișa un draft.)
*/
function show_single_drafts_on_staging( $posts, $wp_query ) {
if ( ENV_PRODUCTION )
return $posts;
// verificăm dacă articolul este o previzualizare pentru a evita afișarea articolelor private publicate
if ( ! is_preview() )
return $posts;
if ( count( $posts ) )
return $posts;
if ( !empty( $wp_query->query['p'] ) ) {
return array ( get_post( $wp_query->query['p'] ) );
}
}
add_filter( 'the_posts', 'show_single_drafts_on_staging', 10, 2 );
Există două părți separate ale filtrelor.
- Un filtru pe hook-ul "pre_get_posts" setează post_status implicit la 'publish,draft' pe site-ul de staging. Acest lucru va returna drafturile în listările de arhivă.
- Este necesar un filtru separat pentru vizualizările individuale, deoarece există o logică complicată în clasa WP_Query care elimină drafturile din rezultatele interogării, cu excepția cazului în care utilizatorul curent le poate edita. Am ocolit acest lucru prin filtrarea 'the_posts' și adăugând articolul dorit înapoi în rezultate.

Acest lucru este uimitor, vă mulțumesc mult pentru că ați împărtășit asta. Absolut perfect și exact de ce aveam nevoie.

@Joelio Poți fi mai specific în legătură cu problema pe care o rezolvi? Ca o abordare simplă, eu tocmai am adăugat acest cod în functions.php și am adăugat o definiție simplă în wp-config.php care setează constanta ENV_PRODUCTION la true sau false în funcție de domeniul solicitat.

@goldenapples Am adăugat acest fragment de cod în fișierul meu function.php, ce ar trebui să adaug în wp-config? Mulțumesc pentru ajutor.

@MatthiasGrahamSlick - Ai nevoie doar de ceva care să seteze constanta ENV_PRODUCTION
dacă ești pe producție. Eu foloseam domain.com pentru producție și staging.domain.com pentru staging, așa că linia mea era define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) );
Te ajută asta?

@goldenapples unde în funcția ta show_single_drafts_on_staging
controlezi afișarea doar a postărilor cu post_status=draft
? Din testele mele, codul tău afișează orice postare (chiar și cele șterse) pe paginile individuale. Sau fac eu ceva greșit?

Nu, așa cum am menționat în întrebare, nu caut soluții bazate pe plugin-uri. Cazul de utilizare este ușor complicat, dar sunt sigur că aceasta este cea mai bună soluție pentru această specifică sarcină pe care încerc să o realizez. :-)

Și eu sunt nedumerit de motiv. Dacă vrei ca toată lumea să vadă postarea, de ce nu o publici pur și simplu? Ai putea folosi câmpuri personalizate pe postare pentru a urmări orice stare specială pe care ai dori să o definești.

Cred că comentariul lui G.M. este cel mai bun aici. Presupun că încerci să faci următoarele:
- Scrie un articol
- Salvează ca draft
- Permite unui utilizator extern (neautentificat) să vizualizeze draftul pentru aprobare
- Publică
Este corect?
Din păcate, nu pot să mă gândesc la nicio metodă simplă pentru a face acest lucru. Ai putea să-l publici ca postare privată, astfel încât să fie nevoie de o parolă pentru a-l vizualiza, dar utilizatorii trebuie să fie autentificați pentru aceasta. Ai putea de asemenea să-l protejezi cu parolă, dar atunci va apărea în fluxul tău și în lista de postări recente, etc. Nu ai putea să creezi un cont de utilizator oaspete și să le dai numele de utilizator/parola când le trimiți URL-ul?
Citește aici pentru mai multe informații: http://codex.wordpress.org/Content_Visibility
Alternativ, există un plugin care ar putea să-ți corespundă nevoilor: http://wordpress.org/extend/plugins/shareadraft/ Am aruncat o privire rapidă asupra codului și se pare că dezvoltatorul modifică valoarea returnată de get_post_status, așa că ai putea să te joci cu asta:
http://codex.wordpress.org/Function_Reference/get_post_status
Hope this helps (HTH)

Aceasta nu este o soluție viabilă pentru o pagină deja publicată. Puteți face modificări la o pagină activă și să le salvați ca draft. Dacă ați urma această abordare pe o pagină live, aceasta ar putea elimina pagina din rezultatele de căutare în timp și ar putea cauza alte probleme.
