WordPress.org

Make WordPress Core

Ticket #38609: 38609.1.diff

File 38609.1.diff, 18.8 KB (added by jnylen0, 4 years ago)

Fix post handling and add tests for posts

  • src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
    index 2749b12..74341db 100644
    a b class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    142142                        $attachment->post_title = preg_replace( '/\.[^.]+$/', '', basename( $file ) );
    143143                }
    144144
    145                 $id = wp_insert_post( $attachment, true );
     145                $id = wp_insert_post( wp_slash( $attachment ), true );
    146146
    147147                if ( is_wp_error( $id ) ) {
    148148                        if ( 'db_update_error' === $id->get_error_code() ) {
    class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    369369                        'description'     => __( 'The caption for the resource.' ),
    370370                        'type'            => 'string',
    371371                        'context'         => array( 'view', 'edit' ),
    372                         'arg_options'     => array(
    373                                 'sanitize_callback' => 'wp_filter_post_kses',
    374                         ),
    375372                );
    376373
    377374                $schema['properties']['description'] = array(
    378375                        'description'     => __( 'The description for the resource.' ),
    379376                        'type'            => 'string',
    380377                        'context'         => array( 'view', 'edit' ),
    381                         'arg_options'     => array(
    382                                 'sanitize_callback' => 'wp_filter_post_kses',
    383                         ),
    384378                );
    385379
    386380                $schema['properties']['media_type'] = array(
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
    index 0122f9a..1408449 100644
    a b class WP_REST_Posts_Controller extends WP_REST_Controller { 
    483483                }
    484484
    485485                $post->post_type = $this->post_type;
    486                 $post_id         = wp_insert_post( $post, true );
     486                $post_id         = wp_insert_post( wp_slash( (array) $post ), true );
    487487
    488488                if ( is_wp_error( $post_id ) ) {
    489489
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    619619                }
    620620
    621621                // convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
    622                 $post_id = wp_update_post( (array) $post, true );
     622                $post_id = wp_update_post( wp_slash( (array) $post ), true );
    623623
    624624                if ( is_wp_error( $post_id ) ) {
    625625                        if ( 'db_update_error' === $post_id->get_error_code() ) {
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    956956                // Post title.
    957957                if ( ! empty( $schema['properties']['title'] ) && isset( $request['title'] ) ) {
    958958                        if ( is_string( $request['title'] ) ) {
    959                                 $prepared_post->post_title = wp_filter_post_kses( $request['title'] );
     959                                $prepared_post->post_title = $request['title'];
    960960                        } elseif ( ! empty( $request['title']['raw'] ) ) {
    961                                 $prepared_post->post_title = wp_filter_post_kses( $request['title']['raw'] );
     961                                $prepared_post->post_title = $request['title']['raw'];
    962962                        }
    963963                }
    964964
    965965                // Post content.
    966966                if ( ! empty( $schema['properties']['content'] ) && isset( $request['content'] ) ) {
    967967                        if ( is_string( $request['content'] ) ) {
    968                                 $prepared_post->post_content = wp_filter_post_kses( $request['content'] );
     968                                $prepared_post->post_content = $request['content'];
    969969                        } elseif ( isset( $request['content']['raw'] ) ) {
    970                                 $prepared_post->post_content = wp_filter_post_kses( $request['content']['raw'] );
     970                                $prepared_post->post_content = $request['content']['raw'];
    971971                        }
    972972                }
    973973
    974974                // Post excerpt.
    975975                if ( ! empty( $schema['properties']['excerpt'] ) && isset( $request['excerpt'] ) ) {
    976976                        if ( is_string( $request['excerpt'] ) ) {
    977                                 $prepared_post->post_excerpt = wp_filter_post_kses( $request['excerpt'] );
     977                                $prepared_post->post_excerpt = $request['excerpt'];
    978978                        } elseif ( isset( $request['excerpt']['raw'] ) ) {
    979                                 $prepared_post->post_excerpt = wp_filter_post_kses( $request['excerpt']['raw'] );
     979                                $prepared_post->post_excerpt = $request['excerpt']['raw'];
    980980                        }
    981981                }
    982982
  • src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
    index ceaa26b..70422d4 100644
    a b class WP_REST_Terms_Controller extends WP_REST_Controller { 
    379379
    380380                $prepared_term = $this->prepare_item_for_database( $request );
    381381
    382                 $term = wp_insert_term( $prepared_term->name, $this->taxonomy, $prepared_term );
     382                $term = wp_insert_term( $prepared_term->name, $this->taxonomy, wp_slash( $prepared_term ) );
    383383                if ( is_wp_error( $term ) ) {
    384384                        /*
    385385                         * If we're going to inform the client that the term already exists,
    class WP_REST_Terms_Controller extends WP_REST_Controller { 
    490490
    491491                // Only update the term if we haz something to update.
    492492                if ( ! empty( $prepared_term ) ) {
    493                         $update = wp_update_term( $term->term_id, $term->taxonomy, (array) $prepared_term );
     493                        $update = wp_update_term( $term->term_id, $term->taxonomy, wp_slash( (array) $prepared_term ) );
    494494
    495495                        if ( is_wp_error( $update ) ) {
    496496                                return $update;
    class WP_REST_Terms_Controller extends WP_REST_Controller { 
    818818                                        'type'         => 'string',
    819819                                        'context'      => array( 'view', 'edit' ),
    820820                                        'arg_options'  => array(
    821                                                 'sanitize_callback' => 'wp_filter_post_kses',
     821                                                'sanitize_callback' => 'wp_kses_post',
    822822                                        ),
    823823                                ),
    824824                                'link'        => array(
  • src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
    index bb3737d..8b0c2d7 100644
    a b class WP_REST_Users_Controller extends WP_REST_Controller { 
    427427                        }
    428428
    429429                        $user->ID = $user_id;
    430                         $user_id  = wp_update_user( $user );
     430                        $user_id  = wp_update_user( wp_slash( $user ) );
    431431
    432432                        if ( is_wp_error( $user_id ) ) {
    433433                                return $user_id;
    434434                        }
    435435                } else {
    436                         $user_id = wp_insert_user( $user );
     436                        $user_id = wp_insert_user( wp_slash( $user ) );
    437437
    438438                        if ( is_wp_error( $user_id ) ) {
    439439                                return $user_id;
    class WP_REST_Users_Controller extends WP_REST_Controller { 
    548548                // Ensure we're operating on the same user we already checked.
    549549                $user->ID = $id;
    550550
    551                 $user_id = wp_update_user( $user );
     551                $user_id = wp_update_user( wp_slash( $user ) );
    552552
    553553                if ( is_wp_error( $user_id ) ) {
    554554                        return $user_id;
    class WP_REST_Users_Controller extends WP_REST_Controller { 
    10561056                                        'type'        => 'string',
    10571057                                        'context'     => array( 'embed', 'view', 'edit' ),
    10581058                                        'arg_options' => array(
    1059                                                 'sanitize_callback' => 'wp_filter_post_kses',
     1059                                                'sanitize_callback' => 'wp_kses_post',
    10601060                                        ),
    10611061                                ),
    10621062                                'link'        => array(
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

    diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
    index dcebfe8..6df2626 100644
    a b  
    1212class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Testcase {
    1313        protected static $post_id;
    1414
     15        protected static $superadmin_id;
    1516        protected static $editor_id;
    1617        protected static $author_id;
    1718        protected static $contributor_id;
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    2122        public static function wpSetUpBeforeClass( $factory ) {
    2223                self::$post_id = $factory->post->create();
    2324
     25                self::$superadmin_id = $factory->user->create( array(
     26                        'role' => 'administrator',
     27                        'user_login' => 'superadmin',
     28                ) );
    2429                self::$editor_id = $factory->user->create( array(
    2530                        'role' => 'editor',
    2631                ) );
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    5459        public function setUp() {
    5560                parent::setUp();
    5661                register_post_type( 'youseeme', array( 'supports' => array(), 'show_in_rest' => true ) );
     62                if ( is_multisite() ) {
     63                        update_site_option( 'site_admins', array( 'superadmin' ) );
     64                }
    5765        }
    5866
    5967        public function test_register_routes() {
    class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    18551863                $this->assertEquals( array(), $new_data['categories'] );
    18561864        }
    18571865
     1866        public function verify_post_roundtrip( $input = array(), $expected_output = array() ) {
     1867                // Create the post
     1868                $request = new WP_REST_Request( 'POST', '/wp/v2/posts' );
     1869                foreach ( $input as $name => $value ) {
     1870                        $request->set_param( $name, $value );
     1871                }
     1872                $response = $this->server->dispatch( $request );
     1873                $this->assertEquals( 201, $response->get_status() );
     1874
     1875                $expected_output = array_merge( $input, $expected_output );
     1876
     1877                $actual_output = $response->get_data();
     1878                $actual_output['content'] = $actual_output['content']['raw'];
     1879                $actual_output['title'] = $actual_output['title']['raw'];
     1880                $actual_output['excerpt'] = $actual_output['excerpt']['raw'];
     1881
     1882                // Compare expected API output to actual API output
     1883                foreach ( $expected_output as $name => $value ) {
     1884                        $this->assertEquals( $expected_output[ $name ], $actual_output[ $name ], "bad $name on create (API)" );
     1885                }
     1886
     1887                // Compare expected API output to WP internal values
     1888                $post = get_post( $actual_output['id'] );
     1889                $this->assertEquals( $expected_output['title'], $post->post_title, 'bad title on create (WP)' );
     1890                $this->assertEquals( $expected_output['content'], $post->post_content, 'bad content on create (WP)' );
     1891                $this->assertEquals( $expected_output['excerpt'], $post->post_excerpt, 'bad excerpt on create (WP)' );
     1892
     1893                // Update the post
     1894                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $actual_output['id'] ) );
     1895                foreach ( $input as $name => $value ) {
     1896                        $request->set_param( $name, $value );
     1897                }
     1898                $response = $this->server->dispatch( $request );
     1899                $this->assertEquals( 200, $response->get_status() );
     1900
     1901                $actual_output = $response->get_data();
     1902                $actual_output['content'] = $actual_output['content']['raw'];
     1903                $actual_output['title'] = $actual_output['title']['raw'];
     1904                $actual_output['excerpt'] = $actual_output['excerpt']['raw'];
     1905
     1906                // Compare expected API output to actual API output
     1907                foreach ( $expected_output as $name => $value ) {
     1908                        $this->assertEquals( $expected_output[ $name ], $actual_output[ $name ], "bad $name on update (API)" );
     1909                }
     1910
     1911                // Compare expected API output to WP internal values
     1912                $post = get_post( $actual_output['id'] );
     1913                $this->assertEquals( $expected_output['title'], $post->post_title, 'bad title on update (WP)' );
     1914                $this->assertEquals( $expected_output['content'], $post->post_content, 'bad content on update (WP)' );
     1915                $this->assertEquals( $expected_output['excerpt'], $post->post_excerpt, 'bad excerpt on update (WP)' );
     1916        }
     1917
     1918        public function test_post_roundtrip_as_author_1() {
     1919                wp_set_current_user( self::$author_id );
     1920                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     1921                $this->verify_post_roundtrip( array(
     1922                        'title'   => '\o/ ¯\_(ツ)_/¯ 🚢',
     1923                        'content' => '\o/ ¯\_(ツ)_/¯ 🚢',
     1924                        'excerpt' => '\o/ ¯\_(ツ)_/¯ 🚢',
     1925                ) );
     1926        }
     1927
     1928        public function test_post_roundtrip_as_author_2() {
     1929                wp_set_current_user( self::$author_id );
     1930                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     1931                $this->verify_post_roundtrip( array(
     1932                        'title'   => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1933                        'content' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1934                        'excerpt' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1935                ), array(
     1936                        'title'   => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1937                        'content' => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1938                        'excerpt' => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1939                ) );
     1940        }
     1941
     1942        public function test_post_roundtrip_as_author_unfiltered_html_1() {
     1943                wp_set_current_user( self::$author_id );
     1944                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     1945                $this->verify_post_roundtrip( array(
     1946                        'title'   => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     1947                        'content' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     1948                        'excerpt' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     1949                ), array(
     1950                        'title'   => 'div <strong>strong</strong> oh noes',
     1951                        'content' => '<div>div</div> <strong>strong</strong> oh noes',
     1952                        'excerpt' => '<div>div</div> <strong>strong</strong> oh noes',
     1953                ) );
     1954        }
     1955
     1956        public function test_post_roundtrip_as_author_unfiltered_html_2() {
     1957                wp_set_current_user( self::$author_id );
     1958                $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     1959                $this->verify_post_roundtrip( array(
     1960                        'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     1961                        'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     1962                        'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     1963                ), array(
     1964                        'title'   => '<a href="#">link</a>',
     1965                        'content' => '<a href="#" target="_blank">link</a>',
     1966                        'excerpt' => '<a href="#" target="_blank">link</a>',
     1967                ) );
     1968        }
     1969
     1970        public function test_post_roundtrip_as_editor_1() {
     1971                wp_set_current_user( self::$editor_id );
     1972                $this->assertEquals( ! is_multisite(), current_user_can( 'unfiltered_html' ) );
     1973                $this->verify_post_roundtrip( array(
     1974                        'title'   => '\o/ ¯\_(ツ)_/¯ 🚢',
     1975                        'content' => '\o/ ¯\_(ツ)_/¯ 🚢',
     1976                        'excerpt' => '\o/ ¯\_(ツ)_/¯ 🚢',
     1977                ) );
     1978        }
     1979
     1980        public function test_post_roundtrip_as_editor_2() {
     1981                wp_set_current_user( self::$editor_id );
     1982                if ( is_multisite() ) {
     1983                        $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     1984                        $this->verify_post_roundtrip( array(
     1985                                'title'   => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1986                                'content' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1987                                'excerpt' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1988                        ), array(
     1989                                'title'   => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1990                                'content' => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1991                                'excerpt' => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
     1992                        ) );
     1993                } else {
     1994                        $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     1995                        $this->verify_post_roundtrip( array(
     1996                                'title'   => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1997                                'content' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1998                                'excerpt' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     1999                        ) );
     2000                }
     2001        }
     2002
     2003        public function test_post_roundtrip_as_editor_unfiltered_html_1() {
     2004                wp_set_current_user( self::$editor_id );
     2005                if ( is_multisite() ) {
     2006                        $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     2007                        $this->verify_post_roundtrip( array(
     2008                                'title'   => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2009                                'content' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2010                                'excerpt' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2011                        ), array(
     2012                                'title'   => 'div <strong>strong</strong> oh noes',
     2013                                'content' => '<div>div</div> <strong>strong</strong> oh noes',
     2014                                'excerpt' => '<div>div</div> <strong>strong</strong> oh noes',
     2015                        ) );
     2016                } else {
     2017                        $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2018                        $this->verify_post_roundtrip( array(
     2019                                'title'   => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2020                                'content' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2021                                'excerpt' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2022                        ) );
     2023                }
     2024        }
     2025
     2026        public function test_post_roundtrip_as_editor_unfiltered_html_2() {
     2027                wp_set_current_user( self::$editor_id );
     2028                if ( is_multisite() ) {
     2029                        $this->assertFalse( current_user_can( 'unfiltered_html' ) );
     2030                        $this->verify_post_roundtrip( array(
     2031                                'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2032                                'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2033                                'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2034                        ), array(
     2035                                'title'   => '<a href="#">link</a>',
     2036                                'content' => '<a href="#" target="_blank">link</a>',
     2037                                'excerpt' => '<a href="#" target="_blank">link</a>',
     2038                        ) );
     2039                } else {
     2040                        $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2041                        $this->verify_post_roundtrip( array(
     2042                                'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2043                                'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2044                                'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2045                        ) );
     2046                }
     2047        }
     2048
     2049        public function test_post_roundtrip_as_superadmin_1() {
     2050                wp_set_current_user( self::$superadmin_id );
     2051                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2052                $this->verify_post_roundtrip( array(
     2053                        'title'   => '\o/ ¯\_(ツ)_/¯ 🚢',
     2054                        'content' => '\o/ ¯\_(ツ)_/¯ 🚢',
     2055                        'excerpt' => '\o/ ¯\_(ツ)_/¯ 🚢',
     2056                ) );
     2057        }
     2058
     2059        public function test_post_roundtrip_as_superadmin_2() {
     2060                wp_set_current_user( self::$superadmin_id );
     2061                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2062                $this->verify_post_roundtrip( array(
     2063                        'title'   => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     2064                        'content' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     2065                        'excerpt' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
     2066                ) );
     2067        }
     2068
     2069        public function test_post_roundtrip_as_superadmin_unfiltered_html_1() {
     2070                wp_set_current_user( self::$superadmin_id );
     2071                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2072                $this->verify_post_roundtrip( array(
     2073                        'title'   => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2074                        'content' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2075                        'excerpt' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2076                ), array(
     2077                        'title'   => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2078                        'content' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2079                        'excerpt' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
     2080                ) );
     2081        }
     2082
     2083        public function test_post_roundtrip_as_superadmin_unfiltered_html_2() {
     2084                wp_set_current_user( self::$superadmin_id );
     2085                $this->assertTrue( current_user_can( 'unfiltered_html' ) );
     2086                $this->verify_post_roundtrip( array(
     2087                        'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2088                        'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2089                        'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2090                ), array(
     2091                        'title'   => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2092                        'content' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2093                        'excerpt' => '<a href="#" target="_blank" data-unfiltered=true>link</a>',
     2094                ) );
     2095        }
     2096
    18582097        public function test_delete_item() {
    18592098                $post_id = $this->factory->post->create( array( 'post_title' => 'Deleted post' ) );
    18602099                wp_set_current_user( self::$editor_id );