From 61350144fb29985cbbc3bb1f55e29c0462552795 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Sat, 9 Dec 2017 22:50:13 +0000 Subject: [PATCH] Role/Capability: When checking capabilities before setting a post slug, ensure the correct post type capabilities are used. Previously, only the `publish_posts` capability was checked. Now, the correct meta or primitive capability for the post type is used where appropriate. Props peterwilsoncc Fixes #42464 git-svn-id: https://develop.svn.wordpress.org/trunk@42380 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/post.php | 12 +- tests/phpunit/tests/post/wpInsertPost.php | 174 ++++++++++++++++++++++ 2 files changed, 184 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 45fb3573b8..94a450f438 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -3304,8 +3304,16 @@ function wp_insert_post( $postarr, $wp_error = false ) { } } - // Don't allow contributors to set the post slug for pending review posts. - if ( 'pending' == $post_status && ! current_user_can( 'publish_posts' ) ) { + /* + * Don't allow contributors to set the post slug for pending review posts. + * + * For new posts check the primitive capability, for updates check the meta capability. + */ + $post_type_object = get_post_type_object( $post_type ); + + if ( ! $update && 'pending' === $post_status && ! current_user_can( $post_type_object->cap->publish_posts ) ) { + $post_name = ''; + } elseif ( $update && 'pending' === $post_status && ! current_user_can( 'publish_post', $post_ID ) ) { $post_name = ''; } diff --git a/tests/phpunit/tests/post/wpInsertPost.php b/tests/phpunit/tests/post/wpInsertPost.php index ff38968c0a..d459d9493d 100644 --- a/tests/phpunit/tests/post/wpInsertPost.php +++ b/tests/phpunit/tests/post/wpInsertPost.php @@ -5,6 +5,53 @@ */ class Tests_WPInsertPost extends WP_UnitTestCase { + protected static $user_ids = array( + 'administrator' => null, + 'contributor' => null, + ); + + static function wpSetUpBeforeClass( $factory ) { + self::$user_ids = array( + 'administrator' => $factory->user->create( array( + 'role' => 'administrator', + ) ), + 'contributor' => $factory->user->create( array( + 'role' => 'contributor', + ) ), + ); + + $role = get_role( 'administrator' ); + $role->add_cap( 'publish_mapped_meta_caps' ); + $role->add_cap( 'publish_unmapped_meta_caps' ); + } + + static function tearDownAfterClass() { + $role = get_role( 'administrator' ); + $role->remove_cap( 'publish_mapped_meta_caps' ); + $role->remove_cap( 'publish_unmapped_meta_caps' ); + + parent::tearDownAfterClass(); + } + + function setUp() { + parent::setUp(); + + register_post_type( 'mapped_meta_caps', array( + 'capability_type' => array( 'mapped_meta_cap', 'mapped_meta_caps' ), + 'map_meta_cap' => true, + ) ); + + register_post_type( 'unmapped_meta_caps', array( + 'capability_type' => array( 'unmapped_meta_cap', 'unmapped_meta_caps' ), + 'map_meta_cap' => false, + ) ); + + register_post_type( 'no_admin_caps', array( + 'capability_type' => array( 'no_admin_cap', 'no_admin_caps' ), + 'map_meta_cap' => false, + ) ); + } + /** * @ticket 11863 */ @@ -103,4 +150,131 @@ class Tests_WPInsertPost extends WP_UnitTestCase { $this->assertEquals( 'about', get_post( $another_about_page_id )->post_name ); $this->assertEquals( 'about-2', get_post( $about_page_id )->post_name ); } + + /** + * Data for testing the ability for users to set the post slug. + * + * @return array Array of test arguments. + */ + function data_various_post_types() { + return array( + array( + 'mapped_meta_caps', + ), + array( + 'unmapped_meta_caps', + ), + array( + 'post', + ), + ); + } + + /** + * Test contributor making changes to the pending post slug. + * + * @ticket 42464 + * @dataProvider data_various_post_types + */ + function test_contributor_cannot_set_post_slug( $post_type ) { + wp_set_current_user( self::$user_ids['contributor'] ); + + $post_id = $this->factory()->post->create( array( + 'post_title' => 'Jefferson claim: nice to have Washington on your side.', + 'post_content' => "I’m in the cabinet. I am complicit in watching him grabbin’ at power and kiss it.\n\nIf Washington isn’t gon’ listen to disciplined dissidents, this is the difference: this kid is out!", + 'post_type' => $post_type, + 'post_name' => 'new-washington', + 'post_status' => 'pending', + ) ); + + $expected = ''; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + + // Now update the post. + wp_update_post( array( + 'ID' => $post_id, + 'post_title' => 'Hamilton has Washington on side: Jefferson', + 'post_name' => 'edited-washington', + ) ); + + $expected = ''; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + } + + /** + * Test administrator making changes to the pending post slug. + * + * @ticket 42464 + * @dataProvider data_various_post_types + */ + function test_administrator_can_set_post_slug( $post_type ) { + wp_set_current_user( self::$user_ids['administrator'] ); + + $post_id = $this->factory()->post->create( array( + 'post_title' => 'What is the Conner Project?', + 'post_content' => "Evan Hansen’s last link to his friend Conner is a signature on his broken arm.", + 'post_type' => $post_type, + 'post_name' => 'dear-evan-hansen-explainer', + 'post_status' => 'pending', + ) ); + + $expected = 'dear-evan-hansen-explainer'; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + + // Now update the post. + wp_update_post( array( + 'ID' => $post_id, + 'post_title' => 'Conner Project to close', + 'post_name' => 'dear-evan-hansen-spoiler', + ) ); + + $expected = 'dear-evan-hansen-spoiler'; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + } + + /** + * Test administrator making changes to a pending post slug for a post type they don't + * have permission to publish. + * + * These assertions failed prior to ticket #42464. + * + * @ticket 42464 + */ + function test_administrator_cannot_set_post_slug_on_post_type_they_cannot_publish() { + wp_set_current_user( self::$user_ids['administrator'] ); + + $post_id = $this->factory()->post->create( array( + 'post_title' => 'Everything is legal in New Jersey', + 'post_content' => 'Shortly before his death, Philip Hamilton was heard to claim everything was legal in the garden state.', + 'post_type' => 'no_admin_caps', + 'post_name' => 'yet-another-duel', + 'post_status' => 'pending', + ) ); + + $expected = ''; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + + // Now update the post. + wp_update_post( array( + 'ID' => $post_id, + 'post_title' => 'Ten things illegal in New Jersey', + 'post_name' => 'foreshadowing-in-nj', + ) ); + + $expected = ''; + $actual = get_post_field( 'post_name', $post_id ); + + $this->assertSame( $expected, $actual ); + } + }