WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

[РЕШЕНО] Реверсивная пагинация — Reverse ordered pagination on home, search and archive pages

(за качество кода ответить не могу )
РЕШЕНИЕ только для домашней страницы, на архивах не срабатывает вывод, но работает логика, нужно дорабатывать код : https://github.com/kingkool68/reverse-pagination
код подправил для работы на архивах , в конструкции отсутствовал total count для архивов

<?php
/*
Plugin Name: WP Reverse Pagination
Description: Pagination starts higher and goes lower for more consistent archive page numbering.
Author: Russell Heimlich
Version: 0.4
*/

/**
 * Logic to make WordPress work with reverse pagination
 */
class WP_Reverse_Pagination {

	/**
	 * Once we figure out what the new paged value should be we can store it here for future uses
	 *
	 * @var integer
	 */
	private $new_paged = 0;

	/**
	 * Stores the original paged value of the current request
	 *
	 * @var integer
	 */
	private $original_paged = 0;

	/**
	 * Store the maximum number of pages value once it has been calculated
	 *
	 * @var integer
	 */
	private $max_num_pages = 0;

	/**
	 * Empty constructor
	 */
	public function construct() {}

	/**
	 * Get an instance of this class
	 */
	public static function get_instance() {
		static $instance = null;
		if ( null === $instance ) {
			$instance = new static();
			$instance->setup_actions();
			$instance->setup_filters();
		}
		return $instance;
	}

	/**
	 * Hook into WordPress via actions
	 */
	public function setup_actions() {
		add_action( 'template_redirect', array( $this, 'action_template_redirect' ) );
	}

	/**
	 * Hook into WordPress via filters
	 */
	public function setup_filters() {
		add_filter( 'redirect_canonical', array( $this, 'filter_redirect_canonical' ), 10, 2 );
		add_filter( 'posts_clauses_request', array( $this, 'filter_posts_clauses_request' ), 10, 2 );
	}

	/**
	 * Redirect to the non /page/ URL if the current $paged value === the max num pages value
	 */
	public function action_template_redirect() {
		global $wp;

		// When the requested paged value == the max_num_pages value then perform
		// a redirect to the non /page/ version of the URL for SEO reasons.
		if ( intval( $this->original_paged ) === intval( $this->max_num_pages ) ) {
			// Get the URL of the current request.
			$url = home_url( $wp->request );
			$url = add_query_arg( array( $_GET ), trailingslashit( $url ) );
			if ( ! $url ) {
				return;
			}

			$redirect = str_replace( '/page/' . $this->original_paged . '/', '', $url );
			if ( $url !== $redirect ) {
				wp_safe_redirect( $redirect, 302 );
				exit;
			}
		}
	}

	/**
	 * Undo some default redirects that WordPress provides
	 *
	 * @param string $redirect_url  The URL to be redirected to.
	 * @param string $requested_url The URL being requested.
	 */
	public function filter_redirect_canonical( $redirect_url = '', $requested_url = '' ) {
		if ( is_admin() ) {
			return;
		}

		if ( stristr( $requested_url, '/page/1/' ) ) {
			return $requested_url;
		}

		if ( stristr( $redirect_url, '/page/' . $this->new_paged . '/' ) ) {
			return $requested_url;
		}

		return $redirect_url;
	}

	/**
	 * Figure out the proper pagination values and modify SQL clauses to make everything work.
	 *
	 * @param array    $clauses The SQL clauses being modified.
	 * @param WP_Query $wp_query The WP_Query being processed.
	 */
	public function filter_posts_clauses_request( $clauses = array(), $wp_query ) {
		global $wpdb;

		if ( is_admin() || ! $wp_query->is_main_query() ) {
			return $clauses;
		}

		// Setup variables.
		$q       = $wp_query->query_vars;
		$where   = $clauses['where'];
		$groupby = $clauses['groupby'];
		if ( ! empty( $groupby ) ) {
			$groupby = 'GROUP BY ' . $groupby;
		}
		$join     = $clauses['join'];
		$orderby  = $clauses['orderby'];
		$distinct = $clauses['distinct'];
		$fields   = $clauses['fields'];
		$limits   = $clauses['limits'];

		// Figure out how many rows we have.
		$found_posts = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} $join WHERE 1=1 $where $groupby ORDER BY $orderby" );

		if ( is_home() || is_front_page() ){
			$found_posts = $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish'" );
		}

		// Set how many found posts there are since we know it now.
		$wp_query->found_posts = intval( $found_posts );
		$wp_query->found_posts = apply_filters_ref_array( 'found_posts', array( $wp_query->found_posts, &$wp_query ) );
		if ( get_queried_object()->term_id > 0 ){
			$wp_query->found_posts = get_term( get_queried_object()->term_id )->count;
		}

		// Set the max number of pages.
		$posts_per_page = intval( $q['posts_per_page'] );
		if ( ! $posts_per_page ) {
			$posts_per_page = get_option( 'posts_per_page' );
		}
		$wp_query->max_num_pages = ceil( $wp_query->found_posts / $posts_per_page );
		$this->max_num_pages     = $wp_query->max_num_pages;

		// Save a database query.
		$wp_query->query_vars['no_found_rows'] = true;

		// Get the current page being paginated.
		$paged     = $q['paged'];
		$new_paged = intval( $wp_query->max_num_pages - $paged ) + 1;
		if ( 0 === $paged ) {
			$new_paged = intval( $wp_query->max_num_pages );
		}
		$this->original_paged = $paged;
		$this->new_paged      = $new_paged;

		// Calculate the new offset.
		$new_offset = ( $wp_query->max_num_pages - $paged ) * $posts_per_page;
		if ( 0 === $paged ) {
			$new_offset = 0;
		}

		// Set the new limit clause if it is a positive number (otherwise a negative number indicates a 404).
		if ( $new_offset >= 0 ) {
			$clauses['limits'] = 'LIMIT ' . $new_offset . ', ' . $posts_per_page;
		}

		return $clauses;
	}
}

// Kick things off!
WP_Reverse_Pagination::get_instance();

/**
 * Display a list of pagination links based on the current query
 *
 * @see paginate_links()
 *
 * @param string $args Args to modify the output.
 */
function reverse_paginate_links( $args = '' ) {
	global $wp_query, $wp_rewrite;

	// Setting up default values based on the current URL.
	$pagenum_link = html_entity_decode( get_pagenum_link() );
	$url_parts    = explode( '?', $pagenum_link );

	// Get max pages and current page out of the current query, if available.
	$total   = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1;
	$current = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : $total;

	// Append the format placeholder to the base URL.
	$pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';

	// URL base depends on permalink settings.
	$format  = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
	$format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';

	$defaults = array(
		'base'               => $pagenum_link, // http://example.com/all_posts.php%_% : %_% is replaced by format (below).
		'format'             => $format, // ?page=%#% : %#% is replaced by the page number
		'total'              => $total,
		'current'            => $current,
		'aria_current'       => 'page',
		'show_all'           => false,
		'prev_next'          => true,
		'prev_text'          => __( 'Previous »' ),
		'next_text'          => __( '« Next' ),
		'end_size'           => 1,
		'mid_size'           => 2,
		'type'               => 'plain',
		'add_args'           => array(), // array of query args to add.
		'add_fragment'       => '',
		'before_page_number' => '',
		'after_page_number'  => '',
	);

	$args = wp_parse_args( $args, $defaults );

	if ( ! is_array( $args['add_args'] ) ) {
		$args['add_args'] = array();
	}

	// Merge additional query vars found in the original URL into 'add_args' array.
	if ( isset( $url_parts[1] ) ) {
		// Find the format argument.
		$format       = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) );
		$format_query = isset( $format[1] ) ? $format[1] : '';
		wp_parse_str( $format_query, $format_args );

		// Find the query args of the requested URL.
		wp_parse_str( $url_parts[1], $url_query_args );

		// Remove the format argument from the array of query arguments, to avoid overwriting custom format.
		foreach ( $format_args as $format_arg => $format_arg_value ) {
			unset( $url_query_args[ $format_arg ] );
		}

		$args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) );
	}

	// Who knows what else people pass in $args.
	$total = (int) $args['total'];
	if ( $total < 2 ) {
		return;
	}
	$current  = (int) $args['current'];
	$end_size = (int) $args['end_size']; // Out of bounds?  Make it the default.
	if ( $end_size < 1 ) {
		$end_size = 1;
	}
	$mid_size = (int) $args['mid_size'];
	if ( $mid_size < 0 ) {
		$mid_size = 2;
	}
	$add_args   = $args['add_args'];
	$r          = '';
	$page_links = array();
	$dots       = false;

	if ( $args['prev_next'] && $current && $current < $total ) :
		$link = str_replace( '%_%', $total - 1 === $current ? '' : $args['format'], $args['base'] );
		$link = str_replace( '%#%', $current + 1, $link );
		if ( $add_args ) {
			$link = add_query_arg( $add_args, $link );
		}
		$link .= $args['add_fragment'];

		/**
		 * Filters the paginated links for the given archive pages.
		 *
		 * @since 3.0.0
		 *
		 * @param string $link The paginated link URL.
		 */
		$page_links[] = '<a class="prev page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['next_text'] . '</a>';
	endif;
	for ( $n = $total; $n >= 1; $n-- ) :
		if ( $n === $current ) :
			$page_links[] = "<span aria-current='" . esc_attr( $args['aria_current'] ) . "' class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</span>';
			$dots         = true;
		else :
			// This logic is weird and needs reworking.
			if (
				$args['show_all']
				|| (
					$n <= $end_size
					|| (
						$current
						&& $n > $current - $mid_size
						&& $n < $current + $mid_size
					)
					|| $n > $total - $end_size
				)
			) :
				$link = str_replace( '%_%', $total === $n ? '' : $args['format'], $args['base'] );
				$link = str_replace( '%#%', $n, $link );
				if ( $add_args ) {
					$link = add_query_arg( $add_args, $link );
				}
				$link .= $args['add_fragment'];

				/** This filter is documented in wp-includes/general-template.php */
				$page_links[] = "<a class='page-numbers' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</a>';
				$dots         = true;
			elseif ( $dots && ! $args['show_all'] ) :
				$page_links[] = '<span class="page-numbers dots">' . __( '…' ) . '</span>';
				$dots         = false;
			endif;
		endif;
	endfor;
	if ( $args['prev_next'] && $current && 1 < $current ) :
		$link = str_replace( '%_%', $args['format'], $args['base'] );
		$link = str_replace( '%#%', $current - 1, $link );
		if ( $add_args ) {
			$link = add_query_arg( $add_args, $link );
		}
		$link .= $args['add_fragment'];

		/** This filter is documented in wp-includes/general-template.php */
		$page_links[] = '<a class="next page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['prev_text'] . '</a>';
	endif;
	switch ( $args['type'] ) {
		case 'array':
			return $page_links;

		case 'list':
			$r .= "<ul class='page-numbers'>\n\t<li>";
			$r .= join( "</li>\n\t<li>", $page_links );
			$r .= "</li>\n</ul>\n";
			break;

		default:
			$r = join( "\n", $page_links );
			break;
	}
	return $r;
}

Как сделать такое? Пример:
https://izismile.com/ в данном примере, автор смог развернуть пагинацию в обратную сторону для домашней страницы , а вот для таксономий не справился или пропустил https://izismile.com/tags/wins/

1 Нужно перевернуть пагинацию
из [HOME или 1].2.3...8.9.10 - сейчас на [10] самые первые\старые посты
в- [HOME или 10].9.8...3.2.1 - тут на [10] и [HOME] домашняя\главная страница

2 Главную страницу и архивы нужно сохранить на чистом домене без пагинации (https://site.com/ или https://site.com/category/test/)

3 Чтоб при нажатии на [10] открывалась главная (домашняя страница) https://site.com/, а на [1] открывались самые первые посты https://site.com/category/test/page/1/

4 простыми словами, текущие стандартная сортировка и вывод постов по дате публикации не должны быть затронуты

Зачем сие мудрение? Часто клиенты (я тоже) пользуются поиском по картинкам (к фразам тоже относится) - Когда идет поиск необычной темы, гугл и яндекс выводит в поиске ссылки на страницы архивов с пагинацией https://site.com/korm/page/25/ сами понимаете, пост при добавлении новых записей смещается в новые номера страниц архивов - в итоге пользователь шуршит по поиску и архивам - обычно 3-5 страниц в разные стороны и в итоге пост теряется для пользователя и сайт теряет посетителя.

еще, бывает в поиске, один и тот же запрос ссылается на 3-6 страниц архивов с пагинацией - но не на одной из страниц поста уже нет.

для продажников плохо что пользователь не находит нужное, для сайтов с рекламой наоборот хорошо так как пользователь просматривает банеры.

Заметки к вопросу:
Kama 1 месяц назад

А какой функцией сейчас выводится пагинация?

kolshix 1 месяц назад
    /****[000] Pagination */     
		function my_pagenavi() {
			global $wp_query;
			$big = 123456789;
			$page_format = paginate_links( array(
				'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
				'format' => '?paged=%#%',
				'current' => max( 1, get_query_var('paged') ),
				'total' => $wp_query->max_num_pages,
				'mid_size'  => 3,
				'end_size'     => 1,
			//  'show_all' => true,
				'type'  => 'array',
				'prev_text'    => __(' ⋘ '),
				'next_text'    => __(' ⋙ ')
			) );
			$navi = '';
			if( is_array($page_format) ) {
				$paged = ( get_query_var('paged') == 0 ) ? 1 : get_query_var('paged');
				$navi = '<table class="pg_nav" ><tbody><tr>';                
				if ($paged == 1 || $paged == '' ){ $navi .= '<td><a class="prev page-numbers disabled" href="#"> ⋘ </a></td>'; }
				foreach ( $page_format as $page ) {                     
						$navi .= '<td>';
						$navi .=  "$page";
						$navi .=  '</td>';                            
				}               
				if ($paged == $wp_query->max_num_pages ){ $navi .= '<td><a href="#" class="disabled"> ⋙ </a></td>'; }
				$navi .=  '</tr></tbody></table>';
			}
			 return $navi;
		}
Kama 1 месяц назад

Такой манипуляции не достаточно?

if( is_array($page_format) ) {
	$page_format = array_reverse( $page_format );

Ну и немного подкрутить параметры...

kolshix 1 месяц назад

1 Переворот пагинации сработал

2 Осталась проблема вывода\сортировки записи - перевернул

    add_filter('pre_get_posts', 'pre_get_posts_hook' ); // 
	function pre_get_posts_hook($wp_query) {
			$wp_query->set( 'order', 'ASC' ); // set query order ascending            
			return $wp_query;       
	}

3 теперь вопрос с главной\первой и страницами архивов. Чтоб ссылки вели на последние добавленные записи - сейчас открываю home, открывается https://site.com/page/1, a нужно https://site.com/page/58/ или без "page/58/" - но с последними добавленными записями - как в примере в вопросе

https://site.com/58/ == https://site.com/
https://site.com/category/test/page/10/ == https://site.com/category/test/
0
kolshix
1 месяц назад 682

Нет ответов на этот вопрос.

    На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация