Come rendere accessibile a tutti un articolo in bozza?
Ho diversi articoli non pubblicati nel mio sito WordPress e sto cercando di renderli accessibili agli utenti normali (che non sono loggati) utilizzando gli slug normali degli articoli (sito.it/articolo-qui
). Capisco che non sia la migliore pratica, ma per il mio scopo specifico, questo deve essere fatto.
Ho provato ad aggiungere il seguente snippet di codice nel mio file functions.php
:
function abilita_visualizzazione_bozze() {
$ruolo = get_role( 'subscriber' );
$ruolo->add_cap( 'read_private_posts' );
$ruolo->add_cap( 'edit_posts' );
}
add_action( 'after_setup_theme', 'abilita_visualizzazione_bozze');
Ho anche provato con l'hook init
invece di after_setup_theme
. Senza successo.
La mia comprensione è che le modifiche ai ruoli vengono salvate nel database quindi devono essere fatte solo una volta. Ecco perché sto usando l'hook after_setup_theme
per chiamare la funzione.
Ma quando provo ad accedere alla pagina come utente normale, mi viene mostrata una pagina 404 invece del contenuto dell'articolo. Ho anche provato a caricare l'URL di anteprima (sito.it/?p=212&preview=true
) ma non ha funzionato neanche quello.
Queste sono le mie ipotesi:
- l'utente normale non ha sufficienti
cap
per leggere gli articoli in bozza. - testare e visualizzare articoli in bozza sul front-end non è possibile per nessun utente (inclusi gli amministratori).
Quali modifiche devo apportare per ottenere ciò che sto cercando di fare? Se non è possibile, quali soluzioni alternative suggerite?
Nota: Non cerco soluzioni basate su plugin.

Non puoi assegnare capacità a utenti sconosciuti. Se vuoi rendere un articolo visibile a tutti, crea un URL separato per questi articoli e aggiungi un elemento di controllo nell'editor degli articoli per abilitare l'anteprima solo su quelli selezionati.
Quando viene chiamato un URL di questo tipo, verifica se l'anteprima è consentita per l'articolo e se l'articolo non è già stato pubblicato. Assicurati inoltre che i motori di ricerca ignorino questo URL.
Per l'URL utilizzerei un endpoint:
add_rewrite_endpoint( 'post-preview', EP_ROOT );
Ora puoi creare URL come…
http://example.com/post-preview/123
…dove 123
è l'ID dell'articolo.
Quindi utilizza un gestore di callback per verificare l'ID dell'articolo, controllare se è valido e sovrascrivere la query principale. Questo è probabilmente l'unico caso d'uso accettabile per query_posts()
. :)
Supponiamo che l'endpoint sia una classe T5_Endpoint
(un modello) e che il gestore dell'output sia una classe T5_Render_Endpoint
(una vista) a cui viene passato il modello precedentemente. Allora probabilmente c'è un metodo render()
chiamato su 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
è un altro modello (classe T5_Post_Meta
) per il valore meta dell'articolo che controlla se è consentita un'anteprima. Il controllo è impostato nel box Pubblica (azione post_submitbox_misc_actions
), reso da un'altra vista che riceve la stessa classe meta.
Quindi T5_Post_Meta
sa dove e quando memorizzare il valore meta, le viste fanno qualcosa con esso.
Inoltre, agganciati a transition_post_status
per eliminare il campo meta dell'articolo quando viene pubblicato. Non vogliamo sprecare risorse, vero?
Questo è solo uno schema. Ci sono molti dettagli da coprire… Ho scritto un piccolo plugin che mostra come implementarlo: T5 Public Preview.

Ho risolto questo problema in un modo che ritengo più semplice rispetto alla risposta di @toscho sopra.
Il mio caso d'uso è che sto utilizzando lo stesso database per un sito di staging intranet interno e un sito pubblico, e il flusso di lavoro prevede che gli autori scrivano bozze e le condividano con altri utenti che le visualizzano sul sito intranet, prima della pubblicazione. Specificamente non volevo richiedere ai revisori di effettuare il login per vedere le bozze, quindi mi affido semplicemente a una costante ENV_PRODUCTION
che viene impostata nel file wp-config in base all'hostname in $_SERVER['SERVER_NAME']
. Questo è ciò che fanno i controlli per ENV_PRODUCTION
qui; escludono semplicemente tutti questi filtri se il sito in produzione viene visualizzato.
È un po' strano, perché devi agganciarti dopo che WP_Query rimuove tutti i post dall'array $wp_query->posts, ma mi sembra stabile e sicuro.
/*
* Nelle pagine home e archivio del sito di staging, le bozze dovrebbero essere visibili.
*/
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' );
/*
* Rendi visibili le bozze nelle visualizzazioni singole del sito di staging.
*
* (Perché nelle visualizzazioni singole, WP_Query applica una logica per assicurarsi che
* l'utente corrente possa modificare il post prima di mostrare una bozza.)
*/
function show_single_drafts_on_staging( $posts, $wp_query ) {
if ( ENV_PRODUCTION )
return $posts;
//assicurarsi che il post sia un'anteprima per evitare di mostrare post privati pubblicati
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 );
Ci sono due parti separate nei filtri:
- Un filtro sull'hook "pre_get_posts" imposta il post_status predefinito a 'publish,draft' sul sito di staging. Questo farà sì che le bozze vengano incluse negli elenchi degli archivi.
- È necessario un filtro separato per le visualizzazioni singole, perché c'è una logica complessa nella classe WP_Query che rimuove le bozze dai risultati della query a meno che l'utente corrente non possa modificarle. Ho aggirato questo problema filtrando 'the_posts' e riaggiungendo il post desiderato direttamente ai risultati.

Questo è incredibile, grazie mille per aver condiviso questo. Assolutamente perfetto e esattamente ciò di cui avevo bisogno.

@Joelio Puoi essere specifico riguardo al problema che stai risolvendo? Come approccio semplice, ho semplicemente aggiunto questo codice al mio functions.php e ho aggiunto una semplice definizione al mio wp-config.php che imposta la costante ENV_PRODUCTION a true o false in base al dominio della richiesta.

@goldenapples Ho aggiunto questo pezzo di codice al mio function.php, cosa dovrei aggiungere a wp-config? Grazie per il tuo aiuto

@MatthiasGrahamSlick - Hai solo bisogno di qualcosa che imposti la costante ENV_PRODUCTION
se sei in produzione. Io usavo domain.com per la produzione e staging.domain.com per lo staging, quindi la mia riga era define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) );
Ti aiuta?

@goldenapples dove nella tua funzione show_single_drafts_on_staging
controlli di mostrare solo i post con post_status=draft
? Per quanto ho testato il tuo codice, mostra qualsiasi post (anche quelli cestinati) nelle pagine singole. O sto facendo qualcosa di sbagliato?

No, come menzionato nella domanda, non sto cercando soluzioni basate su plugin. L'uso è leggermente complicato ma sono sicuro che questa sia la soluzione migliore per questo specifico compito che sto cercando di realizzare. :-)

Anch'io sono perplesso riguardo al motivo. Se vuoi che tutti vedano il post, perché non semplicemente pubblicarlo? Potresti usare campi personalizzati sul post per tenere traccia di qualsiasi stato speciale che desideri definire.

Penso che il commento di G.M. sia il migliore qui. Presumo tu stia cercando di fare quanto segue:
- Scrivere un articolo
- Salvarlo come bozza
- Permettere a un utente esterno (non autenticato) di visualizzare la bozza per approvazione
- Pubblicare
È corretto?
Sfortunatamente, non riesco a pensare a un modo semplice per farlo. Potresti pubblicarlo come articolo privato in modo che debbano inserire una password per visualizzarlo, ma devi essere autenticato per questo. Potresti anche proteggerlo con password, ma in questo caso apparirà comunque nel tuo feed e nell'elenco degli articoli recenti, ecc. Non potresti creare un account utente ospite e fornirgli nome utente/password quando gli dai l'URL?
Leggi qui per maggiori informazioni: http://codex.wordpress.org/Content_Visibility
In alternativa, c'è un plugin che potrebbe fare al caso tuo: http://wordpress.org/extend/plugins/shareadraft/ Ho dato una rapida occhiata al codice e sembra che lo sviluppatore stia modificando il valore restituito da get_post_status, quindi potresti essere in grado di giocarci un po':
http://codex.wordpress.org/Function_Reference/get_post_status
Spero sia d'aiuto

Questa non è una soluzione valida per una pagina già pubblicata. Puoi apportare modifiche a una pagina attualmente online e salvarle come bozza. Se segui questo approccio su una pagina live, rimuoverebbe gradualmente la pagina dai risultati di ricerca e potrebbe causare altri problemi.
