From 2cafc0d78778718c307e09f34b56ea6e275f7b89 Mon Sep 17 00:00:00 2001 From: Konstantin Obenland Date: Mon, 6 Jul 2015 22:40:59 +0000 Subject: [PATCH] Check for all required caps before (un)sticking a post. In cases where a user has the `edit_others_posts` capability but not `publish_posts`, it was possible for that user to unstick a post after editing, since the input field was never made available in that context. Props ericmann, chriscct7. Fixes #24153. git-svn-id: https://develop.svn.wordpress.org/trunk@33096 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/post.php | 2 +- tests/phpunit/tests/post.php | 99 ++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index 2ab53352ad..1968e9662e 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -385,7 +385,7 @@ function edit_post( $post_data = null ) { wp_set_post_lock( $post_ID ); - if ( current_user_can( $ptype->cap->edit_others_posts ) ) { + if ( current_user_can( $ptype->cap->edit_others_posts ) && current_user_can( $ptype->cap->publish_posts ) ) { if ( ! empty( $post_data['sticky'] ) ) stick_post( $post_ID ); else diff --git a/tests/phpunit/tests/post.php b/tests/phpunit/tests/post.php index 86810b9a38..2122d03599 100644 --- a/tests/phpunit/tests/post.php +++ b/tests/phpunit/tests/post.php @@ -1023,4 +1023,103 @@ class Tests_Post extends WP_UnitTestCase { $this->assertEquals( 'closed', $post->ping_status ); _unregister_post_type( $post_type ); } + + /** + * If a post is sticky and is updated by a user that does not have the publish_post capability, it should _stay_ + * sticky. + * + * @ticket 24153 + */ + function test_user_without_publish_cannot_affect_sticky() { + // Create a role with edit_others_posts. + add_role( 'grammarian', 'Grammarian', array( + 'read' => true, + 'edit_posts' => true, + 'edit_others_posts' => true, + 'edit_published_posts' => true, + ) ); + $editor_user = $this->factory->user->create( array( 'role' => 'grammarian' ) ); + $old_uid = get_current_user_id(); + wp_set_current_user( $editor_user ); + + // Sanity Check. + $this->assertFalse( current_user_can( 'publish_posts' ) ); + $this->assertTrue( current_user_can( 'edit_others_posts' ) ); + $this->assertTrue( current_user_can( 'edit_published_posts' ) ); + + // Create a sticky post. + $post = $this->factory->post->create_and_get( array( + 'post_title' => 'Will be changed', + 'post_content' => 'Will be changed', + ) ); + stick_post( $post->ID ); + + // Sanity Check. + $this->assertTrue( is_sticky( $post->ID ) ); + + // Edit the post. + $post->post_title = 'Updated'; + $post->post_content = 'Updated'; + wp_update_post( $post ); + + // Make sure it's still sticky. + $saved_post = get_post( $post->ID ); + $this->assertTrue( is_sticky( $saved_post->ID ) ); + $this->assertEquals( 'Updated', $saved_post->post_title ); + $this->assertEquals( 'Updated', $saved_post->post_content ); + + // Teardown + wp_set_current_user( $old_uid ); + } + + /** + * If the `edit_post()` method is invoked by a user without publish_posts permission, the sticky status of the post + * should not be changed. + * + * @ticket 24153 + */ + function test_user_without_publish_cannot_affect_sticky_with_edit_post() { + // Create a sticky post. + $post = $this->factory->post->create_and_get( array( + 'post_title' => 'Will be changed', + 'post_content' => 'Will be changed', + ) ); + stick_post( $post->ID ); + + // Sanity Check. + $this->assertTrue( is_sticky( $post->ID ) ); + + // Create a role with edit_others_posts. + add_role( 'grammarian', 'Grammarian', array( + 'read' => true, + 'edit_posts' => true, + 'edit_others_posts' => true, + 'edit_published_posts' => true, + ) ); + $editor_user = $this->factory->user->create( array( 'role' => 'grammarian' ) ); + $old_uid = get_current_user_id(); + wp_set_current_user( $editor_user ); + + // Sanity Check. + $this->assertFalse( current_user_can( 'publish_posts' ) ); + $this->assertTrue( current_user_can( 'edit_others_posts' ) ); + $this->assertTrue( current_user_can( 'edit_published_posts' ) ); + + // Edit the post - The key 'sticky' is intentionally unset. + $data = array( + 'post_ID' => $post->ID, + 'post_title' => 'Updated', + 'post_content' => 'Updated', + ); + edit_post( $data ); + + // Make sure it's still sticky + $saved_post = get_post( $post->ID ); + $this->assertTrue( is_sticky( $saved_post->ID ) ); + $this->assertEquals( 'Updated', $saved_post->post_title ); + $this->assertEquals( 'Updated', $saved_post->post_content ); + + // Teardown + wp_set_current_user( $old_uid ); + } }