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.