Changeset 60828
- Timestamp:
- 09/30/2025 05:03:15 PM (5 weeks ago)
- Location:
- branches/5.8
- Files:
-
- 11 edited
-
. (modified) (1 prop)
-
src/js/_enqueues/lib/nav-menu.js (modified) (12 diffs)
-
src/js/_enqueues/wp/customize/nav-menus.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) (12 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) (2 diffs)
-
tests/phpunit/tests/customize/nav-menus.php (modified) (4 diffs)
-
tests/phpunit/tests/rest-api/rest-users-controller.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/5.8
- Property svn:mergeinfo changed
/trunk merged: 60814-60816
- Property svn:mergeinfo changed
-
branches/5.8/src/js/_enqueues/lib/nav-menu.js
r51010 r60828 872 872 * 873 873 * @since 5.8.0 874 */ 874 */ 875 875 attachBulkSelectButtonListeners : function() { 876 876 var that = this; … … 891 891 * 892 892 * @since 5.8.0 893 */ 893 */ 894 894 enableBulkSelection : function() { 895 895 var checkbox = $( '#menu-to-edit .menu-item-checkbox' ); … … 908 908 * 909 909 * @since 5.8.0 910 */ 910 */ 911 911 disableBulkSelection : function() { 912 912 var checkbox = $( '#menu-to-edit .menu-item-checkbox' ); … … 932 932 * 933 933 * @since 5.8.0 934 */ 934 */ 935 935 attachMenuCheckBoxListeners : function() { 936 936 var that = this; … … 945 945 * 946 946 * @since 5.8.0 947 */ 947 */ 948 948 attachMenuItemDeleteButton : function() { 949 949 var that = this; … … 986 986 * 987 987 * @since 5.8.0 988 */ 988 */ 989 989 attachPendingMenuItemsListForDeletion : function() { 990 990 $( '#post-body-content' ).on( 'change', '.menu-item-checkbox', function() { … … 1005 1005 1006 1006 if ( this.checked === true ) { 1007 $( '#pending-menu-items-to-delete ul' ).append( 1008 '<li data-menu-item-id="' + menuItemID + '">' + 1009 '<span class="pending-menu-item-name">' + menuItemName + '</span> ' + 1010 '<span class="pending-menu-item-type">(' + menuItemType + ')</span>' + 1011 '<span class="separator"></span>' + 1012 '</li>' 1013 ); 1007 var $li = $( '<li>', { 'data-menu-item-id': menuItemID } ); 1008 $li.append( $( '<span>', { 1009 'class': 'pending-menu-item-name', 1010 text: menuItemName 1011 } ) ); 1012 $li.append( ' ' ); 1013 $li.append( $( '<span>', { 1014 'class': 'pending-menu-item-type', 1015 text: '(' + menuItemType + ')' 1016 } ) ); 1017 $li.append( $( '<span>', { 'class': 'separator' } ) ); 1018 $( '#pending-menu-items-to-delete ul' ).append( $li ); 1014 1019 } 1015 1020 … … 1023 1028 * 1024 1029 * @since 5.8.0 1025 */ 1030 */ 1026 1031 setBulkDeleteCheckboxStatus : function() { 1027 1032 var that = this; … … 1047 1052 * 1048 1053 * @since 5.8.0 1049 */ 1054 */ 1050 1055 setRemoveSelectedButtonStatus : function() { 1051 1056 var button = $( '.menu-items-delete' ); … … 1398 1403 1399 1404 eventOnClickMenuSave : function() { 1400 var locs = '', 1401 menuName = $('#menu-name'), 1402 menuNameVal = menuName.val(); 1405 var menuName = $('#menu-name'), 1406 menuNameVal = menuName.val(); 1403 1407 1404 1408 // Cancel and warn if invalid menu name. … … 1408 1412 } 1409 1413 // Copy menu theme locations. 1414 // Note: This appears to be dead code since #nav-menu-theme-locations no longer exists, perhaps removed in r32842. 1415 var $updateNavMenu = $('#update-nav-menu'); 1410 1416 $('#nav-menu-theme-locations select').each(function() { 1411 locs += '<input type="hidden" name="' + this.name + '" value="' + $(this).val() + '" />'; 1412 }); 1413 $('#update-nav-menu').append( locs ); 1417 $updateNavMenu.append( 1418 $( '<input>', { 1419 type: 'hidden', 1420 name: this.name, 1421 value: $( this ).val() 1422 } ) 1423 ); 1424 }); 1414 1425 // Update menu item position data. 1415 1426 api.menuList.find('.menu-item-data-position').val( function(index) { return index + 1; } ); … … 1454 1465 1455 1466 if( ! $items.length ) { 1456 $('.categorychecklist', panel).html( '<li><p>' + wp.i18n.__( 'No results found.' ) + '</p></li>' ); 1467 var li = $( '<li>' ); 1468 var p = $( '<p>', { text: wp.i18n.__( 'No results found.' ) } ); 1469 li.append( p ); 1470 $('.categorychecklist', panel).empty().append( li ); 1457 1471 $( '.spinner', panel ).removeClass( 'is-active' ); 1458 1472 wrapper.addClass( 'has-no-menu-item' ); -
branches/5.8/src/js/_enqueues/wp/customize/nav-menus.js
r50547 r60828 527 527 } 528 528 529 this.currentMenuControl.addItemToMenu( menu_item.attributes ); 529 // Leave the title as empty to reuse the original title as a placeholder if set. 530 var nav_menu_item = Object.assign( {}, menu_item.attributes ); 531 if ( nav_menu_item.title === nav_menu_item.original_title ) { 532 nav_menu_item.title = ''; 533 } 534 535 this.currentMenuControl.addItemToMenu( nav_menu_item ); 530 536 531 537 $( menuitemTpl ).find( '.menu-item-handle' ).addClass( 'item-added' ); … … 3021 3027 { 3022 3028 nav_menu_term_id: menuControl.params.menu_id, 3023 original_title: item.title,3024 3029 position: position 3025 3030 } -
branches/5.8/src/wp-includes/class-wp-customize-nav-menus.php
r51047 r60828 191 191 } elseif ( 'post' !== $object && 0 === $page && $post_type->has_archive ) { 192 192 // Add a post type archive link. 193 $title = $post_type->labels->archives; 193 194 $items[] = array( 194 'id' => $object . '-archive', 195 'title' => $post_type->labels->archives, 196 'type' => 'post_type_archive', 197 'type_label' => __( 'Post Type Archive' ), 198 'object' => $object, 199 'url' => get_post_type_archive_link( $object ), 195 'id' => $object . '-archive', 196 'title' => $title, 197 'original_title' => $title, 198 'type' => 'post_type_archive', 199 'type_label' => __( 'Post Type Archive' ), 200 'object' => $object, 201 'url' => get_post_type_archive_link( $object ), 200 202 ); 201 203 } … … 244 246 } 245 247 248 $title = html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ); 246 249 $items[] = array( 247 'id' => "post-{$post->ID}", 248 'title' => html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ), 249 'type' => 'post_type', 250 'type_label' => $post_type_label, 251 'object' => $post->post_type, 252 'object_id' => (int) $post->ID, 253 'url' => get_permalink( (int) $post->ID ), 250 'id' => "post-{$post->ID}", 251 'title' => $title, 252 'original_title' => $title, 253 'type' => 'post_type', 254 'type_label' => $post_type_label, 255 'object' => $post->post_type, 256 'object_id' => (int) $post->ID, 257 'url' => get_permalink( (int) $post->ID ), 254 258 ); 255 259 } … … 276 280 277 281 foreach ( $terms as $term ) { 282 $title = html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ); 278 283 $items[] = array( 279 'id' => "term-{$term->term_id}", 280 'title' => html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ), 281 'type' => 'taxonomy', 282 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name, 283 'object' => $term->taxonomy, 284 'object_id' => (int) $term->term_id, 285 'url' => get_term_link( (int) $term->term_id, $term->taxonomy ), 284 'id' => "term-{$term->term_id}", 285 'title' => $title, 286 'original_title' => $title, 287 'type' => 'taxonomy', 288 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name, 289 'object' => $term->taxonomy, 290 'object_id' => (int) $term->term_id, 291 'url' => get_term_link( (int) $term->term_id, $term->taxonomy ), 286 292 ); 287 293 } -
branches/5.8/src/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
r49624 r60828 57 57 'xfn' => '', 58 58 'status' => 'publish', 59 'original_title' => '',60 59 'nav_menu_term_id' => 0, // This will be supplied as the $menu_id arg for wp_update_nav_menu_item(). 61 60 '_invalid' => false, … … 212 211 */ 213 212 public function value() { 213 $type_label = null; 214 214 if ( $this->is_previewed && get_current_blog_id() === $this->_previewed_blog_id ) { 215 215 $undefined = new stdClass(); // Symbol. … … 220 220 } else { 221 221 $value = $post_value; 222 }223 if ( ! empty( $value ) && empty( $value['original_title'] ) ) {224 $value['original_title'] = $this->get_original_title( (object) $value );225 222 } 226 223 } elseif ( isset( $this->value ) ) { … … 235 232 $is_title_empty = empty( $post->post_title ); 236 233 $value = (array) wp_setup_nav_menu_item( $post ); 234 if ( isset( $value['type_label'] ) ) { 235 $type_label = $value['type_label']; 236 } 237 237 if ( $is_title_empty ) { 238 238 $value['title'] = ''; … … 251 251 } 252 252 253 if ( ! empty( $value ) && empty( $value['type_label'] ) ) { 254 $value['type_label'] = $this->get_type_label( (object) $value ); 253 // These properties are read-only and are part of the setting for use in the Customizer UI. 254 if ( is_array( $value ) ) { 255 $value_obj = (object) $value; 256 $value['type_label'] = isset( $type_label ) ? $type_label : $this->get_type_label( $value_obj ); 257 $value['original_title'] = $this->get_original_title( $value_obj ); 255 258 } 256 259 … … 259 262 260 263 /** 264 * Prepares the value for editing on the client. 265 * 266 * @since 6.8.3 267 * 268 * @return array|false Value prepared for the client. 269 */ 270 public function js_value() { 271 $value = parent::js_value(); 272 if ( is_array( $value ) && isset( $value['original_title'] ) ) { 273 // Decode entities for the sake of displaying the original title as a placeholder. 274 $value['original_title'] = html_entity_decode( $value['original_title'], ENT_QUOTES, get_bloginfo( 'charset' ) ); 275 } 276 return $value; 277 } 278 279 /** 261 280 * Get original title. 262 281 * … … 264 283 * 265 284 * @param object $item Nav menu item. 266 * @return string The original title .285 * @return string The original title, without entity decoding. 267 286 */ 268 287 protected function get_original_title( $item ) { … … 290 309 } 291 310 } 292 $original_title = html_entity_decode( $original_title, ENT_QUOTES, get_bloginfo( 'charset' ) );293 311 return $original_title; 294 312 } … … 346 364 $this->value['status'] = $this->value['post_status']; 347 365 unset( $this->value['post_status'] ); 348 }349 350 if ( ! isset( $this->value['original_title'] ) ) {351 $this->value['original_title'] = $this->get_original_title( (object) $this->value );352 366 } 353 367 … … 596 610 unset( $item->position ); 597 611 598 if ( empty( $item->original_title ) ) {599 $item->original_title = $this->get_original_title( $item );600 }601 612 if ( empty( $item->title ) && ! empty( $item->original_title ) ) { 602 $item->title = $item->original_title; 613 $item->title = $item->original_title; // This is NOT entity-decoded. It comes from self::get_original_title(). 603 614 } 604 615 if ( $item->title ) { … … 654 665 * 655 666 * @since 4.3.0 656 * 657 * @param array $menu_item_value The value to sanitize. 667 * @since 5.9.0 Renamed `$menu_item_value` to `$value` for PHP 8 named parameter support. 668 * 669 * @param array|false $value The menu item value to sanitize. 658 670 * @return array|false|null|WP_Error Null or WP_Error if an input isn't valid. False if it is marked for deletion. 659 671 * Otherwise the sanitized value. … … 709 721 } 710 722 711 $menu_item_value['original_title'] = sanitize_text_field( $menu_item_value['original_title'] );712 713 723 // Apply the same filters as when calling wp_insert_post(). 714 724 -
branches/5.8/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
r51295 r60828 361 361 362 362 foreach ( $query_result as $post ) { 363 if ( ! $this->check_read_permission( $post ) ) { 363 if ( 'edit' === $request['context'] ) { 364 $permission = $this->check_update_permission( $post ); 365 } else { 366 $permission = $this->check_read_permission( $post ); 367 } 368 369 if ( ! $permission ) { 364 370 continue; 365 371 } -
branches/5.8/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
r54548 r60828 331 331 332 332 foreach ( $query_result as $term ) { 333 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', $term->term_id ) ) { 334 continue; 335 } 336 333 337 $data = $this->prepare_item_for_response( $term, $request ); 334 338 $response[] = $this->prepare_response_for_collection( $data ); -
branches/5.8/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
r56884 r60828 202 202 return new WP_Error( 203 203 'rest_forbidden_context', 204 __( 'Sorry, you are not allowed to list users.' ),204 __( 'Sorry, you are not allowed to edit users.' ), 205 205 array( 'status' => rest_authorization_required_code() ) 206 206 ); … … 325 325 326 326 foreach ( $query->results as $user ) { 327 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_user', $user->ID ) ) { 328 continue; 329 } 330 327 331 $data = $this->prepare_item_for_response( $user, $request ); 328 332 $users[] = $this->prepare_response_for_collection( $data ); … … 424 428 } 425 429 426 if ( 'edit' === $request['context'] && ! current_user_can( ' list_users') ) {427 return new WP_Error( 428 'rest_ user_cannot_view',429 __( 'Sorry, you are not allowed to list users.' ),430 if ( 'edit' === $request['context'] && ! current_user_can( 'edit_user', $user->ID ) ) { 431 return new WP_Error( 432 'rest_forbidden_context', 433 __( 'Sorry, you are not allowed to edit this user.' ), 430 434 array( 'status' => rest_authorization_required_code() ) 431 435 ); 432 } elseif ( ! count_user_posts( $user->ID, $types ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) { 436 } 437 438 if ( ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) && ! count_user_posts( $user->ID, $types ) ) { 433 439 return new WP_Error( 434 440 'rest_user_cannot_view', … … 1025 1031 } 1026 1032 1027 if ( in_array( 'roles', $fields, true ) ) {1033 if ( in_array( 'roles', $fields, true ) && ( current_user_can( 'list_users' ) || current_user_can( 'edit_user', $user->ID ) ) ) { 1028 1034 // Defensively call array_values() to ensure an array is returned. 1029 1035 $data['roles'] = array_values( $user->roles ); -
branches/5.8/tests/phpunit/tests/customize/nav-menu-item-setting.php
r49624 r60828 90 90 'xfn' => '', 91 91 'status' => 'publish', 92 'original_title' => '',93 92 'nav_menu_term_id' => 0, 94 93 '_invalid' => false, … … 582 581 'xfn' => 'hello inject', 583 582 'status' => 'draft', 584 'original_title' => 'Hi ',583 'original_title' => 'Hi<script>unfilteredHtml()</script>', 585 584 'nav_menu_term_id' => 0, 586 585 ); -
branches/5.8/tests/phpunit/tests/customize/nav-menus.php
r49108 r60828 169 169 // Expected menu item array. 170 170 $expected = array( 171 'id' => "post-{$post_id}", 172 'title' => 'Post Title', 173 'type' => 'post_type', 174 'type_label' => 'Post', 175 'object' => 'post', 176 'object_id' => (int) $post_id, 177 'url' => get_permalink( (int) $post_id ), 171 'id' => "post-{$post_id}", 172 'title' => 'Post Title', 173 'original_title' => 'Post Title', 174 'type' => 'post_type', 175 'type_label' => 'Post', 176 'object' => 'post', 177 'object_id' => (int) $post_id, 178 'url' => get_permalink( (int) $post_id ), 178 179 ); 179 180 … … 201 202 // Expected menu item array. 202 203 $expected = array( 203 'id' => "post-{$page_id}", 204 'title' => 'Page Title', 205 'type' => 'post_type', 206 'type_label' => 'Page', 207 'object' => 'page', 208 'object_id' => (int) $page_id, 209 'url' => get_permalink( (int) $page_id ), 204 'id' => "post-{$page_id}", 205 'title' => 'Page Title', 206 'original_title' => 'Page Title', 207 'type' => 'post_type', 208 'type_label' => 'Page', 209 'object' => 'page', 210 'object_id' => (int) $page_id, 211 'url' => get_permalink( (int) $page_id ), 210 212 ); 211 213 … … 227 229 // Expected menu item array. 228 230 $expected = array( 229 'id' => "post-{$post_id}", 230 'title' => 'Post Title', 231 'type' => 'post_type', 232 'type_label' => 'Post', 233 'object' => 'post', 234 'object_id' => (int) $post_id, 235 'url' => get_permalink( (int) $post_id ), 231 'id' => "post-{$post_id}", 232 'title' => 'Post Title', 233 'original_title' => 'Post Title', 234 'type' => 'post_type', 235 'type_label' => 'Post', 236 'object' => 'post', 237 'object_id' => (int) $post_id, 238 'url' => get_permalink( (int) $post_id ), 236 239 ); 237 240 … … 253 256 // Expected menu item array. 254 257 $expected = array( 255 'id' => "term-{$term_id}", 256 'title' => 'Term Title', 257 'type' => 'taxonomy', 258 'type_label' => 'Category', 259 'object' => 'category', 260 'object_id' => (int) $term_id, 261 'url' => get_term_link( (int) $term_id, 'category' ), 258 'id' => "term-{$term_id}", 259 'title' => 'Term Title', 260 'original_title' => 'Term Title', 261 'type' => 'taxonomy', 262 'type_label' => 'Category', 263 'object' => 'category', 264 'object_id' => (int) $term_id, 265 'url' => get_term_link( (int) $term_id, 'category' ), 262 266 ); 263 267 -
branches/5.8/tests/phpunit/tests/rest-api/rest-users-controller.php
r49603 r60828 1127 1127 $request->set_param( 'context', 'edit' ); 1128 1128 $response = rest_get_server()->dispatch( $request ); 1129 $this->assertErrorResponse( 'rest_ user_cannot_view', $response, 401 );1129 $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 ); 1130 1130 } 1131 1131
Note: See TracChangeset
for help on using the changeset viewer.