Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Is there a way to override how wordpress displays a number of posts on a post listing page?

I need to limit the number of posts on a page by month instead of limiting it to a number of posts per page, so each previous and next goes back and forth to the previous or next month where there are posts

I did try this method, which seemed to be nearly there. Making next_posts_link(); return posts by month But page 2 and onwards returned no results. It also didn't take in to account where you are in the site, such as category/tag etc

Thanks

share|improve this question

2 Answers 2

If I understand correctly you want to display all month of June on one page? This would require overiding the global $per_page setting it to a high number and also you would need to filter pre_get_posts and adjust the SQL query string to return results by date. The post you linked has the answer. Perhaps displaying your code will allow us to see a problem.

share|improve this answer

If I understand your question you want that for all archives (category, tag, author...) you want to display on 1st page the posts related to the archive but only posted in the current month.

Then you want have link 'Next Page' an 'Previous Page' that shows the posts for the next and the previous month respectively.

The ansqwer you linked gives a grat hel to you, you have to optimize it to run on every archive hooking the pre_get_post action.

My suggestion is to use the m parameter to the required a month, and then set posts_per_page = -1.

This will force to show all the posts for the required month, and using navigation you can browse by month.

Then you need some logic to make the first page (when no page is in the url) show all the pages for the month of the last post published.

After that you can create a couple of function that helps you to output the navigation urls.

I've created a simple plugin that handle what I said:

<?php 
/**
 * Plugin Name: GM Archives By Month
 * Plugin URI: http://wordpress.stackexchange.com/questions/112475/limit-to-months-rather-than-by-number-of-posts
 * Description: A plugin that makes all archives paginating by months and provides functions to show pagination links
 * Author: G.M.
 */

class GMArchivesByMonth {   

static $has_pretty = false;

static $last_date;

static function init() {
  add_filter( 'init', array(__CLASS__, 'sniff_pretty'), 1 );
}

static function sniff_pretty($vars) {
  global $wp_rewrite;
  self::$has_pretty = ( empty($wp_rewrite->get_page_permastruct()) ) ? false : true;
}

static function get_last_post_date( $wp_query = '' ) {
  $args = $wp_query->query_vars;
  $args = wp_parse_args( array('posts_per_page' => 1, 'paged' => 1, 'orderby' => 'date', 'order' => 'DESC'), $args);
  remove_action('pre_get_posts', 'setGMArchivesByMonthPreQuery', 10, 1);
  $posts = get_posts( $args );
  add_action('pre_get_posts', 'setGMArchivesByMonthPreQuery', 10, 1);
  if ( empty($posts) ) return false;
  $lastPost = array_shift( $posts );
  return $lastPost->post_date;
}

static function get_my_from_paged( $paged = 1 ) {
  $date = self::$last_date;
  $m = intval( mysql2date('n', self::$last_date) ) - $paged + 1;
  $y = intval( mysql2date('Y', self::$last_date) );
  if ( $m < 1) { $m = 12; $y--; } 
  if ( $m < 9) { $m = '0' . $m; }
  return "$y$m";
}

static function change_paged_for_month( $query ) {
  if ( is_main_query() && ( ( is_archive() && ! is_date() ) || is_home() ) ) {
    $paged = $query->get('paged') ? : 1;
    self::$last_date = self::get_last_post_date( $query );
    if ( ! self::$last_date ) return;
    if ( $paged == 1 ) {
      // if no month in query set the query to month of last post
      $m = mysql2date('m', self::$last_date );
      $y = mysql2date('Y', self::$last_date );
      $my = "$y$m";
    } else {
      $my = self::get_my_from_paged($paged);
    }
    // set m query var to current request
    $query->set( 'm', $my );
    // set posts per page -1 so all posts in required month are shown
    $query->set('posts_per_page', -1);
  }
}

protected static function get_month_paged_url( $i = '' ) {
  $paged = get_query_var('paged') ? : 1;
  if ( $paged == 1 && $i == -1 ) return false;
  $paged += $i;
  /* ---------------------------------------- 
   * This lines make page loading slower,
   * but prevent the 'Next Page' link is showed whe there are no posts on previous month
   */
    $my = self::get_my_from_paged( $paged );
    global $wp_query;
    $args = $wp_query->query_vars;
    $args = wp_parse_args( array('posts_per_page' => 1, 'paged' => 1, 'orderby' => 'date', 'order' => 'DESC', 'm' => $my), $args);
    remove_action('pre_get_posts', 'setGMArchivesByMonthPreQuery', 10, 1);
    $posts = get_posts( $args );
    add_action('pre_get_posts', 'setGMArchivesByMonthPreQuery', 10, 1);
    if ( empty($posts) ) return false;
  /* ---------------------------------------- */
  if ( ! self::$has_pretty ) {
    return add_query_arg( array( 'paged' => $paged) );
  } elseif ( substr_count($_SERVER['REQUEST_URI'], "page/") ) {
    return preg_replace('/(page\/)([0-9])+/', "page/$paged", $_SERVER['REQUEST_URI']);
  } else {
    return trailingslashit($_SERVER['REQUEST_URI']) . "page/$paged";
  }
}

static function get_previous_month_paged_url() { return self::get_month_paged_url( -1 ); }

static function get_next_month_paged_url() { return self::get_month_paged_url( 1 ); }

static function get_previous_month_paged_link( $text = '' ) {
  $url = self::get_previous_month_paged_url();
  if ( ! $url ) return '';
  if ( empty( $text) ) $text = __('Previous Page');
  return '<a href="' . esc_url( $url ) . '">' . esc_html($text) . '</a>';
}

static function get_next_month_paged_link( $text = '' ) {
  $url = self::get_next_month_paged_url();
  if ( ! $url ) return '';
  if ( empty( $text) ) $text = __('Next Page');
  return '<a href="' . esc_url( $url ) . '">' . esc_html($text) . '</a>';
}

static function previous_month_paged_link( $text = '' ) { echo self::get_previous_month_paged_link($text); }

static function next_month_paged_link( $text = '' ) { echo self::get_next_month_paged_link($text); }

}

// Class init on init action
add_action('after_setup_theme', array('GMArchivesByMonth', 'init') );

// function hooking pre_get_posts in a easy removable way
function setGMArchivesByMonthPreQuery( $query ) {
  GMArchivesByMonth::change_paged_for_month( $query );
}
add_action('pre_get_posts', 'setGMArchivesByMonthPreQuery');

// Helpers
function previous_page_month() { GMArchivesByMonth::previous_month_paged_link(); }
function next_page_month() { GMArchivesByMonth::next_month_paged_link(); }

Comments in code will help you to better understand what plugin does.

Save the plugin in a file under plugin directory and activate it.

After that, in your template files that handle archives, like 'home.php', 'taxonomy.php', 'category.php' and so on put this code to show navigation links:

<p><?php previous_page_month() ?> | <?php  next_page_month(); ?></p>

In your index.php you can wrap it in a if statement that prevent to show links in not supported pages like singular views or date based archives:

<?php if ( ( is_archive() && ! is_date() ) || is_home() ) { ?>
  <p><?php previous_page_month() ?> | <?php  next_page_month(); ?></p>
<?php } ?>

Note that the pagination links are generated by plugin according to your permalink structure. In no pretty permalinks are active the links will use url variables.

share|improve this answer
    
@g-m Thank you so much. However, I want this to work for all post type not just archive pages, so my post pages are monthly rather than limited by an arbitrary number. Installing and activaing the plugin on a template page throws a error: Fatal error: Call to undefined function previous_page_month() –  onebitrocket Sep 4 '13 at 21:22
    
@onebitrocket your sentence "I want this to work for all post type not just archive pages" custom post types view are archive pages. This plugin work for everything: taxonomy, custom taxonomy, custom post types archives, date archives, author archives... this will not work only for single pages and single post (standard or custom type). After that the error is something impossible: the function is defined in the last line of plugin, so if you get that error or you have copied plugin partially or plugin is not activated... (To be sure, I've tested plugin and it works perfectly for me) –  G. M. Sep 5 '13 at 3:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.