Make WordPress Core

Ticket #5272: 5272.2.diff

File 5272.2.diff, 38.7 KB (added by peterwilsoncc, 2 years ago)
  • src/wp-includes/canonical.php

    diff --git a/src/wp-includes/canonical.php b/src/wp-includes/canonical.php
    index 617bcb352d..184fb756e8 100644
    a b function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    7777
    7878        $redirect     = $original;
    7979        $redirect_url = false;
     80        $redirect_obj = false;
    8081
    8182        // Notice fixing.
    8283        if ( ! isset( $redirect['path'] ) ) {
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    102103
    103104        if ( is_feed() && $post_id ) {
    104105                $redirect_url = get_post_comments_feed_link( $post_id, get_query_var( 'feed' ) );
     106                $redirect_obj = get_post( $post_id );
    105107
    106108                if ( $redirect_url ) {
    107109                        $redirect['query'] = _remove_qs_args_if_not_in_url(
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    126128                        }
    127129
    128130                        $redirect_url = get_permalink( $post_id );
     131                        $redirect_obj = get_post( $post_id );
    129132
    130133                        if ( $redirect_url ) {
    131134                                $redirect['query'] = _remove_qs_args_if_not_in_url(
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    150153
    151154                        if ( $post_type_obj && $post_type_obj->public && 'auto-draft' !== $redirect_post->post_status ) {
    152155                                $redirect_url = get_permalink( $redirect_post );
     156                                $redirect_obj = get_post( $redirect_post );
    153157
    154158                                $redirect['query'] = _remove_qs_args_if_not_in_url(
    155159                                        $redirect['query'],
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    197201
    198202                        if ( $post_id ) {
    199203                                $redirect_url = get_permalink( $post_id );
     204                                $redirect_obj = get_post( $post_id );
    200205
    201206                                $redirect['path']  = rtrim( $redirect['path'], (int) get_query_var( 'page' ) . '/' );
    202207                                $redirect['query'] = remove_query_arg( 'page', $redirect['query'] );
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    223228                ) {
    224229                        if ( ! empty( $_GET['attachment_id'] ) ) {
    225230                                $redirect_url = get_attachment_link( get_query_var( 'attachment_id' ) );
     231                                $redirect_obj = get_post( get_query_var( 'attachment_id' ) );
    226232
    227233                                if ( $redirect_url ) {
    228234                                        $redirect['query'] = remove_query_arg( 'attachment_id', $redirect['query'] );
    229235                                }
    230236                        } else {
    231237                                $redirect_url = get_attachment_link();
     238                                $redirect_obj = get_post();
    232239                        }
    233240                } elseif ( is_single() && ! empty( $_GET['p'] ) && ! $redirect_url ) {
    234241                        $redirect_url = get_permalink( get_query_var( 'p' ) );
     242                        $redirect_obj = get_post( get_query_var( 'p' ) );
    235243
    236244                        if ( $redirect_url ) {
    237245                                $redirect['query'] = remove_query_arg( array( 'p', 'post_type' ), $redirect['query'] );
    238246                        }
    239247                } elseif ( is_single() && ! empty( $_GET['name'] ) && ! $redirect_url ) {
    240248                        $redirect_url = get_permalink( $wp_query->get_queried_object_id() );
     249                        $redirect_obj = get_post( $wp_query->get_queried_object_id() );
    241250
    242251                        if ( $redirect_url ) {
    243252                                $redirect['query'] = remove_query_arg( 'name', $redirect['query'] );
    244253                        }
    245254                } elseif ( is_page() && ! empty( $_GET['page_id'] ) && ! $redirect_url ) {
    246255                        $redirect_url = get_permalink( get_query_var( 'page_id' ) );
     256                        $redirect_obj = get_post( get_query_var( 'page_id' ) );
    247257
    248258                        if ( $redirect_url ) {
    249259                                $redirect['query'] = remove_query_arg( 'page_id', $redirect['query'] );
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    256266                        && 'page' === get_option( 'show_on_front' ) && get_query_var( 'page_id' ) === (int) get_option( 'page_for_posts' )
    257267                ) {
    258268                        $redirect_url = get_permalink( get_option( 'page_for_posts' ) );
     269                        $redirect_obj = get_post( get_option( 'page_for_posts' ) );
    259270
    260271                        if ( $redirect_url ) {
    261272                                $redirect['query'] = remove_query_arg( 'page_id', $redirect['query'] );
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    310321                                && $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE $wpdb->posts.post_author = %d AND $wpdb->posts.post_status = 'publish' LIMIT 1", $author->ID ) )
    311322                        ) {
    312323                                $redirect_url = get_author_posts_url( $author->ID, $author->user_nicename );
     324                                $redirect_obj = $author;
    313325
    314326                                if ( $redirect_url ) {
    315327                                        $redirect['query'] = remove_query_arg( 'author', $redirect['query'] );
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    385397                                        || ! has_term( $category->term_id, 'category', $wp_query->get_queried_object_id() )
    386398                                ) {
    387399                                        $redirect_url = get_permalink( $wp_query->get_queried_object_id() );
     400                                        $redirect_obj = get_post( $wp_query->get_queried_object_id() );
    388401                                }
    389402                        }
    390403                }
    function redirect_canonical( $requested_url = null, $do_redirect = true ) { 
    395408
    396409                        if ( ! $redirect_url ) {
    397410                                $redirect_url = get_permalink( get_queried_object_id() );
     411                                $redirect_obj = get_post( get_queried_object_id() );
    398412                        }
    399413
    400414                        if ( $page > 1 ) {
    function lowercase_octets( $matches ) { 
    740754                $requested_url = preg_replace_callback( '|%[a-fA-F0-9][a-fA-F0-9]|', 'lowercase_octets', $requested_url );
    741755        }
    742756
     757        if ( $redirect_obj instanceof WP_Post ) {
     758                $post_status_obj = get_post_status_object( get_post_status( $redirect_obj ) );
     759                /*
     760                 * Unset the redirect object and URL if they are not readable by the user.
     761                 * This condition is a little confusing as the condition needs to pass if
     762                 * the post is not readable by the user. That's why there are ! (not) conditions
     763                 * throughout.
     764                 */
     765                if (
     766                        // Private post statuses only redirect if the user can read them.
     767                        ! (
     768                                $post_status_obj->private &&
     769                                current_user_can( 'read_post', $redirect_obj->ID )
     770                        ) &&
     771                        // For other posts, only redirect if publicly viewable.
     772                        ! is_post_publicly_viewable( $redirect_obj )
     773                ) {
     774                        $redirect_obj = false;
     775                        $redirect_url = false;
     776                }
     777        }
     778
    743779        /**
    744780         * Filters the canonical redirect URL.
    745781         *
  • src/wp-includes/capabilities.php

    diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php
    index ac976ff15c..744ea44421 100644
    a b function map_meta_cap( $cap, $user_id, ...$args ) { 
    245245                                break;
    246246                        }
    247247
    248                         $status_obj = get_post_status_object( $post->post_status );
     248                        $status_obj = get_post_status_object( get_post_status( $post ) );
    249249                        if ( ! $status_obj ) {
    250250                                /* translators: 1: Post status, 2: Capability name. */
    251                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post status %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post with that status.' ), $post->post_status, $cap ), '5.4.0' );
     251                                _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post status %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post with that status.' ), get_post_status( $post ), $cap ), '5.4.0' );
    252252                                $caps[] = 'edit_others_posts';
    253253                                break;
    254254                        }
  • src/wp-includes/link-template.php

    diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php
    index 28e6f98ec7..83e7f607be 100644
    a b function permalink_anchor( $mode = 'id' ) { 
    8989        }
    9090}
    9191
     92/**
     93 * Determine whether post should always use an ugly permalink structure.
     94 *
     95 * @since 5.7.0
     96 *
     97 * @param WP_Post|int|null $post   Optional. Post ID or post object. Defaults to global $post.
     98 * @param bool|null        $sample Optional. Whether to force consideration based on sample links.
     99 *                                 If omitted, a sample link is generated if a post object is passed
     100 *                                 with the filter property set to 'sample'.
     101 * @return bool Whether to use an ugly permalink structure.
     102 */
     103function wp_force_ugly_post_permalink( $post = null, $sample = null ) {
     104        if (
     105                null === $sample &&
     106                is_object( $post ) &&
     107                isset( $post->filter ) &&
     108                'sample' === $post->filter
     109        ) {
     110                $sample = true;
     111        } else {
     112                $post   = get_post( $post );
     113                $sample = null !== $sample ? $sample : false;
     114        }
     115
     116        if ( ! $post ) {
     117                return true;
     118        }
     119
     120        $post_status_obj = get_post_status_object( get_post_status( $post ) );
     121        $post_type_obj   = get_post_type_object( get_post_type( $post ) );
     122
     123        if ( ! $post_status_obj || ! $post_type_obj ) {
     124                return true;
     125        }
     126
     127        if (
     128                // Publicly viewable links never have ugly permalinks.
     129                is_post_status_viewable( $post_status_obj ) ||
     130                (
     131                        // Private posts don't have ugly links if the user can read them.
     132                        $post_status_obj->private &&
     133                        current_user_can( 'read_post', $post->ID )
     134                ) ||
     135                // Protected posts don't have ugly links if getting a sample URL.
     136                ( $post_status_obj->protected && $sample )
     137        ) {
     138                return false;
     139        }
     140
     141        return true;
     142}
     143
    92144/**
    93145 * Retrieves the full permalink for the current post or post ID.
    94146 *
    function get_permalink( $post = 0, $leavename = false ) { 
    166218
    167219        if (
    168220                $permalink &&
    169                 ! in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future', 'trash' ), true )
     221                ! wp_force_ugly_post_permalink( $post )
    170222        ) {
    171223
    172224                $category = '';
    function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { 
    277329
    278330        $slug = $post->post_name;
    279331
    280         $draft_or_pending = get_post_status( $post ) && in_array( get_post_status( $post ), array( 'draft', 'pending', 'auto-draft', 'future' ), true );
     332        $force_ugly_link = wp_force_ugly_post_permalink( $post );
    281333
    282334        $post_type = get_post_type_object( $post->post_type );
    283335
    function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { 
    285337                $slug = get_page_uri( $post );
    286338        }
    287339
    288         if ( ! empty( $post_link ) && ( ! $draft_or_pending || $sample ) ) {
     340        if ( ! empty( $post_link ) && ( ! $force_ugly_link || $sample ) ) {
    289341                if ( ! $leavename ) {
    290342                        $post_link = str_replace( "%$post->post_type%", $slug, $post_link );
    291343                }
    292344                $post_link = home_url( user_trailingslashit( $post_link ) );
    293345        } else {
    294                 if ( $post_type->query_var && ( isset( $post->post_status ) && ! $draft_or_pending ) ) {
     346                if ( $post_type->query_var && ( isset( $post->post_status ) && ! $force_ugly_link ) ) {
    295347                        $post_link = add_query_arg( $post_type->query_var, $slug, '' );
    296348                } else {
    297349                        $post_link = add_query_arg(
    function _get_page_link( $post = false, $leavename = false, $sample = false ) { 
    373425
    374426        $post = get_post( $post );
    375427
    376         $draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ), true );
     428        $force_ugly_link = wp_force_ugly_post_permalink( $post );
    377429
    378430        $link = $wp_rewrite->get_page_permastruct();
    379431
    380         if ( ! empty( $link ) && ( ( isset( $post->post_status ) && ! $draft_or_pending ) || $sample ) ) {
     432        if ( ! empty( $link ) && ( ( isset( $post->post_status ) && ! $force_ugly_link ) || $sample ) ) {
    381433                if ( ! $leavename ) {
    382434                        $link = str_replace( '%pagename%', get_page_uri( $post ), $link );
    383435                }
    function get_attachment_link( $post = null, $leavename = false ) { 
    417469
    418470        $link = false;
    419471
    420         $post   = get_post( $post );
    421         $parent = ( $post->post_parent > 0 && $post->post_parent != $post->ID ) ? get_post( $post->post_parent ) : false;
    422         if ( $parent && ! in_array( $parent->post_type, get_post_types(), true ) ) {
    423                 $parent = false;
     472        $post            = get_post( $post );
     473        $force_ugly_link = wp_force_ugly_post_permalink( $post );
     474        $parent_id       = $post->post_parent;
     475        $parent          = $parent_id ? get_post( $parent_id ) : false;
     476        $parent_valid    = true; // Default for no parent.
     477        if (
     478                $parent_id &&
     479                (
     480                        $post->post_parent === $post->ID ||
     481                        ! $parent ||
     482                        ! is_post_type_viewable( get_post_type( $parent ) )
     483                )
     484        ) {
     485                // Post is either its own parent or parent post unavailable.
     486                $parent_valid = false;
    424487        }
    425488
    426         if ( $wp_rewrite->using_permalinks() && $parent ) {
     489        if ( $force_ugly_link || ! $parent_valid ) {
     490                $link = false;
     491        } elseif ( $wp_rewrite->using_permalinks() && $parent ) {
    427492                if ( 'page' === $parent->post_type ) {
    428493                        $parentlink = _get_page_link( $post->post_parent ); // Ignores page_on_front.
    429494                } else {
  • new file tests/phpunit/tests/canonical/postStatus.php

    diff --git a/tests/phpunit/tests/canonical/postStatus.php b/tests/phpunit/tests/canonical/postStatus.php
    new file mode 100644
    index 0000000000..e189a72f1c
    - +  
     1<?php
     2
     3/**
     4 * @group canonical
     5 * @group rewrite
     6 * @group query
     7 */
     8class Tests_Canonical_PostStatus extends WP_Canonical_UnitTestCase {
     9
     10        /**
     11         * User IDs.
     12         *
     13         * @var array
     14         */
     15        public static $users;
     16
     17        /**
     18         * Post Objects.
     19         *
     20         * @var array
     21         */
     22        public static $posts;
     23
     24        public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
     25                self::setup_custom_types();
     26                self::$users = array(
     27                        'anon'           => 0,
     28                        'subscriber'     => $factory->user->create( array( 'role' => 'subscriber' ) ),
     29                        'content_author' => $factory->user->create( array( 'role' => 'author' ) ),
     30                        'editor'         => $factory->user->create( array( 'role' => 'editor' ) ),
     31                );
     32
     33                $post_statuses = array( 'publish', 'future', 'draft', 'pending', 'private', 'auto-draft', 'a-private-status' );
     34                foreach ( $post_statuses as $post_status ) {
     35                        $post_date = '';
     36                        if ( 'future' === $post_status ) {
     37                                $post_date = strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 year' ) );
     38                        }
     39
     40                        self::$posts[ $post_status ] = $factory->post->create_and_get(
     41                                array(
     42                                        'post_type'    => 'post',
     43                                        'post_title'   => "$post_status post",
     44                                        'post_name'    => "$post_status-post",
     45                                        'post_status'  => $post_status,
     46                                        'post_content' => "Prevent canonical redirect exposing post slugs.\n\n<!--nextpage-->Page 2",
     47                                        'post_author'  => self::$users['content_author'],
     48                                        'post_date'    => $post_date,
     49                                )
     50                        );
     51
     52                        // Add fake attachment to the post (file upload not needed).
     53                        self::$posts[ "$post_status-attachment" ] = $factory->post->create_and_get(
     54                                array(
     55                                        'post_type'    => 'attachment',
     56                                        'post_title'   => "$post_status inherited attachment",
     57                                        'post_name'    => "$post_status-inherited-attachment",
     58                                        'post_status'  => 'inherit',
     59                                        'post_content' => "Prevent canonical redirect exposing post via attachments.\n\n<!--nextpage-->Page 2",
     60                                        'post_author'  => self::$users['content_author'],
     61                                        'post_parent'  => self::$posts[ $post_status ]->ID,
     62                                        'post_date'    => $post_date,
     63                                )
     64                        );
     65
     66                        // Set up a page with same.
     67                        self::$posts[ "$post_status-page" ] = $factory->post->create_and_get(
     68                                array(
     69                                        'post_type'    => 'page',
     70                                        'post_title'   => "$post_status page",
     71                                        'post_name'    => "$post_status-page",
     72                                        'post_status'  => $post_status,
     73                                        'post_content' => "Prevent canonical redirect exposing page slugs.\n\n<!--nextpage-->Page 2",
     74                                        'post_author'  => self::$users['content_author'],
     75                                        'post_date'    => $post_date,
     76                                )
     77                        );
     78                }
     79
     80                // Create a public CPT using a private status.
     81                self::$posts['a-public-cpt'] = $factory->post->create_and_get(
     82                        array(
     83                                'post_type'    => 'a-public-cpt',
     84                                'post_title'   => 'a-public-cpt',
     85                                'post_name'    => 'a-public-cpt',
     86                                'post_status'  => 'private',
     87                                'post_content' => 'Prevent canonical redirect exposing a-public-cpt titles.',
     88                                'post_author'  => self::$users['content_author'],
     89                        )
     90                );
     91
     92                // Add fake attachment to the public cpt (file upload not needed).
     93                self::$posts['a-public-cpt-attachment'] = $factory->post->create_and_get(
     94                        array(
     95                                'post_type'    => 'attachment',
     96                                'post_title'   => 'a-public-cpt post inherited attachment',
     97                                'post_name'    => 'a-public-cpt-inherited-attachment',
     98                                'post_status'  => 'inherit',
     99                                'post_content' => "Prevent canonical redirect exposing post via attachments.\n\n<!--nextpage-->Page 2",
     100                                'post_author'  => self::$users['content_author'],
     101                                'post_parent'  => self::$posts['a-public-cpt']->ID,
     102                        )
     103                );
     104
     105                // Create a private CPT with a public status.
     106                self::$posts['a-private-cpt'] = $factory->post->create_and_get(
     107                        array(
     108                                'post_type'    => 'a-private-cpt',
     109                                'post_title'   => 'a-private-cpt',
     110                                'post_name'    => 'a-private-cpt',
     111                                'post_status'  => 'publish',
     112                                'post_content' => 'Prevent canonical redirect exposing a-private-cpt titles.',
     113                                'post_author'  => self::$users['content_author'],
     114                        )
     115                );
     116
     117                // Add fake attachment to the private cpt (file upload not needed).
     118                self::$posts['a-private-cpt-attachment'] = $factory->post->create_and_get(
     119                        array(
     120                                'post_type'    => 'attachment',
     121                                'post_title'   => 'a-private-cpt post inherited attachment',
     122                                'post_name'    => 'a-private-cpt-inherited-attachment',
     123                                'post_status'  => 'inherit',
     124                                'post_content' => "Prevent canonical redirect exposing post via attachments.\n\n<!--nextpage-->Page 2",
     125                                'post_author'  => self::$users['content_author'],
     126                                'post_parent'  => self::$posts['a-private-cpt']->ID,
     127                        )
     128                );
     129
     130                // Post for trashing.
     131                self::$posts['trash'] = $factory->post->create_and_get(
     132                        array(
     133                                'post_type'    => 'post',
     134                                'post_title'   => 'trash post',
     135                                'post_name'    => 'trash-post',
     136                                'post_status'  => 'publish',
     137                                'post_content' => "Prevent canonical redirect exposing post slugs.\n\n<!--nextpage-->Page 2",
     138                                'post_author'  => self::$users['content_author'],
     139                        )
     140                );
     141
     142                self::$posts['trash-attachment'] = $factory->post->create_and_get(
     143                        array(
     144                                'post_type'    => 'attachment',
     145                                'post_title'   => 'trash post inherited attachment',
     146                                'post_name'    => 'trash-post-inherited-attachment',
     147                                'post_status'  => 'inherit',
     148                                'post_content' => "Prevent canonical redirect exposing post via attachments.\n\n<!--nextpage-->Page 2",
     149                                'post_author'  => self::$users['content_author'],
     150                                'post_parent'  => self::$posts['trash']->ID,
     151                        )
     152                );
     153
     154                // Page for trashing.
     155                self::$posts['trash-page'] = $factory->post->create_and_get(
     156                        array(
     157                                'post_type'    => 'page',
     158                                'post_title'   => 'trash page',
     159                                'post_name'    => 'trash-page',
     160                                'post_status'  => 'publish',
     161                                'post_content' => "Prevent canonical redirect exposing page slugs.\n\n<!--nextpage-->Page 2",
     162                                'post_author'  => self::$users['content_author'],
     163                        )
     164                );
     165                wp_trash_post( self::$posts['trash']->ID );
     166                wp_trash_post( self::$posts['trash-page']->ID );
     167        }
     168
     169        function setUp() {
     170                parent::setUp();
     171                self::setup_custom_types();
     172        }
     173
     174        /**
     175         * Set up a custom post type and private status.
     176         *
     177         * This needs to be called both in the class setup and
     178         * test setup.
     179         */
     180        public static function setup_custom_types() {
     181                // Register public custom post type.
     182                register_post_type(
     183                        'a-public-cpt',
     184                        array(
     185                                'public'  => true,
     186                                'rewrite' => array(
     187                                        'slug' => 'a-public-cpt',
     188                                ),
     189                        )
     190                );
     191
     192                // Register private custom post type.
     193                register_post_type(
     194                        'a-private-cpt',
     195                        array(
     196                                'public'             => false,
     197                                'publicly_queryable' => false,
     198                                'rewrite'            => array(
     199                                        'slug' => 'a-private-cpt',
     200                                ),
     201                                'map_meta_cap'       => true,
     202                        )
     203                );
     204
     205                // Register custom private post status.
     206                register_post_status(
     207                        'a-private-status',
     208                        array(
     209                                'private' => true,
     210                        )
     211                );
     212        }
     213
     214        /**
     215         * Test canonical redirect does not reveal private posts presence.
     216         *
     217         * @ticket 5272
     218         * @dataProvider data_canonical_redirects_to_ugly_permalinks
     219         *
     220         * @param string $post_key  Post key used for creating fixtures.
     221         * @param string $user_role User role.
     222         * @param string $requested Requested URL.
     223         * @param string $expected  Expected URL.
     224         */
     225        public function test_canonical_redirects_to_ugly_permalinks( $post_key, $user_role, $requested, $expected ) {
     226                wp_set_current_user( self::$users[ $user_role ] );
     227                $this->set_permalink_structure( '' );
     228                $post = self::$posts[ $post_key ];
     229                clean_post_cache( $post->ID );
     230
     231                /*
     232                 * The dataProvider runs before the fixures are set up, therefore the
     233                 * post object IDs are placeholders that needs to be replaced.
     234                 */
     235                $requested = str_replace( '%ID%', $post->ID, $requested );
     236                $expected  = str_replace( '%ID%', $post->ID, $expected );
     237
     238                $this->assertCanonical( $requested, $expected );
     239        }
     240
     241        /**
     242         * Data provider for test_canonical_redirects_to_ugly_permalinks.
     243         *
     244         * @return array[] Array of arguments for tests {
     245         *     @type string $post_key  Post key used for creating fixtures.
     246         *     @type string $user_role User role.
     247         *     @type string $requested Requested URL.
     248         *     @type string $expected  Expected URL.
     249         * }
     250         */
     251        function data_canonical_redirects_to_ugly_permalinks() {
     252                $data              = array();
     253                $all_user_list     = array( 'anon', 'subscriber', 'content_author', 'editor' );
     254                $select_allow_list = array( 'content_author', 'editor' );
     255                $select_block_list = array( 'anon', 'subscriber' );
     256                // All post/page keys
     257                $all_user_post_status_keys    = array( 'publish' );
     258                $select_user_post_status_keys = array( 'private', 'a-private-status' );
     259                $no_user_post_status_keys     = array( 'future', 'draft', 'pending', 'auto-draft' ); // Excludes trash for attachment rules.
     260                $select_user_post_type_keys   = array( 'a-public-cpt' );
     261                $no_user_post_type_keys       = array( 'a-private-cpt' );
     262
     263                foreach ( $all_user_post_status_keys as $post_key ) {
     264                        foreach ( $all_user_list as $user ) {
     265                                /*
     266                                 * In the event `redirect_canonical()` is updated to redirect ugly permalinks
     267                                 * to a canonical ugly version, these expected values can be changed.
     268                                 */
     269                                $data[] = array(
     270                                        "$post_key-page",
     271                                        $user,
     272                                        '/?post_type=page&p=%ID%',
     273                                        '/?post_type=page&p=%ID%',
     274                                );
     275
     276                                $data[] = array(
     277                                        $post_key,
     278                                        $user,
     279                                        "/?name=$post_key-post",
     280                                        "/?name=$post_key-post",
     281                                );
     282
     283                                // Ensure rss redirects to rss2.
     284                                $data[] = array(
     285                                        $post_key,
     286                                        $user,
     287                                        '/?feed=rss&p=%ID%',
     288                                        '/?feed=rss2&p=%ID%',
     289                                );
     290
     291                                // Ensure rss redirects to rss2.
     292                                $data[] = array(
     293                                        "$post_key-page",
     294                                        $user,
     295                                        '/?feed=rss&page_id=%ID%',
     296                                        '/?feed=rss2&page_id=%ID%',
     297                                );
     298                        }
     299                }
     300
     301                foreach ( $select_user_post_status_keys as $post_key ) {
     302                        foreach ( $select_allow_list as $user ) {
     303                                /*
     304                                 * In the event `redirect_canonical()` is updated to redirect ugly permalinks
     305                                 * to a canonical ugly version, these expected values can be changed.
     306                                 */
     307                                $data[] = array(
     308                                        "$post_key-page",
     309                                        $user,
     310                                        '/?post_type=page&p=%ID%',
     311                                        '/?post_type=page&p=%ID%',
     312                                );
     313
     314                                $data[] = array(
     315                                        $post_key,
     316                                        $user,
     317                                        "/?name=$post_key-post",
     318                                        "/?name=$post_key-post",
     319                                );
     320
     321                                // Ensure rss redirects to rss2.
     322                                $data[] = array(
     323                                        $post_key,
     324                                        $user,
     325                                        '/?feed=rss&p=%ID%',
     326                                        '/?feed=rss2&p=%ID%',
     327                                );
     328
     329                                // Ensure rss redirects to rss2.
     330                                $data[] = array(
     331                                        "$post_key-page",
     332                                        $user,
     333                                        '/?feed=rss&page_id=%ID%',
     334                                        '/?feed=rss2&page_id=%ID%',
     335                                );
     336                        }
     337
     338                        foreach ( $select_block_list as $user ) {
     339                                /*
     340                                 * In the event `redirect_canonical()` is updated to redirect ugly permalinks
     341                                 * to a canonical ugly version, these expected values MUST NOT be changed.
     342                                 */
     343                                $data[] = array(
     344                                        "$post_key-page",
     345                                        $user,
     346                                        '/?post_type=page&p=%ID%',
     347                                        '/?post_type=page&p=%ID%',
     348                                );
     349
     350                                $data[] = array(
     351                                        $post_key,
     352                                        $user,
     353                                        "/?name=$post_key-post",
     354                                        "/?name=$post_key-post",
     355                                );
     356
     357                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     358                                $data[] = array(
     359                                        $post_key,
     360                                        $user,
     361                                        '/?feed=rss&p=%ID%',
     362                                        '/?feed=rss&p=%ID%',
     363                                );
     364
     365                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     366                                $data[] = array(
     367                                        "$post_key-page",
     368                                        $user,
     369                                        '/?feed=rss&page_id=%ID%',
     370                                        '/?feed=rss&page_id=%ID%',
     371                                );
     372                        }
     373                }
     374
     375                foreach ( $no_user_post_status_keys as $post_key ) {
     376                        foreach ( $all_user_list as $user ) {
     377                                /*
     378                                 * In the event `redirect_canonical()` is updated to redirect ugly permalinks
     379                                 * to a canonical ugly version, these expected values MUST NOT be changed.
     380                                 */
     381                                $data[] = array(
     382                                        "$post_key-page",
     383                                        $user,
     384                                        '/?post_type=page&p=%ID%',
     385                                        '/?post_type=page&p=%ID%',
     386                                );
     387
     388                                $data[] = array(
     389                                        $post_key,
     390                                        $user,
     391                                        "/?name=$post_key-post",
     392                                        "/?name=$post_key-post",
     393                                );
     394
     395                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     396                                $data[] = array(
     397                                        $post_key,
     398                                        $user,
     399                                        '/?feed=rss&p=%ID%',
     400                                        '/?feed=rss&p=%ID%',
     401                                );
     402
     403                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     404                                $data[] = array(
     405                                        "$post_key-page",
     406                                        $user,
     407                                        '/?feed=rss&page_id=%ID%',
     408                                        '/?feed=rss&page_id=%ID%',
     409                                );
     410                        }
     411                }
     412
     413                foreach ( array( 'trash' ) as $post_key ) {
     414                        foreach ( $all_user_list as $user ) {
     415                                /*
     416                                 * In the event `redirect_canonical()` is updated to redirect ugly permalinks
     417                                 * to a canonical ugly version, these expected values MUST NOT be changed.
     418                                 */
     419                                $data[] = array(
     420                                        "$post_key-page",
     421                                        $user,
     422                                        '/?post_type=page&p=%ID%',
     423                                        '/?post_type=page&p=%ID%',
     424                                );
     425
     426                                $data[] = array(
     427                                        $post_key,
     428                                        $user,
     429                                        "/?name=$post_key-post",
     430                                        "/?name=$post_key-post",
     431                                );
     432
     433                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     434                                $data[] = array(
     435                                        $post_key,
     436                                        $user,
     437                                        '/?feed=rss&p=%ID%',
     438                                        '/?feed=rss&p=%ID%',
     439                                );
     440
     441                                // Ensure post's existence is not demonstrated by changing rss to rss2.
     442                                $data[] = array(
     443                                        "$post_key-page",
     444                                        $user,
     445                                        '/?feed=rss&page_id=%ID%',
     446                                        '/?feed=rss&page_id=%ID%',
     447                                );
     448                        }
     449                }
     450
     451                foreach ( $select_user_post_type_keys as $post_key ) {
     452                        foreach ( $select_allow_list as $user ) {
     453                                $data[] = array(
     454                                        $post_key,
     455                                        $user,
     456                                        '/?p=%ID%',
     457                                        '/?a-public-cpt=a-public-cpt',
     458                                );
     459
     460                                $data[] = array(
     461                                        "$post_key-attachment",
     462                                        $user,
     463                                        '/?attachment_id=%ID%',
     464                                        '/?attachment_id=%ID%',
     465                                );
     466
     467                                $data[] = array(
     468                                        $post_key,
     469                                        $user,
     470                                        "/?name=$post_key&post_type=$post_key",
     471                                        "/?name=$post_key&post_type=$post_key",
     472                                );
     473
     474                                // Ensure rss is replaced by rss2.
     475                                $data[] = array(
     476                                        $post_key,
     477                                        $user,
     478                                        '/?feed=rss&p=%ID%',
     479                                        '/?a-public-cpt=a-public-cpt&feed=rss2',
     480                                );
     481                        }
     482
     483                        foreach ( $select_block_list as $user ) {
     484                                $data[] = array(
     485                                        $post_key,
     486                                        $user,
     487                                        '/?p=%ID%',
     488                                        '/?p=%ID%',
     489                                );
     490
     491                                $data[] = array(
     492                                        "$post_key-attachment",
     493                                        $user,
     494                                        '/?attachment_id=%ID%',
     495                                        '/?attachment_id=%ID%',
     496                                );
     497
     498                                $data[] = array(
     499                                        $post_key,
     500                                        $user,
     501                                        "/?name=$post_key&post_type=$post_key",
     502                                        "/?name=$post_key&post_type=$post_key",
     503                                );
     504
     505                                // Ensure rss is not replaced with rss2.
     506                                $data[] = array(
     507                                        $post_key,
     508                                        $user,
     509                                        '/?feed=rss&p=%ID%',
     510                                        '/?feed=rss&p=%ID%',
     511                                );
     512                        }
     513                }
     514
     515                foreach ( $no_user_post_type_keys as $post_key ) {
     516                        foreach ( $all_user_list as $user ) {
     517                                $data[] = array(
     518                                        $post_key,
     519                                        $user,
     520                                        '/?p=%ID%',
     521                                        '/?p=%ID%',
     522                                );
     523
     524                                $data[] = array(
     525                                        "$post_key-attachment",
     526                                        $user,
     527                                        '/?attachment_id=%ID%',
     528                                        '/?attachment_id=%ID%',
     529                                );
     530
     531                                $data[] = array(
     532                                        $post_key,
     533                                        $user,
     534                                        "/?name=$post_key&post_type=$post_key",
     535                                        "/?name=$post_key&post_type=$post_key",
     536                                );
     537
     538                                $data[] = array(
     539                                        $post_key,
     540                                        $user,
     541                                        '/?feed=rss&p=%ID%',
     542                                        '/?feed=rss&p=%ID%',
     543                                );
     544                        }
     545                }
     546
     547                return $data;
     548        }
     549
     550        /**
     551         * Test canonical redirect does not reveal private slugs.
     552         *
     553         * @ticket 5272
     554         * @dataProvider data_canonical_redirects_to_pretty_permalinks
     555         *
     556         * @param string $post_key  Post key used for creating fixtures.
     557         * @param string $user_role User role.
     558         * @param string $requested Requested URL.
     559         * @param string $expected  Expected URL.
     560         */
     561        public function test_canonical_redirects_to_pretty_permalinks( $post_key, $user_role, $requested, $expected ) {
     562                wp_set_current_user( self::$users[ $user_role ] );
     563                $this->set_permalink_structure( '/%postname%/' );
     564                $post = self::$posts[ $post_key ];
     565                clean_post_cache( $post->ID );
     566
     567                /*
     568                 * The dataProvider runs before the fixures are set up, therefore the
     569                 * post object IDs are placeholders that needs to be replaced.
     570                 */
     571                $requested = str_replace( '%ID%', $post->ID, $requested );
     572                $expected  = str_replace( '%ID%', $post->ID, $expected );
     573
     574                $this->assertCanonical( $requested, $expected );
     575        }
     576
     577        /**
     578         * Data provider for test_canonical_redirects_to_pretty_permalinks.
     579         *
     580         * @return array[] Array of arguments for tests {
     581         *     @type string $post_key  Post key used for creating fixtures.
     582         *     @type string $user_role User role.
     583         *     @type string $requested Requested URL.
     584         *     @type string $expected  Expected URL.
     585         * }
     586         */
     587        function data_canonical_redirects_to_pretty_permalinks() {
     588                $data              = array();
     589                $all_user_list     = array( 'anon', 'subscriber', 'content_author', 'editor' );
     590                $select_allow_list = array( 'content_author', 'editor' );
     591                $select_block_list = array( 'anon', 'subscriber' );
     592                // All post/page keys
     593                $all_user_post_status_keys    = array( 'publish' );
     594                $select_user_post_status_keys = array( 'private', 'a-private-status' );
     595                $no_user_post_status_keys     = array( 'future', 'draft', 'pending', 'auto-draft' ); // Excludes trash for attachment rules.
     596                $select_user_post_type_keys   = array( 'a-public-cpt' );
     597                $no_user_post_type_keys       = array( 'a-private-cpt' );
     598
     599                foreach ( $all_user_post_status_keys as $post_key ) {
     600                        foreach ( $all_user_list as $user ) {
     601                                $data[] = array(
     602                                        $post_key,
     603                                        $user,
     604                                        '/?p=%ID%',
     605                                        "/$post_key-post/",
     606                                );
     607
     608                                $data[] = array(
     609                                        "$post_key-attachment",
     610                                        $user,
     611                                        '/?attachment_id=%ID%',
     612                                        "/$post_key-post/$post_key-inherited-attachment/",
     613                                );
     614
     615                                $data[] = array(
     616                                        "$post_key-page",
     617                                        $user,
     618                                        '/?post_type=page&p=%ID%',
     619                                        "/$post_key-page/",
     620                                );
     621
     622                                $data[] = array(
     623                                        "$post_key-page",
     624                                        $user,
     625                                        '/?page_id=%ID%',
     626                                        "/$post_key-page/",
     627                                );
     628
     629                                $data[] = array(
     630                                        $post_key,
     631                                        $user,
     632                                        "/?name=$post_key-post",
     633                                        "/$post_key-post/",
     634                                );
     635
     636                                $data[] = array(
     637                                        $post_key,
     638                                        $user,
     639                                        '/?feed=rss&p=%ID%',
     640                                        "/$post_key-post/feed/",
     641                                );
     642
     643                                $data[] = array(
     644                                        "$post_key-page",
     645                                        $user,
     646                                        '/?feed=rss&page_id=%ID%',
     647                                        "/$post_key-page/feed/",
     648                                );
     649                        }
     650                }
     651
     652                foreach ( $select_user_post_status_keys as $post_key ) {
     653                        foreach ( $select_allow_list as $user ) {
     654                                $data[] = array(
     655                                        $post_key,
     656                                        $user,
     657                                        '/?p=%ID%',
     658                                        "/$post_key-post/",
     659                                );
     660
     661                                $data[] = array(
     662                                        "$post_key-attachment",
     663                                        $user,
     664                                        '/?attachment_id=%ID%',
     665                                        "/$post_key-post/$post_key-inherited-attachment/",
     666                                );
     667
     668                                $data[] = array(
     669                                        "$post_key-page",
     670                                        $user,
     671                                        '/?post_type=page&p=%ID%',
     672                                        "/$post_key-page/",
     673                                );
     674
     675                                $data[] = array(
     676                                        "$post_key-page",
     677                                        $user,
     678                                        '/?page_id=%ID%',
     679                                        "/$post_key-page/",
     680                                );
     681
     682                                $data[] = array(
     683                                        $post_key,
     684                                        $user,
     685                                        "/?name=$post_key-post",
     686                                        "/$post_key-post/",
     687                                );
     688
     689                                $data[] = array(
     690                                        $post_key,
     691                                        $user,
     692                                        '/?feed=rss&p=%ID%',
     693                                        "/$post_key-post/feed/",
     694                                );
     695
     696                                $data[] = array(
     697                                        "$post_key-page",
     698                                        $user,
     699                                        '/?feed=rss&page_id=%ID%',
     700                                        "/$post_key-page/feed/",
     701                                );
     702                        }
     703
     704                        foreach ( $select_block_list as $user ) {
     705                                $data[] = array(
     706                                        $post_key,
     707                                        $user,
     708                                        '/?p=%ID%',
     709                                        '/?p=%ID%',
     710                                );
     711
     712                                $data[] = array(
     713                                        "$post_key-attachment",
     714                                        $user,
     715                                        '/?attachment_id=%ID%',
     716                                        '/?attachment_id=%ID%',
     717                                );
     718
     719                                $data[] = array(
     720                                        "$post_key-page",
     721                                        $user,
     722                                        '/?post_type=page&p=%ID%',
     723                                        '/?post_type=page&p=%ID%',
     724                                );
     725
     726                                $data[] = array(
     727                                        "$post_key-page",
     728                                        $user,
     729                                        '/?page_id=%ID%',
     730                                        '/?page_id=%ID%',
     731                                );
     732
     733                                $data[] = array(
     734                                        $post_key,
     735                                        $user,
     736                                        "/?name=$post_key-post",
     737                                        "/?name=$post_key-post",
     738                                );
     739
     740                                $data[] = array(
     741                                        $post_key,
     742                                        $user,
     743                                        '/?feed=rss&p=%ID%',
     744                                        '/?feed=rss&p=%ID%',
     745                                );
     746
     747                                $data[] = array(
     748                                        "$post_key-page",
     749                                        $user,
     750                                        '/?feed=rss&page_id=%ID%',
     751                                        '/?feed=rss&page_id=%ID%',
     752                                );
     753                        }
     754                }
     755
     756                foreach ( $select_user_post_type_keys as $post_key ) {
     757                        foreach ( $select_allow_list as $user ) {
     758                                $data[] = array(
     759                                        $post_key,
     760                                        $user,
     761                                        '/?p=%ID%',
     762                                        "/$post_key/$post_key/",
     763                                );
     764
     765                                $data[] = array(
     766                                        "$post_key-attachment",
     767                                        $user,
     768                                        '/?attachment_id=%ID%',
     769                                        "/$post_key/$post_key/$post_key-inherited-attachment/",
     770                                );
     771
     772                                $data[] = array(
     773                                        $post_key,
     774                                        $user,
     775                                        "/?name=$post_key&post_type=$post_key",
     776                                        "/$post_key/$post_key/?post_type=$post_key",
     777                                );
     778
     779                                $data[] = array(
     780                                        $post_key,
     781                                        $user,
     782                                        '/?feed=rss&p=%ID%',
     783                                        "/$post_key/$post_key/feed/",
     784                                );
     785                        }
     786
     787                        foreach ( $select_block_list as $user ) {
     788                                $data[] = array(
     789                                        $post_key,
     790                                        $user,
     791                                        '/?p=%ID%',
     792                                        '/?p=%ID%',
     793                                );
     794
     795                                $data[] = array(
     796                                        "$post_key-attachment",
     797                                        $user,
     798                                        '/?attachment_id=%ID%',
     799                                        '/?attachment_id=%ID%',
     800                                );
     801
     802                                $data[] = array(
     803                                        $post_key,
     804                                        $user,
     805                                        "/?name=$post_key&post_type=$post_key",
     806                                        "/?name=$post_key&post_type=$post_key",
     807                                );
     808
     809                                $data[] = array(
     810                                        $post_key,
     811                                        $user,
     812                                        '/?feed=rss&p=%ID%',
     813                                        '/?feed=rss&p=%ID%',
     814                                );
     815                        }
     816                }
     817
     818                foreach ( $no_user_post_type_keys as $post_key ) {
     819                        foreach ( $all_user_list as $user ) {
     820                                $data[] = array(
     821                                        $post_key,
     822                                        $user,
     823                                        '/?p=%ID%',
     824                                        '/?p=%ID%',
     825                                );
     826
     827                                $data[] = array(
     828                                        "$post_key-attachment",
     829                                        $user,
     830                                        '/?attachment_id=%ID%',
     831                                        '/?attachment_id=%ID%',
     832                                        // "/$post_key-inherited-attachment/",
     833                                );
     834
     835                                $data[] = array(
     836                                        $post_key,
     837                                        $user,
     838                                        "/?name=$post_key&post_type=$post_key",
     839                                        "/?name=$post_key&post_type=$post_key",
     840                                );
     841
     842                                $data[] = array(
     843                                        $post_key,
     844                                        $user,
     845                                        '/?feed=rss&p=%ID%',
     846                                        '/?feed=rss&p=%ID%',
     847                                );
     848                        }
     849                }
     850
     851                foreach ( $no_user_post_status_keys as $post_key ) {
     852                        foreach ( $all_user_list as $user ) {
     853                                $data[] = array(
     854                                        $post_key,
     855                                        $user,
     856                                        '/?p=%ID%',
     857                                        '/?p=%ID%',
     858                                );
     859
     860                                $data[] = array(
     861                                        "$post_key-attachment",
     862                                        $user,
     863                                        '/?attachment_id=%ID%',
     864                                        '/?attachment_id=%ID%',
     865                                );
     866
     867                                $data[] = array(
     868                                        "$post_key-page",
     869                                        $user,
     870                                        '/?post_type=page&p=%ID%',
     871                                        '/?post_type=page&p=%ID%',
     872                                );
     873
     874                                $data[] = array(
     875                                        "$post_key-page",
     876                                        $user,
     877                                        '/?page_id=%ID%',
     878                                        '/?page_id=%ID%',
     879                                );
     880
     881                                $data[] = array(
     882                                        $post_key,
     883                                        $user,
     884                                        "/?name=$post_key-post",
     885                                        "/?name=$post_key-post",
     886                                );
     887
     888                                $data[] = array(
     889                                        $post_key,
     890                                        $user,
     891                                        '/?feed=rss&p=%ID%',
     892                                        '/?feed=rss&p=%ID%',
     893                                );
     894
     895                                $data[] = array(
     896                                        "$post_key-page",
     897                                        $user,
     898                                        '/?feed=rss&page_id=%ID%',
     899                                        '/?feed=rss&page_id=%ID%',
     900                                );
     901                        }
     902                }
     903
     904                foreach ( array( 'trash' ) as $post_key ) {
     905                        foreach ( $all_user_list as $user ) {
     906                                $data[] = array(
     907                                        $post_key,
     908                                        $user,
     909                                        '/?p=%ID%',
     910                                        '/?p=%ID%',
     911                                );
     912
     913                                $data[] = array(
     914                                        "$post_key-attachment",
     915                                        $user,
     916                                        '/?attachment_id=%ID%',
     917                                        '/?attachment_id=%ID%',
     918                                );
     919
     920                                $data[] = array(
     921                                        "$post_key-attachment",
     922                                        $user,
     923                                        '/trash-post/trash-post-inherited-attachment/',
     924                                        '/?attachment_id=%ID%',
     925                                );
     926
     927                                $data[] = array(
     928                                        "$post_key-attachment",
     929                                        $user,
     930                                        '/trash-post__trashed/trash-post-inherited-attachment/',
     931                                        '/?attachment_id=%ID%',
     932                                );
     933
     934                                $data[] = array(
     935                                        "$post_key-page",
     936                                        $user,
     937                                        '/?post_type=page&p=%ID%',
     938                                        '/?post_type=page&p=%ID%',
     939                                );
     940
     941                                $data[] = array(
     942                                        "$post_key-page",
     943                                        $user,
     944                                        '/?page_id=%ID%',
     945                                        '/?page_id=%ID%',
     946                                );
     947
     948                                $data[] = array(
     949                                        $post_key,
     950                                        $user,
     951                                        "/?name=$post_key-post",
     952                                        "/?name=$post_key-post",
     953                                );
     954
     955                                $data[] = array(
     956                                        $post_key,
     957                                        $user,
     958                                        '/?feed=rss&p=%ID%',
     959                                        '/?feed=rss&p=%ID%',
     960                                );
     961
     962                                $data[] = array(
     963                                        "$post_key-page",
     964                                        $user,
     965                                        '/?feed=rss&page_id=%ID%',
     966                                        '/?feed=rss&page_id=%ID%',
     967                                );
     968                        }
     969                }
     970
     971                return $data;
     972        }
     973}
  • tests/phpunit/tests/link.php

    diff --git a/tests/phpunit/tests/link.php b/tests/phpunit/tests/link.php
    index 62f55fbd7d..9eae2a1401 100644
    a b public function test_attachment_attached_to_non_existent_post_type_has_a_pretty_ 
    204204                        }
    205205                }
    206206
    207                 $this->assertSame( home_url( user_trailingslashit( $attachment->post_name ) ), get_permalink( $attachment_id ) );
     207                $this->assertSame( home_url( "/?attachment_id={$attachment->ID}" ), get_permalink( $attachment_id ) );
     208                // Visit permalink.
     209                $this->go_to( get_permalink( $attachment_id ) );
     210                $this->assertQueryTrue( 'is_attachment', 'is_single', 'is_singular' );
    208211        }
    209212}
  • tests/phpunit/tests/media.php

    diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php
    index e7326fec65..055618f620 100644
    a b function test_gallery_shortcode_when_is_feed_true() { 
    31223122         * @ticket 51776
    31233123         *
    31243124         * @param string $post_key     Post as keyed in the shared fixture array.
    3125          * @param string $expected     Expected result.
     3125         * @param string $expected_url Expected permalink.
    31263126         * @param bool   $expected_404 Whether the page is expected to return a 404 result.
    31273127         *
    31283128         */
    3129         function test_attachment_permalinks_based_on_parent_status( $post_key, $expected, $expected_404 ) {
     3129        function test_attachment_permalinks_based_on_parent_status( $post_key, $expected_url, $expected_404 ) {
    31303130                $this->set_permalink_structure( '/%postname%' );
    31313131                $post = get_post( self::$post_ids[ $post_key ] );
    31323132
    function test_attachment_permalinks_based_on_parent_status( $post_key, $expected 
    31343134                 * The dataProvider runs before the fixures are set up, therefore the
    31353135                 * post object IDs are placeholders that needs to be replaced.
    31363136                 */
    3137                 $expected = home_url( str_replace( '%ID%', $post->ID, $expected ) );
     3137                $expected_url = home_url( str_replace( '%ID%', $post->ID, $expected_url ) );
    31383138
    3139                 $this->assertSame( $expected, get_permalink( $post ) );
    31403139                $this->go_to( get_permalink( $post ) );
    3141                 $this->assertSame( $expected_404, is_404() );
     3140                $this->assertSame( $expected_url, get_permalink( $post ) );
     3141                if ( $expected_404 ) {
     3142                        $this->assertQueryTrue( 'is_404' );
     3143                } else {
     3144                        $this->assertQueryTrue( 'is_attachment', 'is_single', 'is_singular' );
     3145                }
     3146                $this->assertSame( 'attachment', $post->post_type );
    31423147        }
    31433148
    31443149        /**
    function test_attachment_permalinks_based_on_parent_status( $post_key, $expected 
    31463151         *
    31473152         * @return array[] {
    31483153         *     @type string $post_key     Post as keyed in the shared fixture array.
    3149          *     @type string $expected     Expected result.
     3154         *     @type string $expected_url Expected permalink.
    31503155         *     $type bool   $expected_404 Whether the page is expected to return a 404 result.
    31513156         * }
    31523157         */