WordPress.org

Make WordPress Core

Ticket #14134: wordpress-menuitem-3.9.patch

File wordpress-menuitem-3.9.patch, 10.0 KB (added by okax, 6 years ago)

update wordpress-menuitem.patch to work with wp 3.9

  • wordpress/wp-admin/includes/nav-menu.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    8787                        $classes[] = 'pending';
    8888                        /* translators: %s: title of menu item in draft status */
    8989                        $title = sprintf( __('%s (Pending)'), $item->title );
     90                } else {
     91                        $classes[] = 'menu-item-unchanged';
    9092                }
    9193
    9294                $title = ( ! isset( $item->label ) || '' == $item->label ) ? $title : $item->label;
     
    12531255 * @return array $messages The menu updated message
    12541256 */
    12551257function wp_nav_menu_update_menu_items ( $nav_menu_selected_id, $nav_menu_selected_title ) {
    1256         $unsorted_menu_items = wp_get_nav_menu_items( $nav_menu_selected_id, array( 'orderby' => 'ID', 'output' => ARRAY_A, 'output_key' => 'ID', 'post_status' => 'draft,publish' ) );
     1258    // Loop through all the menu items' which should be deleted
     1259    if ( ! empty( $_POST['menu-item-delete'] ) ) {
     1260        foreach ( (array) $_POST['menu-item-delete'] as $_key => $k ) {
     1261            if ( is_nav_menu_item( $_key ) ) {
     1262                wp_delete_post( $_key );
     1263            }
     1264        }
     1265    }
    12571266
    1258         $menu_items = array();
     1267    $menu_items_sorted_by_position = wp_get_nav_menu_items( $nav_menu_selected_id, array( 'orderby' => 'menu_order', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'post_status' => 'draft,publish' ) );
     1268    $unchanged_menu_items = array();
     1269    $changed_menu_items = array();
     1270
    12591271        // Index menu items by db ID
    1260         foreach ( $unsorted_menu_items as $_item )
    1261                 $menu_items[$_item->db_id] = $_item;
     1272    foreach ( $menu_items_sorted_by_position as $_item )
     1273        $unchanged_menu_items[ $_item->db_id ] = $_item;
    12621274
    12631275        $post_fields = array(
    12641276                'menu-item-db-id', 'menu-item-object-id', 'menu-item-object',
     
    12841296
    12851297                        if ( is_wp_error( $menu_item_db_id ) )
    12861298                                $messages[] = '<div id="message" class="error"><p>' . $menu_item_db_id->get_error_message() . '</p></div>';
    1287                         elseif ( isset( $menu_items[$menu_item_db_id] ) )
    1288                                 unset( $menu_items[$menu_item_db_id] );
    1289                 }
    1290         }
    1291 
    1292         // Remove menu items from the menu that weren't in $_POST
    1293         if ( ! empty( $menu_items ) ) {
    1294                 foreach ( array_keys( $menu_items ) as $menu_item_id ) {
    1295                         if ( is_nav_menu_item( $menu_item_id ) ) {
    1296                                 wp_delete_post( $menu_item_id );
    1297                         }
    1298                 }
    1299         }
     1299            else {
     1300                if ( isset( $unchanged_menu_items[ $menu_item_db_id ] ) )
     1301                    unset( $unchanged_menu_items[ $menu_item_db_id ] );
     1302                $changed_menu_items[ $args['menu-item-position'] ] = (object) array(
     1303                    'db_id' => $menu_item_db_id,
     1304                    'menu_order' => $args[ 'menu-item-position' ],
     1305                    'menu_item_parent' => $args[ 'menu-item-parent-id' ]
     1306                );
     1307                        }
     1308                }
     1309        }
     1310    wp_update_menu_item_positions( $menu_items_sorted_by_position, $unchanged_menu_items, $changed_menu_items );
    13001311
    13011312        // Store 'auto-add' pages.
    13021313        $auto_add = ! empty( $_POST['auto-add-pages'] );
     
    13201331        do_action( 'wp_update_nav_menu', $nav_menu_selected_id );
    13211332
    13221333        $messages[] = '<div id="message" class="updated"><p>' . sprintf( __( '<strong>%1$s</strong> has been updated.' ), $nav_menu_selected_title ) . '</p></div>';
    1323         unset( $menu_items, $unsorted_menu_items );
    1324 
     1334    unset( $unchanged_menu_items, $changed_menu_items, $menu_items_sorted_by_position );
    13251335        return $messages;
    13261336}
     1337/**
     1338 * Update the position of all menu items if necessary
     1339 * As only changed menu items will be posted from the browser a position change of one item can lead to a reordering
     1340 * of all other items
     1341 *
     1342 * @param array $menu_items_sorted_by_position The array of all menu items of a menu prior to the change sorted by position
     1343 * @param array $unchanged_menu_items The map of all unchanged menu items with db_id as key
     1344 * @param array $changed_menu_items The map of all changed or new menu items with the position as key
     1345 */
     1346function wp_update_menu_item_positions( $menu_items_sorted_by_position, $unchanged_menu_items, $changed_menu_items)
     1347{
     1348    $total_menu_item_count = count( $unchanged_menu_items ) + count( $changed_menu_items );
     1349
     1350    // Create an array that associate a parent id to an array of all direct child items to this parent
     1351    $menu_items_grouped_by_parent_id = array();
     1352    foreach ( $menu_items_sorted_by_position as $menu_item ) {
     1353        // Only unchanged menu items should be in the array
     1354        if ( isset( $unchanged_menu_items[ $menu_item->db_id ] ) ) {
     1355            $menu_items_grouped_by_parent_id[ $menu_item->menu_item_parent ][ ] = $menu_item;
     1356        }
     1357    }
     1358
     1359    $menu_items_for_current_parent_id = &$menu_items_grouped_by_parent_id[ 0 ];
     1360    $parent_id_stack = array( 0 );
     1361
     1362    // Loop over all indices, calculate the menu item for each index and assign the index as menu_order value.
     1363    // Every time a menu item has child items, the item id is put on top of the $parent_id_stack and the array with
     1364    // all child items is assigned to $menu_items_for_current_parent_id.
     1365    for ( $index = 1; $index <= $total_menu_item_count; $index ++ ) {
     1366        if ( isset( $changed_menu_items[ $index ] ) ) {
     1367            // at this position is a new or changed item and the position was already saved
     1368            $id = $changed_menu_items[ $index ]->db_id;
     1369        } else {
     1370            $menu_item = current( $menu_items_for_current_parent_id );
     1371            // update the position if needed
     1372            if ( $menu_item->menu_order != $index ) {
     1373                $menu_item->menu_order = $index;
     1374                wp_update_post( $menu_item );
     1375            }
     1376            $id = $menu_item->db_id;
     1377            next( $menu_items_for_current_parent_id );
     1378        }
     1379
     1380        if ( isset( $menu_items_grouped_by_parent_id[ $id ] ) or
     1381            (
     1382                isset( $changed_menu_items[ $index + 1 ] ) and
     1383                $changed_menu_items[ $index + 1 ]->menu_item_parent == $id
     1384            )
     1385        ) {
     1386            // there exist a child for the item at the current index
     1387            array_push( $parent_id_stack, $id );
     1388            // get the children for this parent to iterate over
     1389            $menu_items_for_current_parent_id = &$menu_items_grouped_by_parent_id[ $id ];
     1390        } else {
     1391            if ( isset( $changed_menu_items[ $index + 1 ] ) ) {
     1392                // next menu item is a changed one and not a child of the current menu item
     1393                // pop from the stack until the correct parent for the next item is found
     1394                $parentId = $changed_menu_items[ $index + 1 ]->menu_item_parent;
     1395                while ( ! empty( $parent_id_stack ) and end( $parent_id_stack ) != $parentId ) {
     1396                    array_pop( $parent_id_stack );
     1397                }
     1398            } else {
     1399                if ( isset( $menu_items_for_current_parent_id ) ) {
     1400                    $menu_item = current( $menu_items_for_current_parent_id );
     1401                } else {
     1402                    $menu_item = false;
     1403                }
     1404                while ( false == $menu_item ) {
     1405                    if ( empty( $parent_id_stack ) ) break;
     1406                    array_pop( $parent_id_stack );
     1407                    $menu_items_for_current_parent_id = &$menu_items_grouped_by_parent_id[ end( $parent_id_stack ) ];
     1408                    if ( isset( $menu_items_for_current_parent_id ) ) {
     1409                        $menu_item = current( $menu_items_for_current_parent_id );
     1410                    }
     1411                }
     1412            }
     1413        }
     1414    }
     1415}
     1416
  • wordpress/wp-admin/js/nav-menu.js

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    643643                                                updateMenuMaxDepth( depthChange );
    644644                                        }
    645645                                        // Register a change
    646                                         api.registerChange();
     646                                        api.registerChange( ui.item );
    647647                                        // Update the item data.
    648648                                        ui.item.updateParentMenuItemDBId();
    649649
     
    948948                },
    949949
    950950                attachUnsavedChangesListener : function() {
    951                         $('#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select').change(function(){
    952                                 api.registerChange();
     951                        $('#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select').change(function(changeEvent){
     952                                var menuItem = $(changeEvent.target).parents('.menu-item');
     953                                api.registerChange( menuItem );
    953954                        });
    954955
    955956                        if ( 0 !== $('#menu-to-edit').length || 0 !== $('.menu-location-menus select').length ) {
     
    963964                        }
    964965                },
    965966
    966                 registerChange : function() {
     967                registerChange:function( menuItem ) {
     968                        if ( menuItem !== undefined ) {
     969                                menuItem.removeClass( "menu-item-unchanged" );
     970                        }
    967971                        api.menusChanged = true;
    968972                },
    969973
     
    10881092                        $('#update-nav-menu').append( locs );
    10891093                        // Update menu item position data
    10901094                        api.menuList.find('.menu-item-data-position').val( function(index) { return index + 1; } );
     1095                        //disable unchanged items before submit
     1096                        api.menuList.find('.menu-item-unchanged :input').each(function() { $(this).attr("disabled", "disabled"); } );
    10911097                        window.onbeforeunload = null;
    10921098
    10931099                        return true;
     
    11041110
    11051111                eventOnClickMenuItemDelete : function(clickedEl) {
    11061112                        var itemID = parseInt(clickedEl.id.replace('delete-', ''), 10);
    1107                         api.removeMenuItem( $('#menu-item-' + itemID) );
     1113                        api.removeMenuItem( $('#menu-item-' + itemID), itemID );
    11081114                        api.registerChange();
    11091115                        return false;
    11101116                },
     
    11561162                        $('.spinner', panel).hide();
    11571163                },
    11581164
    1159                 removeMenuItem : function(el) {
     1165                removeMenuItem : function(el, itemId) {
    11601166                        var children = el.childMenuItems();
     1167
     1168                        //add deleted entry to the form
     1169                        var deleted = '<input type="hidden" name="menu-item-delete[' + itemId + ']" value="' + itemId + '" />';
     1170                        $('#update-nav-menu').append( deleted );
    11611171
    11621172                        el.addClass('deleting').animate({
    11631173                                        opacity : 0,