Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
869faa0
add _reset_privacy_policy_page_for_post function
masteradhoc Apr 5, 2026
e5745b5
add actions
masteradhoc Apr 5, 2026
6b3e05b
add reset option
masteradhoc Apr 5, 2026
3930d1c
Removed the "page is in trash" error
masteradhoc Apr 5, 2026
e391d36
add feedback of mukesh
masteradhoc Apr 6, 2026
f4dfb44
add feedback of mukesh
masteradhoc Apr 6, 2026
555e5c6
Fix whitespace
masteradhoc Apr 6, 2026
47d48d6
fix phpstan error
masteradhoc Apr 6, 2026
beb4349
add westons feedback
masteradhoc Apr 6, 2026
fbf18e4
remove redundant code
masteradhoc Apr 6, 2026
f8e9ddb
add unit tests
masteradhoc Apr 6, 2026
d398eeb
upgrade failing test
masteradhoc Apr 6, 2026
ccfd7f2
update test
masteradhoc Apr 6, 2026
49426c4
fix tests
masteradhoc Apr 9, 2026
e903c22
Merge branch 'trunk' into 56694-uncached-database-reads
masteradhoc May 3, 2026
bbe7337
Merge branch 'trunk' into 56694-uncached-database-reads
westonruter Jun 2, 2026
4477dd6
Add void return types
westonruter Jun 2, 2026
1ba5c0f
Add assertion for factory output
westonruter Jun 2, 2026
bd4b5f1
Use native property hint
westonruter Jun 2, 2026
0572273
Remove unnecessary tags from unit test class
westonruter Jun 2, 2026
b60e3ee
Revert "Remove unnecessary tags from unit test class"
westonruter Jun 2, 2026
20afd2c
wait until trash operation was successful
masteradhoc Jun 2, 2026
7f20c96
Merge branch 'trunk' into 56694-uncached-database-reads
masteradhoc Jun 16, 2026
a9dab60
reset wp_page_for_privacy_policy on permanent deletion only, not on t…
masteradhoc Jun 16, 2026
ef2ea1b
Merge branch '56694-uncached-database-reads' of https://github.com/ma…
masteradhoc Jun 16, 2026
12e9319
update docblock and testcase
masteradhoc Jun 16, 2026
ada2915
add test cases
masteradhoc Jun 16, 2026
e20b62b
Merge branch 'WordPress:trunk' into 56694-uncached-database-reads
masteradhoc Jun 16, 2026
4eee3f5
update tests
masteradhoc Jun 16, 2026
877c32c
Merge branch '56694-uncached-database-reads' of https://github.com/ma…
masteradhoc Jun 16, 2026
c0dd628
fix The closing brace for the class must go on the next line after th…
masteradhoc Jun 17, 2026
80a466c
Merge branch 'trunk' into 56694-uncached-database-reads
masteradhoc Jun 17, 2026
0e757af
Merge remote-tracking branch 'upstream/trunk' into pr/11443
joedolson Jul 24, 2026
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
6 changes: 6 additions & 0 deletions src/wp-admin/includes/class-wp-privacy-policy-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ public static function notice( $post = null ) {
$current_screen = get_current_screen();
$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

// If the privacy policy page has been deleted, reset the option and bail.
if ( $policy_page_id && ! get_post( $policy_page_id ) ) {
update_option( 'wp_page_for_privacy_policy', 0 );
return;
}
Comment thread
masteradhoc marked this conversation as resolved.

if ( 'post' !== $current_screen->base || $policy_page_id !== $post->ID ) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/wp-includes/default-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@
add_action( 'init', 'create_initial_post_types', 0 ); // Highest priority.
add_action( 'admin_menu', '_add_post_type_submenus' );
add_action( 'before_delete_post', '_reset_front_page_settings_for_post' );
add_action( 'before_delete_post', '_reset_privacy_policy_page_for_post' );
add_action( 'wp_trash_post', '_reset_front_page_settings_for_post' );
add_action( 'change_locale', 'create_initial_post_types' );

Expand Down
16 changes: 16 additions & 0 deletions src/wp-includes/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -4052,6 +4052,22 @@ function _reset_front_page_settings_for_post( $post_id ) {
unstick_post( $post->ID );
}

/**
* Resets the Privacy Policy page ID option when the Privacy Policy page
* is permanently deleted, to prevent uncached database queries for a
* non-existent page.
*
Comment thread
masteradhoc marked this conversation as resolved.
* @since 7.1.0
* @access private
*
* @param int $post_id The ID of the post being deleted.
*/
function _reset_privacy_policy_page_for_post( int $post_id ): void {
if ( 'page' === get_post_type( $post_id ) && ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post_id ) ) {
update_option( 'wp_page_for_privacy_policy', 0 );
}
}

/**
* Moves a post or page to the Trash
*
Expand Down
172 changes: 172 additions & 0 deletions tests/phpunit/tests/privacy/wpPrivacyResetPolicyPageForPost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php
/**
* Tests for _reset_privacy_policy_page_for_post() and the self-healing
* check in WP_Privacy_Policy_Content::notice().
*
* @package WordPress
* @subpackage UnitTests
* @since 7.1.0
*
* @group privacy
*
* @covers ::_reset_privacy_policy_page_for_post
*/
class Tests_Privacy_WpPrivacyResetPolicyPageForPost extends WP_UnitTestCase {
/**
* ID of the page set as the Privacy Policy page.
*/
private int $policy_page_id;

public function set_up(): void {
parent::set_up();

$page_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
assert( is_int( $page_id ) );
$this->policy_page_id = $page_id;
Comment thread
westonruter marked this conversation as resolved.
update_option( 'wp_page_for_privacy_policy', $this->policy_page_id );
}

public function tear_down(): void {
delete_option( 'wp_page_for_privacy_policy' );
parent::tear_down();
}

/**
* Tests that trashing the Privacy Policy page does NOT reset the option,
* so that restoring from trash preserves the assignment.
*
* @ticket 56694
*/
public function test_trashing_privacy_policy_page_does_not_reset_option(): void {
wp_trash_post( $this->policy_page_id );

$this->assertSame(
$this->policy_page_id,
(int) get_option( 'wp_page_for_privacy_policy' ),
'Trashing the Privacy Policy page should not reset wp_page_for_privacy_policy.'
);
}

/**
* Tests that permanently deleting the Privacy Policy page resets the option to 0.
*
* @ticket 56694
*/
public function test_deleting_privacy_policy_page_resets_option(): void {
wp_delete_post( $this->policy_page_id, true );

$this->assertSame( 0, (int) get_option( 'wp_page_for_privacy_policy' ) );
}

/**
* Tests that trashing a different page does not change the option.
*
* @ticket 56694
*/
public function test_trashing_a_different_page_does_not_reset_option(): void {
$other_page_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
$this->assertIsInt( $other_page_id );
wp_trash_post( $other_page_id );

$this->assertSame(
$this->policy_page_id,
(int) get_option( 'wp_page_for_privacy_policy' ),
'Trashing an unrelated page should not reset wp_page_for_privacy_policy.'
);
}

/**
* Tests that deleting a non-page post type does not change the option.
*
* @ticket 56694
*/
public function test_deleting_non_page_post_type_does_not_reset_option(): void {
$post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
$this->assertIsInt( $post_id );
wp_delete_post( $post_id, true );

$this->assertSame(
$this->policy_page_id,
(int) get_option( 'wp_page_for_privacy_policy' ),
'Deleting a non-page post should not reset wp_page_for_privacy_policy.'
);
}

/**
* Tests that WP_Privacy_Policy_Content::notice() resets the option to 0
* when the stored ID points to a page that no longer exists.
*
* @ticket 56694
*
* @covers WP_Privacy_Policy_Content::notice
*/
public function test_notice_self_heals_when_policy_page_does_not_exist(): void {
require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php';

update_option( 'wp_page_for_privacy_policy', 99999 );

$user_id = self::factory()->user->create( array( 'role' => 'administrator' ) );
$this->assertIsInt( $user_id );
wp_set_current_user( $user_id );
if ( is_multisite() ) {
grant_super_admin( $user_id );
}
set_current_screen( 'post' );

$post = self::factory()->post->create_and_get( array( 'post_type' => 'page' ) );
$this->assertInstanceOf( WP_Post::class, $post );
WP_Privacy_Policy_Content::notice( $post );

$this->assertSame(
0,
(int) get_option( 'wp_page_for_privacy_policy' ),
'notice() should reset the option to 0 when the stored page does not exist.'
);
}

/**
* Tests that _reset_privacy_policy_page_for_post() does not call
* update_option() when wp_page_for_privacy_policy is already 0.
*
* @ticket 56694
*/
public function test_no_update_option_when_policy_page_already_zero(): void {
update_option( 'wp_page_for_privacy_policy', 0 );

$call_count = 0;
add_filter(
'pre_update_option_wp_page_for_privacy_policy',
static function ( $value ) use ( &$call_count ) {
++$call_count;
return $value;
}
);

$other_page_id = self::factory()->post->create( array( 'post_type' => 'page' ) );
$this->assertIsInt( $other_page_id );
wp_delete_post( $other_page_id, true );

Comment thread
westonruter marked this conversation as resolved.
$this->assertSame(
0,
$call_count,
'update_option() should not be called when wp_page_for_privacy_policy is already 0.'
);
}

/**
* Tests that untrashing the Privacy Policy page preserves the option,
* confirming the trash/restore cycle keeps the assignment intact.
*
* @ticket 56694
*/
public function test_untrashing_privacy_policy_page_preserves_option(): void {
wp_trash_post( $this->policy_page_id );
wp_untrash_post( $this->policy_page_id );

$this->assertSame(
$this->policy_page_id,
(int) get_option( 'wp_page_for_privacy_policy' ),
'Untrashing the Privacy Policy page should preserve wp_page_for_privacy_policy.'
);
}
}
Loading