Changeset 60839
- Timestamp:
- 09/30/2025 05:06:42 PM (5 weeks ago)
- Location:
- branches/4.7
- Files:
-
- 12 edited
-
. (modified) (1 prop)
-
src/wp-admin/js/customize-nav-menus.js (modified) (2 diffs)
-
src/wp-admin/js/nav-menu.js (modified) (2 diffs)
-
src/wp-includes/class-wp-customize-nav-menus.php (modified) (3 diffs)
-
src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php (modified) (11 diffs)
-
src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php (modified) (1 diff)
-
src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php (modified) (1 diff)
-
src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php (modified) (4 diffs)
-
tests/phpunit/tests/customize/nav-menu-item-setting.php (modified) (10 diffs)
-
tests/phpunit/tests/customize/nav-menus.php (modified) (4 diffs)
-
tests/phpunit/tests/rest-api/rest-tags-controller.php (modified) (1 diff)
-
tests/phpunit/tests/rest-api/rest-users-controller.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/4.7
- Property svn:mergeinfo changed
/trunk merged: 60814-60816
- Property svn:mergeinfo changed
-
branches/4.7/src/wp-admin/js/customize-nav-menus.js
r40401 r60839 517 517 } 518 518 519 this.currentMenuControl.addItemToMenu( menu_item.attributes ); 519 // Leave the title as empty to reuse the original title as a placeholder if set. 520 var nav_menu_item = Object.assign( {}, menu_item.attributes ); 521 if ( nav_menu_item.title === nav_menu_item.original_title ) { 522 nav_menu_item.title = ''; 523 } 524 525 this.currentMenuControl.addItemToMenu( nav_menu_item ); 520 526 521 527 $( menuitemTpl ).find( '.menu-item-handle' ).addClass( 'item-added' ); … … 2634 2640 { 2635 2641 nav_menu_term_id: menuControl.params.menu_id, 2636 original_title: item.title,2637 2642 position: position 2638 2643 } -
branches/4.7/src/wp-admin/js/nav-menu.js
r38981 r60839 1158 1158 1159 1159 eventOnClickMenuSave : function() { 1160 var locs = '',1161 menuName = $('#menu-name'),1162 menuNameVal = menuName.val(); 1163 // Cancel and warn if invalid menu name 1160 var menuName = $('#menu-name'), 1161 menuNameVal = menuName.val(); 1162 1163 // Cancel and warn if invalid menu name. 1164 1164 if( !menuNameVal || menuNameVal == menuName.attr('title') || !menuNameVal.replace(/\s+/, '') ) { 1165 1165 menuName.parent().addClass('form-invalid'); 1166 1166 return false; 1167 1167 } 1168 // Copy menu theme locations 1168 // Copy menu theme locations. 1169 // Note: This appears to be dead code since #nav-menu-theme-locations no longer exists, perhaps removed in r32842. 1170 var $updateNavMenu = $('#update-nav-menu'); 1169 1171 $('#nav-menu-theme-locations select').each(function() { 1170 locs += '<input type="hidden" name="' + this.name + '" value="' + $(this).val() + '" />'; 1171 }); 1172 $('#update-nav-menu').append( locs ); 1173 // Update menu item position data 1172 $updateNavMenu.append( 1173 $( '<input>', { 1174 type: 'hidden', 1175 name: this.name, 1176 value: $( this ).val() 1177 } ) 1178 ); 1179 }); 1180 // Update menu item position data. 1174 1181 api.menuList.find('.menu-item-data-position').val( function(index) { return index + 1; } ); 1175 1182 window.onbeforeunload = null; … … 1211 1218 1212 1219 if( ! $items.length ) { 1213 $('.categorychecklist', panel).html( '<li><p>' + navMenuL10n.noResultsFound + '</p></li>' ); 1220 var li = $( '<li>' ); 1221 var p = $( '<p>', { text: navMenuL10n.noResultsFound } ); 1222 li.append( p ); 1223 $('.categorychecklist', panel).empty().append( li ); 1214 1224 $( '.spinner', panel ).removeClass( 'is-active' ); 1215 1225 wrapper.addClass( 'has-no-menu-item' ); -
branches/4.7/src/wp-includes/class-wp-customize-nav-menus.php
r40098 r60839 165 165 } elseif ( 'post' !== $object && 0 === $page && $post_type->has_archive ) { 166 166 // Add a post type archive link. 167 $title = $post_type->labels->archives; 167 168 $items[] = array( 168 'id' => $object . '-archive', 169 'title' => $post_type->labels->archives, 170 'type' => 'post_type_archive', 171 'type_label' => __( 'Post Type Archive' ), 172 'object' => $object, 173 'url' => get_post_type_archive_link( $object ), 169 'id' => $object_name . '-archive', 170 'title' => $title, 171 'original_title' => $title, 172 'type' => 'post_type_archive', 173 'type_label' => __( 'Post Type Archive' ), 174 'object' => $object_name, 175 'url' => get_post_type_archive_link( $object_name ), 174 176 ); 175 177 } … … 200 202 $post_title = sprintf( __( '#%d (no title)' ), $post->ID ); 201 203 } 204 205 $title = html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ); 202 206 $items[] = array( 203 'id' => "post-{$post->ID}", 204 'title' => html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ), 205 'type' => 'post_type', 206 'type_label' => get_post_type_object( $post->post_type )->labels->singular_name, 207 'object' => $post->post_type, 208 'object_id' => intval( $post->ID ), 209 'url' => get_permalink( intval( $post->ID ) ), 207 'id' => "post-{$post->ID}", 208 'title' => $title, 209 'original_title' => $title, 210 'type' => 'post_type', 211 'type_label' => get_post_type_object( $post->post_type )->labels->singular_name, 212 'object' => $post->post_type, 213 'object_id' => (int) $post->ID, 214 'url' => get_permalink( (int) $post->ID ), 210 215 ); 211 216 } … … 228 233 229 234 foreach ( $terms as $term ) { 235 $title = html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ); 230 236 $items[] = array( 231 'id' => "term-{$term->term_id}", 232 'title' => html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ), 233 'type' => 'taxonomy', 234 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name, 235 'object' => $term->taxonomy, 236 'object_id' => intval( $term->term_id ), 237 'url' => get_term_link( intval( $term->term_id ), $term->taxonomy ), 237 'id' => "term-{$term->term_id}", 238 'title' => $title, 239 'original_title' => $title, 240 'type' => 'taxonomy', 241 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name, 242 'object' => $term->taxonomy, 243 'object_id' => (int) $term->term_id, 244 'url' => get_term_link( (int) $term->term_id, $term->taxonomy ), 238 245 ); 239 246 } -
branches/4.7/src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
r39395 r60839 59 59 'xfn' => '', 60 60 'status' => 'publish', 61 'original_title' => '',62 61 'nav_menu_term_id' => 0, // This will be supplied as the $menu_id arg for wp_update_nav_menu_item(). 63 62 '_invalid' => false, … … 225 224 */ 226 225 public function value() { 227 if ( $this->is_previewed && $this->_previewed_blog_id === get_current_blog_id() ) { 226 $type_label = null; 227 if ( $this->is_previewed && get_current_blog_id() === $this->_previewed_blog_id ) { 228 228 $undefined = new stdClass(); // Symbol. 229 229 $post_value = $this->post_value( $undefined ); … … 233 233 } else { 234 234 $value = $post_value; 235 }236 if ( ! empty( $value ) && empty( $value['original_title'] ) ) {237 $value['original_title'] = $this->get_original_title( (object) $value );238 235 } 239 236 } elseif ( isset( $this->value ) ) { … … 248 245 $is_title_empty = empty( $post->post_title ); 249 246 $value = (array) wp_setup_nav_menu_item( $post ); 247 if ( isset( $value['type_label'] ) ) { 248 $type_label = $value['type_label']; 249 } 250 250 if ( $is_title_empty ) { 251 251 $value['title'] = ''; … … 264 264 } 265 265 266 if ( ! empty( $value ) && empty( $value['type_label'] ) ) { 267 $value['type_label'] = $this->get_type_label( (object) $value ); 268 } 269 266 // These properties are read-only and are part of the setting for use in the Customizer UI. 267 if ( is_array( $value ) ) { 268 $value_obj = (object) $value; 269 $value['type_label'] = isset( $type_label ) ? $type_label : $this->get_type_label( $value_obj ); 270 $value['original_title'] = $this->get_original_title( $value_obj ); 271 } 272 273 return $value; 274 } 275 276 /** 277 * Prepares the value for editing on the client. 278 * 279 * @since 6.8.3 280 * 281 * @return array|false Value prepared for the client. 282 */ 283 public function js_value() { 284 $value = parent::js_value(); 285 if ( is_array( $value ) && isset( $value['original_title'] ) ) { 286 // Decode entities for the sake of displaying the original title as a placeholder. 287 $value['original_title'] = html_entity_decode( $value['original_title'], ENT_QUOTES, get_bloginfo( 'charset' ) ); 288 } 270 289 return $value; 271 290 } … … 278 297 * 279 298 * @param object $item Nav menu item. 280 * @return string The original title .299 * @return string The original title, without entity decoding. 281 300 */ 282 301 protected function get_original_title( $item ) { … … 304 323 } 305 324 } 306 $original_title = html_entity_decode( $original_title, ENT_QUOTES, get_bloginfo( 'charset' ) );307 325 return $original_title; 308 326 } … … 362 380 $this->value['status'] = $this->value['post_status']; 363 381 unset( $this->value['post_status'] ); 364 }365 366 if ( ! isset( $this->value['original_title'] ) ) {367 $this->value['original_title'] = $this->get_original_title( (object) $this->value );368 382 } 369 383 … … 607 621 unset( $item->position ); 608 622 609 if ( empty( $item->original_title ) ) {610 $item->original_title = $this->get_original_title( $item );611 }612 623 if ( empty( $item->title ) && ! empty( $item->original_title ) ) { 613 $item->title = $item->original_title; 624 $item->title = $item->original_title; // This is NOT entity-decoded. It comes from self::get_original_title(). 614 625 } 615 626 if ( $item->title ) { … … 662 673 * @access public 663 674 * 664 * @param array $menu_item_value The value to sanitize.675 * @param array|false $menu_item_value The value to sanitize. 665 676 * @return array|false|null Null if an input isn't valid. False if it is marked for deletion. 666 677 * Otherwise the sanitized value. … … 716 727 } 717 728 718 $menu_item_value['original_title'] = sanitize_text_field( $menu_item_value['original_title'] );719 720 729 // Apply the same filters as when calling wp_insert_post(). 721 730 $menu_item_value['title'] = wp_unslash( apply_filters( 'title_save_pre', wp_slash( $menu_item_value['title'] ) ) ); -
branches/4.7/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
r50733 r60839 345 345 346 346 foreach ( $query_result as $post ) { 347 if ( ! $this->check_read_permission( $post ) ) { 347 if ( 'edit' === $request['context'] ) { 348 $permission = $this->check_update_permission( $post ); 349 } else { 350 $permission = $this->check_read_permission( $post ); 351 } 352 353 if ( ! $permission ) { 348 354 continue; 349 355 } -
branches/4.7/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
r54566 r60839 317 317 318 318 foreach ( $query_result as $term ) { 319 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', $term->term_id ) ) { 320 continue; 321 } 319 322 $data = $this->prepare_item_for_response( $term, $request ); 320 323 $response[] = $this->prepare_response_for_collection( $data ); -
branches/4.7/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
r56862 r60839 184 184 185 185 if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { 186 return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );186 return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit users.' ), array( 'status' => rest_authorization_required_code() ) ); 187 187 } 188 188 … … 282 282 283 283 foreach ( $query->results as $user ) { 284 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_user', $user->ID ) ) { 285 continue; 286 } 284 287 $data = $this->prepare_item_for_response( $user, $request ); 285 288 $users[] = $this->prepare_response_for_collection( $data ); … … 377 380 } 378 381 379 if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { 380 return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) ); 381 } elseif ( ! count_user_posts( $user->ID, $types ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) { 382 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_user', $user->ID ) ) { 383 return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) ); 384 } 385 386 if ( ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) && ! count_user_posts( $user->ID, $types ) ) { 382 387 return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) ); 383 388 } … … 879 884 } 880 885 881 if ( ! empty( $schema['properties']['roles'] ) ) {886 if ( ! empty( $schema['properties']['roles'] ) && ( current_user_can( 'list_users' ) || current_user_can( 'edit_user', $user->ID ) ) ) { 882 887 // Defensively call array_values() to ensure an array is returned. 883 888 $data['roles'] = array_values( $user->roles ); -
branches/4.7/tests/phpunit/tests/customize/nav-menu-item-setting.php
r39395 r60839 1 1 2 <?php 2 3 /** … … 90 91 'xfn' => '', 91 92 'status' => 'publish', 92 'original_title' => '',93 93 'nav_menu_term_id' => 0, 94 94 '_invalid' => false, … … 154 154 $menu_id = wp_create_nav_menu( 'Menu' ); 155 155 $item_title = 'Greetings'; 156 $item_id = wp_update_nav_menu_item( $menu_id, 0, array( 157 'menu-item-type' => 'post_type', 158 'menu-item-object' => 'post', 159 'menu-item-object-id' => $post_id, 160 'menu-item-title' => $item_title, 161 'menu-item-status' => 'publish', 162 ) ); 156 $item_id = wp_update_nav_menu_item( 157 $menu_id, 158 0, 159 array( 160 'menu-item-type' => 'post_type', 161 'menu-item-object' => 'post', 162 'menu-item-object-id' => $post_id, 163 'menu-item-title' => $item_title, 164 'menu-item-status' => 'publish', 165 ) 166 ); 163 167 164 168 $post = get_post( $item_id ); … … 170 174 171 175 $value = $setting->value(); 172 $this->assert Equals( $menu_item->title, $value['title'] );173 $this->assert Equals( $menu_item->type, $value['type'] );176 $this->assertSame( $menu_item->title, $value['title'] ); 177 $this->assertSame( $menu_item->type, $value['type'] ); 174 178 $this->assertEquals( $menu_item->object_id, $value['object_id'] ); 175 $this->assert Equals( $menu_id, $value['nav_menu_term_id'] );176 $this->assert Equals( 'Hello World', $value['original_title'] );179 $this->assertSame( $menu_id, $value['nav_menu_term_id'] ); 180 $this->assertSame( 'Hello World', $value['original_title'] ); 177 181 178 182 $other_menu_id = wp_create_nav_menu( 'Menu2' ); 179 wp_update_nav_menu_item( $other_menu_id, $item_id, array( 180 'menu-item-title' => 'Hola', 181 ) ); 183 wp_update_nav_menu_item( 184 $other_menu_id, 185 $item_id, 186 array( 187 'menu-item-title' => 'Hola', 188 ) 189 ); 182 190 $value = $setting->value(); 183 $this->assert Equals( 'Hola', $value['title'] );184 $this->assert Equals( $other_menu_id, $value['nav_menu_term_id'] );191 $this->assertSame( 'Hola', $value['title'] ); 192 $this->assertSame( $other_menu_id, $value['nav_menu_term_id'] ); 185 193 } 186 194 … … 209 217 210 218 $value = $setting->value(); 211 $this->assert Equals( '', $value['title'] );212 $this->assert Equals( $original_title, $value['original_title'] );219 $this->assertSame( '', $value['title'] ); 220 $this->assertSame( $original_title, $value['original_title'] ); 213 221 } 214 222 … … 225 233 $menu_id = wp_create_nav_menu( 'Menu' ); 226 234 $item_title = 'Greetings'; 227 $item_id = wp_update_nav_menu_item( $menu_id, 0, array( 228 'menu-item-type' => 'taxonomy', 229 'menu-item-object' => 'category', 230 'menu-item-object-id' => $tax_id, 231 'menu-item-title' => $item_title, 232 'menu-item-status' => 'publish', 233 ) ); 235 $item_id = wp_update_nav_menu_item( 236 $menu_id, 237 0, 238 array( 239 'menu-item-type' => 'taxonomy', 240 'menu-item-object' => 'category', 241 'menu-item-object-id' => $tax_id, 242 'menu-item-title' => $item_title, 243 'menu-item-status' => 'publish', 244 ) 245 ); 234 246 235 247 $post = get_post( $item_id ); … … 241 253 242 254 $value = $setting->value(); 243 $this->assert Equals( $menu_item->title, $value['title'] );244 $this->assert Equals( $menu_item->type, $value['type'] );255 $this->assertSame( $menu_item->title, $value['title'] ); 256 $this->assertSame( $menu_item->type, $value['type'] ); 245 257 $this->assertEquals( $menu_item->object_id, $value['object_id'] ); 246 $this->assert Equals( $menu_id, $value['nav_menu_term_id'] );247 $this->assert Equals( 'Salutations', $value['original_title'] );258 $this->assertSame( $menu_id, $value['nav_menu_term_id'] ); 259 $this->assertSame( 'Salutations', $value['original_title'] ); 248 260 } 249 261 … … 272 284 273 285 $value = $setting->value(); 274 $this->assert Equals( $menu_item->type_label, 'Custom Label' );275 $this->assert Equals( $menu_item->type_label, $value['type_label'] );286 $this->assertSame( $menu_item->type_label, 'Custom Label' ); 287 $this->assertSame( $menu_item->type_label, $value['type_label'] ); 276 288 } 277 289 … … 487 499 'xfn' => 'hello " inject="', 488 500 'status' => 'forbidden', 489 'original_title' => 'Hi<script>unfilteredHtml()</script>',501 'original_title' => 'Hi<script>unfilteredHtml()</script>', 490 502 'nav_menu_term_id' => 'heilo', 491 503 '_invalid' => false, … … 506 518 'xfn' => 'hello inject', 507 519 'status' => 'draft', 508 'original_title' => 'Hi',520 'original_title' => 'Hi<script>unfilteredHtml()</script>', 509 521 'nav_menu_term_id' => 0, 510 522 ); -
branches/4.7/tests/phpunit/tests/customize/nav-menus.php
r40098 r60839 171 171 'id' => "post-{$post_id}", 172 172 'title' => 'Post Title', 173 'original_title' => 'Post Title', 173 174 'type' => 'post_type', 174 175 'type_label' => 'Post', 175 176 'object' => 'post', 176 'object_id' => intval( $post_id ),177 'url' => get_permalink( intval( $post_id )),177 'object_id' => (int) $post_id, 178 'url' => get_permalink( (int) $post_id ), 178 179 ); 179 180 … … 198 199 'id' => "post-{$page_id}", 199 200 'title' => 'Page Title', 201 'original_title' => 'Page Title', 200 202 'type' => 'post_type', 201 203 'type_label' => 'Page', 202 204 'object' => 'page', 203 'object_id' => intval( $page_id ),204 'url' => get_permalink( intval( $page_id )),205 'object_id' => (int) $page_id, 206 'url' => get_permalink( (int) $page_id ), 205 207 ); 206 208 … … 224 226 'id' => "post-{$post_id}", 225 227 'title' => 'Post Title', 228 'original_title' => 'Post Title', 226 229 'type' => 'post_type', 227 230 'type_label' => 'Post', 228 231 'object' => 'post', 229 'object_id' => intval( $post_id ),230 'url' => get_permalink( intval( $post_id )),232 'object_id' => (int) $post_id, 233 'url' => get_permalink( (int) $post_id ), 231 234 ); 232 235 … … 250 253 'id' => "term-{$term_id}", 251 254 'title' => 'Term Title', 255 'original_title' => 'Term Title', 252 256 'type' => 'taxonomy', 253 257 'type_label' => 'Category', 254 258 'object' => 'category', 255 'object_id' => intval( $term_id ),256 'url' => get_term_link( intval( $term_id ), 'category' ),259 'object_id' => (int) $term_id, 260 'url' => get_term_link( (int) $term_id, 'category' ), 257 261 ); 258 262 -
branches/4.7/tests/phpunit/tests/rest-api/rest-tags-controller.php
r40427 r60839 1003 1003 } 1004 1004 1005 /** 1006 * Callback for map_meta_cap filter to disallow edit_term capability 1007 * 1008 * @param array $caps Required capabilities. 1009 * @param string $cap Capability being checked. 1010 * @return array Modified capabilities. 1011 */ 1012 public function disallow_edit_term_cap( $caps, $cap ) { 1013 if ( 'edit_term' === $cap ) { 1014 return array( 'do_not_allow' ); 1015 } 1016 1017 return $caps; 1018 } 1019 1005 1020 public function tearDown() { 1006 1021 _unregister_taxonomy( 'batman' ); -
branches/4.7/tests/phpunit/tests/rest-api/rest-users-controller.php
r40426 r60839 819 819 $request->set_param( 'context', 'edit' ); 820 820 $response = $this->server->dispatch( $request ); 821 $this->assertErrorResponse( 'rest_ user_cannot_view', $response, 401 );821 $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 ); 822 822 } 823 823 … … 2396 2396 } 2397 2397 2398 /** 2399 * Callback for map_meta_cap filter to disallow edit_user capability 2400 * 2401 * @param array $caps Required capabilities. 2402 * @param string $cap Capability being checked. 2403 * @return array Modified capabilities. 2404 */ 2405 public function disallow_edit_user_cap( $caps, $cap ) { 2406 if ( 'edit_user' === $cap ) { 2407 return array( 'do_not_allow' ); 2408 } 2409 2410 return $caps; 2411 } 2412 2413 /** 2414 * Callback for map_meta_cap filter to allow edit_user capability 2415 * 2416 * @param array $caps Required capabilities. 2417 * @param string $cap Capability being checked. 2418 * @return array Modified capabilities. 2419 */ 2420 public function allow_edit_user_cap( $caps, $cap ) { 2421 if ( 'edit_user' === $cap ) { 2422 return array(); 2423 } 2424 2425 return $caps; 2426 } 2427 2398 2428 protected function allow_user_to_manage_multisite() { 2399 2429 wp_set_current_user( self::$user );
Note: See TracChangeset
for help on using the changeset viewer.