Created
August 21, 2018 16:59
-
-
Save Langmans/ac9ccf53861a06721c26e88b3b855924 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 | |
class Menu extends \Timber\Menu { | |
public $MenuItemClass = 'MenuItem'; | |
} | |
class MenuItem extends \Timber\MenuItem { | |
/** @var MenuItem */ | |
public $parent; | |
/** | |
* @param MenuItem $item | |
*/ | |
public function add_child( $item ) { | |
if ( $item === $this || $item->id == $this->id ) { | |
throw new \InvalidArgumentException( 'recursion error??' ); | |
} | |
parent::add_child( $item ); | |
$item->set_parent( $this ); | |
} | |
/** | |
* @return MenuItem | |
*/ | |
public function get_parents() { | |
$parent = $this; | |
$parents = []; | |
while ( $parent = $parent->get_parent() ) { | |
$parents[] = $parent; | |
} | |
return $parent; | |
} | |
/** | |
* @return MenuItem|bool | |
*/ | |
public function get_parent() { | |
return $this->parent ?: false; | |
} | |
public function set_parent( MenuItem $parent ) { | |
// if ( $this->parent ) { | |
// $this->parent->remove_child( $parent ); | |
// } | |
$this->parent = $parent; | |
} | |
} | |
add_filter('timber_context', function( array $context ) { | |
$ancestor_links = []; | |
if ( is_post_type_hierarchical( get_post_type() ) ) { | |
// For pages or any post type with hierarchy. | |
// We use this if a page is 5 levels deep and the menu only has one level of dropdowns. | |
$ancestor_links = get_post_ancestors( get_the_ID() ); | |
} elseif ( get_post_type() === 'post' && get_option( 'show_on_front' ) === 'page' && ( $page_for_posts = get_option( 'page_for_posts' ) ) ) { | |
// we selected a page for a news article. So use that as selected menu item if it's available, or any of the ancestors. | |
$ancestor_links = get_post_ancestors( $page_for_posts ); | |
$ancestor_links [] = $page_for_posts; | |
} | |
if ( $ancestor_links ) { | |
$ancestor_links = array_map( 'get_permalink', $ancestor_links ); | |
} | |
foreach ( get_nav_menu_locations() as $location => $menu_id ) { | |
$context['menus'][ $location ] = $menu = new Menu( $menu_id ); | |
if ( $ancestor_links ) { | |
// Check if the menu has an item active. | |
$has_active_item = false; | |
/** @var MenuItem $item */ | |
foreach ( $menu->get_items() as $item ) { | |
if ( $item->current || $item->current_item_ancestor || $item->current_item_parent ) { | |
$has_active_item = true; | |
break; | |
} | |
} | |
if ( ! $has_active_item ) { | |
/** @var MenuItem $selected_menu_item */ | |
$selected_menu_item = null; | |
/** @var MenuItem[] $items */ | |
$items = []; | |
$stack = [ $menu->get_items() ]; | |
while ( $stack_items = array_pop( $stack ) ) { | |
/** @var MenuItem $item */ | |
foreach ( $stack_items as $item ) { | |
if ( strtok( $item->link(), '#' ) ) { | |
$items[] = $item; | |
} | |
$children = $item->children(); | |
if ( $children ) { | |
// loop the children too! | |
$stack[] = $children; | |
} | |
} | |
} | |
// we have all the links in the menu now. | |
// search for a menu item in reverse order. We dont want to highlight the ancestors first. | |
while ( $item = array_pop( $items ) ) { | |
// strip hashtags, ie page.html#bladiebla | |
$link = strtok( $item->link(), '#' ); | |
if ( in_array( $link, $ancestor_links, false ) ) { | |
$item->current = true; | |
$item->add_class( 'current-menu-item' ); | |
if ( $parent = $item->parent ) { | |
$parent->current_item_parent = true; | |
$parent->current_item_ancestor = true; | |
$parent->add_class( 'current-menu-parent' ); | |
$parent->add_class( 'current-menu-ancestor' ); | |
while ( $parent = $parent->parent ) { | |
$parent->current_item_ancestor = true; | |
$parent->add_class( 'current-menu-ancestor' ); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment