Skip to content

Instantly share code, notes, and snippets.

@isotopie
Forked from coxmi/Menu.php
Created May 15, 2016 11:42
Show Gist options
  • Save isotopie/2ee76b1d0b542ca8d9bb6341d384d64e to your computer and use it in GitHub Desktop.
Save isotopie/2ee76b1d0b542ca8d9bb6341d384d64e to your computer and use it in GitHub Desktop.
Custom wordpress menu: Get menu as hierarchical array with children
<?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