Instantly share code, notes, and snippets.
Last active
March 6, 2019 14:06
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save Micemade/7d65a83d5c4608dd6d6e61ff5e777d37 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CUSTOM WP NAV MENU - no walker | |
* | |
* @package WordPress | |
* @subpackage My theme | |
* | |
* @details custom replacement menu for wp_nav_menu() | |
* with a "little" help from : | |
* David Baker - https://dtbaker.net/ | |
* https://stackoverflow.com/questions/8840319/build-a-tree-from-a-flat-array-in-php | |
* https://developer.wordpress.org/reference/functions/wp_get_nav_menu_items/ | |
*/ | |
/** | |
* Menu function | |
* | |
* @param string $theme_location - registered theme menu locations. | |
* @return void - output html for menu | |
*/ | |
function my_theme_menu_f( $theme_location ) { | |
$locations = get_nav_menu_locations(); | |
if ( ( $theme_location ) && $locations && isset( $locations[ $theme_location ] ) ) { | |
// Get flat array of menu items with wp_get_nav_menu_items. | |
$menu = get_term( $locations[ $theme_location ], 'nav_menu' ); | |
// If no menu object on theme location, abort. | |
if ( is_wp_error( $menu ) ) { | |
return; | |
} | |
$menu_id = $menu->term_id; | |
$array_menu = wp_get_nav_menu_items( $menu_id ); | |
// Another layer of checking. | |
if ( empty( $array_menu ) ) { | |
return; | |
} | |
// Extract only values needed | |
// look up for all values with print($array_menu) ). | |
$menu = array(); | |
foreach ( $array_menu as $m ) { | |
$menu[ $m->ID ] = array(); | |
$menu[ $m->ID ]['ID'] = $m->ID; | |
$menu[ $m->ID ]['title'] = $m->title; | |
$menu[ $m->ID ]['url'] = $m->url; | |
$menu[ $m->ID ]['target'] = $m->target; | |
$menu[ $m->ID ]['xfn'] = $m->xfn; | |
$menu[ $m->ID ]['desc'] = $m->description; | |
$menu[ $m->ID ]['classes'] = $m->classes; | |
$menu[ $m->ID ]['attr_title'] = $m->attr_title; | |
$menu[ $m->ID ]['parent'] = $m->menu_item_parent; | |
$menu[ $m->ID ]['curr'] = $m->object_id; | |
$menu[ $m->ID ]['children'] = array(); | |
$item_meta = get_post_meta( $m->ID ); | |
$menu[ $m->ID ]['urlargs'] = isset( $item_meta['menu-item-urlargs'] ) ? $item_meta['menu-item-urlargs'][0] : ''; | |
$menu[ $m->ID ]['mega'] = isset( $item_meta['menu-item-select-mega'] ) ? $item_meta['menu-item-select-mega'][0] : ''; | |
$menu[ $m->ID ]['icon'] = isset( $item_meta['menu-item-select-icon'] ) ? $item_meta['menu-item-select-icon'][0] : ''; | |
} | |
// MAKE MULTIDIMENSIONAL ARRAY FROM FLAT ARRAY / CREATE MENU TREE. | |
$menu_tree = my_theme_build_tree( $menu ); | |
// if error in build_tree function, abort. | |
if ( empty( $menu_tree ) ) { | |
return; | |
} | |
// Offcanvas theme location css selector to menu. | |
$offc_css = ''; | |
if ( 'offcanvas-menu' === $theme_location ) { | |
$offc_css = ' offcanvasopen'; | |
} | |
// Start menu. | |
echo '<ul class="navigation ' . esc_attr( $theme_location . $offc_css ) . '" id="' . esc_attr( $theme_location ) . '">'; | |
my_theme_build_menu( $menu_tree, $theme_location ); | |
echo '</ul>'; | |
} | |
} | |
add_action( 'my_theme_menu', 'my_theme_menu_f', 10, 1 ); | |
if ( ! function_exists( 'my_theme_menuitem_elements' ) ) { | |
/** | |
* Output menu items | |
* | |
* @param array $item - menu item. | |
* @param string $theme_location - location in theme. | |
* @return void - echo $output html | |
*/ | |
function my_theme_menuitem_elements( $item, $theme_location ) { | |
// Current page id. | |
$current_page_id = get_queried_object_id(); | |
$title = ! empty( $item['title'] ) ? $item['title'] : ''; | |
$attr_title = ! empty( $item['attr_title'] ) ? ' title="' . esc_attr( $item['attr_title'] ) . '"' : ''; | |
$url = ! empty( $item['url'] ) ? $item['url'] : '#'; | |
$target = ! empty( $item['target'] ) ? ' target="' . esc_attr( $item['target'] ) . '"' : ''; | |
$xfn = ! empty( $item['xfn'] ) ? ' rel="' . esc_attr( $item['xfn'] ) . '"' : ''; | |
$desc = ! empty( $item['desc'] ) ? $item['desc'] : ''; | |
$classes = ! empty( $item['classes'] ) ? implode( ' ', $item['classes'] ) : ''; | |
$current = ! empty( $item['curr'] ) ? intval( $item['curr'] ) : ''; | |
$children = ! empty( $item['children'] ) ? $item['children'] : array(); | |
// Custom meta for nav_menu_item CPT. | |
$urlargs = ! empty( $item['urlargs'] ) ? $item['urlargs'] : ''; | |
$mega = ! empty( $item['mega'] ) ? $item['mega'] : ''; | |
$icon = ! empty( $item['icon'] ) ? $item['icon'] : ''; | |
// Theme locations (Offcanvas or Vertical) submenu arrow indicator. | |
$arr = ''; | |
if ( 'offcanvas-menu' === $theme_location || 'vertical-menu' === $theme_location ) { | |
$arr = '<a href="#" class="sub"><i class="typcn typcn-chevron-right" aria-hidden="true"></i></a>'; | |
} | |
// CSS classes for menu list item. | |
$item_class = ''; | |
if ( $current_page_id === $current ) { | |
$item_class .= ' current'; | |
} | |
$item_class .= my_theme_subs( $children, $mega ); | |
// OUTPUT MENU ITEM ELEMENTS. | |
$output = '<li class="menu-item' . esc_attr( $item_class ) . '">'; | |
// $urlargs var is custom meta defined. | |
$output .= '<a href="' . esc_url( $url . $urlargs ) . '" class="menu-link ' . esc_attr( $classes ) . '" ' . $attr_title . $target . $xfn . '>'; | |
// $icon var is custom meta defined | |
$output .= ( $icon ? '<i class="item-icon typcn ' . esc_attr( $icon ) . '"></i>' : '' ); | |
$output .= ( $title ? '<span class="title">' . esc_html( $title ) . '</span>' : '' ); | |
$output .= ( $desc ? '<span class="desc">' . esc_html( $desc ) . '</span>' : '' ); | |
// $mega var is custom meta defined | |
$output .= ( ( ! empty( $children ) || $mega ) ? '<span class="append-sub-arrow"></span>' : '' ); | |
$output .= '</a>'; | |
$output .= ( ! empty( $children ) ? wp_kses_post( $arr ) : '' ); | |
echo wp_kses_post( $output ); | |
} | |
} | |
if ( ! function_exists( 'my_theme_subs' ) ) { | |
/** | |
* CSS Class if there are children | |
* | |
* @param array $children - sub items of menu. | |
* @param string $mega - ID of megamenu (if any). | |
* @return $css | |
*/ | |
function my_theme_subs( $children, $mega ) { | |
$css = ''; | |
if ( ! empty( $children ) || $mega ) { | |
$css = ' dropdown'; | |
} | |
return $css; | |
} | |
} | |
if ( ! function_exists( 'my_theme_build_tree' ) ) { | |
/** | |
* Build tree menu ( multidimensional array ) | |
* | |
* @param array $elements - array of elements. | |
* @param integer $parent_id - ID of parent item. | |
* @return $branch | |
*/ | |
function my_theme_build_tree( array &$elements, $parent_id = 0 ) { | |
$branch = array(); | |
foreach ( $elements as $element ) { | |
if ( $element['parent'] == $parent_id ) { | |
$children = my_theme_build_tree( $elements, $element['ID'] ); | |
if ( $children ) { | |
$element['children'] = $children; | |
} | |
$branch[ $element['ID'] ] = $element; | |
//unset($elements[$element['ID']]); | |
} | |
} | |
return $branch; | |
} | |
} | |
if ( ! function_exists( 'my_theme_build_menu' ) ) { | |
/** | |
* Build menu | |
* | |
* @param array $menu_tree | |
* @param string $theme_location | |
* @return html | |
* Recursive function to print out multidimensional array | |
* as menu in nested unordered list format | |
*/ | |
function my_theme_build_menu( array &$menu_tree, $theme_location ) { | |
foreach ( $menu_tree as $id => $branch ) { | |
my_theme_menuitem_elements( $branch, $theme_location ); | |
$children = ! empty( $branch['children'] ) ? true : false; | |
$mega = ! empty( $branch['mega'] ) ? $branch['mega'] : ''; | |
if ( $children || isset( $mega ) ) { | |
// If megamenu is set in custom meta | |
// AND theme location is hor. menu, render mega menu. | |
if ( $mega && 'horizontal-menu' === $theme_location ) { | |
echo '<ul class="sub-menu mega-menu">'; | |
echo apply_filters( 'my_theme_render_mega_menu', $mega ); | |
} else { | |
echo '<ul class="sub-menu">'; | |
my_theme_build_menu( $branch['children'], $theme_location ); | |
} | |
echo '</ul>'; | |
} | |
echo '</li>'; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An alternative to WP menu walker. Use at your own risk, but this served well for Micemade themes.
Usage:
do_action( 'my_theme_menu', 'my-menu-name' );
Remove unnecessarry vars or funcs ( custom meta - $icon $mega,$urlargs , my_theme_render_mega_menu action ... etc. )
Feel free to suggest a better solution(s) or improvements.