Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ includes:
- tests/phpstan/baselines/method.childParameterType.neon
- tests/phpstan/baselines/method.unused.neon
- tests/phpstan/baselines/notIdentical.alwaysTrue.neon
- tests/phpstan/baselines/nullCoalesce.property.neon
- tests/phpstan/baselines/offsetAccess.nonOffsetAccessible.neon
- tests/phpstan/baselines/offsetAccess.notFound.neon
- tests/phpstan/baselines/offsetAssign.valueType.neon
Expand Down
3 changes: 2 additions & 1 deletion src/wp-includes/class-wp-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class WP_Query {
*
* @since 2.1.0
* @var int
* @phpstan-var int<0, max>
*/
public $max_num_pages = 0;

Expand Down Expand Up @@ -3732,7 +3733,7 @@ private function set_found_posts( $query_vars, $limits ) {
$this->found_posts = (int) apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );

if ( ! empty( $limits ) ) {
$this->max_num_pages = (int) ceil( $this->found_posts / $query_vars['posts_per_page'] );
$this->max_num_pages = max( 0, (int) ceil( $this->found_posts / (int) $query_vars['posts_per_page'] ) );
Comment thread
westonruter marked this conversation as resolved.
Resolved
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/wp-includes/general-template.php
Original file line number Diff line number Diff line change
Expand Up @@ -4983,7 +4983,7 @@ function paginate_links( $args = '' ) {
$url_parts = explode( '?', $pagenum_link );

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

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public function get_max_num_pages( $object_subtype = '' ) {
$query = new WP_Query( $args );

$min_num_pages = ( 'page' === $post_type && 'posts' === get_option( 'show_on_front' ) ) ? 1 : 0;
return isset( $query->max_num_pages ) ? max( $min_num_pages, $query->max_num_pages ) : 1;
return max( $min_num_pages, $query->max_num_pages );
}

/**
Expand Down
5 changes: 0 additions & 5 deletions tests/phpstan/baselines/isset.property.neon
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,6 @@ parameters:
identifier: isset.property
count: 1
path: ../../../src/wp-includes/rest-api/endpoints/class-wp-rest-font-families-controller.php
-
message: '#^Property WP_Query\:\:\$max_num_pages \(int\) in isset\(\) is not nullable\.$#'
identifier: isset.property
count: 1
path: ../../../src/wp-includes/sitemaps/providers/class-wp-sitemaps-posts.php
-
message: '#^Property WP_Site\:\:\$domain \(string\) in isset\(\) is not nullable\.$#'
identifier: isset.property
Expand Down
25 changes: 0 additions & 25 deletions tests/phpstan/baselines/nullCoalesce.property.neon

This file was deleted.

58 changes: 58 additions & 0 deletions tests/phpunit/tests/query/noFoundRows.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,62 @@ public function test_no_found_rows_default_with_postsperpage_minus1() {
$this->assertStringNotContainsString( 'SQL_CALC_FOUND_ROWS', $q->request );
$this->assertSame( 1, $q->found_posts );
}

/**
* Ensures {@see WP_Query::$max_num_pages} is not negative when the
* {@see 'found_posts'} filter returns a negative count.
*
* @ticket 65817
*/
public function test_max_num_pages_is_not_negative_when_found_posts_is_filtered_negative() {
self::factory()->post->create_many( 3 );

add_filter(
'found_posts',
static function (): int {
return -5;
}
);

$q = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => 2,
)
);

$this->assertSame( -5, $q->found_posts, 'Expected the filtered found_posts value to be kept.' );
$this->assertSame( 0, $q->max_num_pages, 'Expected max_num_pages to be clamped to zero.' );
}

/**
* Ensures {@see WP_Query::$max_num_pages} is not negative when a
* {@see 'post_limits'} filter injects a non-empty `LIMIT` clause on a
* `posts_per_page = -1` query, which otherwise never runs the found-rows
* calculation and skips the `max_num_pages` division entirely.
*
* @ticket 65817
*/
public function test_max_num_pages_is_not_negative_when_limits_are_filtered_with_postsperpage_minus1() {
self::factory()->post->create_many( 3 );

add_filter(
'post_limits',
static function (): string {
return 'LIMIT 0, 2';
}
);

$q = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => -1,
)
);

$this->assertIsString( $q->request );
$this->assertStringContainsString( 'SQL_CALC_FOUND_ROWS', $q->request, 'Expected the filtered LIMIT to trigger the found-rows query.' );
$this->assertSame( 3, $q->found_posts, 'Expected found_posts to reflect all matching rows.' );
$this->assertSame( 0, $q->max_num_pages, 'Expected max_num_pages to be clamped to zero.' );
}
}
Loading