Ticket #5272: 5272.diff
File 5272.diff, 48.7 KB (added by , 4 years ago) |
---|
-
src/wp-includes/canonical.php
diff --git a/src/wp-includes/canonical.php b/src/wp-includes/canonical.php index 617bcb352d..f7c5caa889 100644
a b function redirect_canonical( $requested_url = null, $do_redirect = true ) { 77 77 78 78 $redirect = $original; 79 79 $redirect_url = false; 80 $redirect_obj = false; 80 81 81 82 // Notice fixing. 82 83 if ( ! isset( $redirect['path'] ) ) { … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 102 103 103 104 if ( is_feed() && $post_id ) { 104 105 $redirect_url = get_post_comments_feed_link( $post_id, get_query_var( 'feed' ) ); 106 $redirect_obj = get_post( $post_id ); 105 107 106 108 if ( $redirect_url ) { 107 109 $redirect['query'] = _remove_qs_args_if_not_in_url( … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 126 128 } 127 129 128 130 $redirect_url = get_permalink( $post_id ); 131 $redirect_obj = get_post( $post_id ); 129 132 130 133 if ( $redirect_url ) { 131 134 $redirect['query'] = _remove_qs_args_if_not_in_url( … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 150 153 151 154 if ( $post_type_obj && $post_type_obj->public && 'auto-draft' !== $redirect_post->post_status ) { 152 155 $redirect_url = get_permalink( $redirect_post ); 156 $redirect_obj = get_post( $redirect_post ); 153 157 154 158 $redirect['query'] = _remove_qs_args_if_not_in_url( 155 159 $redirect['query'], … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 197 201 198 202 if ( $post_id ) { 199 203 $redirect_url = get_permalink( $post_id ); 204 $redirect_obj = get_post( $post_id ); 200 205 201 206 $redirect['path'] = rtrim( $redirect['path'], (int) get_query_var( 'page' ) . '/' ); 202 207 $redirect['query'] = remove_query_arg( 'page', $redirect['query'] ); … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 223 228 ) { 224 229 if ( ! empty( $_GET['attachment_id'] ) ) { 225 230 $redirect_url = get_attachment_link( get_query_var( 'attachment_id' ) ); 231 $redirect_obj = get_post( get_query_var( 'attachment_id' ) ); 226 232 227 233 if ( $redirect_url ) { 228 234 $redirect['query'] = remove_query_arg( 'attachment_id', $redirect['query'] ); 229 235 } 230 236 } else { 231 237 $redirect_url = get_attachment_link(); 238 $redirect_obj = get_post(); 232 239 } 233 240 } elseif ( is_single() && ! empty( $_GET['p'] ) && ! $redirect_url ) { 234 241 $redirect_url = get_permalink( get_query_var( 'p' ) ); 242 $redirect_obj = get_post( get_query_var( 'p' ) ); 235 243 236 244 if ( $redirect_url ) { 237 245 $redirect['query'] = remove_query_arg( array( 'p', 'post_type' ), $redirect['query'] ); 238 246 } 239 247 } elseif ( is_single() && ! empty( $_GET['name'] ) && ! $redirect_url ) { 240 248 $redirect_url = get_permalink( $wp_query->get_queried_object_id() ); 249 $redirect_obj = get_post( $wp_query->get_queried_object_id() ); 241 250 242 251 if ( $redirect_url ) { 243 252 $redirect['query'] = remove_query_arg( 'name', $redirect['query'] ); 244 253 } 245 254 } elseif ( is_page() && ! empty( $_GET['page_id'] ) && ! $redirect_url ) { 246 255 $redirect_url = get_permalink( get_query_var( 'page_id' ) ); 256 $redirect_obj = get_post( get_query_var( 'page_id' ) ); 247 257 248 258 if ( $redirect_url ) { 249 259 $redirect['query'] = remove_query_arg( 'page_id', $redirect['query'] ); … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 256 266 && 'page' === get_option( 'show_on_front' ) && get_query_var( 'page_id' ) === (int) get_option( 'page_for_posts' ) 257 267 ) { 258 268 $redirect_url = get_permalink( get_option( 'page_for_posts' ) ); 269 $redirect_obj = get_post( get_option( 'page_for_posts' ) ); 259 270 260 271 if ( $redirect_url ) { 261 272 $redirect['query'] = remove_query_arg( 'page_id', $redirect['query'] ); … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 310 321 && $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 ) ) 311 322 ) { 312 323 $redirect_url = get_author_posts_url( $author->ID, $author->user_nicename ); 324 $redirect_obj = $author; 313 325 314 326 if ( $redirect_url ) { 315 327 $redirect['query'] = remove_query_arg( 'author', $redirect['query'] ); … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 385 397 || ! has_term( $category->term_id, 'category', $wp_query->get_queried_object_id() ) 386 398 ) { 387 399 $redirect_url = get_permalink( $wp_query->get_queried_object_id() ); 400 $redirect_obj = get_post( $wp_query->get_queried_object_id() ); 388 401 } 389 402 } 390 403 } … … function redirect_canonical( $requested_url = null, $do_redirect = true ) { 395 408 396 409 if ( ! $redirect_url ) { 397 410 $redirect_url = get_permalink( get_queried_object_id() ); 411 $redirect_obj = get_post( get_queried_object_id() ); 398 412 } 399 413 400 414 if ( $page > 1 ) { … … function lowercase_octets( $matches ) { 740 754 $requested_url = preg_replace_callback( '|%[a-fA-F0-9][a-fA-F0-9]|', 'lowercase_octets', $requested_url ); 741 755 } 742 756 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 * rather 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 743 779 /** 744 780 * Filters the canonical redirect URL. 745 781 * -
src/wp-includes/capabilities.php
diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php index 22eff2b1e3..ef61d3e0cb 100644
a b function map_meta_cap( $cap, $user_id, ...$args ) { 239 239 break; 240 240 } 241 241 242 $status_obj = get_post_status_object( $post->post_status);242 $status_obj = get_post_status_object( get_post_status( $post ) ); 243 243 if ( ! $status_obj ) { 244 244 /* translators: 1: Post status, 2: Capability name. */ 245 _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' );245 _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' ); 246 246 $caps[] = 'edit_others_posts'; 247 247 break; 248 248 } -
src/wp-includes/link-template.php
diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index 28e6f98ec7..b5e5064d17 100644
a b function permalink_anchor( $mode = 'id' ) { 89 89 } 90 90 } 91 91 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 $sample Optional. Whether to force consideration based on sample links. 99 * @return bool Whether to use an ugly permalink structure. 100 */ 101 function wp_force_ugly_post_permalink( $post = null, $sample = null ) { 102 if ( 103 null === $sample && 104 is_object( $post ) && 105 isset( $post->filter ) && 106 'sample' === $post->filter 107 ) { 108 $sample = true; 109 } else { 110 $post = get_post( $post ); 111 $sample = null !== $sample ? $sample : false; 112 } 113 114 if ( ! $post ) { 115 return true; 116 } 117 118 $post_status_obj = get_post_status_object( get_post_status( $post ) ); 119 $post_type_obj = get_post_type_object( get_post_type( $post ) ); 120 121 if ( ! $post_status_obj || ! $post_type_obj ) { 122 return true; 123 } 124 125 if ( 126 // Publicly viewable links never have ugly permalinks. 127 is_post_status_viewable( $post_status_obj ) || 128 ( 129 // Private posts don't have ugly links if the user can read them. 130 $post_status_obj->private && 131 current_user_can( 'read_post', $post->ID ) 132 ) || 133 // Protected posts don't have ugly links if getting a sample URL. 134 ( $post_status_obj->protected && $sample ) 135 ) { 136 return false; 137 } 138 139 return true; 140 } 141 92 142 /** 93 143 * Retrieves the full permalink for the current post or post ID. 94 144 * … … function get_permalink( $post = 0, $leavename = false ) { 166 216 167 217 if ( 168 218 $permalink && 169 ! in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft', 'future', 'trash' ), true)219 ! wp_force_ugly_post_permalink( $post ) 170 220 ) { 171 221 172 222 $category = ''; … … function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { 277 327 278 328 $slug = $post->post_name; 279 329 280 $ draft_or_pending = get_post_status( $post ) && in_array( get_post_status( $post ), array( 'draft', 'pending', 'auto-draft', 'future' ), true);330 $force_ugly_link = wp_force_ugly_post_permalink( $post ); 281 331 282 332 $post_type = get_post_type_object( $post->post_type ); 283 333 … … function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { 285 335 $slug = get_page_uri( $post ); 286 336 } 287 337 288 if ( ! empty( $post_link ) && ( ! $ draft_or_pending|| $sample ) ) {338 if ( ! empty( $post_link ) && ( ! $force_ugly_link || $sample ) ) { 289 339 if ( ! $leavename ) { 290 340 $post_link = str_replace( "%$post->post_type%", $slug, $post_link ); 291 341 } 292 342 $post_link = home_url( user_trailingslashit( $post_link ) ); 293 343 } else { 294 if ( $post_type->query_var && ( isset( $post->post_status ) && ! $ draft_or_pending) ) {344 if ( $post_type->query_var && ( isset( $post->post_status ) && ! $force_ugly_link ) ) { 295 345 $post_link = add_query_arg( $post_type->query_var, $slug, '' ); 296 346 } else { 297 347 $post_link = add_query_arg( … … function _get_page_link( $post = false, $leavename = false, $sample = false ) { 373 423 374 424 $post = get_post( $post ); 375 425 376 $ draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ), true);426 $force_ugly_link = wp_force_ugly_post_permalink( $post ); 377 427 378 428 $link = $wp_rewrite->get_page_permastruct(); 379 429 380 if ( ! empty( $link ) && ( ( isset( $post->post_status ) && ! $ draft_or_pending) || $sample ) ) {430 if ( ! empty( $link ) && ( ( isset( $post->post_status ) && ! $force_ugly_link ) || $sample ) ) { 381 431 if ( ! $leavename ) { 382 432 $link = str_replace( '%pagename%', get_page_uri( $post ), $link ); 383 433 } … … function get_attachment_link( $post = null, $leavename = false ) { 417 467 418 468 $link = false; 419 469 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; 470 $post = get_post( $post ); 471 $force_ugly_link = wp_force_ugly_post_permalink( $post ); 472 $parent_id = $post->post_parent; 473 $parent = $parent_id ? get_post( $parent_id ) : false; 474 $parent_valid = true; // Default for no parent. 475 if ( 476 $parent_id && 477 ( 478 $post->post_parent === $post->ID || 479 ! $parent || 480 ! is_post_type_viewable( get_post_type( $parent ) ) 481 ) 482 ) { 483 // Post is either its own parent or parent post unavailable. 484 $parent_valid = false; 424 485 } 425 486 426 if ( $wp_rewrite->using_permalinks() && $parent ) { 487 if ( $force_ugly_link || ! $parent_valid ) { 488 $link = false; 489 } elseif ( $wp_rewrite->using_permalinks() && $parent ) { 427 490 if ( 'page' === $parent->post_type ) { 428 491 $parentlink = _get_page_link( $post->post_parent ); // Ignores page_on_front. 429 492 } else { -
src/wp-includes/post.php
diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index f04900aed3..a2be7ce8ae 100644
a b function is_post_type_viewable( $post_type ) { 2016 2016 } 2017 2017 } 2018 2018 2019 if ( ! is_object( $post_type ) ) { 2020 return false; 2021 } 2022 2019 2023 return $post_type->publicly_queryable || ( $post_type->_builtin && $post_type->public ); 2020 2024 } 2021 2025 2026 /** 2027 * Determine whether a post status is considered "viewable". 2028 * 2029 * For built-in post statuses such as publish and private, the 'public' value will be evaluted. 2030 * For all others, the 'publicly_queryable' value will be used. 2031 * 2032 * @since 5.7.0 2033 * 2034 * @param string|stdClass $post_status Post status name or object. 2035 * @return bool Whether the post status should be considered viewable. 2036 */ 2037 function is_post_status_viewable( $post_status ) { 2038 if ( is_scalar( $post_status ) ) { 2039 $post_status = get_post_status_object( $post_status ); 2040 if ( ! $post_status ) { 2041 return false; 2042 } 2043 } 2044 2045 if ( 2046 ! is_object( $post_status ) || 2047 $post_status->internal || 2048 $post_status->protected 2049 ) { 2050 return false; 2051 } 2052 2053 return $post_status->publicly_queryable || ( $post_status->_builtin && $post_status->public ); 2054 } 2055 2056 /** 2057 * Determine whether a post is publicly viewable. 2058 * 2059 * Posts are considered publicly viewable if both the post status and post type 2060 * are viewable. 2061 * 2062 * @since 5.7.0 2063 * 2064 * @param int|WP_Post|null $post Optional. Post ID or post object. Defaults to global $post. 2065 * @return bool Whether the post is publicly viewable. 2066 */ 2067 function is_post_publicly_viewable( $post = null ) { 2068 $post = get_post( $post ); 2069 2070 if ( ! $post ) { 2071 return false; 2072 } 2073 2074 $post_type = get_post_type( $post ); 2075 $post_status = get_post_status( $post ); 2076 2077 return is_post_type_viewable( $post_type ) && is_post_status_viewable( $post_status ); 2078 } 2079 2022 2080 /** 2023 2081 * Retrieves an array of the latest posts, or posts matching the given criteria. 2024 2082 * -
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 */ 8 class 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_ 204 204 } 205 205 } 206 206 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' ); 208 211 } 209 212 } -
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() { 3122 3122 * @ticket 51776 3123 3123 * 3124 3124 * @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. 3126 3126 * @param bool $expected_404 Whether the page is expected to return a 404 result. 3127 3127 * 3128 3128 */ 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 ) { 3130 3130 $this->set_permalink_structure( '/%postname%' ); 3131 3131 $post = get_post( self::$post_ids[ $post_key ] ); 3132 3132 … … function test_attachment_permalinks_based_on_parent_status( $post_key, $expected 3134 3134 * The dataProvider runs before the fixures are set up, therefore the 3135 3135 * post object IDs are placeholders that needs to be replaced. 3136 3136 */ 3137 $expected = home_url( str_replace( '%ID%', $post->ID, $expected) );3137 $expected_url = home_url( str_replace( '%ID%', $post->ID, $expected_url ) ); 3138 3138 3139 $this->assertSame( $expected, get_permalink( $post ) );3140 3139 $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 ); 3142 3147 } 3143 3148 3144 3149 /** … … function test_attachment_permalinks_based_on_parent_status( $post_key, $expected 3146 3151 * 3147 3152 * @return array[] { 3148 3153 * @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. 3150 3155 * $type bool $expected_404 Whether the page is expected to return a 404 result. 3151 3156 * } 3152 3157 */ -
new file tests/phpunit/tests/post/isPostPubliclyViewable.php
diff --git a/tests/phpunit/tests/post/isPostPubliclyViewable.php b/tests/phpunit/tests/post/isPostPubliclyViewable.php new file mode 100644 index 0000000000..9d5d781e88
- + 1 <?php 2 3 /** 4 * @group post 5 */ 6 class Tests_Post_IsPostPubliclyViewable extends WP_UnitTestCase { 7 8 /** 9 * Array of post IDs to use as parents. 10 * 11 * @var array 12 */ 13 public static $parent_post_ids = array(); 14 15 public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { 16 $post_statuses = array( 'publish', 'private', 'future', 'trash', 'delete' ); 17 foreach ( $post_statuses as $post_status ) { 18 $date = ''; 19 $actual_status = $post_status; 20 if ( 'future' === $post_status ) { 21 $date = strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 year' ) ); 22 } elseif ( in_array( $post_status, array( 'trash', 'delete' ), true ) ) { 23 $actual_status = 'publish'; 24 } 25 26 self::$parent_post_ids[ $post_status ] = $factory->post->create( 27 array( 28 'post_status' => $actual_status, 29 'post_name' => "$post_status-post", 30 'post_date' => $date, 31 'post_type' => 'page', 32 ) 33 ); 34 } 35 36 wp_trash_post( self::$parent_post_ids['trash'] ); 37 wp_delete_post( self::$parent_post_ids['delete'], true ); 38 } 39 40 /** 41 * Unit tests for is_post_publicly_viewable(). 42 * 43 * @dataProvider data_is_post_publicly_viewable 44 * @ticket 49380 45 * 46 * @param string $post_type The post type. 47 * @param string $post_status The post status. 48 * @param bool $expected The expected result of the function call. 49 * @param string $parent_key The parent key as set up in shared fixtures. 50 */ 51 public function test_is_post_publicly_viewable( $post_type, $post_status, $expected, $parent_key = '' ) { 52 $date = ''; 53 if ( 'future' === $post_status ) { 54 $date = strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 year' ) ); 55 } 56 57 $post_id = $this->factory()->post->create( 58 array( 59 'post_type' => $post_type, 60 'post_status' => $post_status, 61 'post_parent' => $parent_key ? self::$parent_post_ids[ $parent_key ] : 0, 62 'post_date' => $date, 63 ) 64 ); 65 66 $this->assertSame( $expected, is_post_publicly_viewable( $post_id ) ); 67 } 68 69 /** 70 * Data provider for test_is_post_publicly_viewable(). 71 * 72 * return array[] { 73 * @type string $post_type The post type. 74 * @type string $post_status The post status. 75 * @type bool $expected The expected result of the function call. 76 * @type string $parent_key The parent key as set up in shared fixtures. 77 * } 78 */ 79 public function data_is_post_publicly_viewable() { 80 return array( 81 array( 'post', 'publish', true ), 82 array( 'post', 'private', false ), 83 array( 'post', 'future', false ), 84 85 array( 'page', 'publish', true ), 86 array( 'page', 'private', false ), 87 array( 'page', 'future', false ), 88 89 array( 'unregistered_cpt', 'publish', false ), 90 array( 'unregistered_cpt', 'private', false ), 91 92 array( 'post', 'unregistered_cps', false ), 93 array( 'page', 'unregistered_cps', false ), 94 95 array( 'attachment', 'inherit', true, 'publish' ), 96 array( 'attachment', 'inherit', false, 'private' ), 97 array( 'attachment', 'inherit', false, 'future' ), 98 array( 'attachment', 'inherit', true, 'trash' ), 99 array( 'attachment', 'inherit', true, 'delete' ), 100 101 array( 'page', 'publish', true, 'publish' ), 102 array( 'page', 'publish', true, 'private' ), 103 array( 'page', 'publish', true, 'future' ), 104 array( 'page', 'publish', true, 'trash' ), 105 array( 'page', 'publish', true, 'delete' ), 106 ); 107 } 108 } -
new file tests/phpunit/tests/post/isPostStatusViewable.php
diff --git a/tests/phpunit/tests/post/isPostStatusViewable.php b/tests/phpunit/tests/post/isPostStatusViewable.php new file mode 100644 index 0000000000..9658ca2066
- + 1 <?php 2 3 /** 4 * @group post 5 */ 6 class Tests_Post_IsPostStatusViewable extends WP_UnitTestCase { 7 8 /** 9 * Remove the test status from the global when finished. 10 * 11 * @global $wp_post_statuses 12 */ 13 static function wpTearDownAfterClass() { 14 global $wp_post_statuses; 15 unset( $wp_post_statuses['wp_tests_ps'] ); 16 } 17 18 /** 19 * Test custom post status. 20 * 21 * This may include emulations of built in (_builtin) statuses. 22 * 23 * @ticket 49380 24 * @dataProvider data_custom_post_statuses 25 * 26 * @param array $cps_args Registration arguments. 27 * @param bool $expected Expected result. 28 */ 29 public function test_custom_post_statuses( $cps_args, $expected ) { 30 register_post_status( 31 'wp_tests_ps', 32 $cps_args 33 ); 34 35 // Test status passed as string. 36 $this->assertSame( $expected, is_post_status_viewable( 'wp_tests_ps' ) ); 37 // Test status passed as object. 38 $this->assertSame( $expected, is_post_status_viewable( get_post_status_object( 'wp_tests_ps' ) ) ); 39 } 40 41 /** 42 * Data provider for custom post status tests. 43 * 44 * @return array[] { 45 * array CPS registration args. 46 * bool Expected result. 47 * } 48 */ 49 public function data_custom_post_statuses() { 50 return array( 51 // 0. False for non-publically queryable types. 52 array( 53 array( 54 'publicly_queryable' => false, 55 '_builtin' => false, 56 'public' => true, 57 ), 58 false, 59 ), 60 // 1. True for publically queryable types. 61 array( 62 array( 63 'publicly_queryable' => true, 64 '_builtin' => false, 65 'public' => false, 66 ), 67 true, 68 ), 69 // 2. False for built-in non-public types. 70 array( 71 array( 72 'publicly_queryable' => false, 73 '_builtin' => true, 74 'public' => false, 75 ), 76 false, 77 ), 78 // 3. False for non-built-in public types. 79 array( 80 array( 81 'publicly_queryable' => false, 82 '_builtin' => false, 83 'public' => true, 84 ), 85 false, 86 ), 87 // 4. True for built-in public types. 88 array( 89 array( 90 'publicly_queryable' => false, 91 '_builtin' => true, 92 'public' => true, 93 ), 94 true, 95 ), 96 ); 97 } 98 99 /** 100 * Test built-in and unregistered post status. 101 * 102 * @dataProvider data_built_unregistered_in_status_types 103 * @ticket 49380 104 * 105 * @param mixed $status Post status to check. 106 * @param bool $expected Expected viewable status. 107 */ 108 function test_built_unregistered_in_status_types( $status, $expected ) { 109 // Test status passed as string. 110 $this->assertSame( $expected, is_post_status_viewable( $status ) ); 111 // Test status passed as object. 112 $this->assertSame( $expected, is_post_status_viewable( get_post_status_object( $status ) ) ); 113 } 114 115 /** 116 * Data provider for built-in and unregistered post status tests. 117 * 118 * @return array[] { 119 * @type mixed $status Post status to check. 120 * @type bool $expected Expected viewable status. 121 * } 122 */ 123 public function data_built_unregistered_in_status_types() { 124 return array( 125 array( 'publish', true ), 126 array( 'future', false ), 127 array( 'draft', false ), 128 array( 'pending', false ), 129 array( 'private', false ), 130 array( 'trash', false ), 131 array( 'auto-draft', false ), 132 array( 'inherit', false ), 133 array( 'request-pending', false ), 134 array( 'request-confirmed', false ), 135 array( 'request-failed', false ), 136 array( 'request-completed', false ), 137 138 // Various unregistered statuses. 139 array( 'unregistered-status', false ), 140 array( false, false ), 141 array( true, false ), 142 array( 20, false ), 143 array( null, false ), 144 array( '', false ), 145 ); 146 } 147 148 /** 149 * Sanitize key should not be run when testing. 150 * 151 * @ticket 49380 152 */ 153 public function test_sanitize_key_not_run() { 154 register_post_status( 155 'WP_Tests_ps', 156 array( 157 'publicly_queryable' => true, 158 '_builtin' => false, 159 'public' => true, 160 ) 161 ); 162 163 // Sanitized key should return true. 164 $this->assertTrue( is_post_status_viewable( 'wp_tests_ps' ) ); 165 $this->assertTrue( is_post_status_viewable( get_post_status_object( 'wp_tests_ps' ) ) ); 166 167 // Unsanitized key should return false. 168 $this->assertFalse( is_post_status_viewable( 'WP_tests_ps' ) ); 169 $this->assertFalse( is_post_status_viewable( get_post_status_object( 'WP_tests_ps' ) ) ); 170 } 171 }