limit to months rather than by number of posts

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

Read More

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

Related posts

2 comments

  1. 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.

  2. 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.

Comments are closed.