/** * Displays a navigation menu. * * Optional $args contents: * * menu - The menu that is desired. Accepts (matching in order) id, slug, name. Defaults to blank. * menu_class - CSS class to use for the ul element which forms the menu. Defaults to 'menu'. * menu_id - The ID that is applied to the ul element which forms the menu. Defaults to the menu slug, incremented. * container - Whether to wrap the ul, and what to wrap it with. Defaults to 'div'. * container_class - the class that is applied to the container. Defaults to 'menu-{menu slug}-container'. * container_id - The ID that is applied to the container. Defaults to blank. * fallback_cb - If the menu doesn't exists, a callback function will fire. Defaults to 'nxt_page_menu'. Set to false for no fallback. * before - Text before the link text. * after - Text after the link text. * link_before - Text before the link. * link_after - Text after the link. * echo - Whether to echo the menu or return it. Defaults to echo. * depth - how many levels of the hierarchy are to be included. 0 means all. Defaults to 0. * walker - allows a custom walker to be specified. * theme_location - the location in the theme to be used. Must be registered with register_nav_menu() in order to be selectable by the user. * items_wrap - How the list items should be wrapped. Defaults to a ul with an id and class. Uses printf() format with numbered placeholders. * * @since 3.0.0 * * @param array $args Arguments */ function nxt_nav_menu($args = array()) { static $menu_id_slugs = array(); $defaults = array('menu' => '', 'container' => 'div', 'container_class' => '', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '', 'echo' => true, 'fallback_cb' => 'nxt_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'depth' => 0, 'walker' => '', 'theme_location' => ''); $args = nxt_parse_args($args, $defaults); $args = apply_filters('nxt_nav_menu_args', $args); $args = (object) $args; // Get the nav menu based on the requested menu $menu = nxt_get_nav_menu_object($args->menu); // Get the nav menu based on the theme_location if (!$menu && $args->theme_location && ($locations = get_nav_menu_locations()) && isset($locations[$args->theme_location])) { $menu = nxt_get_nav_menu_object($locations[$args->theme_location]); } // get the first menu that has items if we still can't find a menu if (!$menu && !$args->theme_location) { $menus = nxt_get_nav_menus(); foreach ($menus as $menu_maybe) { if ($menu_items = nxt_get_nav_menu_items($menu_maybe->term_id)) { $menu = $menu_maybe; break; } } } // If the menu exists, get its items. if ($menu && !is_nxt_error($menu) && !isset($menu_items)) { $menu_items = nxt_get_nav_menu_items($menu->term_id); } // If no menu was found or if the menu has no items and no location was requested, call the fallback_cb if it exists if ((!$menu || is_nxt_error($menu) || isset($menu_items) && empty($menu_items) && !$args->theme_location) && $args->fallback_cb && is_callable($args->fallback_cb)) { return call_user_func($args->fallback_cb, (array) $args); } // If no fallback function was specified and the menu doesn't exists, bail. if (!$menu || is_nxt_error($menu)) { return false; } $nav_menu = $items = ''; $show_container = false; if ($args->container) { $allowed_tags = apply_filters('nxt_nav_menu_container_allowedtags', array('div', 'nav')); if (in_array($args->container, $allowed_tags)) { $show_container = true; $class = $args->container_class ? ' class="' . esc_attr($args->container_class) . '"' : ' class="menu-' . $menu->slug . '-container"'; $id = $args->container_id ? ' id="' . esc_attr($args->container_id) . '"' : ''; $nav_menu .= '<' . $args->container . $id . $class . '>'; } } // Set up the $menu_item variables _nxt_menu_item_classes_by_context($menu_items); $sorted_menu_items = array(); foreach ((array) $menu_items as $key => $menu_item) { $sorted_menu_items[$menu_item->menu_order] = $menu_item; } unset($menu_items); $sorted_menu_items = apply_filters('nxt_nav_menu_objects', $sorted_menu_items, $args); $items .= walk_nav_menu_tree($sorted_menu_items, $args->depth, $args); unset($sorted_menu_items); // Attributes if (!empty($args->menu_id)) { $wrap_id = $args->menu_id; } else { $wrap_id = 'menu-' . $menu->slug; while (in_array($wrap_id, $menu_id_slugs)) { if (preg_match('#-(\\d+)$#', $wrap_id, $matches)) { $wrap_id = preg_replace('#-(\\d+)$#', '-' . ++$matches[1], $wrap_id); } else { $wrap_id = $wrap_id . '-1'; } } } $menu_id_slugs[] = $wrap_id; $wrap_class = $args->menu_class ? $args->menu_class : ''; // Allow plugins to hook into the menu to add their own <li>'s $items = apply_filters('nxt_nav_menu_items', $items, $args); $items = apply_filters("nxt_nav_menu_{$menu->slug}_items", $items, $args); $nav_menu .= sprintf($args->items_wrap, esc_attr($wrap_id), esc_attr($wrap_class), $items); unset($items); if ($show_container) { $nav_menu .= '</' . $args->container . '>'; } $nav_menu = apply_filters('nxt_nav_menu', $nav_menu, $args); if ($args->echo) { echo $nav_menu; } else { return $nav_menu; } }
function widget($args, $instance) { // Get menu $nav_menu = !empty($instance['nav_menu']) ? nxt_get_nav_menu_object($instance['nav_menu']) : false; if (!$nav_menu) { return; } $instance['title'] = apply_filters('widget_title', empty($instance['title']) ? '' : $instance['title'], $instance, $this->id_base); echo $args['before_widget']; if (!empty($instance['title'])) { echo $args['before_title'] . $instance['title'] . $args['after_title']; } nxt_nav_menu(array('fallback_cb' => '', 'menu' => $nav_menu)); echo $args['after_widget']; }
/** * Returns all menu items of a navigation menu. * * @since 3.0.0 * * @param string $menu menu name, id, or slug * @param string $args * @return mixed $items array of menu items, else false. */ function nxt_get_nav_menu_items($menu, $args = array()) { global $_nxt_using_ext_object_cache; $menu = nxt_get_nav_menu_object($menu); if (!$menu) { return false; } static $fetched = array(); $items = get_objects_in_term($menu->term_id, 'nav_menu'); if (empty($items)) { return $items; } $defaults = array('order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item', 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true, 'update_post_term_cache' => false); $args = nxt_parse_args($args, $defaults); if (count($items) > 1) { $args['include'] = implode(',', $items); } else { $args['include'] = $items[0]; } $items = get_posts($args); if (is_nxt_error($items) || !is_array($items)) { return false; } // Get all posts and terms at once to prime the caches if (empty($fetched[$menu->term_id]) || $_nxt_using_ext_object_cache) { $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); $object = get_post_meta($item->ID, '_menu_item_object', true); $type = get_post_meta($item->ID, '_menu_item_type', true); if ('post_type' == $type) { $posts[$object][] = $object_id; } elseif ('taxonomy' == $type) { $terms[$object][] = $object_id; } } if (!empty($posts)) { 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); if (!empty($terms)) { foreach (array_keys($terms) as $taxonomy) { get_terms($taxonomy, array('include' => $terms[$taxonomy])); } } unset($terms); } $items = array_map('nxt_setup_nav_menu_item', $items); if (!is_admin()) { // Remove invalid items only in frontend $items = array_filter($items, '_is_valid_nav_menu_item'); } 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++; } } return apply_filters('nxt_get_nav_menu_items', $items, $menu, $args); }
if (!$recently_edited && is_nav_menu($nav_menu_selected_id)) { $recently_edited = $nav_menu_selected_id; // Else if $nav_menu_selected_id is not a menu and not requesting that we create a new menu, but $recently_edited is a menu, grab that one. } elseif (0 == $nav_menu_selected_id && !isset($_REQUEST['menu']) && is_nav_menu($recently_edited)) { $nav_menu_selected_id = $recently_edited; // Else try to grab the first menu from the menus list } elseif (0 == $nav_menu_selected_id && !isset($_REQUEST['menu']) && !empty($nav_menus)) { $nav_menu_selected_id = $nav_menus[0]->term_id; } // Update the user's setting if ($nav_menu_selected_id != $recently_edited && is_nav_menu($nav_menu_selected_id)) { update_user_meta($current_user->ID, 'nav_menu_recently_edited', $nav_menu_selected_id); } // If there's a menu, get its name. if (!$nav_menu_selected_title && is_nav_menu($nav_menu_selected_id)) { $_menu_object = nxt_get_nav_menu_object($nav_menu_selected_id); $nav_menu_selected_title = !is_nxt_error($_menu_object) ? $_menu_object->name : ''; } // Generate truncated menu names foreach ((array) $nav_menus as $key => $_nav_menu) { $_nav_menu->truncated_name = trim(nxt_html_excerpt($_nav_menu->name, 40)); if ($_nav_menu->truncated_name != $_nav_menu->name) { $_nav_menu->truncated_name .= '…'; } $nav_menus[$key]->truncated_name = $_nav_menu->truncated_name; } // Ensure the user will be able to scroll horizontally // by adding a class for the max menu depth. global $_nxt_nav_menu_max_depth; $_nxt_nav_menu_max_depth = 0; // Calling nxt_get_nav_menu_to_edit generates $_nxt_nav_menu_max_depth
/** * Returns the menu formatted to edit. * * @since 3.0.0 * * @param string $menu_id The ID of the menu to format. * @return string|nxt_Error $output The menu formatted to edit or error object on failure. */ function nxt_get_nav_menu_to_edit($menu_id = 0) { $menu = nxt_get_nav_menu_object($menu_id); // If the menu exists, get its items. if (is_nav_menu($menu)) { $menu_items = nxt_get_nav_menu_items($menu->term_id, array('post_status' => 'any')); $result = '<div id="menu-instructions" class="post-body-plain'; $result .= !empty($menu_items) ? ' menu-instructions-inactive">' : '">'; $result .= '<p>' . __('Select menu items (pages, categories, links) from the boxes at left to begin building your custom menu.') . '</p>'; $result .= '</div>'; if (empty($menu_items)) { return $result . ' <ul class="menu" id="menu-to-edit"> </ul>'; } $walker_class_name = apply_filters('nxt_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $menu_id); if (class_exists($walker_class_name)) { $walker = new $walker_class_name(); } else { return new nxt_Error('menu_walker_not_exist', sprintf(__('The Walker class named <strong>%s</strong> does not exist.'), $walker_class_name)); } $some_pending_menu_items = $some_invalid_menu_items = false; foreach ((array) $menu_items as $menu_item) { if (isset($menu_item->post_status) && 'draft' == $menu_item->post_status) { $some_pending_menu_items = true; } if (!empty($menu_item->_invalid)) { $some_invalid_menu_items = true; } } if ($some_pending_menu_items) { $result .= '<div class="updated inline"><p>' . __('Click Save Menu to make pending menu items public.') . '</p></div>'; } if ($some_invalid_menu_items) { $result .= '<div class="error inline"><p>' . __('There are some invalid menu items. Please check or delete them.') . '</p></div>'; } $result .= '<ul class="menu" id="menu-to-edit"> '; $result .= walk_nav_menu_tree(array_map('nxt_setup_nav_menu_item', $menu_items), 0, (object) array('walker' => $walker)); $result .= ' </ul> '; return $result; } elseif (is_nxt_error($menu)) { return $menu; } }