¿Cómo hago que un borrador de publicación sea accesible para todos?

13

Tengo varias publicaciones no publicadas en mi sitio web de Wordpress y estoy tratando de hacer que sea accesible para usuarios normales (que no han iniciado sesión) utilizando los mensajes de publicación normales ( site.com/post-here). Entiendo que puede que no sea la mejor práctica, pero para mi propósito especial, esto debe hacerse.

Intenté agregar el siguiente fragmento de código en mi functions.phparchivo:

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

También he intentado inithook en lugar de after_setup_theme. Sin suerte.

Tengo entendido que los cambios en los roles se guardan en la base de datos, por lo que solo deben hacerse una vez. Es por eso que estoy usando after_setup_themehook para llamar a la función.

Pero cuando intento acceder a la página como un usuario normal, se me muestra una página 404 en lugar de mostrar el contenido de la publicación. También intenté cargar la URL de vista previa ( site.com/?p=212&preview=true) pero tampoco funcionó.

Estas son mis conjeturas:

  • el usuario normal no tiene suficiente capspara leer la publicación de borradores.
  • No es posible probar y ver borradores de publicaciones en el front-end para ningún usuario (incluidos los administradores).

¿Qué cambios tengo que hacer para lograr lo que estoy tratando de hacer? Si no es posible, ¿qué soluciones alternativas sugiere?

Nota: no estoy buscando soluciones basadas en complementos.

Amal Murali
fuente
2
Creo que hay un poco de confusión aquí. Si alguien no ha iniciado sesión, él / ella no es un usuario, por lo que no tiene ningún límite. Los suscriptores son usuarios, por lo que deben estar registrados y hacer que el inicio de sesión sea reconocido como suscriptores. No puede dar capacidades a alguien que no haya iniciado sesión. Si desea que alguien que no esté registrado vea sus publicaciones, simplemente no son diferentes de las publicaciones publicadas. Entonces, ¿por qué no publicarlo? ¿O desea mostrar un borrador a los suscriptores (conectados como suscriptores)?
gmazzap
@GM: Estoy tratando de hacer que las publicaciones no publicadas sean accesibles para todos los que conocen el enlace directo a la publicación. Puede parecer un requisito extraño, pero necesito esto para un proyecto. Como mencioné en mi pregunta, si esto no es posible, ¿puede sugerir otras soluciones (si conoce una, por supuesto)?
Amal Murali
@ GM: ¿Conoces un complemento que haga eso?
Amal Murali
¿Has leído la respuesta a continuación con 3 votos a favor? Explica cómo hacerlo y al final de la respuesta encontrará un enlace para descargar un complemento completo de trabajo de github.
gmazzap
2
Para lectores posteriores: hay este complemento de Dominik Schilling disponible en GitHub.
kaiser

Respuestas:

12

No puede asignar capacidades a usuarios desconocidos. Si desea hacer que una publicación sea visible para todos, cree una URL separada para estas publicaciones y agregue un elemento de control al editor de publicaciones para habilitar la vista previa solo en las publicaciones seleccionadas.
Cuando se llama a dicha URL, verifique si se permite una vista previa de la publicación y si la publicación aún no se ha publicado. También asegúrese de que los motores de búsqueda ignoren esta URL.

Para la URL, usaría un punto final :

add_rewrite_endpoint( 'post-preview', EP_ROOT );

Ahora puede crear URL como ...

http://example.com/post-preview/123

... ¿Dónde está 123la identificación de la publicación?

Luego use un controlador de devolución de llamada para inspeccionar la ID de la publicación, verificar si es válida y sobrescribir la consulta principal. Este es probablemente el único caso de uso aceptable para query_posts(). :)

Digamos que el punto final es una clase T5_Endpoint(un modelo), y el controlador de salida es una clase T5_Render_Endpoint(una vista) que hace que el modelo se pase antes. Entonces, probablemente hay un método render()llamado 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->metaes otro modelo (clase T5_Post_Meta) para el metavalor posterior que controla si se permite una vista previa. El control se establece en el cuadro Publicar ( acciónpost_submitbox_misc_actions ), representado por otra vista que obtiene la misma metaclase.

captura de pantalla

Entonces, T5_Post_Metasabe dónde y cuándo almacenar el metavalor, las vistas hacen algo con él.
Además, conéctesetransition_post_status para eliminar el metacampo de la publicación cuando se publique la publicación. No queremos desperdiciar recursos, ¿verdad?

Esto es solo un esbozo. Hay muchos detalles para cubrir ... He escrito un pequeño complemento que muestra cómo implementar esto: T5 Public Preview .

fuxia
fuente
Muchas gracias. Finalmente logré mi objetivo con algunos ajustes. Increíble. : D
Amal Murali
6

Resolví este problema en lo que pensé que era una forma más simple que la respuesta de @ toscho anterior.

Mi caso de uso es que estoy usando la misma base de datos para un sitio interno de organización de la intranet y un sitio público, y el flujo de trabajo es que los autores escriben borradores y los comparten con otros usuarios que ven esos borradores en el sitio de la intranet, antes de publicar. Específicamente no quería exigir a los revisores que inicien sesión para ver borradores, por lo que solo estoy dependiendo de una constante, ENV_PRODUCTIONque se establece en el archivo wp-config en función del nombre de host en $_SERVER['SERVER_NAME']. Eso es lo que ENV_PRODUCTIONestán haciendo los controles aquí; simplemente acortando todos estos filtros si se está viendo el sitio de producción.

Esto es un poco extraño, ya que debes conectarte después de que WP_Query elimine todas las publicaciones de la matriz $ wp_query-> posts, pero me parece estable y seguro.

/*
 * On staging site home and archives, drafts should be visible.
 */
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' );


/*
 * Make drafts visible on staging site single views.
 *
 * (Because on single views, WP_Query goes through logic to make sure the 
 * current user can edit the post before displaying a draft.)
 */
function show_single_drafts_on_staging( $posts, $wp_query ) {
    if ( ENV_PRODUCTION )
        return $posts;

    //making sure the post is a preview to avoid showing published private posts
    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 );

Hay dos partes separadas para los filtros.

  • Un filtro en el gancho "pre_get_posts" establece el post_status predeterminado en 'publicar, borrador' en el sitio de preparación. Esto devolverá los borradores de publicaciones en listados de archivos.
  • Se necesita un filtro separado para vistas individuales, porque hay una lógica desagradable en la clase WP_Query para eliminar borradores de publicaciones de los resultados de la consulta a menos que el usuario actual pueda editarlos. Lo solucioné filtrando 'the_posts' y agregando la publicación que quería de vuelta a los resultados.
goldenapples
fuente
2
Esto es increíble , muchas gracias por compartir esto. Absolutamente perfecto y exactamente lo que necesitaba.
Christian Varga
¿Dónde pongo este código? (¿
Qué
@Joelio ¿Puedes ser específico sobre el problema que estás resolviendo? Como un enfoque simple, acabo de agregar este código a mi functions.php, y agregué una definición simple a mi wp-config.php que establece la constante ENV_PRODUCTION en verdadero o falso dependiendo del dominio de solicitud.
goldenapples
@goldenapples Agregué este fragmento de código a mi function.php, ¿qué debo agregar a wp-config? Gracias por su ayuda
Graham Slick
@MatthiasGrahamSlick: solo necesita algo que establezca la ENV_PRODUCTIONconstante si está en producción. Estaba usando domain.com para la producción y staging.domain.com para la puesta en escena, así que mi línea fue define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) );¿ Eso ayuda?
goldenapples
0

Creo que el complemento "User Role Editor" disponible en el sitio web de WordPress.org podría ser lo que estás buscando. Por cierto, ¿por qué quieres dar acceso a tus borradores a todos? Personalmente, no puedo pensar en una instancia en la que esto sea necesario.

Georgi Demirev
fuente
No, como se menciona en la pregunta, no estoy buscando soluciones basadas en complementos. El caso de uso es un poco complicado, pero estoy seguro de que esta es la mejor solución para esta tarea específica que estoy tratando de lograr. :-)
Amal Murali
Estoy perplejo sobre la razón también. Si quieres que todos vean la publicación, ¿por qué no simplemente publicar la publicación? Puede usar campos personalizados en la publicación para rastrear cualquier estado especial que desee definir.
KenB
Dejo que los usuarios vean el contenido, pero por alguna razón específica no quiero que se publiquen las publicaciones.
Amal Murali
0

Simplemente puede cambiar la visibilidad en la página / publicación a "Privada", que solo es visible para Editores y Administradores y no para visitantes públicos, motores de búsqueda, feeds RSS, etc.

NickJAB
fuente
0

Creo que el comentario de GM es el mejor aquí. Supongo que está intentando hacer lo siguiente:

  1. Escribir una publicación
  2. Guardar como borrador
  3. Permitir que un usuario externo (no conectado) vea el borrador para su aprobación
  4. Publicar

¿Es eso correcto?

Desafortunadamente, no puedo pensar en una forma simple de hacer esto. Puede publicarlo como una publicación privada para que necesiten ingresar una contraseña para verla, pero debe iniciar sesión para esto. También podría protegerlo con contraseña, pero aún aparecerá en su feed y lista de publicaciones recientes, etc. ¿No podría crear una cuenta de usuario invitado y darles el nombre de usuario / contraseña cuando les dé la URL?

Lea aquí para más información: http://codex.wordpress.org/Content_Visibility

Alternativamente, hay un complemento que podría satisfacer sus necesidades: http://wordpress.org/extend/plugins/shareadraft/ Eché un vistazo rápido al código y parece que el desarrollador está modificando el valor devuelto por get_post_status para que pueda estar capaz de jugar con eso:

http://codex.wordpress.org/Function_Reference/get_post_status

HTH

TomC
fuente
0

Si no le importa si la publicación está "publicada" o no, solo desea que todos puedan acceder a ella en la URL publicada normal y que no se muestre en la página principal / resultados de búsqueda / feeds rss, etc., este complemento funcionó con WP 4.6. 1 y le permite ajustar dónde aparece una publicación:

https://wordpress.org/plugins/wp-hide-post/

Sarah Northway
fuente