From 50af9626537f04f62861823ad48c3f3054844813 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Wed, 17 Feb 2021 22:56:34 +0000 Subject: [PATCH] Posts/Post Types: Prevent duplicates in sticky posts option. In `unstick_post()` if a post ID is duplicated in the `sticky_posts` option remove all instances. In both `stick_post()` and `unstick_post()` check for duplicate IDs already stored in the `sticky_post` option and remove them if the option is updated. Props rahmohn, archon810. Fixes #52007. git-svn-id: https://develop.svn.wordpress.org/trunk@50380 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/post.php | 12 +-- tests/phpunit/tests/post.php | 154 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 526d8f7f36..b46d97bf14 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -2626,19 +2626,19 @@ function sanitize_post_field( $field, $value, $post_id, $context = 'display' ) { function stick_post( $post_id ) { $post_id = (int) $post_id; $stickies = get_option( 'sticky_posts' ); + $updated = false; if ( ! is_array( $stickies ) ) { - $stickies = array(); + $stickies = array( $post_id ); + } else { + $stickies = array_unique( array_map( 'intval', $stickies ) ); } - $stickies = array_map( 'intval', $stickies ); - if ( ! in_array( $post_id, $stickies, true ) ) { $stickies[] = $post_id; + $updated = update_option( 'sticky_posts', array_values( $stickies ) ); } - $updated = update_option( 'sticky_posts', $stickies ); - if ( $updated ) { /** * Fires once a post has been added to the sticky list. @@ -2668,7 +2668,7 @@ function unstick_post( $post_id ) { return; } - $stickies = array_map( 'intval', $stickies ); + $stickies = array_values( array_unique( array_map( 'intval', $stickies ) ) ); if ( ! in_array( $post_id, $stickies, true ) ) { return; diff --git a/tests/phpunit/tests/post.php b/tests/phpunit/tests/post.php index 2a3fb2a70b..69d2035ea0 100644 --- a/tests/phpunit/tests/post.php +++ b/tests/phpunit/tests/post.php @@ -1637,4 +1637,158 @@ class Tests_Post extends WP_UnitTestCase { $resolved_post_date = wp_resolve_post_date( $invalid_date, $invalid_date ); $this->assertFalse( $resolved_post_date ); } + + /** + * Ensure sticking post updates option. + * + * @covers ::stick_post + */ + function test_sticky_posts() { + stick_post( 1 ); + $this->assertSameSets( array( 1 ), get_option( 'sticky_posts' ) ); + + stick_post( 2 ); + $this->assertSameSets( array( 1, 2 ), get_option( 'sticky_posts' ) ); + } + + /** + * Ensure sticking posts can not duplicate options. + * + * @ticket 52007 + * @covers ::stick_post + * @dataProvider data_sticky_posts_not_duplicate_with_the_same_value + * + * @param mixed $stick Value to pass to stick_post(). + */ + function test_sticky_posts_not_duplicate_with_the_same_value( $stick ) { + update_option( 'sticky_posts', array( 1, 2 ) ); + + stick_post( $stick ); + $this->assertSameSets( array( 1, 2 ), get_option( 'sticky_posts' ) ); + } + + /** + * Data provider for test_sticky_posts_not_duplicate_with_the_same_value(). + * + * @return array[] { + * Arguments passed to test. + * + * @type mixed $stick Value to pass to stick_post(). + * } + */ + function data_sticky_posts_not_duplicate_with_the_same_value() { + return array( + array( 1 ), + array( '1' ), + array( 2.0 ), + ); + } + + /** + * Ensure sticking post removes other duplicates. + * + * @ticket 52007 + * @covers ::stick_post + * + * @param mixed $stick Value to pass to stick_post(). + */ + function test_sticky_posts_remove_duplicate_ids_when_add_new_value() { + update_option( 'sticky_posts', array( 1, 1, 2, 2 ) ); + + stick_post( 3 ); + $this->assertSameSets( array( 1, 2, 3 ), get_option( 'sticky_posts' ) ); + } + + function test_unsticky_posts() { + update_option( 'sticky_posts', array( 1 ) ); + unstick_post( 1 ); + $this->assertEmpty( get_option( 'sticky_posts' ) ); + + update_option( 'sticky_posts', array( 1, 2 ) ); + unstick_post( 1 ); + $this->assertSameSets( array( 2 ), get_option( 'sticky_posts' ) ); + } + + /** + * Ensure duplicates removed when unsticking posts. + * + * @ticket 52007 + * @covers ::unstick_post + * + * @dataProvider data_unstick_posts_with_duplicate_id + * + * @param array $starting_option Original value of `sticky_posts` option. + * @param mixed $unstick Parameter passed to `unstick_post()` + * @param array $expected + */ + function test_unstick_posts_with_duplicate_id( $starting_option, $unstick, $expected ) { + update_option( 'sticky_posts', $starting_option ); + unstick_post( $unstick ); + $this->assertSameSets( $expected, get_option( 'sticky_posts' ) ); + } + + /** + * Data provider for test_unstick_posts_with_duplicate_id + * + * @return array[] { + * Arguments passed to test. + * + * @type array $starting_option Original value of `sticky_posts` option. + * @type mixed $unstick Parameter passed to `unstick_post()` + * @type array $expected + * } + */ + function data_unstick_posts_with_duplicate_id() { + return array( + array( + array( 1, 1 ), + 1, + array(), + ), + array( + array( 1, 1 ), + '1', + array(), + ), + array( + array( 1, 2, 1 ), + 1, + array( 2 ), + ), + array( + array( 1, 2, 1 ), + 2, + array( 1 ), + ), + array( + array( 1, 2, 1 ), + 2.0, + array( 1 ), + ), + ); + } + + /** + * Ensure sticking duplicate does not trigger db update. + * + * @ticket 52007 + * @covers ::stick_post + */ + function test_sticking_dupes_does_not_trigger_update() { + update_option( 'sticky_posts', array( 1, 2, 2 ) ); + stick_post( 2 ); + $this->assertEquals( array( 1, 2, 2 ), get_option( 'sticky_posts' ) ); + } + + /** + * Ensure unsticking unstuck post does not trigger db update. + * + * @ticket 52007 + * @covers ::unstick_post + */ + function test_unsticking_unstuck_post_does_not_trigger_update() { + update_option( 'sticky_posts', array( 1, 2, 2 ) ); + unstick_post( 3 ); + $this->assertEquals( array( 1, 2, 2 ), get_option( 'sticky_posts' ) ); + } }