J'utilise un site Web avec WordPress 4.2 et j'ai changé la façon dont les articles brouillon ou en cours de révision sont affichés pour les utilisateurs non connectés (ces articles sont également visibles par quiconque visite le site Web).
J'ai implémenté cette solution présentée ici: https://wordpress.org/support/topic/problem-filtering-query-to-allow-displaying-drafts-even-for-not-logged-users
Maintenant, alors que n'importe qui peut maintenant accéder aux brouillons/sans avoir à se connecter, les posts ne sont accessibles que via post_id, comme ceci:
Ils ne sont pas accessibles via leur lien permanent/permalien Nice, qui était comme ça:
http://my-domain.com/2015/12/07/post-with-Nice-slug/
Quelqu'un a-t-il une idée sur la manière de "activer" les liens permanents pour les brouillons/les messages en attente?
Je vous remercie!
UPDATE 20 février
La réponse donnée par @userabuser fonctionne à merveille !! Étant donné que tous mes projets en attente/brouillon étaient des publications antérieures, je n'avais pas besoin de faire le tour pour publier en premier. J'avais pensé que j'avais moi-même trouvé une solution de travail - mais: voici le code que j'ai utilisé auparavant, qui ne fonctionnait pas (et je ne vois pas pourquoi):
function guest_enable_hidden_single_post($query) {
if(is_user_logged_in()) return $query;
//user is not logged
if(!is_single()) return $query;
//this is a single post
if(!$query->is_main_query())return $query;
//this is the main query
$query->set('post_status',array('publish', 'pending'));
//allowed post statuses for guest
return $query;
}
function guest_reload_hidden_single_post($posts) {
global $wp_query, $wpdb;
if(is_user_logged_in()) return $posts;
//user is not logged
if(!is_single()) return $posts;
//this is a single post
if(!$wp_query->is_main_query()) return $posts;
//this is the main query
if($wp_query->post_count) return $posts;
//no posts were found
$posts = $wpdb->get_results($wp_query->request);
return $posts;
}
//allow guests to view single posts even if they have not post_status="publish"
add_filter('pre_get_posts', 'guest_enable_hidden_single_post');
//reload hidden posts
add_filter('the_posts', 'guest_reload_hidden_single_post');
UPDATE 22 février
Il y avait un problème avec les pages privées non affichées aux administrateurs/utilisateurs connectés. J'ai corrigé cela avec le code suivant:
function preview_draft_posts($query) {
if(is_user_logged_in()) return $query;
// user is not logged
if(is_admin()) return $query;
// user is not admin
if(is_attachment()) return $query;
// is not an attachment
if(get_query_var('suppress_filters')) return $query;
// no suppressed filters
if(!is_single()) return $query;
// query for a single post
if(!$query->is_main_query()) return $query;
// this is the main query
$query->set('post_status', array('publish', 'pending'));
return $query;
}
add_filter('pre_get_posts', 'preview_draft_posts');
Désormais, les publications en attente sont affichées à tout le monde et les publications privées ne sont encore visibles que par les administrateurs ;-)
Avertissement: les exemples de code dans cette réponse sont très basiques et peuvent nécessiter ou non une logique conditionnelle supplémentaire pour s'adapter à vos besoins précis. Cette logique est conçue à titre d'exemple pour vous permettre de progresser.
Vous devez prendre en compte deux considérations:
Si vous ajoutez une nouvelle publication et l'enregistrez avec un post_status
de draft first, la publication n'aura pas la variable slug
dans le champ post_name
de la table *_posts
de la base de données jusqu'à ce que vous publiez au moins une fois .
Si vous ajoutez un nouveau post, enregistrez-le avec un post_status
de draft , ou passez simplement le draft stage et passez directement à publish puis remettez le post dans un brouillon post_status
, alors le billet aura le slug inséré dans la colonne post_name
de la table *_posts
.
WordPress s'appuie sur au moins un marqueur d'identification, généralement le id
ou le post_name
, qui est unique pour pouvoir récupérer un message.
Vous remarquerez que lorsque vous créez un brouillon et tentez de le prévisualiser, WordPress vous conduit à une URL de prévisualisation similaire à:
http://example.com/?p=123&preview=true
C'est parce que le seul moyen d'identifier et de prévisualiser le message en question consiste à le faire à l'aide de l'ID auquel il est associé dans la base de données.
Si vous publiez la publication au moins une fois, puis remettez-la dans draft , vous pourrez accéder à la publication tant que draft status sera utilisée avec le slug ( très permalien) car la colonne post_name
contient la valeur slug.
Le code suivant vous permettra de renvoyer des publications dans un draft ou en attente status en utilisant le slug tant que la publication a été publiée au moins une fois auparavant (voir considération 2).
function preview_draft_posts($query) {
if ( is_admin() || get_query_var('suppress_filters') )
return $query;
$query->set('post_status', array('publish', 'pending', 'draft'));
return $query;
}
add_filter('pre_get_posts', 'preview_draft_posts');
Ce qui précède fonctionnera pour les utilisateurs connectés et déconnectés.
Ok, donc si le draf n’a pas été publié au moins une fois auparavant, le seul moyen de prévisualiser le message consiste à utiliser le format suivant:
http://example.com/?p=123
WordPress dépend de ce format pour trouver un article où il n’a pas de slug.
Si vous êtes déconnecté, vous ne pourrez pas voir ce message malgré la logique pre_get_posts
utilisée dans l'exemple ci-dessus.
Au lieu de cela, vous devez vous connecter au filtre the_posts
et rajouter la publication aux résultats à afficher, car WP_Query
exclura draft posts de l'ensemble de résultats pour les utilisateurs déconnectés, car les utilisateurs déconnectés ne disposent pas du des capacités d'utilisateur appropriées.
Si, par contre, vous essayez (en étant déconnecté) d'accéder à un message similaire à celui de la considération 1 par son URL de prévisualisation par défaut, comme indiqué ci-dessus dans l'exemple http://example.com/?p=123&preview=true
(avec ou sans le preview=true
), un message d'erreur s'affiche. Avis de page non trouvée.
L'exemple de code suivant corrige cela:
function the_posts_preview_draft_posts($posts, $wp_query) {
//abort if $posts is not empty, this query ain't for us...
if ( count($posts) ) {
return $posts;
}
$p = get_query_var('p');
//get our post instead and return it as the result...
if ( !empty($p) ) {
return array(get_post($p));
}
}
add_filter('the_posts', 'the_posts_preview_draft_posts', 10, 2);
Génial ... mais accrochez-vous, ça craint toujours, en quelque sorte, car vous devez utiliser un format d'URL tel que http://example.com/?p=123
pour accéder à la publication.
Revenons au problème principal décrit dans Considération 1 , les seules solutions auxquelles je puisse penser sont les suivantes:
Exemple...
function the_posts_preview_draft_posts($posts, $wp_query) {
//abort if $posts is not empty, this query ain't for us...
if ( count($posts) ) {
return $posts;
}
$id = get_query_var('p');
$name = get_query_var('name');
//this is a bit of a bad idea...
if ( empty($id) && !empty($name) ) {
$name = preg_replace('/\W/', ' ', $name);
global $wpdb;
$id = $wpdb->get_var(
"
SELECT ID
FROM $wpdb->posts
WHERE UPPER(post_title) LIKE UPPER('".$name."')
LIMIT 1"
);
}
//get our post instead and return it as the result...
if ( !empty($id) ) {
return array(get_post($id));
}
}
add_filter('the_posts', 'the_posts_preview_draft_posts', 10, 2);
Ce qui précède ... ↑ ... est une mauvaise idée, mais juste un exemple des longueurs auxquelles vous devez aller. Pourquoi ceci est une mauvaise idée est simple, vous devez vous assurer que vous n'avez aucun titre d'article en double dans la base de données et vous ne devez pas modifier le slug afin qu'il soit différent du titre lorsque vous l'enregistrez en tant que brouillon .
Beaucoup de problèmes, comme vous pouvez le voir.
Une meilleure solution consiste probablement à définir le post_status de la publication sur publish afin que la colonne post_name
obtienne la valeur slug, puis à replacer immédiatement la publication dans un draft status .
Faire cela manuellement serait nul alors voici du code:
function allow_draft_public_preview( ) {
global $post;
if ( !empty($post->post_name) )
return;
$html =<<<DOC
<div class="misc-pub-section">
<label>
<input type="checkbox" id="_allow_public_preview" name="_allow_public_preview" value="1" />
Allow public preview
</label>
</div>
DOC;
echo $html;
}
add_action('post_submitbox_misc_actions', 'allow_draft_public_preview');
function update_post_status( $post_id, $post, $update ) {
if ( !empty($_POST['_allow_public_preview']) ) {
//un-hook to prevent infinite loop
remove_action( 'save_post', 'update_post_status', 13, 2 );
//set the post to publish so it gets the slug is saved to post_name
wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );
//immediately put it back to draft status
wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );
//re-hool
add_action( 'save_post', 'update_post_status', 13, 2 );
}
}
add_action('save_post', 'update_post_status', 13, 2);
Le premier rappel attaché à l'action post_submitbox_misc_actions
ajoute une case à cocher à l'écran d'édition postérieure "Autoriser l'aperçu public" ...
... lorsque vous cochez cette case, elle sera reconnue par le deuxième rappel déclenché sur l'action save_post
.
Dans l'action save_post
, nous vérifions l'existence de notre case à cocher dans le $_POST
superglobal et si elle est présente, nous affectons le statut de publication à publish puis nous le remettons immédiatement à draft .
Vous pouvez maintenant accéder aux brouillons, connectés ou déconnectés, par leurs liens permanents/jolis permaliens.
function preview_draft_posts($query) {
if ( is_admin() || get_query_var('suppress_filters') )
return $query;
$query->set('post_status', array('publish', 'pending', 'draft'));
return $query;
}
add_filter('pre_get_posts', 'preview_draft_posts');
function the_posts_preview_draft_posts($posts, $wp_query) {
//abort if $posts is not empty, this query ain't for us...
if ( count($posts) ) {
return $posts;
}
$p = get_query_var('p');
//get our post instead and return it as the result...
if ( !empty($p) ) {
return array(get_post($p));
}
}
add_filter('the_posts', 'the_posts_preview_draft_posts', 10, 2);
function allow_draft_public_preview( ) {
global $post;
if ( !empty($post->post_name) )
return;
$html =<<<DOC
<div class="misc-pub-section">
<label>
<input type="checkbox" id="_allow_public_preview" name="_allow_public_preview" value="1" />
Allow public preview
</label>
</div>
DOC;
echo $html;
}
add_action('post_submitbox_misc_actions', 'allow_draft_public_preview');
function update_post_status( $post_id, $post, $update ) {
if ( !empty($_POST['_allow_public_preview']) ) {
//un-hook to prevent infinite loop
remove_action( 'save_post', 'update_post_status', 13, 2 );
//set the post to publish so it gets the slug is saved to post_name
wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );
//immediately put it back to draft status
wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );
//re-hool
add_action( 'save_post', 'update_post_status', 13, 2 );
}
}
add_action('save_post', 'update_post_status', 13, 2);