Make WordPress Core


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/nav-menu.php

    r15235 r15008  
    1717 *
    1818 * @param string $menu Menu id, slug or name
    19  * @return mixed false if $menu param isn't supplied or term does not exist, menu object if successful.
     19 * @return mixed false if $menu param isn't supplied or term does not exist, menu object if successfull
    2020 */
    2121function wp_get_nav_menu_object( $menu ) {
     
    3131                $menu_obj = get_term_by( 'name', $menu, 'nav_menu' );
    3232
    33         if ( ! $menu_obj )
     33        if ( ! $menu_obj ) {
    3434                $menu_obj = false;
     35        }
    3536
    3637        return $menu_obj;
     
    3839
    3940/**
    40  * Check if the given ID is a navigation menu.
     41 * Check if the given ID is a nav menu.
    4142 *
    4243 * Returns true if it is; false otherwise.
     
    6566
    6667/**
    67  * Register navigation menus for a theme.
     68 * Register nav menus for a theme.
    6869 *
    6970 * @since 3.0.0
     
    7475        global $_wp_registered_nav_menus;
    7576
    76         add_theme_support( 'menus' );
     77        add_theme_support( 'nav-menus' );
    7778
    7879        $_wp_registered_nav_menus = array_merge( (array) $_wp_registered_nav_menus, $locations );
     
    8081
    8182/**
    82  * Register a navigation menu for a theme.
     83 * Register nav menu for a theme.
    8384 *
    8485 * @since 3.0.0
     
    9192}
    9293/**
    93  * Returns an array of all registered navigation menus in a theme
     94 * Returns an array of all registered nav menus in a theme
    9495 *
    9596 * @since 3.0.0
     
    104105
    105106/**
    106  * Returns an array with the registered navigation menu locations and the menu assigned to it
     107 * Returns an array with the registered nav menu locations and the menu assigned to it
    107108 *
    108109 * @since 3.0.0
     
    111112
    112113function get_nav_menu_locations() {
    113         return get_theme_mod( 'nav_menu_locations' );
    114 }
    115 
    116 /**
    117  * Whether a registered nav menu location has a menu assigned to it.
    118  *
    119  * @since 3.0.0
    120  * @param string $location Menu location identifier.
    121  * @return bool Whether location has a menu.
    122  */
    123 function has_nav_menu( $location ) {
    124         $locations = get_nav_menu_locations();
    125         return ( ! empty( $locations[ $location ] ) );
     114        return get_theme_mod('nav_menu_locations');
    126115}
    127116
     
    141130 * Create a Navigation Menu.
    142131 *
     132 * Optional args:
     133 * slug - the url friendly version of the nav menu.
     134 *
    143135 * @since 3.0.0
    144136 *
    145137 * @param string $menu_name Menu Name
    146  * @return mixed Menu object on success|WP_Error on failure
    147  */
    148 function wp_create_nav_menu( $menu_name ) {
    149         return wp_update_nav_menu_object( 0, array( 'menu-name' => $menu_name ) );
     138 * @param string $args Optional.
     139 * @return mixed Menu object on sucess|WP_Error on failure
     140 */
     141function wp_create_nav_menu( $menu_name, $args = array() ) {
     142        $menu_exists = get_term_by( 'name', $menu_name, 'nav_menu' );
     143
     144        if ( $menu_exists )
     145                return new WP_Error( 'menu_exists', sprintf( __('The menu name <strong>%s</strong> conflicts with another menu name. Please try another.'), esc_html( $menu_name ) ) );
     146
     147        $menu = wp_insert_term( $menu_name, 'nav_menu' );
     148
     149        if ( is_wp_error($menu) )
     150                return $menu;
     151
     152        $result = get_term( $menu['term_id'], 'nav_menu' );
     153
     154        if ( $result && !is_wp_error($result) ) {
     155                do_action( 'wp_create_nav_menu', $menu['term_id'] );
     156                return $result;
     157        } else {
     158                return $result;
     159        }
    150160}
    151161
     
    156166 *
    157167 * @param string $menu name|id|slug
    158  * @return mixed Menu object on success|WP_Error on failure
     168 * @return mixed Menu object on sucess|WP_Error on failure
    159169 */
    160170function wp_delete_nav_menu( $menu ) {
    161171        $menu = wp_get_nav_menu_object( $menu );
    162         if ( ! $menu )
     172        if ( ! $menu  )
    163173                return false;
    164174
    165175        $menu_objects = get_objects_in_term( $menu->term_id, 'nav_menu' );
    166         if ( ! empty( $menu_objects ) ) {
     176        if ( !empty( $menu_objects ) ) {
    167177                foreach ( $menu_objects as $item ) {
    168178                        wp_delete_post( $item );
     
    172182        $result = wp_delete_term( $menu->term_id, 'nav_menu' );
    173183
    174         if ( $result && !is_wp_error($result) )
     184        if ( $result && !is_wp_error($result) ) {
    175185                do_action( 'wp_delete_nav_menu', $menu->term_id );
    176 
    177         return $result;
     186                return $result;
     187        } else {
     188                return $result;
     189        }
    178190}
    179191
     
    183195 * @since 3.0.0
    184196 *
    185  * @param int $menu_id The ID of the menu or "0" to create a new menu.
     197 * @param int $menu_id The ID of the menu
    186198 * @param array $menu_data The array of menu data.
    187199 * @return int|error object The menu's ID or WP_Error object.
     
    192204        $_menu = wp_get_nav_menu_object( $menu_id );
    193205
    194         $args = array(
    195                 'description' => ( isset( $menu_data['description'] ) ? $menu_data['description']  : '' ),
    196                 'name'        => ( isset( $menu_data['menu-name']   ) ? $menu_data['menu-name']    : '' ),
    197                 'parent'      => ( isset( $menu_data['parent']      ) ? (int) $menu_data['parent'] : 0  ),
    198                 'slug'        => null,
    199         );
    200 
    201         // double-check that we're not going to have one menu take the name of another
    202         $_possible_existing = get_term_by( 'name', $menu_data['menu-name'], 'nav_menu' );
    203         if (
    204                 $_possible_existing &&
    205                 ! is_wp_error( $_possible_existing ) &&
    206                 isset( $_possible_existing->term_id ) &&
    207                 $_possible_existing->term_id != $menu_id
    208         )
    209                 return new WP_Error( 'menu_exists', sprintf( __('The menu name <strong>%s</strong> conflicts with another menu name. Please try another.'), esc_html( $menu_data['menu-name'] ) ) );
    210 
    211         // menu doesn't already exist, so create a new menu
    212         if ( ! $_menu || is_wp_error( $_menu ) ) {
    213                 $menu_exists = get_term_by( 'name', $menu_data['menu-name'], 'nav_menu' );
    214 
    215                 if ( $menu_exists )
     206        // menu doesn't already exist
     207        if ( ! $_menu || is_wp_error( $_menu ) )
     208                $_menu = wp_create_nav_menu( $menu_data['menu-name'] );
     209
     210        if ( is_wp_error( $_menu ) )
     211                return $_menu;
     212
     213        if ( $_menu && isset( $_menu->term_id ) ) {
     214                $args = array(
     215                        'description' => ( isset( $menu_data['description'] ) ? $menu_data['description'] : '' ),
     216                        'name' => ( isset( $menu_data['menu-name'] ) ? $menu_data['menu-name'] : '' ),
     217                        'parent' => ( isset( $menu_data['parent'] ) ? (int) $menu_data['parent'] : 0 ),
     218                        'slug' => null,
     219                );
     220
     221                $menu_id = (int) $_menu->term_id;
     222
     223                // double-check that we're not changing a menu to the name of another
     224                $_possible_existing = get_term_by( 'name', $menu_data['menu-name'], 'nav_menu' );
     225                if (
     226                        $_possible_existing &&
     227                        ! is_wp_error( $_possible_existing ) &&
     228                        isset( $_possible_existing->term_id ) &&
     229                        $_possible_existing->term_id != $menu_id
     230                ) {
    216231                        return new WP_Error( 'menu_exists', sprintf( __('The menu name <strong>%s</strong> conflicts with another menu name. Please try another.'), esc_html( $menu_data['menu-name'] ) ) );
    217 
    218                 $_menu = wp_insert_term( $menu_data['menu-name'], 'nav_menu', $args );
    219 
    220                 if ( is_wp_error( $_menu ) )
    221                         return $_menu;
    222 
    223                 do_action( 'wp_create_nav_menu', $_menu['term_id'], $menu_data );
    224 
    225                 return (int) $_menu['term_id'];
    226         }
    227 
    228         if ( ! $_menu || ! isset( $_menu->term_id ) )
     232                }
     233
     234                $update_response = wp_update_term( $menu_id, 'nav_menu', $args );
     235
     236                if ( ! is_wp_error( $update_response ) )
     237                        return $menu_id;
     238                else
     239                        return $update_response;
     240        } else {
    229241                return 0;
    230 
    231         $menu_id = (int) $_menu->term_id;
    232 
    233         $update_response = wp_update_term( $menu_id, 'nav_menu', $args );
    234 
    235         if ( is_wp_error( $update_response ) )
    236                 return $update_response;
    237 
    238         do_action( 'wp_update_nav_menu', $menu_id, $menu_data );
    239         return $menu_id;
     242        }
    240243}
    241244
     
    245248 * @since 3.0.0
    246249 *
    247  * @param int $menu_id The ID of the menu. Required. If "0", makes the menu item a pending orphan.
     250 * @param int $menu_id The ID of the menu. Required. If "0", makes the menu item a draft orphan.
    248251 * @param int $menu_item_db_id The ID of the menu item. If "0", creates a new menu item.
    249252 * @param array $menu_item_data The menu item's data.
     
    263266                return $menu;
    264267
    265         $menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'draft,pending,publish' ) );
     268        $menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) );
    266269
    267270        $count = count( $menu_items );
     
    285288
    286289        $args = wp_parse_args( $menu_item_data, $defaults );
    287 
     290       
    288291        if ( 0 == $menu_id ) {
    289292                $args['menu-item-position'] = 1;
     
    313316                        $original_title = $original_object->post_title;
    314317
    315                         if ( 'trash' == get_post_status( $args['menu-item-object-id'] ) )
     318                        if ( 'trash' == get_post_status( $args['menu-item-object-id'] ) ) {
    316319                                return new WP_Error('update_nav_menu_item_failed', sprintf(__('The menu item "%1$s" belongs to something that is in the trash, so it cannot be updated.'), $args['menu-item-title'] ) );
     320                        }
    317321                }
    318322
     
    321325
    322326                        // hack to get wp to create a post object when too many properties are empty
    323                         if ( empty( $args['menu-item-description'] ) )
     327                        if ( empty( $args['menu-item-description'] ) ) {
    324328                                $args['menu-item-description'] = ' ';
     329                        }
    325330                }
    326331        }
     
    340345                $post['tax_input'] = array( 'nav_menu' => array( intval( $menu->term_id ) ) );
    341346
    342         // New menu item. Default is pending status
     347        // New menu item. Default is draft status
    343348        if ( 0 == $menu_item_db_id ) {
    344349                $post['ID'] = 0;
    345                 $post['post_status'] = 'publish' == $args['menu-item-status'] ? 'publish' : 'pending';
     350                $post['post_status'] = 'publish' == $args['menu-item-status'] ? 'publish' : 'draft';
    346351                $menu_item_db_id = wp_insert_post( $post );
    347352
     
    358363        }
    359364
    360         if ( ! $menu_item_db_id || is_wp_error( $menu_item_db_id ) )
    361                 return $menu_item_db_id;
    362 
    363         $menu_item_db_id = (int) $menu_item_db_id;
    364 
    365         update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key($args['menu-item-type']) );
    366         update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (int) $args['menu-item-parent-id'] );
    367         update_post_meta( $menu_item_db_id, '_menu_item_object_id', (int) $args['menu-item-object-id'] );
    368         update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key($args['menu-item-object']) );
    369         update_post_meta( $menu_item_db_id, '_menu_item_target', sanitize_key($args['menu-item-target']) );
    370 
    371         $args['menu-item-classes'] = array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-classes'] ) );
    372         $args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) );
    373         update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] );
    374         update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] );
    375         update_post_meta( $menu_item_db_id, '_menu_item_url', esc_url_raw($args['menu-item-url']) );
    376 
    377         if ( 0 == $menu_id )
    378                 update_post_meta( $menu_item_db_id, '_menu_item_orphaned', time() );
    379         else
    380                 delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' );
    381 
    382         do_action('wp_update_nav_menu_item', $menu_id, $menu_item_db_id, $args );
     365        if ( $menu_item_db_id && ! is_wp_error( $menu_item_db_id ) ) {
     366
     367                $menu_item_db_id = (int) $menu_item_db_id;
     368
     369                update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key($args['menu-item-type']) );
     370                update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (int) $args['menu-item-parent-id'] );
     371                update_post_meta( $menu_item_db_id, '_menu_item_object_id', (int) $args['menu-item-object-id'] );
     372                update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key($args['menu-item-object']) );
     373                update_post_meta( $menu_item_db_id, '_menu_item_target', sanitize_key($args['menu-item-target']) );
     374               
     375                $args['menu-item-classes'] = array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-classes'] ) );
     376                $args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) );
     377                update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] );
     378                update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] );
     379                update_post_meta( $menu_item_db_id, '_menu_item_url', esc_url_raw($args['menu-item-url']) );
     380               
     381                if ( 0 == $menu_id )
     382                        update_post_meta( $menu_item_db_id, '_menu_item_orphaned', time() );
     383                else
     384                        delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' );
     385
     386                do_action('wp_update_nav_menu_item', $menu_id, $menu_item_db_id, $args );
     387        }
    383388
    384389        return $menu_item_db_id;
     
    396401        $defaults = array( 'hide_empty' => false, 'orderby' => 'none' );
    397402        $args = wp_parse_args( $args, $defaults );
    398         return apply_filters( 'wp_get_nav_menus', get_terms( 'nav_menu',  $args), $args );
    399 }
     403        return get_terms( 'nav_menu',  $args);
     404}
     405
    400406
    401407/**
     
    409415 * @return int -1, 0, or 1 if $a is considered to be respectively less than, equal to, or greater than $b.
    410416 */
    411 function _sort_nav_menu_items( $a, $b ) {
     417function _sort_nav_menu_items($a, $b) {
    412418        global $_menu_item_sort_prop;
    413419
    414         if ( empty( $_menu_item_sort_prop ) )
     420        if ( empty( $_menu_item_sort_prop ) ) {
    415421                return 0;
    416 
    417         if ( ! isset( $a->$_menu_item_sort_prop ) || ! isset( $b->$_menu_item_sort_prop ) )
     422        }
     423
     424        if ( isset( $a->$_menu_item_sort_prop ) && isset( $b->$_menu_item_sort_prop ) ) {
     425                $_a = (int) $a->$_menu_item_sort_prop;
     426                $_b = (int) $b->$_menu_item_sort_prop;
     427
     428                if ( $a->$_menu_item_sort_prop == $b->$_menu_item_sort_prop ) {
     429                        return 0;
     430                } elseif (
     431                        ( $_a == $a->$_menu_item_sort_prop ) &&
     432                        ( $_b == $b->$_menu_item_sort_prop )
     433                ) {
     434                        return $_a < $_b ? -1 : 1;
     435                } else {
     436                        return strcmp( $a->$_menu_item_sort_prop, $b->$_menu_item_sort_prop );
     437                }
     438        } else {
    418439                return 0;
    419 
    420         $_a = (int) $a->$_menu_item_sort_prop;
    421         $_b = (int) $b->$_menu_item_sort_prop;
    422 
    423         if ( $a->$_menu_item_sort_prop == $b->$_menu_item_sort_prop )
    424                 return 0;
    425         elseif ( $_a == $a->$_menu_item_sort_prop && $_b == $b->$_menu_item_sort_prop )
    426                 return $_a < $_b ? -1 : 1;
    427         else
    428                 return strcmp( $a->$_menu_item_sort_prop, $b->$_menu_item_sort_prop );
     440        }
    429441}
    430442
     
    453465                return $items;
    454466
    455         $defaults = array( 'order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item',
    456                 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
    457                 'update_post_term_cache' => false );
     467        $defaults = array( 'order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item', 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true,
     468                                          'update_post_term_cache' => false);
    458469        $args = wp_parse_args( $args, $defaults );
    459470        if ( count( $items ) > 1 )
     
    468479
    469480        // Get all posts and terms at once to prime the caches
    470         if ( empty( $fetched[$menu->term_id] ) || $_wp_using_ext_object_cache ) {
     481        if ( empty($fetched[$menu->term_id]) || $_wp_using_ext_object_cache ) {
    471482                $fetched[$menu->term_id] = true;
    472483                $posts = array();
     
    474485                foreach ( $items as $item ) {
    475486                        $object_id = get_post_meta( $item->ID, '_menu_item_object_id', true );
    476                         $object    = get_post_meta( $item->ID, '_menu_item_object',    true );
    477                         $type      = get_post_meta( $item->ID, '_menu_item_type',      true );
     487                        $object = get_post_meta( $item->ID, '_menu_item_object', true );
     488                        $type = get_post_meta( $item->ID, '_menu_item_type', true );
    478489
    479490                        if ( 'post_type' == $type )
     
    483494                }
    484495
    485                 if ( ! empty( $posts ) ) {
     496                if ( !empty($posts) ) {
    486497                        foreach ( array_keys($posts) as $post_type ) {
    487498                                get_posts( array('post__in' => $posts[$post_type], 'post_type' => $post_type, 'nopaging' => true, 'update_post_term_cache' => false) );
     
    490501                unset($posts);
    491502
    492                 if ( ! empty( $terms ) ) {
     503                if ( !empty($terms) ) {
    493504                        foreach ( array_keys($terms) as $taxonomy ) {
    494505                                get_terms($taxonomy, array('include' => $terms[$taxonomy]) );
     
    645656        foreach( (array) $menu_items as $menu_item ) {
    646657                if ( isset( $menu_item->ID ) && is_nav_menu_item( $menu_item->ID ) ) {
    647                         if ( get_post_meta( $menu_item->ID, '_menu_item_type', true ) != $object_type )
     658                        if ( get_post_meta($menu_item->ID, '_menu_item_type', true) != $object_type )
    648659                                continue;
    649660
     
    671682        foreach( (array) $menu_item_ids as $menu_item_id ) {
    672683                $menu_item = get_post( $menu_item_id, ARRAY_A );
    673                 $menu_item['post_status'] = 'pending';
     684                $menu_item['post_status'] = 'draft';
    674685                wp_insert_post($menu_item);
    675686        }
     
    736747
    737748/**
    738  * Modify a navigational menu upon post object status change, if appropos.
     749 * Automatically add newly published page objects to menus with that as an option.
    739750 *
    740751 * @since 3.0.0
     
    746757 * @return void
    747758 */
    748 function _wp_menu_changing_status_observer( $new_status, $old_status, $post ) {
    749         // append new top-level page objects to a menu for which that option is selected
    750         if (
    751                 'publish' == $new_status &&
    752                 'publish' != $old_status &&
    753                 'page' == $post->post_type &&
    754                 empty( $post->post_parent )
    755         ) {
    756                 $auto_add = get_option( 'nav_menu_options' );
    757                 if (
    758                         isset( $auto_add['auto_add'] ) &&
    759                         is_array( $auto_add['auto_add'] )
    760                 ) {
    761                         $args = array(
    762                                 'menu-item-object-id' => $post->ID,
    763                                 'menu-item-object' => $post->post_type,
    764                                 'menu-item-type' => 'post_type',
    765                                 'menu-item-status' => 'publish',
    766                         );
    767 
    768                         foreach ( $auto_add['auto_add'] as $menu_id ) {
    769                                 $items = wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'draft,pending,publish' ) );
    770                                 if ( ! is_array( $items ) )
    771                                         continue;
    772                                 foreach ( $items as $item ) {
    773                                         if ( $post->ID == $item->object_id )
    774                                                 continue 2;
    775                                 }
    776                                 wp_update_nav_menu_item( $menu_id, 0, $args );
    777                         }
    778                 }
    779         }
    780 
    781         // give menu items draft status if their associated post objects change from "publish" to "draft", or vice versa (draft item being re-published)
    782         if (
    783                 ! empty( $post->ID ) &&
    784                 (
    785                         ( 'publish' == $old_status && 'draft' == $new_status ) ||
    786                         ( 'draft' == $old_status && 'publish' == $new_status )
    787                 )
    788         ) {
    789                 $menu_items = get_posts(array(
    790                         'meta_key' => '_menu_item_object_id',
    791                         'meta_value' => $post->ID,
    792                         'post_status' => 'any',
    793                         'post_type' => 'nav_menu_item',
    794                 ));
    795 
    796                 foreach( (array) $menu_items as $menu_item ) {
    797                         if ( ! empty( $menu_item->ID ) ) {
    798                                 $properties = get_object_vars( $menu_item );
    799                                 $properties['post_status'] = $new_status;
    800 
    801                                 wp_insert_post( $properties );
    802                         }
    803                 }
    804         }
    805 }
     759function _wp_auto_add_pages_to_menu( $new_status, $old_status, $post ) {
     760        if ( 'publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type )
     761                return;
     762        $auto_add = get_option( 'nav_menu_options' );
     763        if ( empty( $auto_add ) || ! is_array( $auto_add ) || ! isset( $auto_add['auto_add'] ) )
     764                return;
     765        $auto_add = $auto_add['auto_add'];
     766        if ( empty( $auto_add ) || ! is_array( $auto_add ) )
     767                return;
     768
     769        $args = array(
     770                'menu-item-object-id' => $post->ID,
     771                'menu-item-object' => $post->post_type,
     772                'menu-item-type' => 'post_type',
     773                'menu-item-status' => 'publish',
     774        );
     775
     776        foreach ( $auto_add as $menu_id ) {
     777                $items = wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) );
     778                if ( ! is_array( $items ) )
     779                        continue;
     780                foreach ( $items as $item ) {
     781                        if ( $post->ID == $item->object_id )
     782                                continue 2;
     783                }
     784                wp_update_nav_menu_item( $menu_id, 0, $args );
     785        }
     786}
     787add_action( 'transition_post_status', '_wp_auto_add_pages_to_menu', 10, 3 );
    806788
    807789?>
Note: See TracChangeset for help on using the changeset viewer.