Filtrer next_post_link () et previous_post_link () par meta_key?

8

J'ai une page avec deux sections, chacune utilise un différent WP_Query()pour tirer events, qui sont un type de message personnalisé. Chacun WP_Query()interroge a meta_keypour la date de l'événement afin que la section 1 affiche uniquement les événements à venir eventset la section 2 les événements passés events.

La prochaine eventssection 1 affiche toutes les informations pertinentes sur ma page, il n'est donc pas possible de cliquer dessus.

Le passé eventsde la section 2 n'affiche que le eventtitre et est cliquable. Lorsque les utilisateurs cliquent sur un passé, eventils établissent un lien vers un single-event.phpmodèle personnalisé pour le passé event.

Je souhaite afficher la navigation précédente / suivante dans le single-event.phpmodèle, mais la navigation doit uniquement pointer vers le passé events.

J'ai essayé d'utiliser next_post_link()et previous_post_link()mais ceux-ci seront liés à la prochaine eventsaussi, ce que je ne veux pas. Je peux probablement configurer un nouveau WP_Query()sur mon single-event.phpet le parcourir pour obtenir les identifiants précédent / suivant, mais répéter la requête semble être une étape radicale.

J'apprécierais vraiment un aperçu sur un moyen de filtrer les eventsliens à venir de mes articles précédents / suivants. J'ai vu cette question mais je préférerais ne pas utiliser de plugin.

cfx
la source
1
la réponse à cette question est indiquée dans l'autre réponse à la question que vous avez liée - vous devrez filtrer les clauses join / where / sort dans la get_adjacent_postfonction.
Milo
Oui, c'est fait. J'aimerais vraiment voir un exemple de travail si possible.
cfx
1
Je n'ai pas le temps de coder quelque chose pour le moment, mais un bon point de départ serait d'effectuer une requête via WP_Query, puis d'inspecter $your_query_object->request, ce qui révèlera une bonne partie du SQL dont vous aurez besoin pour le retirer.
Milo
Merci pour l'indice @Milo, pensez que je l'ai compris! Voir ci-dessous!
cfx

Réponses:

6

J'ai réussi à faire fonctionner cela en utilisant uniquement des filtres WordPress, grâce à l'indice de @ Milo.

Notez juste que ceux-ci sont assez spécifiques à mon cas, mais vous ne devriez pas avoir de problème à les modifier pour votre propre usage. J'utilise des champs personnalisés avancés avec un champ Sélecteur de date appelé dateet les liens Précédent / Suivant ne pointent que vers des événements avec des datechamps définis à n'importe quel jour avant aujourd'hui.

J'ai créé 5 filtres:

  • 1 à modifier JOIN(à ajouter wp_postmeta)
  • 1 à modifier WHEREpour le lien précédent
  • 1 à modifier WHEREpour le lien suivant
  • 1 à modifier SORTpour le lien précédent
  • 1 à modifier SORTpour le lien suivant

Voici ce que j'ai trouvé, cela semble fonctionner, mais si quelqu'un repère des problèmes, j'aimerais avoir des commentaires:

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
la source
3

J'ai eu un problème assez similaire, j'avais besoin de trier et d'exclure plusieurs messages de la navigation précédente / suivante. Le problème avec la solution de @ cfx était: ce n'est pas capable d'ajax: la is_singular()fonction retourne false, si vous chargez le contenu via wp-ajax. donc cela a fonctionné sur le chargement de la page, mais pas, lorsque le contenu a été modifié par ajax. global $post;m'aidait ici.

voici ma solution:

/**
  * 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 );
 });

dans ce cas, la requête de champ costum est la suivante: exclure tous les articles pour lesquels cf est not_clickabledéfini sur true.

un autre problème que j'ai rencontré: j'ai créé du contenu, puis j'ai implémenté ce champ personnalisé par la suite. gardez cela à l'esprit lorsque vous utilisez ce type de filtrage. assurez-vous que chaque publication a une valeur ou considérez-la dans votre syntaxe sql.

honk31
la source