From da2acf666ae184d7b4f3c6c90563dd1fa629486e Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Sun, 29 Nov 2015 02:24:15 +0000 Subject: [PATCH] When a post is scheduled for publication, treat it the same as a published post when calculating the capabilities required to edit or delete it. Fixes #33694 git-svn-id: https://develop.svn.wordpress.org/trunk@35747 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/capabilities.php | 26 ++++++++++------- tests/phpunit/tests/user/capabilities.php | 34 +++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php index 69bfb6fc50..7c570c4a1d 100644 --- a/src/wp-includes/capabilities.php +++ b/src/wp-includes/capabilities.php @@ -83,12 +83,15 @@ function map_meta_cap( $cap, $user_id ) { // If the post author is set and the user is the author... if ( $post->post_author && $user_id == $post->post_author ) { - // If the post is published... - if ( 'publish' == $post->post_status ) { + // If the post is published or scheduled... + if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; } elseif ( 'trash' == $post->post_status ) { - if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) { + $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); + if ( in_array( $status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; + } else { + $caps[] = $post_type->cap->delete_posts; } } else { // If the post is draft... @@ -97,8 +100,8 @@ function map_meta_cap( $cap, $user_id ) { } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->delete_others_posts; - // The post is published, extra cap required. - if ( 'publish' == $post->post_status ) { + // The post is published or scheduled, extra cap required. + if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->delete_published_posts; } elseif ( 'private' == $post->post_status ) { $caps[] = $post_type->cap->delete_private_posts; @@ -141,12 +144,15 @@ function map_meta_cap( $cap, $user_id ) { // If the post author is set and the user is the author... if ( $post->post_author && $user_id == $post->post_author ) { - // If the post is published... - if ( 'publish' == $post->post_status ) { + // If the post is published or scheduled... + if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; } elseif ( 'trash' == $post->post_status ) { - if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) { + $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); + if ( in_array( $status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; + } else { + $caps[] = $post_type->cap->edit_posts; } } else { // If the post is draft... @@ -155,8 +161,8 @@ function map_meta_cap( $cap, $user_id ) { } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; - // The post is published, extra cap required. - if ( 'publish' == $post->post_status ) { + // The post is published or scheduled, extra cap required. + if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { $caps[] = $post_type->cap->edit_published_posts; } elseif ( 'private' == $post->post_status ) { $caps[] = $post_type->cap->edit_private_posts; diff --git a/tests/phpunit/tests/user/capabilities.php b/tests/phpunit/tests/user/capabilities.php index 99b0c56b2a..1c3cefd4ca 100644 --- a/tests/phpunit/tests/user/capabilities.php +++ b/tests/phpunit/tests/user/capabilities.php @@ -981,6 +981,40 @@ class Tests_User_Capabilities extends WP_UnitTestCase { $this->assertTrue( current_user_can( 'edit_user', $user->ID ) ); } + /** + * @ticket 33694 + */ + function test_contributor_cannot_edit_scheduled_post() { + + // Add a contributor + $contributor = $this->factory->user->create_and_get( array( + 'role' => 'contributor', + ) ); + + // Give them a scheduled post + $post = $this->factory->post->create_and_get( array( + 'post_author' => $contributor->ID, + 'post_status' => 'future', + ) ); + + // Ensure contributor can't edit or trash the post + $this->assertFalse( user_can( $contributor->ID, 'edit_post', $post->ID ) ); + $this->assertFalse( user_can( $contributor->ID, 'delete_post', $post->ID ) ); + + // Test the tests + $this->assertTrue( defined( 'EMPTY_TRASH_DAYS' ) ); + $this->assertNotEmpty( EMPTY_TRASH_DAYS ); + + // Trash it + $trashed = wp_trash_post( $post->ID ); + $this->assertNotEmpty( $trashed ); + + // Ensure contributor can't edit, un-trash, or delete the post + $this->assertFalse( user_can( $contributor->ID, 'edit_post', $post->ID ) ); + $this->assertFalse( user_can( $contributor->ID, 'delete_post', $post->ID ) ); + + } + function test_multisite_administrator_with_manage_network_users_can_edit_users() { if ( ! is_multisite() ) { $this->markTestSkipped( 'Test only runs in multisite' );