¿Cómo hacer que una publicación en borrador sea accesible para todos?

18 jul 2013, 23:14:37
Vistas: 16.8K
Votos: 14

Tengo varias publicaciones no publicadas en mi sitio Wordpress y estoy intentando hacerlas accesibles para usuarios normales (que no han iniciado sesión) usando los slugs normales de las publicaciones (sitio.com/publicacion-aqui). Entiendo que puede no ser la mejor práctica, pero para mi propósito especial, esto necesita hacerse.

He intentado agregar el siguiente fragmento de código en mi archivo functions.php:

function habilitar_ver_borradores() {
$rol = get_role( 'subscriber' ); 
$rol->add_cap( 'read_private_posts' ); 
$rol->add_cap( 'edit_posts' );
}
add_action( 'after_setup_theme', 'habilitar_ver_borradores');

También he probado el hook init en lugar de after_setup_theme. Sin éxito.

Mi entendimiento es que los cambios en los roles se guardan en la base de datos, por lo que solo necesitan hacerse una vez. Por eso estoy usando el hook after_setup_theme para llamar a la función.

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

Estas son mis suposiciones:

  • el usuario normal no tiene suficientes capacidades para leer la publicación en borrador.
  • probar y ver publicaciones en borrador en el front-end no es posible para ningún usuario (incluidos los administradores).

¿Qué cambios debo hacer para lograr lo que intento hacer? Si no es posible, ¿qué soluciones alternativas sugieres?

Nota: No estoy buscando soluciones basadas en plugins.

5
Comentarios

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 permiso. Los suscriptores son usuarios, por lo que deben estar registrados e iniciar sesión para ser reconocidos como suscriptores. No puedes dar capacidades a alguien que no ha iniciado sesión. Si quieres que cualquier persona no registrada vea tus publicaciones, estas no son diferentes en absoluto de las publicaciones publicadas. Entonces, ¿por qué no publicarlas? ¿O quieres mostrar borradores a los suscriptores (que han iniciado sesión como suscriptores)?

gmazzap gmazzap
3 sept 2013 03:13:14

@G.M.: Estoy intentando hacer que las publicaciones no publicadas sean accesibles para todos los que conocen el enlace permanente directo a la publicación. Puede parecer un requisito extraño, pero lo necesito para un proyecto. Como mencioné en mi pregunta, si esto no es posible, ¿puedes sugerir otras soluciones alternativas (si conoces alguna, por supuesto)?

Amal Amal
4 nov 2013 16:14:09

@G.M.: ¿Conoces algún plugin que haga eso?

Amal Amal
4 nov 2013 16:26:37

¿Has leído la respuesta justo debajo con 3 votos a favor? Explica cómo hacerlo y al final de la respuesta encontrarás un enlace para descargar un plugin completamente funcional desde GitHub.

gmazzap gmazzap
4 nov 2013 17:04:05

Para lectores posteriores: Existe este plugin de Dominik Schilling disponible en GitHub.

kaiser kaiser
27 nov 2013 14:32:58
Todas las respuestas a la pregunta 5
1
13

No puedes asignar capacidades a usuarios desconocidos. Si deseas hacer una publicación visible para todos, crea una URL separada para estas publicaciones y agrega un elemento de control al editor de publicaciones para habilitar la vista previa solo en publicaciones seleccionadas.
Cuando se llame a dicha URL, verifica si se permite una vista previa para la publicación y si la publicación aún no se ha publicado. También asegúrate de que los motores de búsqueda ignoren esta URL.

Para la URL, usaría un endpoint:

add_rewrite_endpoint( 'post-preview', EP_ROOT );

Ahora puedes crear URLs como …

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

… donde 123 es el ID de la publicación.

Luego usa un manejador de callback para inspeccionar el ID de la publicación, verificar si es válido y sobrescribir la consulta principal. Este es probablemente el único caso de uso aceptable para query_posts(). :)

Digamos que el endpoint es una clase T5_Endpoint (un modelo), y el manejador de salida es una clase T5_Render_Endpoint (una vista) que recibe el modelo pasado anteriormente. Entonces probablemente habrá un método render() llamado en 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 es otro modelo (clase T5_Post_Meta) para el valor meta de la publicación que controla si se permite una vista previa. El control se establece en el cuadro de Publicar (acción post_submitbox_misc_actions), renderizado por otra vista que obtiene la misma clase meta.

captura de pantalla

Entonces, T5_Post_Meta sabe dónde y cuándo almacenar el valor meta, las vistas hacen algo con él.
Además, conecta con transition_post_status para eliminar el campo meta de la publicación cuando esta se publique. No queremos desperdiciar recursos, ¿verdad?

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

3 oct 2013 20:05:44
Comentarios

Muchas gracias. Finalmente logré mi objetivo con algunos ajustes. Increíble. :D

Amal Amal
6 nov 2013 21:07:45
7

Resolví este problema de una manera que consideré más simple que la respuesta de @toscho mencionada anteriormente.

Mi caso de uso es que estoy utilizando la misma base de datos para un sitio de staging interno de 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 intranet, antes de publicarlos. Específicamente no quería requerir que los revisores iniciaran sesión para ver borradores, así que solo dependo de una constante, ENV_PRODUCTION que se establece en el archivo wp-config según el nombre del host en $_SERVER['SERVER_NAME']. Eso es lo que hacen las verificaciones de ENV_PRODUCTION aquí; simplemente anulan todos estos filtros si se está viendo el sitio de producción.

Esto es un poco extraño, porque hay que engancharse después de que WP_Query elimina todas las publicaciones del array $wp_query->posts, pero me parece estable y seguro.

/*
 * En la página de inicio y archivos del sitio de staging, los borradores deben ser visibles.
 */
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' );


/*
 * Hacer que los borradores sean visibles en las vistas individuales del sitio de staging.
 *
 * (Porque en vistas individuales, WP_Query aplica lógica para asegurarse de que el 
 * usuario actual pueda editar la publicación antes de mostrar un borrador.)
 */
function show_single_drafts_on_staging( $posts, $wp_query ) {
    if ( ENV_PRODUCTION )
        return $posts;

    //asegurándose de que la publicación es una vista previa para evitar mostrar publicaciones privadas publicadas
    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 en los filtros.

  • Un filtro en el hook "pre_get_posts" establece el post_status predeterminado como 'publish,draft' en el sitio de staging. Esto devolverá los borradores en los listados de archivo.
  • Se necesita un filtro separado para las vistas individuales, porque hay una lógica complicada en la clase WP_Query para eliminar borradores 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.
10 oct 2014 23:38:01
Comentarios

Esto es increíble, muchas gracias por compartirlo. Absolutamente perfecto y exactamente lo que necesitaba.

Christian Christian
4 feb 2015 08:30:23

¿Dónde coloco este código? (¿en qué archivo(s)?)

Joelio Joelio
27 abr 2015 23:21:51

@Joelio ¿Puedes ser específico sobre el problema que estás resolviendo? Como enfoque simple, simplemente agregué este código a mi functions.php, y añadí una definición simple a mi wp-config.php que establece la constante ENV_PRODUCTION como verdadera o falsa dependiendo del dominio de la solicitud.

goldenapples goldenapples
29 abr 2015 01:59:09

@goldenapples He añadido este fragmento de código a mi function.php, ¿qué debería añadir a wp-config? Gracias por tu ayuda

Graham Slick Graham Slick
26 sept 2015 13:04:04

@MatthiasGrahamSlick - Solo necesitas algo que establezca la constante ENV_PRODUCTION si estás en producción. Yo estaba usando domain.com para producción y staging.domain.com para staging, así que mi línea era define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) ); ¿Te ayuda eso?

goldenapples goldenapples
28 sept 2015 15:58:37

@goldenapples ¿Dónde en tu función show_single_drafts_on_staging controlas para mostrar solo entradas con post_status=draft? Según lo que he probado de tu código, mostrará cualquier entrada (incluso las eliminadas) en las páginas individuales. ¿O estoy haciendo algo mal?

Sebastian Sebastian
17 feb 2016 01:36:25

Esto es exactamente lo que necesitaba para un sitio donde los usuarios no registrados pueden enviar contenido; la segunda función funcionó para permitirles previsualizaciones (eliminé la verificación de ENV_PRODUCTION)

cogdog cogdog
16 oct 2019 03:37:37
Mostrar los 2 comentarios restantes
3

Creo que el plugin "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 se me ocurre una situación en la que esto sería necesario.

19 jul 2013 04:27:03
Comentarios

No, como se mencionó en la pregunta, no estoy buscando soluciones basadas en plugins. 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 Amal
19 jul 2013 04:32:53

También estoy perplejo por la razón. Si quieres que todos vean la publicación, ¿por qué no simplemente publicarla? Podrías usar campos personalizados en la publicación para rastrear cualquier estado especial que desees definir.

KenB KenB
26 jul 2013 03:11:28

Estoy permitiendo que los usuarios vean el contenido, pero por alguna razón específica no quiero que las publicaciones estén publicadas.

Amal Amal
26 jul 2013 10:20:52
0

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

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

¿Es eso correcto?

Desafortunadamente, no se me ocurre ninguna forma sencilla de hacer esto. Podrías publicarlo como una entrada privada para que necesiten ingresar una contraseña para verla, pero necesitarías estar registrado para esto. También podrías protegerla con contraseña, pero aún así aparecerá en tu feed y lista de entradas recientes, etc. ¿No podrías crear una cuenta de usuario invitado y darles el nombre de usuario/contraseña cuando les des la URL?

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

Alternativamente, hay un plugin que podría adaptarse a tus 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, así que podrías jugar con eso:

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

Espero que esto ayude

24 sept 2013 09:01:57
1
-1

Podrías simplemente cambiar la visibilidad de la página/entrada a "Privada", que solo será visible para Editores y Administradores y no para visitantes públicos, motores de búsqueda, feeds RSS, etc.

3 sept 2013 01:09:25
Comentarios

Esta no es una solución viable para una página ya publicada. Puedes hacer ediciones en una página actualmente en vivo y guardarlas como borrador. Si siguieras este enfoque en una página en vivo, eliminaría la página en vivo de los resultados de búsqueda con el tiempo y potencialmente causaría otros problemas.

Hunter Nelson Hunter Nelson
13 dic 2021 17:39:01