Instantly share code, notes, and snippets.
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save isotopie/2ee76b1d0b542ca8d9bb6341d384d64e to your computer and use it in GitHub Desktop.
Custom wordpress menu: Get menu as hierarchical array with children
This file contains 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 | |
// is child of, recursive | |
function is_child_of( $post, $possible_parent_ID ) { | |
if ($post->ID == $possible_parent_ID) { | |
return true; | |
} elseif ($post->post_parent == 0) { | |
return false; | |
} else { | |
return is_child_of( get_post($post->post_parent), $possible_parent_ID ); | |
} | |
} | |
// convert relative to absolute URLs | |
function relative_to_absolute_URL($rel, $base) { | |
/* return if already absolute URL */ | |
if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel; | |
/* queries and anchors */ | |
if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel; | |
/* parse base URL and convert to local variables: | |
$scheme, $host, $path */ | |
extract(parse_url($base)); | |
/* remove non-directory element from path */ | |
$path = preg_replace('#/[^/]*$#', '', $path); | |
/* destroy path if relative url points to root */ | |
if ($rel[0] == '/') $path = ''; | |
/* dirty absolute URL */ | |
$abs = "$host$path/$rel"; | |
/* replace '//' or '/./' or '/foo/../' with '/' */ | |
$re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'); | |
for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {} | |
/* absolute URL is ready! */ | |
return $scheme.'://'.$abs; | |
} | |
// custom menu url (e.g. '/custom-archive') – is it current? | |
function custom_post_type_menu_current($menuitem) { | |
// menu item URL | |
$url = $menuitem->url; | |
$url = relative_to_absolute_URL($url, site_url()); | |
// custom post type archive link | |
$post_type = get_post_type( get_the_ID() ); | |
$post_type_archive_link = get_post_type_archive_link($post_type); | |
$custom_post_type_archive_link = rtrim($post_type_archive_link,"/"); | |
if (!$custom_post_type_archive_link) { | |
return false; | |
} | |
if (strpos($url,$custom_post_type_archive_link) !== false) { | |
return true; | |
} | |
return false; | |
} | |
function category_menu_current($post, $menuitem) { | |
if ($menuitem->object !== 'category') { | |
return false; | |
} | |
$categories = get_the_category( $post->ID ); | |
if (is_category($menuitem->object_id)) { | |
return true; | |
} | |
if ((is_page() || is_single()) && ((int)$menuitem->object_id === $category->term_taxonomy_id)) { | |
return true; | |
} | |
return false; | |
} | |
// hierarchical menus | |
function menu_has_children($item) { | |
if (!empty($item->children)) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
// find id in multidimensional menuitems, recursive | |
function find_parent_in_multi_menuitems($id, $menuitems) { | |
foreach ($menuitems as $menuitem) { | |
if ((int) $id === (int) $menuitem->ID) { | |
// $menuitem->level = $level; | |
return $menuitem; | |
} else { | |
// get children | |
if ($children = $menuitem->children) { | |
// find parent | |
$parent = find_parent_in_multi_menuitems($id, $children); | |
} | |
} | |
} | |
return false; | |
} | |
// for each menuitems, recursive | |
function get_heirachical_menu($menu_name, $locations) { | |
global $post; | |
// get current post object | |
$the_post_id = false; | |
if (!empty($post->ID)) { | |
$the_post_id = $post->ID; | |
} | |
if (empty($locations[$menu_name])) { | |
return false; | |
} | |
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] ); | |
// get wordpress menu items from menu | |
$menuitems = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) ); | |
$menu_items_multidimensional = array(); | |
foreach ($menuitems as $menuitem) { | |
// add current classes | |
$menuitem->current = false; | |
// current page is current | |
if ($the_post_id === (int)$menuitem->object_id && $menuitem->object === 'page') { | |
$menuitem->current = true; | |
} | |
// current post is current | |
if ($the_post_id === (int)$menuitem->object_id && $menuitem->object === 'post') { | |
$menuitem->current = true; | |
} | |
// if is child of post | |
if ( is_child_of($post, (int)$menuitem->object_id) && ($menuitem->object === 'page') ) { | |
$menuitem->current = true; | |
} | |
// get parent ID | |
$parentID = $menuitem->menu_item_parent; | |
// setup childrens array if doesn't exist | |
if (!$menuitem->children) { | |
$menuitem->children = array(); | |
} | |
// if menu item is top level | |
if ((int) $parentID === 0) { | |
// add to multidimensional array; | |
$menuitem->level = 0; | |
$menu_items_multidimensional[] = $menuitem; | |
} else { | |
// find parent | |
$parent = find_parent_in_multi_menuitems($parentID, $menuitems); | |
// add this item to parent->children array(); | |
if ($menuitem->current) { | |
$parent->current = true; | |
} | |
$menuitem->level = $parent->level + 1; | |
$parent->children[] = $menuitem; | |
} | |
// sort custom post type current classes | |
if (custom_post_type_menu_current($menuitem)) { | |
$menuitem->current = true; | |
} | |
if (category_menu_current($post, $menuitem)) { | |
$menuitem->current = true; | |
} | |
} | |
return $menu_items_multidimensional; | |
} | |
// get wordpress menu locations | |
$menu_locations = get_nav_menu_locations(); | |
// get menus with $menu = get_heirachical_menu('menu_name', $menu_locations); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment