¿Filtrar next_post_link () y previous_post_link () por meta_key?

8

Tengo una página con dos secciones, cada una utiliza una diferente WP_Query()para tirar en events, que son un tipo de mensaje personalizado. Cada uno WP_Query()consulta meta_keyla fecha del evento para que la Sección 1 solo muestre los próximos eventsy la Sección 2 los pasados events.

El próximo eventsen la Sección 1 muestra toda la información relevante en mi página, por lo que no es posible hacer clic en ellos.

El pasado eventsen la Sección 2 solo muestra el eventtítulo y se puede hacer clic en él. Cuando los usuarios hacen clic en un pasado, eventse vinculan a una single-event.phpplantilla personalizada para el pasado event.

Quiero mostrar la navegación Anterior / Siguiente en la single-event.phpplantilla, pero la navegación solo debería apuntar al pasado events.

Intenté usar next_post_link()y, previous_post_link()pero estos también se vincularán a los próximos events, que no quiero. Probablemente pueda configurar un nuevo WP_Query()en mi single-event.phpy recorrerlo para obtener las ID de Prev / Next, pero repetir la consulta parece un paso drástico.

Realmente agradecería una idea de cómo filtrar los próximos eventsenlaces de mis publicaciones anteriores / siguientes. He visto esta pregunta pero preferiría no usar un complemento.

cfx
fuente
1
la respuesta a esto se insinúa en la otra respuesta a la pregunta que ha vinculado: deberá filtrar las cláusulas join / where / sort en la get_adjacent_postfunción.
Milo
Sí, se insinúa. Realmente me encantaría ver un ejemplo de trabajo si es posible.
cfx
1
No tengo tiempo para codificar algo en este momento, pero un buen punto de partida sería realizar una consulta a través de WP_Query, luego inspeccionar $your_query_object->request, lo que revelará una buena parte del SQL que necesitará para llevarlo a cabo.
Milo
Gracias por la pista @Milo, ¡creo que lo descubrí! ¡Vea abajo!
cfx

Respuestas:

6

Logré que esto funcionara utilizando nada más que filtros de WordPress, gracias a la sugerencia de @ Milo.

Solo tenga en cuenta que estos son bastante específicos para mi caso, pero no debería tener problemas para modificarlos para su propio uso. Estoy usando campos personalizados avanzados con un campo selector de fecha llamado datey los enlaces Anterior / Siguiente solo apuntan a eventos con datecampos configurados en cualquier día antes de hoy.

Creé 5 filtros:

  • 1 para modificar JOIN(para agregar wp_postmeta)
  • 1 para modificar WHEREpara el enlace anterior
  • 1 para modificar WHEREpara el siguiente enlace
  • 1 para modificar SORTpara el enlace anterior
  • 1 para modificar SORTpara el siguiente enlace

Esto es lo que se me ocurrió, parece estar funcionando, pero si alguien detecta algún problema, me encantaría recibir comentarios:

function get_adjacent_past_events_join($join) {
  if(is_singular('event')) {
    global $wpdb;
    $new_join = $join."INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
    return $new_join;
  }
  return $join;
}
add_filter('get_previous_post_join', 'get_adjacent_past_events_join');
add_filter('get_next_post_join', 'get_adjacent_past_events_join');

function get_prev_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type = 'event' AND p.post_status = 'publish' AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_previous_post_where', 'get_prev_past_events_where');

function get_next_past_events_where($where) {
  if(is_singular('event')) {
    global $wpdb, $post;
    $id = $post->ID;
    $current_event_date = get_field('date', $id);
    $today = date('Ymd');
    $new_where = "WHERE p.post_type = 'event' AND p.post_status = 'publish' AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) < '$today')) AND (m.meta_key = 'date' AND (m.meta_key = 'date' AND CAST(m.meta_value AS CHAR) > '$current_event_date'))";
    return $new_where;
  }
  return $where;
}
add_filter('get_next_post_where', 'get_next_past_events_where');

function get_prev_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 DESC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_previous_post_sort', 'get_prev_past_events_sort');

function get_next_past_events_sort($sort) {
  if(is_singular('event')) {
    global $wpdb;
    $new_sort = " GROUP BY p.ID ORDER BY m.meta_value+0 ASC";
    return $new_sort;
  }
  return $sort;
}
add_filter('get_next_post_sort', 'get_next_past_events_sort');
cfx
fuente
3

Tuve un problema bastante similar, necesitaba ordenar y excluir varias publicaciones de la navegación anterior / siguiente. El problema con la solución de @ cfx era: no es capaz de ajax: la is_singular()función devuelve falso si carga contenido a través de wp-ajax. así que funcionó en la carga de la página, pero no lo hizo, cuando ajax cambió el contenido. global $post;me estaba ayudando aquí.

Aquí está mi solución:

/**
  * WP: join postmeta to our sql query, so we can filter for custom fields
  *
  * @param $join
  * @return string
  */
function jnz_adjacent_work_join( $join ) {
  global $post;
  if ( get_post_type( $post ) == 'work' ) {
    global $wpdb;
    return $join . "INNER JOIN $wpdb->postmeta AS m ON p.ID = m.post_id ";
  }
  return $join;
}
add_filter('get_previous_post_join', 'jnz_adjacent_work_join');
add_filter('get_next_post_join', 'jnz_adjacent_work_join');



/**
 * WP: Change order of post for prev / next navigation
  * exclude posts with custom field "not_clickable" set to true
  *
  * @param $where
  * @param $operator
  * @return string|void
  */
 function jnz_adjacent_work_where( $where, $operator ) {
   global $post;
   if ( get_post_type( $post ) == 'work' ) :
     global $wpdb;
     $where = $wpdb->prepare("WHERE p.post_title {$operator} '%s' AND p.post_type = 'work' AND p.post_status = 'publish' AND (m.meta_key = 'not_clickable' AND (m.meta_key = 'not_clickable' AND m.meta_value != 1))", $post->post_title );
   endif;

   return $where;
 }

 $gt = '<';
 $lt = '>';
 add_filter( 'get_next_post_where', function( $where ) use ( $lt ) {
   return jnz_adjacent_work_where( $where, $lt );
 });
 add_filter( 'get_previous_post_where', function( $where ) use ( $gt ) {
   return jnz_adjacent_work_where( $where, $gt );
 });

en este caso, la consulta de campo de costum es: excluir todas las publicaciones que tienen cf not_clickableestablecido en true.

Otro problema que encontré: tuve un poco de contenido creado y luego implementé ese campo personalizado después, por lo que la consulta también excluyó las publicaciones que ni siquiera tenían ese campo adjunto a la publicación, sin importar si era verdadero o falso. solo tenlo en cuenta cuando uses este tipo de filtrado. asegúrese de que cada publicación tenga un valor o considere esto en su sintaxis sql.

honk31
fuente