Make WordPress Core


Ignore:
File:
1 edited

Legend:

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

    r15008 r15235  
    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 successfull
     19 * @return mixed false if $menu param isn't supplied or term does not exist, menu object if successful.
    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         }
    3635
    3736        return $menu_obj;
     
    3938
    4039/**
    41  * Check if the given ID is a nav menu.
     40 * Check if the given ID is a navigation menu.
    4241 *
    4342 * Returns true if it is; false otherwise.
     
    6665
    6766/**
    68  * Register nav menus for a theme.
     67 * Register navigation menus for a theme.
    6968 *
    7069 * @since 3.0.0
     
    7574        global $_wp_registered_nav_menus;
    7675
    77         add_theme_support( 'nav-menus' );
     76        add_theme_support( 'menus' );
    7877
    7978        $_wp_registered_nav_menus = array_merge( (array) $_wp_registered_nav_menus, $locations );
     
    8180
    8281/**
    83  * Register nav menu for a theme.
     82 * Register a navigation menu for a theme.
    8483 *
    8584 * @since 3.0.0
     
    9291}
    9392/**
    94  * Returns an array of all registered nav menus in a theme
     93 * Returns an array of all registered navigation menus in a theme
    9594 *
    9695 * @since 3.0.0
     
    105104
    106105/**
    107  * Returns an array with the registered nav menu locations and the menu assigned to it
     106 * Returns an array with the registered navigation menu locations and the menu assigned to it
    108107 *
    109108 * @since 3.0.0
     
    112111
    113112function get_nav_menu_locations() {
    114         return get_theme_mod('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 */
     123function has_nav_menu( $location ) {
     124        $locations = get_nav_menu_locations();
     125        return ( ! empty( $locations[ $location ] ) );
    115126}
    116127
     
    130141 * Create a Navigation Menu.
    131142 *
    132  * Optional args:
    133  * slug - the url friendly version of the nav menu.
    134  *
    135143 * @since 3.0.0
    136144 *
    137145 * @param string $menu_name Menu Name
    138  * @param string $args Optional.
    139  * @return mixed Menu object on sucess|WP_Error on failure
    140  */
    141 function 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         }
     146 * @return mixed Menu object on success|WP_Error on failure
     147 */
     148function wp_create_nav_menu( $menu_name ) {
     149        return wp_update_nav_menu_object( 0, array( 'menu-name' => $menu_name ) );
    160150}
    161151
     
    166156 *
    167157 * @param string $menu name|id|slug
    168  * @return mixed Menu object on sucess|WP_Error on failure
     158 * @return mixed Menu object on success|WP_Error on failure
    169159 */
    170160function wp_delete_nav_menu( $menu ) {
    171161        $menu = wp_get_nav_menu_object( $menu );
    172         if ( ! $menu  )
     162        if ( ! $menu )
    173163                return false;
    174164
    175165        $menu_objects = get_objects_in_term( $menu->term_id, 'nav_menu' );
    176         if ( !empty( $menu_objects ) ) {
     166        if ( ! empty( $menu_objects ) ) {
    177167                foreach ( $menu_objects as $item ) {
    178168                        wp_delete_post( $item );
     
    182172        $result = wp_delete_term( $menu->term_id, 'nav_menu' );
    183173
    184         if ( $result && !is_wp_error($result) ) {
     174        if ( $result && !is_wp_error($result) )
    185175                do_action( 'wp_delete_nav_menu', $menu->term_id );
    186                 return $result;
    187         } else {
    188                 return $result;
    189         }
     176
     177        return $result;
    190178}
    191179
     
    195183 * @since 3.0.0
    196184 *
    197  * @param int $menu_id The ID of the menu
     185 * @param int $menu_id The ID of the menu or "0" to create a new menu.
    198186 * @param array $menu_data The array of menu data.
    199187 * @return int|error object The menu's ID or WP_Error object.
     
    204192        $_menu = wp_get_nav_menu_object( $menu_id );
    205193
    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                 ) {
     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 )
    231216                        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'] ) ) );
    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 {
     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 ) )
    241229                return 0;
    242         }
     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;
    243240}
    244241
     
    248245 * @since 3.0.0
    249246 *
    250  * @param int $menu_id The ID of the menu. Required. If "0", makes the menu item a draft orphan.
     247 * @param int $menu_id The ID of the menu. Required. If "0", makes the menu item a pending orphan.
    251248 * @param int $menu_item_db_id The ID of the menu item. If "0", creates a new menu item.
    252249 * @param array $menu_item_data The menu item's data.
     
    266263                return $menu;
    267264
    268         $menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) );
     265        $menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'draft,pending,publish' ) );
    269266
    270267        $count = count( $menu_items );
     
    288285
    289286        $args = wp_parse_args( $menu_item_data, $defaults );
    290        
     287
    291288        if ( 0 == $menu_id ) {
    292289                $args['menu-item-position'] = 1;
     
    316313                        $original_title = $original_object->post_title;
    317314
    318                         if ( 'trash' == get_post_status( $args['menu-item-object-id'] ) ) {
     315                        if ( 'trash' == get_post_status( $args['menu-item-object-id'] ) )
    319316                                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                         }
    321317                }
    322318
     
    325321
    326322                        // hack to get wp to create a post object when too many properties are empty
    327                         if ( empty( $args['menu-item-description'] ) ) {
     323                        if ( empty( $args['menu-item-description'] ) )
    328324                                $args['menu-item-description'] = ' ';
    329                         }
    330325                }
    331326        }
     
    345340                $post['tax_input'] = array( 'nav_menu' => array( intval( $menu->term_id ) ) );
    346341
    347         // New menu item. Default is draft status
     342        // New menu item. Default is pending status
    348343        if ( 0 == $menu_item_db_id ) {
    349344                $post['ID'] = 0;
    350                 $post['post_status'] = 'publish' == $args['menu-item-status'] ? 'publish' : 'draft';
     345                $post['post_status'] = 'publish' == $args['menu-item-status'] ? 'publish' : 'pending';
    351346                $menu_item_db_id = wp_insert_post( $post );
    352347
     
    363358        }
    364359
    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         }
     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 );
    388383
    389384        return $menu_item_db_id;
     
    401396        $defaults = array( 'hide_empty' => false, 'orderby' => 'none' );
    402397        $args = wp_parse_args( $args, $defaults );
    403         return get_terms( 'nav_menu',  $args);
    404 }
    405 
     398        return apply_filters( 'wp_get_nav_menus', get_terms( 'nav_menu',  $args), $args );
     399}
    406400
    407401/**
     
    415409 * @return int -1, 0, or 1 if $a is considered to be respectively less than, equal to, or greater than $b.
    416410 */
    417 function _sort_nav_menu_items($a, $b) {
     411function _sort_nav_menu_items( $a, $b ) {
    418412        global $_menu_item_sort_prop;
    419413
    420         if ( empty( $_menu_item_sort_prop ) ) {
     414        if ( empty( $_menu_item_sort_prop ) )
    421415                return 0;
    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 {
     416
     417        if ( ! isset( $a->$_menu_item_sort_prop ) || ! isset( $b->$_menu_item_sort_prop ) )
    439418                return 0;
    440         }
     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 );
    441429}
    442430
     
    465453                return $items;
    466454
    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);
     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 );
    469458        $args = wp_parse_args( $args, $defaults );
    470459        if ( count( $items ) > 1 )
     
    479468
    480469        // Get all posts and terms at once to prime the caches
    481         if ( empty($fetched[$menu->term_id]) || $_wp_using_ext_object_cache ) {
     470        if ( empty( $fetched[$menu->term_id] ) || $_wp_using_ext_object_cache ) {
    482471                $fetched[$menu->term_id] = true;
    483472                $posts = array();
     
    485474                foreach ( $items as $item ) {
    486475                        $object_id = get_post_meta( $item->ID, '_menu_item_object_id', true );
    487                         $object = get_post_meta( $item->ID, '_menu_item_object', true );
    488                         $type = get_post_meta( $item->ID, '_menu_item_type', true );
     476                        $object    = get_post_meta( $item->ID, '_menu_item_object',    true );
     477                        $type      = get_post_meta( $item->ID, '_menu_item_type',      true );
    489478
    490479                        if ( 'post_type' == $type )
     
    494483                }
    495484
    496                 if ( !empty($posts) ) {
     485                if ( ! empty( $posts ) ) {
    497486                        foreach ( array_keys($posts) as $post_type ) {
    498487                                get_posts( array('post__in' => $posts[$post_type], 'post_type' => $post_type, 'nopaging' => true, 'update_post_term_cache' => false) );
     
    501490                unset($posts);
    502491
    503                 if ( !empty($terms) ) {
     492                if ( ! empty( $terms ) ) {
    504493                        foreach ( array_keys($terms) as $taxonomy ) {
    505494                                get_terms($taxonomy, array('include' => $terms[$taxonomy]) );
     
    656645        foreach( (array) $menu_items as $menu_item ) {
    657646                if ( isset( $menu_item->ID ) && is_nav_menu_item( $menu_item->ID ) ) {
    658                         if ( get_post_meta($menu_item->ID, '_menu_item_type', true) != $object_type )
     647                        if ( get_post_meta( $menu_item->ID, '_menu_item_type', true ) != $object_type )
    659648                                continue;
    660649
     
    682671        foreach( (array) $menu_item_ids as $menu_item_id ) {
    683672                $menu_item = get_post( $menu_item_id, ARRAY_A );
    684                 $menu_item['post_status'] = 'draft';
     673                $menu_item['post_status'] = 'pending';
    685674                wp_insert_post($menu_item);
    686675        }
     
    747736
    748737/**
    749  * Automatically add newly published page objects to menus with that as an option.
     738 * Modify a navigational menu upon post object status change, if appropos.
    750739 *
    751740 * @since 3.0.0
     
    757746 * @return void
    758747 */
    759 function _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 }
    787 add_action( 'transition_post_status', '_wp_auto_add_pages_to_menu', 10, 3 );
     748function _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}
    788806
    789807?>
Note: See TracChangeset for help on using the changeset viewer.