2010-02-24 09:06:36 +01:00
< ? php
/**
* Navigation Menu functions
*
* @ package WordPress
2010-03-31 09:54:09 +02:00
* @ subpackage Nav_Menus
2010-02-24 09:06:36 +01:00
* @ since 3.0 . 0
*/
2010-02-28 21:00:49 +01:00
/**
2010-03-22 20:56:16 +01:00
* Returns a navigation menu object .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2014-05-02 13:59:14 +02:00
* @ param string $menu Menu ID , slug , or name .
2010-05-31 18:11:20 +02:00
* @ return mixed false if $menu param isn ' t supplied or term does not exist , menu object if successful .
2010-02-28 21:00:49 +01:00
*/
function wp_get_nav_menu_object ( $menu ) {
2010-05-03 22:26:11 +02:00
if ( ! $menu )
2010-04-27 03:05:58 +02:00
return false ;
$menu_obj = get_term ( $menu , 'nav_menu' );
if ( ! $menu_obj )
$menu_obj = get_term_by ( 'slug' , $menu , 'nav_menu' );
if ( ! $menu_obj )
$menu_obj = get_term_by ( 'name' , $menu , 'nav_menu' );
2010-05-31 18:11:20 +02:00
if ( ! $menu_obj )
2010-04-27 03:05:58 +02:00
$menu_obj = false ;
return $menu_obj ;
2010-02-28 21:00:49 +01:00
}
2010-02-24 09:06:36 +01:00
2010-02-28 21:00:49 +01:00
/**
2010-05-31 18:11:20 +02:00
* Check if the given ID is a navigation menu .
2010-02-28 21:00:49 +01:00
*
2010-04-28 04:04:30 +02:00
* Returns true if it is ; false otherwise .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2014-05-02 13:59:14 +02:00
* @ param int | string $menu The menu to check ( ID , slug , or name ) .
2010-04-27 03:05:58 +02:00
* @ return bool Whether the menu exists .
2010-02-28 21:00:49 +01:00
*/
function is_nav_menu ( $menu ) {
2010-04-27 03:05:58 +02:00
if ( ! $menu )
2010-03-02 18:56:24 +01:00
return false ;
2010-05-03 22:26:11 +02:00
2010-04-27 03:05:58 +02:00
$menu_obj = wp_get_nav_menu_object ( $menu );
2010-03-02 18:56:24 +01:00
2010-05-03 22:26:11 +02:00
if (
$menu_obj &&
! is_wp_error ( $menu_obj ) &&
2010-04-28 20:30:32 +02:00
! empty ( $menu_obj -> taxonomy ) &&
'nav_menu' == $menu_obj -> taxonomy
2010-05-03 22:26:11 +02:00
)
2010-04-27 03:05:58 +02:00
return true ;
2010-05-03 22:26:11 +02:00
2010-04-27 03:05:58 +02:00
return false ;
2010-02-24 09:06:36 +01:00
}
2010-05-14 00:14:54 +02:00
/**
2010-05-31 18:11:20 +02:00
* Register navigation menus for a theme .
2010-05-14 00:14:54 +02:00
*
* @ since 3.0 . 0
*
2010-05-14 08:20:30 +02:00
* @ param array $locations Associative array of menu location identifiers ( like a slug ) and descriptive text .
2010-05-14 00:14:54 +02:00
*/
2010-05-14 08:20:30 +02:00
function register_nav_menus ( $locations = array () ) {
2010-05-14 00:14:54 +02:00
global $_wp_registered_nav_menus ;
2010-06-10 19:57:30 +02:00
add_theme_support ( 'menus' );
2010-05-14 00:14:54 +02:00
2010-05-14 08:20:30 +02:00
$_wp_registered_nav_menus = array_merge ( ( array ) $_wp_registered_nav_menus , $locations );
2010-05-14 00:14:54 +02:00
}
2010-07-22 22:50:11 +02:00
/**
* Unregisters a navigation menu for a theme .
*
2014-10-25 15:43:18 +02:00
* @ param string $location The menu location identifier .
2010-07-22 22:50:11 +02:00
* @ return bool True on success , false on failure .
*/
function unregister_nav_menu ( $location ) {
global $_wp_registered_nav_menus ;
if ( is_array ( $_wp_registered_nav_menus ) && isset ( $_wp_registered_nav_menus [ $location ] ) ) {
unset ( $_wp_registered_nav_menus [ $location ] );
2014-02-21 19:14:14 +01:00
if ( empty ( $_wp_registered_nav_menus ) ) {
_remove_theme_support ( 'menus' );
}
2010-07-22 22:50:11 +02:00
return true ;
}
return false ;
}
2010-05-14 08:20:30 +02:00
/**
2010-05-31 18:11:20 +02:00
* Register a navigation menu for a theme .
2010-05-14 08:20:30 +02:00
*
* @ since 3.0 . 0
*
* @ param string $location Menu location identifier , like a slug .
* @ param string $description Menu location descriptive text .
*/
function register_nav_menu ( $location , $description ) {
register_nav_menus ( array ( $location => $description ) );
}
2010-05-18 07:59:25 +02:00
/**
2010-05-31 18:11:20 +02:00
* Returns an array of all registered navigation menus in a theme
2010-05-18 07:59:25 +02:00
*
* @ since 3.0 . 0
* @ return array
*/
2010-05-14 08:20:30 +02:00
function get_registered_nav_menus () {
2010-05-21 21:02:36 +02:00
global $_wp_registered_nav_menus ;
if ( isset ( $_wp_registered_nav_menus ) )
return $_wp_registered_nav_menus ;
return array ();
2010-05-14 00:14:54 +02:00
}
2010-05-18 07:59:25 +02:00
/**
2010-05-31 18:11:20 +02:00
* Returns an array with the registered navigation menu locations and the menu assigned to it
2010-05-18 07:59:25 +02:00
*
* @ since 3.0 . 0
* @ return array
*/
2010-05-14 08:20:30 +02:00
function get_nav_menu_locations () {
2013-03-01 16:51:16 +01:00
$locations = get_theme_mod ( 'nav_menu_locations' );
return ( is_array ( $locations ) ) ? $locations : array ();
2010-05-14 00:14:54 +02:00
}
2010-06-01 18:40:14 +02:00
/**
* Whether a registered nav menu location has a menu assigned to it .
*
* @ since 3.0 . 0
* @ param string $location Menu location identifier .
* @ return bool Whether location has a menu .
*/
function has_nav_menu ( $location ) {
2014-09-07 12:04:16 +02:00
$registered_nav_menus = get_registered_nav_menus ();
if ( ! isset ( $registered_nav_menus [ $location ] ) ) {
2014-06-26 02:57:15 +02:00
return false ;
}
2010-06-01 18:40:14 +02:00
$locations = get_nav_menu_locations ();
return ( ! empty ( $locations [ $location ] ) );
}
2010-04-28 04:04:30 +02:00
/**
* Determine whether the given ID is a nav menu item .
*
* @ since 3.0 . 0
*
* @ param int $menu_item_id The ID of the potential nav menu item .
* @ return bool Whether the given ID is that of a nav menu item .
*/
function is_nav_menu_item ( $menu_item_id = 0 ) {
return ( ! is_wp_error ( $menu_item_id ) && ( 'nav_menu_item' == get_post_type ( $menu_item_id ) ) );
}
2010-02-28 21:00:49 +01:00
/**
2010-03-22 20:56:16 +01:00
* Create a Navigation Menu .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2014-05-02 13:59:14 +02:00
* @ param string $menu_name Menu name .
* @ return int | WP_Error Menu ID on success , WP_Error object on failure .
2010-02-28 21:00:49 +01:00
*/
2010-05-31 18:11:20 +02:00
function wp_create_nav_menu ( $menu_name ) {
2010-06-02 15:43:46 +02:00
return wp_update_nav_menu_object ( 0 , array ( 'menu-name' => $menu_name ) );
2010-02-24 09:06:36 +01:00
}
2010-02-28 21:00:49 +01:00
/**
2010-03-22 20:56:16 +01:00
* Delete a Navigation Menu .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2014-05-02 13:59:14 +02:00
* @ param string $menu Menu ID , slug , or name .
* @ return bool | WP_Error True on success , false or WP_Error object on failure .
2010-02-28 21:00:49 +01:00
*/
function wp_delete_nav_menu ( $menu ) {
$menu = wp_get_nav_menu_object ( $menu );
2010-05-31 18:11:20 +02:00
if ( ! $menu )
2010-02-28 21:00:49 +01:00
return false ;
$menu_objects = get_objects_in_term ( $menu -> term_id , 'nav_menu' );
2010-05-31 18:11:20 +02:00
if ( ! empty ( $menu_objects ) ) {
2010-02-28 21:00:49 +01:00
foreach ( $menu_objects as $item ) {
wp_delete_post ( $item );
}
}
2010-03-26 20:36:49 +01:00
2010-03-22 20:56:16 +01:00
$result = wp_delete_term ( $menu -> term_id , 'nav_menu' );
2010-03-26 20:36:49 +01:00
2013-04-04 06:28:12 +02:00
// Remove this menu from any locations.
2013-08-31 03:39:09 +02:00
$locations = get_nav_menu_locations ();
foreach ( $locations as $location => $menu_id ) {
2013-04-09 22:50:45 +02:00
if ( $menu_id == $menu -> term_id )
2013-04-04 06:28:12 +02:00
$locations [ $location ] = 0 ;
}
set_theme_mod ( 'nav_menu_locations' , $locations );
2010-05-31 18:11:20 +02:00
if ( $result && ! is_wp_error ( $result ) )
2014-03-25 10:04:14 +01:00
/**
* Fires after a navigation menu has been successfully deleted .
*
* @ since 3.0 . 0
*
* @ param int $term_id ID of the deleted menu .
*/
2010-03-22 20:56:16 +01:00
do_action ( 'wp_delete_nav_menu' , $menu -> term_id );
2010-05-31 18:11:20 +02:00
return $result ;
2010-02-28 21:00:49 +01:00
}
2010-04-27 03:05:58 +02:00
/**
* Save the properties of a menu or create a new menu with those properties .
*
* @ since 3.0 . 0
*
2010-06-02 15:43:46 +02:00
* @ param int $menu_id The ID of the menu or " 0 " to create a new menu .
2010-04-27 03:05:58 +02:00
* @ param array $menu_data The array of menu data .
2014-05-02 13:59:14 +02:00
* @ return int | WP_Error Menu ID on success , WP_Error object on failure .
2010-04-27 03:05:58 +02:00
*/
function wp_update_nav_menu_object ( $menu_id = 0 , $menu_data = array () ) {
$menu_id = ( int ) $menu_id ;
$_menu = wp_get_nav_menu_object ( $menu_id );
2010-05-31 18:11:20 +02:00
$args = array (
'description' => ( isset ( $menu_data [ 'description' ] ) ? $menu_data [ 'description' ] : '' ),
'name' => ( isset ( $menu_data [ 'menu-name' ] ) ? $menu_data [ 'menu-name' ] : '' ),
'parent' => ( isset ( $menu_data [ 'parent' ] ) ? ( int ) $menu_data [ 'parent' ] : 0 ),
'slug' => null ,
);
2010-04-27 03:05:58 +02:00
2010-06-02 15:43:46 +02:00
// double-check that we're not going to have one menu take the name of another
2010-05-31 18:11:20 +02:00
$_possible_existing = get_term_by ( 'name' , $menu_data [ 'menu-name' ], 'nav_menu' );
if (
$_possible_existing &&
! is_wp_error ( $_possible_existing ) &&
isset ( $_possible_existing -> term_id ) &&
$_possible_existing -> term_id != $menu_id
)
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' ] ) ) );
2010-06-02 15:43:46 +02:00
// menu doesn't already exist, so create a new menu
if ( ! $_menu || is_wp_error ( $_menu ) ) {
$menu_exists = get_term_by ( 'name' , $menu_data [ 'menu-name' ], 'nav_menu' );
if ( $menu_exists )
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' ] ) ) );
$_menu = wp_insert_term ( $menu_data [ 'menu-name' ], 'nav_menu' , $args );
if ( is_wp_error ( $_menu ) )
return $_menu ;
2014-03-25 10:04:14 +01:00
/**
* Fires after a navigation menu is successfully created .
*
* @ since 3.0 . 0
*
* @ param int $term_id ID of the new menu .
* @ param array $menu_data An array of menu data .
*/
2010-06-02 15:43:46 +02:00
do_action ( 'wp_create_nav_menu' , $_menu [ 'term_id' ], $menu_data );
return ( int ) $_menu [ 'term_id' ];
}
if ( ! $_menu || ! isset ( $_menu -> term_id ) )
return 0 ;
$menu_id = ( int ) $_menu -> term_id ;
2010-05-31 18:11:20 +02:00
$update_response = wp_update_term ( $menu_id , 'nav_menu' , $args );
2010-06-02 15:43:46 +02:00
if ( is_wp_error ( $update_response ) )
2010-05-31 18:11:20 +02:00
return $update_response ;
2010-06-02 15:43:46 +02:00
2014-03-25 10:04:14 +01:00
/**
* Fires after a navigation menu has been successfully updated .
*
* @ since 3.0 . 0
*
* @ param int $menu_id ID of the updated menu .
* @ param array $menu_data An array of menu data .
*/
2010-06-02 15:43:46 +02:00
do_action ( 'wp_update_nav_menu' , $menu_id , $menu_data );
return $menu_id ;
2010-04-27 03:05:58 +02:00
}
/**
* Save the properties of a menu item or create a new one .
*
* @ since 3.0 . 0
*
2010-06-14 21:52:30 +02:00
* @ param int $menu_id The ID of the menu . Required . If " 0 " , makes the menu item a draft orphan .
2010-04-27 03:05:58 +02:00
* @ param int $menu_item_db_id The ID of the menu item . If " 0 " , creates a new menu item .
* @ param array $menu_item_data The menu item ' s data .
2014-02-25 01:51:13 +01:00
* @ return int | WP_Error The menu item ' s database ID or WP_Error object on failure .
2010-04-27 03:05:58 +02:00
*/
function wp_update_nav_menu_item ( $menu_id = 0 , $menu_item_db_id = 0 , $menu_item_data = array () ) {
$menu_id = ( int ) $menu_id ;
$menu_item_db_id = ( int ) $menu_item_db_id ;
2010-04-28 04:04:30 +02:00
// make sure that we don't convert non-nav_menu_item objects into nav_menu_item objects
2010-05-28 00:22:09 +02:00
if ( ! empty ( $menu_item_db_id ) && ! is_nav_menu_item ( $menu_item_db_id ) )
2014-02-25 01:51:13 +01:00
return new WP_Error ( 'update_nav_menu_item_failed' , __ ( 'The given object ID is not that of a menu item.' ) );
2010-04-28 04:04:30 +02:00
2010-04-27 03:05:58 +02:00
$menu = wp_get_nav_menu_object ( $menu_id );
2014-02-25 01:51:13 +01:00
if ( ! $menu && 0 !== $menu_id ) {
return new WP_Error ( 'invalid_menu_id' , __ ( 'Invalid menu ID.' ) );
}
if ( is_wp_error ( $menu ) ) {
2010-04-27 03:05:58 +02:00
return $menu ;
2014-02-25 01:51:13 +01:00
}
2010-04-27 03:05:58 +02:00
$defaults = array (
'menu-item-db-id' => $menu_item_db_id ,
'menu-item-object-id' => 0 ,
'menu-item-object' => '' ,
'menu-item-parent-id' => 0 ,
'menu-item-position' => 0 ,
'menu-item-type' => 'custom' ,
'menu-item-title' => '' ,
'menu-item-url' => '' ,
'menu-item-description' => '' ,
'menu-item-attr-title' => '' ,
'menu-item-target' => '' ,
'menu-item-classes' => '' ,
'menu-item-xfn' => '' ,
2010-05-26 08:59:14 +02:00
'menu-item-status' => '' ,
2010-04-27 03:05:58 +02:00
);
$args = wp_parse_args ( $menu_item_data , $defaults );
2010-06-02 22:04:07 +02:00
2010-05-28 00:22:09 +02:00
if ( 0 == $menu_id ) {
$args [ 'menu-item-position' ] = 1 ;
} elseif ( 0 == ( int ) $args [ 'menu-item-position' ] ) {
2012-10-15 16:27:16 +02:00
$menu_items = 0 == $menu_id ? array () : ( array ) wp_get_nav_menu_items ( $menu_id , array ( 'post_status' => 'publish,draft' ) );
2010-04-27 03:05:58 +02:00
$last_item = array_pop ( $menu_items );
2012-10-15 16:27:16 +02:00
$args [ 'menu-item-position' ] = ( $last_item && isset ( $last_item -> menu_order ) ) ? 1 + $last_item -> menu_order : count ( $menu_items );
2010-04-27 03:05:58 +02:00
}
2010-05-03 22:26:11 +02:00
2010-05-04 21:40:04 +02:00
$original_parent = 0 < $menu_item_db_id ? get_post_field ( 'post_parent' , $menu_item_db_id ) : 0 ;
2010-04-28 20:30:32 +02:00
if ( 'custom' != $args [ 'menu-item-type' ] ) {
/* if non - custom menu item , then :
* use original object ' s URL
* blank default title to sync with original object ' s
*/
$args [ 'menu-item-url' ] = '' ;
$original_title = '' ;
if ( 'taxonomy' == $args [ 'menu-item-type' ] ) {
2010-05-04 21:40:04 +02:00
$original_parent = get_term_field ( 'parent' , $args [ 'menu-item-object-id' ], $args [ 'menu-item-object' ], 'raw' );
2010-04-28 20:30:32 +02:00
$original_title = get_term_field ( 'name' , $args [ 'menu-item-object-id' ], $args [ 'menu-item-object' ], 'raw' );
} elseif ( 'post_type' == $args [ 'menu-item-type' ] ) {
2010-04-29 09:33:56 +02:00
2010-04-28 20:30:32 +02:00
$original_object = get_post ( $args [ 'menu-item-object-id' ] );
2010-05-04 21:40:04 +02:00
$original_parent = ( int ) $original_object -> post_parent ;
2010-04-28 20:30:32 +02:00
$original_title = $original_object -> post_title ;
}
2013-05-10 20:03:09 +02:00
if ( $args [ 'menu-item-title' ] == $original_title )
2010-04-28 20:30:32 +02:00
$args [ 'menu-item-title' ] = '' ;
2013-05-10 20:03:09 +02:00
// hack to get wp to create a post object when too many properties are empty
if ( '' == $args [ 'menu-item-title' ] && '' == $args [ 'menu-item-description' ] )
$args [ 'menu-item-description' ] = ' ' ;
2010-04-28 20:30:32 +02:00
}
2010-04-27 03:05:58 +02:00
// Populate the menu item object
$post = array (
'menu_order' => $args [ 'menu-item-position' ],
'ping_status' => 0 ,
'post_content' => $args [ 'menu-item-description' ],
'post_excerpt' => $args [ 'menu-item-attr-title' ],
2010-05-04 21:40:04 +02:00
'post_parent' => $original_parent ,
2010-05-03 22:26:11 +02:00
'post_title' => $args [ 'menu-item-title' ],
'post_type' => 'nav_menu_item' ,
2010-04-27 03:05:58 +02:00
);
2012-10-15 16:27:16 +02:00
$update = 0 != $menu_item_db_id ;
2010-06-14 21:52:30 +02:00
// New menu item. Default is draft status
2012-10-15 16:27:16 +02:00
if ( ! $update ) {
2010-04-28 04:04:30 +02:00
$post [ 'ID' ] = 0 ;
2010-06-14 21:52:30 +02:00
$post [ 'post_status' ] = 'publish' == $args [ 'menu-item-status' ] ? 'publish' : 'draft' ;
2010-04-27 03:05:58 +02:00
$menu_item_db_id = wp_insert_post ( $post );
2012-10-15 16:27:16 +02:00
if ( ! $menu_item_db_id || is_wp_error ( $menu_item_db_id ) )
return $menu_item_db_id ;
2010-04-27 03:05:58 +02:00
}
2014-03-15 07:07:16 +01:00
// Associate the menu item with the menu term
// Only set the menu term if it isn't set to avoid unnecessary wp_get_object_terms()
if ( $menu_id && ( ! $update || ! is_object_in_term ( $menu_item_db_id , 'nav_menu' , ( int ) $menu -> term_id ) ) ) {
wp_set_object_terms ( $menu_item_db_id , array ( $menu -> term_id ), 'nav_menu' );
}
2010-04-27 03:05:58 +02:00
if ( 'custom' == $args [ 'menu-item-type' ] ) {
$args [ 'menu-item-object-id' ] = $menu_item_db_id ;
$args [ 'menu-item-object' ] = 'custom' ;
}
2010-05-31 18:11:20 +02:00
$menu_item_db_id = ( int ) $menu_item_db_id ;
2013-03-01 17:28:40 +01:00
update_post_meta ( $menu_item_db_id , '_menu_item_type' , sanitize_key ( $args [ 'menu-item-type' ]) );
update_post_meta ( $menu_item_db_id , '_menu_item_menu_item_parent' , strval ( ( int ) $args [ 'menu-item-parent-id' ] ) );
update_post_meta ( $menu_item_db_id , '_menu_item_object_id' , strval ( ( int ) $args [ 'menu-item-object-id' ] ) );
update_post_meta ( $menu_item_db_id , '_menu_item_object' , sanitize_key ( $args [ 'menu-item-object' ]) );
update_post_meta ( $menu_item_db_id , '_menu_item_target' , sanitize_key ( $args [ 'menu-item-target' ]) );
2010-06-02 22:04:07 +02:00
2010-05-31 18:11:20 +02:00
$args [ 'menu-item-classes' ] = array_map ( 'sanitize_html_class' , explode ( ' ' , $args [ 'menu-item-classes' ] ) );
$args [ 'menu-item-xfn' ] = implode ( ' ' , array_map ( 'sanitize_html_class' , explode ( ' ' , $args [ 'menu-item-xfn' ] ) ) );
2013-03-01 17:28:40 +01:00
update_post_meta ( $menu_item_db_id , '_menu_item_classes' , $args [ 'menu-item-classes' ] );
update_post_meta ( $menu_item_db_id , '_menu_item_xfn' , $args [ 'menu-item-xfn' ] );
update_post_meta ( $menu_item_db_id , '_menu_item_url' , esc_url_raw ( $args [ 'menu-item-url' ]) );
2010-06-02 22:04:07 +02:00
2010-05-31 18:11:20 +02:00
if ( 0 == $menu_id )
2013-03-01 17:28:40 +01:00
update_post_meta ( $menu_item_db_id , '_menu_item_orphaned' , ( string ) time () );
2012-10-15 16:27:16 +02:00
elseif ( get_post_meta ( $menu_item_db_id , '_menu_item_orphaned' ) )
2010-05-31 18:11:20 +02:00
delete_post_meta ( $menu_item_db_id , '_menu_item_orphaned' );
2012-10-15 16:27:16 +02:00
// Update existing menu item. Default is publish status
if ( $update ) {
$post [ 'ID' ] = $menu_item_db_id ;
$post [ 'post_status' ] = 'draft' == $args [ 'menu-item-status' ] ? 'draft' : 'publish' ;
wp_update_post ( $post );
}
2014-03-25 10:04:14 +01:00
/**
* Fires after a navigation menu item has been updated .
*
* @ since 3.0 . 0
*
2015-02-23 17:51:25 +01:00
* @ see wp_update_nav_menu_item ()
2014-03-25 10:04:14 +01:00
*
* @ param int $menu_id ID of the updated menu .
* @ param int $menu_item_db_id ID of the updated menu item .
* @ param array $args An array of arguments used to update a menu item .
*/
do_action ( 'wp_update_nav_menu_item' , $menu_id , $menu_item_db_id , $args );
2010-04-27 03:05:58 +02:00
return $menu_item_db_id ;
}
2010-02-28 21:00:49 +01:00
/**
2010-03-22 20:56:16 +01:00
* Returns all navigation menu objects .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
2014-11-28 13:15:23 +01:00
* @ since 4.1 . 0 Default value of the 'orderby' argument was changed from 'none'
* to 'name' .
2010-03-15 17:26:46 +01:00
*
2014-11-28 13:15:23 +01:00
* @ param array $args Optional . Array of arguments passed on to { @ see get_terms ()} .
* Default empty array .
* @ return array Menu objects .
2010-02-28 21:00:49 +01:00
*/
2010-05-19 20:52:37 +02:00
function wp_get_nav_menus ( $args = array () ) {
2014-09-29 17:45:16 +02:00
$defaults = array ( 'hide_empty' => false , 'orderby' => 'name' );
2010-05-19 20:52:37 +02:00
$args = wp_parse_args ( $args , $defaults );
2014-03-25 10:04:14 +01:00
/**
* Filter the navigation menu objects being returned .
*
* @ since 3.0 . 0
*
* @ see get_terms ()
*
* @ param array $menus An array of menu objects .
* @ param array $args An array of arguments used to retrieve menu objects .
*/
2010-06-02 18:31:42 +02:00
return apply_filters ( 'wp_get_nav_menus' , get_terms ( 'nav_menu' , $args ), $args );
2010-02-25 22:06:44 +01:00
}
2010-04-27 03:05:58 +02:00
/**
* Sort menu items by the desired key .
*
* @ since 3.0 . 0
* @ access private
*
* @ param object $a The first object to compare
* @ param object $b The second object to compare
* @ return int - 1 , 0 , or 1 if $a is considered to be respectively less than , equal to , or greater than $b .
*/
2010-05-31 18:11:20 +02:00
function _sort_nav_menu_items ( $a , $b ) {
2010-04-27 03:05:58 +02:00
global $_menu_item_sort_prop ;
2010-05-31 18:11:20 +02:00
if ( empty ( $_menu_item_sort_prop ) )
2010-04-27 03:05:58 +02:00
return 0 ;
2010-05-31 18:11:20 +02:00
if ( ! isset ( $a -> $_menu_item_sort_prop ) || ! isset ( $b -> $_menu_item_sort_prop ) )
2010-04-27 03:05:58 +02:00
return 0 ;
2010-05-31 18:11:20 +02:00
$_a = ( int ) $a -> $_menu_item_sort_prop ;
$_b = ( int ) $b -> $_menu_item_sort_prop ;
if ( $a -> $_menu_item_sort_prop == $b -> $_menu_item_sort_prop )
return 0 ;
elseif ( $_a == $a -> $_menu_item_sort_prop && $_b == $b -> $_menu_item_sort_prop )
return $_a < $_b ? - 1 : 1 ;
else
return strcmp ( $a -> $_menu_item_sort_prop , $b -> $_menu_item_sort_prop );
2010-04-27 03:05:58 +02:00
}
2011-06-11 02:55:48 +02:00
/**
2014-10-10 19:14:19 +02:00
* Return if a menu item is valid .
*
* @ link https :// core . trac . wordpress . org / ticket / 13958
2011-06-11 02:55:48 +02:00
*
* @ since 3.2 . 0
* @ access private
*
2014-10-10 19:14:19 +02:00
* @ param object $item The menu item to check .
* @ return bool False if invalid , otherwise true .
2011-06-11 02:55:48 +02:00
*/
function _is_valid_nav_menu_item ( $item ) {
if ( ! empty ( $item -> _invalid ) )
return false ;
return true ;
}
2010-02-28 21:00:49 +01:00
/**
2014-10-10 19:14:19 +02:00
* Return all menu items of a navigation menu .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2014-10-10 19:14:19 +02:00
* @ param string $menu Menu name , ID , or slug .
* @ param array $args Optional . Arguments to pass to { @ see get_posts ()} .
* @ return mixed $items Array of menu items , otherwise false .
2010-02-28 21:00:49 +01:00
*/
2010-02-24 09:06:36 +01:00
function wp_get_nav_menu_items ( $menu , $args = array () ) {
2010-02-28 21:00:49 +01:00
$menu = wp_get_nav_menu_object ( $menu );
2010-03-17 17:27:25 +01:00
2010-04-27 03:05:58 +02:00
if ( ! $menu )
2010-02-28 21:00:49 +01:00
return false ;
2010-05-03 22:26:11 +02:00
2010-05-11 17:55:17 +02:00
static $fetched = array ();
2010-02-28 21:00:49 +01:00
$items = get_objects_in_term ( $menu -> term_id , 'nav_menu' );
2010-02-24 09:06:36 +01:00
2010-05-11 16:21:03 +02:00
if ( empty ( $items ) )
return $items ;
2010-05-31 18:11:20 +02:00
$defaults = array ( 'order' => 'ASC' , 'orderby' => 'menu_order' , 'post_type' => 'nav_menu_item' ,
2012-10-15 16:17:50 +02:00
'post_status' => 'publish' , 'output' => ARRAY_A , 'output_key' => 'menu_order' , 'nopaging' => true );
2010-05-11 16:21:03 +02:00
$args = wp_parse_args ( $args , $defaults );
2014-06-24 19:17:14 +02:00
$args [ 'include' ] = $items ;
2010-05-11 16:21:03 +02:00
$items = get_posts ( $args );
if ( is_wp_error ( $items ) || ! is_array ( $items ) )
return false ;
// Get all posts and terms at once to prime the caches
2013-09-06 20:10:09 +02:00
if ( empty ( $fetched [ $menu -> term_id ] ) || wp_using_ext_object_cache () ) {
2010-05-11 17:55:17 +02:00
$fetched [ $menu -> term_id ] = true ;
$posts = array ();
$terms = array ();
foreach ( $items as $item ) {
$object_id = get_post_meta ( $item -> ID , '_menu_item_object_id' , true );
2010-05-31 18:11:20 +02:00
$object = get_post_meta ( $item -> ID , '_menu_item_object' , true );
$type = get_post_meta ( $item -> ID , '_menu_item_type' , true );
2010-05-18 07:59:25 +02:00
2010-05-11 17:55:17 +02:00
if ( 'post_type' == $type )
$posts [ $object ][] = $object_id ;
elseif ( 'taxonomy' == $type )
$terms [ $object ][] = $object_id ;
2010-05-11 16:21:03 +02:00
}
2010-05-18 07:59:25 +02:00
2010-05-31 18:11:20 +02:00
if ( ! empty ( $posts ) ) {
2010-05-11 17:55:17 +02:00
foreach ( array_keys ( $posts ) as $post_type ) {
get_posts ( array ( 'post__in' => $posts [ $post_type ], 'post_type' => $post_type , 'nopaging' => true , 'update_post_term_cache' => false ) );
}
}
unset ( $posts );
2010-05-18 07:59:25 +02:00
2010-05-31 18:11:20 +02:00
if ( ! empty ( $terms ) ) {
2010-05-11 17:55:17 +02:00
foreach ( array_keys ( $terms ) as $taxonomy ) {
get_terms ( $taxonomy , array ( 'include' => $terms [ $taxonomy ]) );
}
2010-04-28 20:30:32 +02:00
}
2010-05-11 17:55:17 +02:00
unset ( $terms );
2010-05-11 16:21:03 +02:00
}
2010-04-28 20:30:32 +02:00
2010-05-11 16:21:03 +02:00
$items = array_map ( 'wp_setup_nav_menu_item' , $items );
2011-06-11 17:44:06 +02:00
2011-06-11 17:52:15 +02:00
if ( ! is_admin () ) // Remove invalid items only in frontend
2011-06-11 02:55:48 +02:00
$items = array_filter ( $items , '_is_valid_nav_menu_item' );
2010-04-28 20:30:32 +02:00
2010-05-11 16:21:03 +02:00
if ( ARRAY_A == $args [ 'output' ] ) {
$GLOBALS [ '_menu_item_sort_prop' ] = $args [ 'output_key' ];
usort ( $items , '_sort_nav_menu_items' );
$i = 1 ;
foreach ( $items as $k => $item ) {
$items [ $k ] -> $args [ 'output_key' ] = $i ++ ;
2010-02-24 09:06:36 +01:00
}
}
2010-05-11 16:21:03 +02:00
2014-03-25 10:04:14 +01:00
/**
* Filter the navigation menu items being returned .
*
* @ since 3.0 . 0
*
* @ param array $items An array of menu item post objects .
* @ param object $menu The menu object .
* @ param array $args An array of arguments used to retrieve menu item objects .
*/
2010-06-14 22:50:55 +02:00
return apply_filters ( 'wp_get_nav_menu_items' , $items , $menu , $args );
2010-02-24 09:06:36 +01:00
}
2010-02-28 21:00:49 +01:00
/**
2010-04-27 03:05:58 +02:00
* Decorates a menu item object with the shared navigation menu item properties .
2010-03-22 20:56:16 +01:00
*
2010-04-27 03:05:58 +02:00
* Properties :
2010-05-04 21:40:04 +02:00
* - db_id : The DB ID of this item as a nav_menu_item object , if it exists ( 0 if it doesn ' t exist ) .
2010-04-27 03:05:58 +02:00
* - object_id : The DB ID of the original object this menu item represents , e . g . ID for posts and term_id for categories .
* - type : The family of objects originally represented , such as " post_type " or " taxonomy. "
* - object : The type of object originally represented , such as " category, " " post " , or " attachment. "
2010-05-11 21:52:50 +02:00
* - type_label : The singular label used to describe this type of menu item .
2010-05-04 21:40:04 +02:00
* - post_parent : The DB ID of the original object ' s parent object , if any ( 0 otherwise ) .
2011-12-14 00:45:31 +01:00
* - menu_item_parent : The DB ID of the nav_menu_item that is this item ' s menu parent , if any . 0 otherwise .
2010-04-27 03:05:58 +02:00
* - url : The URL to which this menu item points .
* - title : The title of this menu item .
* - target : The target attribute of the link element for this menu item .
2010-05-03 22:26:11 +02:00
* - attr_title : The title attribute of the link element for this menu item .
2010-05-26 17:41:21 +02:00
* - classes : The array of class attribute values for the link element of this menu item .
2010-04-27 03:05:58 +02:00
* - xfn : The XFN relationship expressed in the link of this menu item .
* - description : The description of this menu item .
2010-02-28 21:00:49 +01:00
*
* @ since 3.0 . 0
*
2010-04-27 03:05:58 +02:00
* @ param object $menu_item The menu item to modify .
* @ return object $menu_item The menu item with standard menu item properties .
2010-02-28 21:00:49 +01:00
*/
2010-04-27 03:05:58 +02:00
function wp_setup_nav_menu_item ( $menu_item ) {
if ( isset ( $menu_item -> post_type ) ) {
if ( 'nav_menu_item' == $menu_item -> post_type ) {
2010-03-15 17:26:46 +01:00
$menu_item -> db_id = ( int ) $menu_item -> ID ;
2010-05-27 04:24:33 +02:00
$menu_item -> menu_item_parent = empty ( $menu_item -> menu_item_parent ) ? get_post_meta ( $menu_item -> ID , '_menu_item_menu_item_parent' , true ) : $menu_item -> menu_item_parent ;
$menu_item -> object_id = empty ( $menu_item -> object_id ) ? get_post_meta ( $menu_item -> ID , '_menu_item_object_id' , true ) : $menu_item -> object_id ;
$menu_item -> object = empty ( $menu_item -> object ) ? get_post_meta ( $menu_item -> ID , '_menu_item_object' , true ) : $menu_item -> object ;
$menu_item -> type = empty ( $menu_item -> type ) ? get_post_meta ( $menu_item -> ID , '_menu_item_type' , true ) : $menu_item -> type ;
2010-05-03 22:26:11 +02:00
2010-03-22 20:56:16 +01:00
if ( 'post_type' == $menu_item -> type ) {
$object = get_post_type_object ( $menu_item -> object );
2011-06-11 02:55:48 +02:00
if ( $object ) {
$menu_item -> type_label = $object -> labels -> singular_name ;
} else {
$menu_item -> type_label = $menu_item -> object ;
$menu_item -> _invalid = true ;
}
2010-04-07 17:25:48 +02:00
$menu_item -> url = get_permalink ( $menu_item -> object_id );
2010-05-03 22:26:11 +02:00
2010-04-28 20:30:32 +02:00
$original_object = get_post ( $menu_item -> object_id );
$original_title = $original_object -> post_title ;
2014-11-21 06:57:22 +01:00
if ( '' === $original_title ) {
$original_title = sprintf ( __ ( '#%d (no title)' ), $original_object -> ID );
}
2010-04-28 20:30:32 +02:00
$menu_item -> title = '' == $menu_item -> post_title ? $original_title : $menu_item -> post_title ;
2010-03-26 20:36:49 +01:00
2010-03-22 20:56:16 +01:00
} elseif ( 'taxonomy' == $menu_item -> type ) {
$object = get_taxonomy ( $menu_item -> object );
2011-06-11 02:55:48 +02:00
if ( $object ) {
$menu_item -> type_label = $object -> labels -> singular_name ;
} else {
$menu_item -> type_label = $menu_item -> object ;
$menu_item -> _invalid = true ;
}
2010-05-13 18:34:14 +02:00
$term_url = get_term_link ( ( int ) $menu_item -> object_id , $menu_item -> object );
$menu_item -> url = ! is_wp_error ( $term_url ) ? $term_url : '' ;
2010-03-26 20:36:49 +01:00
2010-04-28 20:30:32 +02:00
$original_title = get_term_field ( 'name' , $menu_item -> object_id , $menu_item -> object , 'raw' );
2011-07-11 21:03:04 +02:00
if ( is_wp_error ( $original_title ) )
$original_title = false ;
2010-04-28 20:30:32 +02:00
$menu_item -> title = '' == $menu_item -> post_title ? $original_title : $menu_item -> post_title ;
2010-03-22 20:56:16 +01:00
} else {
2015-03-12 07:15:27 +01:00
$menu_item -> type_label = __ ( 'Custom Link' );
2010-04-28 20:30:32 +02:00
$menu_item -> title = $menu_item -> post_title ;
2010-05-27 04:24:33 +02:00
$menu_item -> url = empty ( $menu_item -> url ) ? get_post_meta ( $menu_item -> ID , '_menu_item_url' , true ) : $menu_item -> url ;
2010-03-22 20:56:16 +01:00
}
2010-05-03 22:26:11 +02:00
2010-05-27 04:24:33 +02:00
$menu_item -> target = empty ( $menu_item -> target ) ? get_post_meta ( $menu_item -> ID , '_menu_item_target' , true ) : $menu_item -> target ;
2010-03-17 17:27:25 +01:00
2014-03-25 10:04:14 +01:00
/**
* Filter a navigation menu item ' s title attribute .
*
* @ since 3.0 . 0
*
* @ param string $item_title The menu item title attribute .
*/
2010-05-27 04:24:33 +02:00
$menu_item -> attr_title = empty ( $menu_item -> attr_title ) ? apply_filters ( 'nav_menu_attr_title' , $menu_item -> post_excerpt ) : $menu_item -> attr_title ;
2011-09-21 00:57:47 +02:00
2014-03-25 10:04:14 +01:00
if ( empty ( $menu_item -> description ) ) {
/**
* Filter a navigation menu item ' s description .
*
* @ since 3.0 . 0
*
* @ param string $description The menu item description .
*/
$menu_item -> description = apply_filters ( 'nav_menu_description' , wp_trim_words ( $menu_item -> post_content , 200 ) );
}
2010-03-17 17:27:25 +01:00
2010-05-27 04:24:33 +02:00
$menu_item -> classes = empty ( $menu_item -> classes ) ? ( array ) get_post_meta ( $menu_item -> ID , '_menu_item_classes' , true ) : $menu_item -> classes ;
$menu_item -> xfn = empty ( $menu_item -> xfn ) ? get_post_meta ( $menu_item -> ID , '_menu_item_xfn' , true ) : $menu_item -> xfn ;
2010-04-27 03:05:58 +02:00
} else {
2010-03-15 17:26:46 +01:00
$menu_item -> db_id = 0 ;
2010-05-04 21:40:04 +02:00
$menu_item -> menu_item_parent = 0 ;
2010-03-15 17:26:46 +01:00
$menu_item -> object_id = ( int ) $menu_item -> ID ;
2010-04-27 03:05:58 +02:00
$menu_item -> type = 'post_type' ;
2010-03-17 17:27:25 +01:00
2010-04-27 03:05:58 +02:00
$object = get_post_type_object ( $menu_item -> post_type );
2010-03-22 20:56:16 +01:00
$menu_item -> object = $object -> name ;
2010-05-11 21:52:50 +02:00
$menu_item -> type_label = $object -> labels -> singular_name ;
2010-03-15 17:26:46 +01:00
2013-07-05 17:41:46 +02:00
if ( '' === $menu_item -> post_title )
$menu_item -> post_title = sprintf ( __ ( '#%d (no title)' ), $menu_item -> ID );
2010-03-15 17:26:46 +01:00
$menu_item -> title = $menu_item -> post_title ;
2010-03-16 17:34:30 +01:00
$menu_item -> url = get_permalink ( $menu_item -> ID );
2010-04-04 00:52:30 +02:00
$menu_item -> target = '' ;
2010-03-17 17:27:25 +01:00
2014-03-25 10:04:14 +01:00
/** This filter is documented in wp-includes/nav-menu.php */
2011-09-20 23:58:37 +02:00
$menu_item -> attr_title = apply_filters ( 'nav_menu_attr_title' , '' );
2014-03-25 10:04:14 +01:00
/** This filter is documented in wp-includes/nav-menu.php */
2011-09-20 23:58:37 +02:00
$menu_item -> description = apply_filters ( 'nav_menu_description' , '' );
2010-05-26 17:41:21 +02:00
$menu_item -> classes = array ();
2010-03-22 20:56:16 +01:00
$menu_item -> xfn = '' ;
2010-04-27 03:05:58 +02:00
}
} elseif ( isset ( $menu_item -> taxonomy ) ) {
$menu_item -> ID = $menu_item -> term_id ;
$menu_item -> db_id = 0 ;
2010-05-04 21:40:04 +02:00
$menu_item -> menu_item_parent = 0 ;
2010-04-27 03:05:58 +02:00
$menu_item -> object_id = ( int ) $menu_item -> term_id ;
$menu_item -> post_parent = ( int ) $menu_item -> parent ;
$menu_item -> type = 'taxonomy' ;
$object = get_taxonomy ( $menu_item -> taxonomy );
$menu_item -> object = $object -> name ;
2010-05-14 02:34:04 +02:00
$menu_item -> type_label = $object -> labels -> singular_name ;
2010-04-27 03:05:58 +02:00
$menu_item -> title = $menu_item -> name ;
$menu_item -> url = get_term_link ( $menu_item , $menu_item -> taxonomy );
$menu_item -> target = '' ;
$menu_item -> attr_title = '' ;
2010-05-24 00:56:51 +02:00
$menu_item -> description = get_term_field ( 'description' , $menu_item -> term_id , $menu_item -> taxonomy );
2010-05-26 17:41:21 +02:00
$menu_item -> classes = array ();
2010-04-27 03:05:58 +02:00
$menu_item -> xfn = '' ;
2010-03-15 17:26:46 +01:00
2010-03-26 20:36:49 +01:00
}
2010-04-27 03:05:58 +02:00
2014-03-25 10:04:14 +01:00
/**
* Filter a navigation menu item object .
*
* @ since 3.0 . 0
*
* @ param object $menu_item The menu item object .
*/
2010-04-27 03:05:58 +02:00
return apply_filters ( 'wp_setup_nav_menu_item' , $menu_item );
2010-02-24 09:06:36 +01:00
}
2010-04-29 09:33:56 +02:00
/**
* Get the menu items associated with a particular object .
*
* @ since 3.0 . 0
2010-05-03 22:26:11 +02:00
*
2010-04-29 09:33:56 +02:00
* @ param int $object_id The ID of the original object .
* @ param string $object_type The type of object , such as " taxonomy " or " post_type. "
2013-08-29 18:45:10 +02:00
* @ param string $taxonomy If $object_type is " taxonomy " , $taxonomy is the name of the tax that $object_id belongs to
2010-04-29 09:33:56 +02:00
* @ return array The array of menu item IDs ; empty array if none ;
*/
2013-08-29 18:45:10 +02:00
function wp_get_associated_nav_menu_items ( $object_id = 0 , $object_type = 'post_type' , $taxonomy = '' ) {
2010-04-29 09:33:56 +02:00
$object_id = ( int ) $object_id ;
$menu_item_ids = array ();
$query = new WP_Query ;
$menu_items = $query -> query (
array (
'meta_key' => '_menu_item_object_id' ,
'meta_value' => $object_id ,
'post_status' => 'any' ,
'post_type' => 'nav_menu_item' ,
2010-10-13 07:25:00 +02:00
'posts_per_page' => - 1 ,
2010-04-29 09:33:56 +02:00
)
);
foreach ( ( array ) $menu_items as $menu_item ) {
if ( isset ( $menu_item -> ID ) && is_nav_menu_item ( $menu_item -> ID ) ) {
2014-02-09 22:37:11 +01:00
$menu_item_type = get_post_meta ( $menu_item -> ID , '_menu_item_type' , true );
if (
'post_type' == $object_type &&
'post_type' == $menu_item_type
) {
$menu_item_ids [] = ( int ) $menu_item -> ID ;
2015-01-08 08:05:25 +01:00
} elseif (
2014-02-09 22:37:11 +01:00
'taxonomy' == $object_type &&
'taxonomy' == $menu_item_type &&
get_post_meta ( $menu_item -> ID , '_menu_item_object' , true ) == $taxonomy
) {
$menu_item_ids [] = ( int ) $menu_item -> ID ;
}
2010-04-29 09:33:56 +02:00
}
}
return array_unique ( $menu_item_ids );
}
/**
* Callback for handling a menu item when its original object is deleted .
*
* @ since 3.0 . 0
* @ access private
*
* @ param int $object_id The ID of the original object being trashed .
*
*/
function _wp_delete_post_menu_item ( $object_id = 0 ) {
$object_id = ( int ) $object_id ;
$menu_item_ids = wp_get_associated_nav_menu_items ( $object_id , 'post_type' );
foreach ( ( array ) $menu_item_ids as $menu_item_id ) {
wp_delete_post ( $menu_item_id , true );
}
}
/**
* Callback for handling a menu item when its original object is deleted .
*
* @ since 3.0 . 0
* @ access private
*
* @ param int $object_id The ID of the original object being trashed .
*
*/
2013-08-29 18:45:10 +02:00
function _wp_delete_tax_menu_item ( $object_id = 0 , $tt_id , $taxonomy ) {
2010-04-29 09:33:56 +02:00
$object_id = ( int ) $object_id ;
2013-08-29 18:45:10 +02:00
$menu_item_ids = wp_get_associated_nav_menu_items ( $object_id , 'taxonomy' , $taxonomy );
2010-04-29 09:33:56 +02:00
foreach ( ( array ) $menu_item_ids as $menu_item_id ) {
wp_delete_post ( $menu_item_id , true );
}
}
2010-05-28 00:22:09 +02:00
/**
2010-06-14 21:52:30 +02:00
* Automatically add newly published page objects to menus with that as an option .
2010-05-28 00:22:09 +02:00
*
* @ since 3.0 . 0
* @ access private
*
* @ param string $new_status The new status of the post object .
* @ param string $old_status The old status of the post object .
* @ param object $post The post object being transitioned from one status to another .
* @ return void
*/
2010-06-14 21:52:30 +02:00
function _wp_auto_add_pages_to_menu ( $new_status , $old_status , $post ) {
if ( 'publish' != $new_status || 'publish' == $old_status || 'page' != $post -> post_type )
return ;
if ( ! empty ( $post -> post_parent ) )
return ;
$auto_add = get_option ( 'nav_menu_options' );
if ( empty ( $auto_add ) || ! is_array ( $auto_add ) || ! isset ( $auto_add [ 'auto_add' ] ) )
return ;
$auto_add = $auto_add [ 'auto_add' ];
if ( empty ( $auto_add ) || ! is_array ( $auto_add ) )
return ;
2010-06-11 22:19:35 +02:00
2010-06-14 21:52:30 +02:00
$args = array (
'menu-item-object-id' => $post -> ID ,
'menu-item-object' => $post -> post_type ,
'menu-item-type' => 'post_type' ,
'menu-item-status' => 'publish' ,
);
2010-05-26 04:42:15 +02:00
2010-06-14 21:52:30 +02:00
foreach ( $auto_add as $menu_id ) {
$items = wp_get_nav_menu_items ( $menu_id , array ( 'post_status' => 'publish,draft' ) );
if ( ! is_array ( $items ) )
continue ;
foreach ( $items as $item ) {
if ( $post -> ID == $item -> object_id )
continue 2 ;
2010-05-25 15:49:56 +02:00
}
2010-06-14 21:52:30 +02:00
wp_update_nav_menu_item ( $menu_id , 0 , $args );
2010-05-25 15:49:56 +02:00
}
}