Skip to content

Instantly share code, notes, and snippets.

@sevenspark
Created December 22, 2016 13:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sevenspark/7a4df3c71f046ed7dd98d58e421ccca4 to your computer and use it in GitHub Desktop.
Save sevenspark/7a4df3c71f046ed7dd98d58e421ccca4 to your computer and use it in GitHub Desktop.
<?php
/**
* Parent Class
*/
abstract class UberMenuItem{
protected $type = 'unknown'; //Item Type getType() default, dynamic_term, dynamic_post,
protected $ID = 0; //Menu Item ID getID()
protected $source_id = 0;
protected $output;
protected $item;
protected $depth;
protected $args;
protected $id;
protected $walker;
protected $settings;
protected $submenu_advanced;
protected $submenu_tag = 'ul';
protected $submenu_classes = array();
protected $item_classes = array( 0 => '' ); //Put in an empty entry to mimic the custom class used by real items, for when we have a dummy item
protected $item_atts = array();
protected $auto_child = '';
protected $prev_auto_child = '';
protected $alter_structure = false;
protected $has_children = false;
protected $submenu_type = false;
protected $drop_sub = false;
protected $closable_sub = false;
protected $is_dummy = false;
protected $is_tab = false;
//protected $branch_prefix = '';
/*
protected $detached = false;
protected $detached_submenu = false;
protected $parent_detached_context = 0;
protected $passed_content = '';
*/
function __construct( &$output , &$item , $depth = 0, &$args = array() , $id = 0 , &$walker , $has_children = false ){
$this->output = &$output;
$this->item = &$item;
$this->depth = $depth;
$this->args = &$args;
$this->id = $id;
$this->walker = &$walker;
$this->has_children = $has_children;
$this->ID = $this->item->ID;
//up( $this->ID );
//Setup dummy
if( isset( $this->item->is_dummy ) && $this->item->is_dummy ){
$this->is_dummy = true;
}
//Setup settings
$this->settings = $this->get_settings();
$this->source_id = $this->item->db_id;
if( isset( $this->item->object ) && ( $this->item->object == 'ubermenu-custom' ) ){
//echo 'set source_id ' . $this->item->object_id;
$this->source_id = $this->item->object_id;
}
//New filter in 4.4 - 'nav_menu_item_args'
//Since this filter is most likely going to just break the menu, it is disabled by default, but can be enabled by adding
//define( 'UBERMENU_ALLOW_NAV_MENU_ITEM_ARGS_FILTER' , true );
//in the wp-config.php
if( UBERMENU_ALLOW_NAV_MENU_ITEM_ARGS_FILTER ) $this->args = apply_filters( 'nav_menu_item_args' , $this->args , $this->item );
$this->init();
//Only check if necessary (Advanced submenu set to auto)
if( $this->getSetting( 'submenu_advanced' ) == 'auto' ){
if( $this->item->classes == null ){
//echo '<h3>[['.$this->item->title.']]</h3>';
//up( $this->item );
}
if( is_array( $this->item->classes ) ){
if( in_array( 'advanced-sub' , $this->item->classes ) ){
$this->submenu_advanced = true;
$this->submenu_tag = 'div';
}
}
}
else if( $this->getSetting( 'submenu_advanced' ) == 'enabled' ){
$this->submenu_advanced = true;
$this->submenu_tag = 'div';
}
}
/* Allows subclasses to hook in */
function init(){}
function get_item(){
return $this->item;
}
function get_branch_prefix(){
return $this->branch_prefix;
}
function get_id(){
return $this->ID;
}
function getID(){
return $this->ID;
}
function get_transient_key( $prefix ){
return 'ubertk_'.$prefix.$this->walker->unique_path_key( $this->get_id() );
}
function get_depth(){
return $this->depth;
}
function is_tab(){
return $this->is_tab;
}
function display_on(){
if( $this->getSetting( 'disable_on_mobile' ) == 'on' ){
if( ubermenu_is_mobile( 'disable_on_mobile' ) ){
return false;
}
}
if( $this->getSetting( 'disable_on_desktop' ) == 'on' ){
if( !ubermenu_is_mobile( 'disable_on_desktop' ) ){
return false;
}
}
return true;
}
function disable_children(){
$this->has_children = false;
$_item = $this->item;
if( ( $key = array_search( 'menu-item-has-children', $_item->classes ) ) !== false) {
unset( $_item->classes[$key] );
}
//Possibly remove menu item parent/menu item ancestor classes as well
}
function create_reference( $source_id , &$children , $reference_index = '' ){
if( $reference_index == '' ){
$reference_index = '_ref_'.$source_id;
}
if( !$this->walker->feed_trash_collector( $reference_index ) ){
if( isset( $children[$source_id] ) && !empty( $children[$source_id] ) ){
$children[$reference_index] = $children[$source_id];
}
}
return $reference_index;
}
/* If this item models a term, return its ID */
function get_term_id(){
return false;
}
/* If this item models a post, return its ID */
function get_post_id(){
return false;
}
function dynamic_alter( $tab_id , $source_id , $umitem , &$children ){
return false;
}
function get_settings(){
if( isset( $this->settings ) ) return $this->settings;
$settings = get_post_meta( $this->item->ID, UBERMENU_MENU_ITEM_META_KEY , true );
if( !$settings ) $settings = array();
//Allow dummy settings to override source item settings
if( $this->is_dummy && isset( $this->item->settings ) ){
if( !is_array( $settings ) ) $settings = array();
foreach( $this->item->settings as $key => $val ){
$settings[$key] = $val;
}
}
$settings = apply_filters( 'ubermenu_item_settings' , $settings , $this->ID );
return $settings;
}
function get_menu_op( $op ){
//Determine menu instance
//$instance = 'main'; //TODO
//$instance = $this->args[0]->uber_instance;
$instance = $this->get_config_id();
return ubermenu_op( $op , $instance );
}
function get_config_id(){
return $this->args->uber_instance;
}
function alter_structure(){
return $this->alter_structure;
}
function alter( &$children ){}
function get_submenu_tag(){
return $this->submenu_tag;
}
function pass_content( $content ){
$this->passed_content.= $content;
}
function getAutoChild(){
return $this->auto_child;
}
function getType(){
return $this->type;
}
function getSetting( $key ){
if( isset( $this->settings[$key] ) ){
$val = $this->settings[$key];
}
else{ //} if( isset( $this->walker->setting_defaults[$key] ) ){
$val = $this->walker->setting_defaults[$key];
}
return $val;
}
//1
function start_el(){
$this->output.= apply_filters( 'walker_nav_menu_start_el' , $this->get_start_el() , $this->item , $this->depth , $this->args );
}
//4
function end_el(){
$this->output.= $this->get_end_el();
}
//2
function start_lvl(){
$this->output.= $this->get_submenu_wrap_start();
}
//3
function end_lvl(){
$this->output.= $this->get_submenu_wrap_end();
}
//Detached content
function detach(){
$this->detached_submenu = true;
$this->walker->detach( $this->ID );
//echo 'detached ' . $this->ID . '<br/>';
}
function undetach(){
$this->detached_submenu = false;
$this->walker->undetach();
}
function complete_detachment(){} //do nothing by default
abstract function get_start_el();
function get_end_el(){
$item_output = "</li>"; //<!-- end ".$this->item->ID."-->\n";
return $item_output;
}
function get_submenu_type( $submenu_type = false ){
if( !$this->has_children ) return false;
//If already cached, don't reprocess
if( $this->submenu_type ) return $this->submenu_type;
//If not passed, grab setting
if( !$submenu_type ) $submenu_type = $this->getSetting( 'submenu_type' );
//echo $this->item->title . ' : '. $submenu_type ." : $this->depth <br/>";
if( $submenu_type == 'auto' ){
//$classes[] = 'ubermenu-submenu-type-auto';
//figure it out
if( $this->depth == 0 ){
$submenu_type = 'mega';
}
else if( $this->depth >= 1 ){
$parent = $this->walker->parent_item();
if( $parent && $parent->type == 'row' ){
$parent = $this->walker->grandparent_item();
}
//up( $parent );
//echo 'Parent of '.$this->item->title . ' is ' . $parent->getSetting( 'submenu_type_calc' ) .'<br/>';
$parent_submenu = $parent->getSetting( 'submenu_type_calc' );
//echo ' -- ' .$this->item->title . ' : ' . $parent_submenu . '<br/>';
switch( $parent_submenu ){
case 'mega':
case 'block':
case 'tab-content-panel':
case 'toggles-content-panel':
$submenu_type = 'stack';
break;
case 'flyout':
$submenu_type = 'flyout';
break;
default:
//inherit parent
$submenu_type = $parent_submenu;
break;
}
}
}
$this->submenu_type = $submenu_type;
return $submenu_type;
}
function get_submenu_wrap_start(){
//Standard WordPress Classes
$classes = $this->submenu_classes;
$classes[] = 'ubermenu-submenu';
$classes[] = 'ubermenu-submenu-id-' . $this->item->ID;
//Submenu Type
$submenu_type = $this->getSetting( 'submenu_type' );
//echo $this->item->title . ' : '. $submenu_type ." : $this->depth <br/>";
if( $submenu_type == 'auto' ){
$classes[] = 'ubermenu-submenu-type-auto';
$submenu_type = $this->get_submenu_type( $submenu_type );
}
$this->settings['submenu_type_calc'] = $submenu_type;
$classes[] = 'ubermenu-submenu-type-'.$submenu_type;
//echo $submenu_type.'<br/>';
if( in_array( $submenu_type , array( 'mega' , 'flyout' ) ) ){
$this->drop_sub = true;
$classes[] = 'ubermenu-submenu-drop';
}
if( $this->drop_sub || $submenu_type == 'tab-content-panel' ){
$this->closable_sub = true;
}
//Mega menu submenu alignment
if( $submenu_type == 'mega' ){
$classes[] = 'ubermenu-submenu-align-' . $this->getSetting( 'submenu_position' );
}
else if( $submenu_type == 'flyout' ){
$classes[] = 'ubermenu-submenu-align-' . $this->getSetting( 'flyout_submenu_position' );
}
//Menu menu submenu content alignment
$submenu_content_align = $this->getSetting( 'submenu_content_align' );
if( $submenu_content_align && $submenu_content_align != 'default' ){
$classes[] = 'ubermenu-submenu-content-align-' . $submenu_content_align;
}
//Autoclear
$submenu_col_default = $this->getSetting( 'submenu_column_default' );
if( $this->getSetting( 'submenu_column_autoclear' ) == 'on' && $submenu_col_default != 'auto' && $submenu_col_default != 'natural' ){
$classes[] = 'ubermenu-autoclear';
}
//Padding
if( $this->getSetting( 'submenu_padded' ) == 'on' ){
$classes[] = 'ubermenu-submenu-padded';
}
//Background Image
if( $this->getSetting( 'submenu_background_image' ) ){ //Not 'on', image URL
$classes[] = 'ubermenu-submenu-bkg-img';
}
//Submenu Grid
if( $this->getSetting( 'submenu_grid' ) == 'on' ){
$classes[] = 'ubermenu-submenu-grid';
}
//Indent
if( $this->getSetting( 'submenu_indent' ) == 'on' ){
$classes[] = 'ubermenu-submenu-indent';
}
//Retractors
$retractor_top = $this->closable_sub && ubermenu_display_retractors() && ( ubermenu_op( 'display_retractor_top' , $this->args->uber_instance ) == 'on' );
if( $retractor_top ) $classes[] = 'ubermenu-submenu-retractor-top';
//Close Button
$close_button = $this->closable_sub && ( ubermenu_op( 'display_submenu_close_button' , $this->args->uber_instance ) == 'on' );
if( $close_button ){
if( $retractor_top ) $classes[] = 'ubermenu-submenu-retractor-top-2';
else $classes[] = 'ubermenu-submenu-retractor-top';
}
$class = 'class="'.implode( ' ' , $classes ).'"';
//Inline styles
$_styles = array();
//Explicit width (should be moved)
/*$submenu_width = $this->getSetting( 'submenu_width' );
if( $submenu_width != '' ){
if( is_numeric( $submenu_width ) ) $submenu_width.= 'px';
$_styles['width'] = $submenu_width;
}
*/
//Create inline styles string if necessary
$styles = '';
if( count( $_styles ) > 0 ){
$styles.= 'style="';
foreach( $_styles as $property => $val ){
$styles.= "$property:$val;";
}
$styles.='"';
}
$item_output = "<$this->submenu_tag $class $styles>";
//Retractor Top
if( $retractor_top ){
$retractor_tag = $this->submenu_tag == 'ul' ? 'li' : 'div';
$retractor_label = ubermenu_op( 'retractor_label' , $this->args->uber_instance );
if( !$retractor_label ) $retractor_label = __( 'Close' , 'ubermenu' );
$item_output.= '<'.$retractor_tag.' class="ubermenu-retractor ubermenu-retractor-mobile"><i class="fa fa-times"></i> '.$retractor_label.'</'.$retractor_tag.'>';
}
//Close button
if( $close_button ){
$retractor_tag = $this->submenu_tag == 'ul' ? 'li' : 'div';
$item_output.= '<'.$retractor_tag.' class="ubermenu-retractor ubermenu-retractor-desktop"><i class="fa fa-times"></i></'.$retractor_tag.'>';
}
return $item_output;
}
function get_submenu_wrap_end(){
$html = '';
//Footer Content
$footer_content = $this->getSetting( 'submenu_footer_content' );
if( $footer_content ){
$fc_tag = 'li';
if( $this->submenu_tag != 'ul' ) $fc_tag = 'div';
$html.= '<'.$fc_tag.' class="ubermenu-submenu-footer ubermenu-submenu-footer-id-'.$this->ID.'">'.$footer_content.'</'.$fc_tag.'>';
}
//'tab-content-panel'
//Retractor Bottom
if( $this->closable_sub && ubermenu_display_retractors() && ( ubermenu_op( 'display_retractor_bottom' , $this->args->uber_instance ) == 'on' ) ){
$retractor_tag = $this->submenu_tag == 'ul' ? 'li' : 'div';
$retractor_label = ubermenu_op( 'retractor_label' , $this->args->uber_instance );
if( !$retractor_label ) $retractor_label = __( 'Close' , 'ubermenu' );
$html.= '<'.$retractor_tag.' class="ubermenu-retractor ubermenu-retractor-mobile"><i class="fa fa-times"></i> '.$retractor_label.'</'.$retractor_tag.'>';
}
$html.= "</$this->submenu_tag>";
return $html;
}
function getVirtualDepth(){
return $this->depth;
}
function add_class_item_defaults(){
//$this->item_classes = empty( $this->item->classes ) ? array() : (array) $this->item->classes;
if( is_array( $this->item->classes ) ){
$this->item_classes = array_merge( $this->item_classes , $this->item->classes );
//Disable Current Menu Item Classes (do this first for efficiency)
if( $this->getSetting( 'disable_current' ) == 'on' ){
$remove_current = array( 'current-menu-item' , 'current-menu-parent' , 'current-menu-ancestor' );
foreach( $this->item_classes as $k => $c ){
if( in_array( $c , $remove_current ) ){
unset( $this->item_classes[$k] );
}
}
$this->item_classes[] = 'nocurrent';
}
}
}
function add_class_id(){
$this->item_classes[] = 'menu-item-' . $this->item->ID;
}
function prefix_classes(){
//uberp( $this->item_classes );
$k = 0;
$found = false;
foreach( $this->item_classes as $i => $class ){
//if( $class == 'menu-item' ) $classes[$i] = 'ubermenu-item';
//The first class is custom, so ignore it
//if( $k == 0 ){ $k++; continue; }
//menu-item marks the first class we want to preix, so ignore everything before that
if( !$found && $class == 'menu-item' ) $found = true;
if( !$found ) continue;
if( $class ){
if( substr( $class , 0 , 4 ) == 'menu' ){
$this->item_classes[$i] = 'uber'.$class;
}
else $this->item_classes[$i] = 'ubermenu-'.$class;
//add to end if using both
}
}
}
function add_class_item_display(){
$this->settings['item_display_calc'] = '';
//Item Display
if( $this->depth > 0 ){
$item_display = $this->getSetting( 'item_display' );
$this->item_classes[] = 'ubermenu-item-'.$item_display;
//Determine auto
if( $item_display == 'auto' ){
$parent_type = $this->walker->parent_item()->getType();
switch( $parent_type ){
//For items inside a content panel, act like a mega sub
case 'toggle_content_panel':
$item_display = 'header';
break;
//For terms inside a content panel, look to the grandparent
case 'dynamic_posts':
case 'dynamic_terms':
if( $this->walker->grandparent_item() ){
if( $this->walker->grandparent_item()->getType() == 'toggle_content_panel' ){
$item_display = 'header';
}
//echo '//'.$this->walker->grandparent_item()->getType().'//<br/>';
}
break;
//case 'column':
// $item_display = 'normal';
// break;
}
//Still auto?
if( $item_display == 'auto' ){
$in_sub = $this->walker->parent_item()->getSetting('submenu_type_calc');
switch( $in_sub ){
case 'mega' :
if( $this->depth == 1 ){
$item_display = 'header';
}
else if( $this->depth > 1 && $this->walker->parent_item()->getVirtualDepth() == 1 ){
$item_display = 'header';
}
else if( $this->walker->parent_item()->getType() == 'row' ){
$item_display = 'header';
}
else if( $this->walker->parent_item()->getType() == 'menu_segment' &&
$this->walker->grandparent_item()->getType() == 'row'){
$item_display = 'header';
}
else if( $this->depth > 1 && $this->walker->grandparent_item()->getSetting('submenu_type_calc') == 'flyout' ){
$item_display = 'header';
}
else{
//For items that are in the submenu but yet undetermined
if( $this->depth > 1 ){
//If it's parent wasn't a header, but the sub of the parent was a mega, this should probably be a header
if( $this->walker->parent_item()->getSetting( 'item_display_calc' ) != 'header' ){
$item_display = 'header';
}
}
else $item_display = 'normal';
}
break;
case 'flyout':
$item_display = 'normal';
break;
case 'stack':
$item_display = 'normal';
break;
case 'block':
$item_display = 'header';
break;
case 'tabs-group':
case 'toggles-group':
//Ignore, use 'ubermenu-toggle' instead
$item_display = '';
break;
case 'tab-content-panel':
case 'toggles-content-panel':
$item_display = 'header';
break;
/*
case 'dynamic-terms':
$item_display = 'header';
break;*/
default:
$item_display = 'unknown-['.$in_sub.']';
break;
}
}
if( $item_display ){
$this->item_classes[] = 'ubermenu-item-'.$item_display;
// $this->settings['item_display_calc'] = $item_display;
}
}
$this->settings['item_display_calc'] = $item_display;
}
}
function add_class_level(){
$this->item_classes[] = 'ubermenu-item-level-'.$this->getVirtualDepth(); //$this->depth;
}
function add_class_layout_columns(){
if( $this->depth > 0 ){
$parent_submenu_type = $this->walker->parent_item()->getSetting('submenu_type_calc');
if( $parent_submenu_type == 'flyout' ) return; //no columns in flyouts
}
//if( $this->depth > 1 ){
$cols = $this->getSetting( 'columns' );
if( $this->depth > 0 ){
//Widgets are full width if Columns set to Auto
if( ( $this->getSetting( 'widget_area' ) || $this->getSetting( 'auto_widget_area' ) )
&& $cols == 'auto' ){
$cols = 'full';
}
//If set to auto, apply submenu column default from parent item
else if( $cols == 'auto' ){
$cols = $this->walker->parent_item()->getSetting( 'submenu_column_default' );
}
}
$this->item_classes[] = 'ubermenu-column ubermenu-column-' . $cols;
//New Row
if( $this->getSetting( 'clear_row' ) == 'on' ){
$this->item_classes[] = 'ubermenu-clear-row';
}
//if( $this->walker->parent_item()->getSetting)
}
function add_class_alignment(){
$align = $this->getSetting( 'item_align' );
if( $align && $align != 'auto' ){
$this->item_classes[] = 'ubermenu-align-'.$align;
}
}
function add_class_mini_item(){
if( $this->getSetting( 'mini_item' ) == 'on' ){
$this->item_classes[] = 'ubermenu-item-mini';
}
}
function add_class_rtl_sub(){
if( ( $this->get_submenu_type() == 'mega' ) && ( $this->getSetting( 'submenu_position' ) == 'right_edge_item' ) ) {
$this->item_classes[] = 'ubermenu-submenu-rtl';
}
else if( ( $this->get_submenu_type() == 'flyout' ) && ( $this->getSetting( 'flyout_submenu_position' ) == 'right_edge_item' ) ){
$this->item_classes[] = 'ubermenu-submenu-rtl';
$this->item_classes[] = 'ubermenu-submenu-reverse';
}
}
function add_class_responsive(){
if( $this->getSetting( 'hide_on_mobile' ) == 'on' ){
$this->item_classes[] = 'ubermenu-hide-mobile';
}
if( $this->getSetting( 'hide_on_desktop' ) == 'on' ){
$this->item_classes[] = 'ubermenu-hide-desktop';
}
}
function add_class_submenu(){
$submenu_type = $this->get_submenu_type();
if( $submenu_type ){
if( in_array( $submenu_type , array( 'mega' , 'flyout' ) ) ){
$this->item_classes[] = 'ubermenu-has-submenu-drop';
//Show current
if( ( $this->getSetting( 'show_current' ) == 'on' ) &&
( in_array( 'ubermenu-current-menu-ancestor' , $this->item_classes ) ||
in_array( 'ubermenu-current-menu-item' , $this->item_classes )
) ){
$this->item_classes[] = 'ubermenu-active';
}
//Show Default
if( $this->getSetting( 'show_default' ) == 'on' ){
$this->item_classes[] = 'ubermenu-active';
}
}
$this->item_classes[] = 'ubermenu-has-submenu-'.$submenu_type;
}
if( ( $this->getSetting( 'submenu_position' ) == 'vertical_parent_item' ) ||
( $this->getSetting( 'flyout_submenu_position' ) == 'vertical_parent_item' ) ){
$this->item_classes[] = 'ubermenu-relative';
}
if( $submenu_type == 'flyout' && $this->getSetting( 'flyout_submenu_position' ) == 'vertical_full_height' ){
$this->item_classes[] = 'ubermenu-flyout-full-height';
}
}
function add_class_disable_padding(){
$disable_padding = $this->getSetting( 'disable_padding' );
if( $disable_padding == 'on' ){
$this->item_classes[] = 'ubermenu-disable-padding';
}
}
function filter_item_classes(){
/**
* Filter the CSS class(es) applied to a menu item's <li>.
*
* @since 3.0.0
*
* @param array $classes The CSS classes that are applied to the menu item's <li>.
* @param object $item The current menu item.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $this->item_classes ), $this->item, $this->args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
return $class_names;
}
function filter_item_id(){
/**
* Filter the ID applied to a menu item's <li>.
*
* @since 3.0.1
*
* @param string The ID that is applied to the menu item's <li>.
* @param object $item The current menu item.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $this->item->ID, $this->item, $this->args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
return $id;
}
function setup_trigger(){
$trigger = $this->getSetting( 'item_trigger' );
if( $trigger && $trigger != 'auto' ){
$this->item_atts['data-ubermenu-trigger'] = $trigger;
}
}
function get_url(){
return $this->item->url;
}
function set_url( $url ){
$this->item->url = $url;
}
/**
* Get the attributes for the anchor, including class, title, target, rel, href
* Filterable with 'nav_menu_link_attributes'
* @return array An array of attributes with attribute names as keys and attribute values as values i.e. $key="$val"
*/
function anchor_atts(){
$atts = array();
$atts['class'] = 'ubermenu-target'; //add UberMenu specific meta
$atts['title'] = ! empty( $this->item->attr_title ) ? $this->item->attr_title : '';
$atts['target'] = ! empty( $this->item->target ) ? $this->item->target : '';
$atts['rel'] = ! empty( $this->item->xfn ) ? $this->item->xfn : '';
$atts['href'] = ! empty( $this->item->url ) ? $this->item->url : '';
if( $this->depth == 0 ){
$atts['tabindex'] = 0;
}
/**
* Filter the HTML attributes applied to a menu item's <a>.
*
* @since 3.6.0
*
* @param array $atts {
* The HTML attributes applied to the menu item's <a>, empty strings are ignored.
*
* @type string $title The title attribute.
* @type string $target The target attribute.
* @type string $rel The rel attribute.
* @type string $href The href attribute.
* }
* @param object $item The current menu item.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $this->item, $this->args );
return $atts;
}
/**
* Get the Anchor and its contents
* @param array $atts An array of attributes to add to the anchor
* @return string The HTML for the anchor
*/
function get_anchor( $atts ){
if( $this->item->title == '--divide--' ){
return '<div class="ubermenu-divider"><hr/></div>';
}
$a = '';
$tag = 'a';
//Highlight
if( $this->getSetting( 'highlight' ) == 'on' ){
$atts['class'].= ' ubermenu-highlight';
}
//Image
$image = $this->get_image();
if( $image ) $atts['class'] .= ' ubermenu-target-with-image';
//Icon
$icon = $this->getSetting( 'icon' );
$icon_classes = apply_filters( 'ubermenu_icon_custom_class' , $icon , $this->ID , isset( $this->settings['icon_custom_class'] ) ? $this->settings['icon_custom_class'] : '' );
if( $icon_classes ){
$atts['class'] .= ' ubermenu-target-with-icon';
$icon_tag = $this->get_menu_op( 'icon_tag' );
if( !$icon_tag ) $icon_tag = 'i';
$icon = '<'.$icon_tag.' class="ubermenu-icon '.$icon_classes.'"></'.$icon_tag.'>';
}
//Layout
$layout = $this->getSetting( 'item_layout' );
$atts['class'].= ' ubermenu-item-layout-'.$layout;
//Content Align
$content_align = $this->getSetting( 'content_alignment' );
if( $content_align != 'default' ){
$atts['class'].= ' ubermenu-content-align-'.$content_align;
}
if( $layout == 'default' ){
if( $image ){
$layout = 'image_left';
}
else if( $icon ){
if( function_exists( 'ubermenu_icon_layout_default' ) ){
$layout = ubermenu_icon_layout_default( $this );
}
else $layout = 'icon_left';
}
else{
$layout = 'text_only';
}
$atts['class'].= ' ubermenu-item-layout-'.$layout;
}
$layout_order = ubermenu_get_item_layouts( $layout );
if( !$layout_order ){
ubermenu_admin_notice( __( 'Unknown layout order:', 'ubermenu' ).' '.$layout.' ['.$this->item->title.'] ('.$this->ID.')' );
}
//No wrap
if( $this->getSetting( 'no_wrap' ) == 'on' ){
$atts['class'].= ' ubermenu-target-nowrap';
}
//Disabled Link (change tag)
$disable_link = false;
if( $this->getSetting( 'disable_link' ) == 'on' ){
$tag = 'span';
$disable_link = true;
unset( $atts['href'] );
}
//Disable Submenu Indicator
$disable_submenu_indicator = false;
if( $this->getSetting( 'disable_submenu_indicator' ) == 'on' ){
$atts['class'].= ' ubermenu-noindicator';
}
//ScrollTo
$scrollTo = $this->getSetting( 'scrollto' );
if( $scrollTo ){
$atts['data-ubermenu-scrolltarget'] = $scrollTo;
}
//Target ID
$target_id = $this->getSetting( 'target_id' );
if( $target_id ){
$atts['id'] = $target_id;
}
//Target Class
$target_class = $this->getSetting( 'target_class' );
if( $target_class ){
$atts['class'].= ' '.$target_class;
}
//Note: anchor atts used to be here
//Title
$title = '';
if( $this->getSetting( 'disable_text' ) == 'off' ){
$_title = $this->item->title;
if( $this->get_menu_op( 'allow_shortcodes_in_labels' ) == 'on' ){
$_title = do_shortcode( $_title );
}
$title .= '<span class="ubermenu-target-title ubermenu-target-text">';
$title .= apply_filters( 'the_title', $_title, $this->item->ID );
//$title .= $_title;
$title .= '</span>';
}
else{
//Flag items with disabled text
$atts['class'].= ' ubermenu-item-notext';
}
//Description
$description = '';
//if( $this->getSetting( 'disable_text' ) == 'off' ){
if( $this->item->description ){
if( ( ( $this->depth == 0 ) && ( $this->get_menu_op( 'descriptions_top_level' ) == 'on' ) ) ||
( ( $this->depth > 0 ) && ( $this->getSetting('item_display_calc') == 'header' ) && ( $this->get_menu_op( 'descriptions_headers' ) == 'on' ) ) ||
( ( $this->depth > 0 ) && ( $this->getSetting('item_display_calc') == 'normal' ) && ( $this->get_menu_op( 'descriptions_normal' ) == 'on' ) ) ||
( ( $this->depth > 0 ) && ( $this->type == 'tab' ) && $this->get_menu_op( 'descriptions_tab' ) == 'on' ) ){
$_desc = $this->item->description;
if( $this->get_menu_op( 'allow_shortcodes_in_labels' ) == 'on' ){
$_desc = do_shortcode( $_desc );
}
//Divider
$divider = $this->get_menu_op( 'target_divider' );
if( $title && $divider ) $description.= '<span class="ubermenu-target-divider">'.$divider.'</span>';
$description.= '<span class="ubermenu-target-description ubermenu-target-text">';
$description.= $_desc;
$description.= '</span>';
}
}
//ShiftNav Toggle
if( $this->getSetting( 'shiftnav_target' ) ){
$atts['data-shiftnav-target'] = $this->getSetting( 'shiftnav_target' );
$atts['class'].= ' shiftnav-toggle';
}
//Filter attributes
$atts = apply_filters( 'ubermenu_anchor_attributes' , $atts , $this->item->type , $this->ID /* Menu Item ID */ , $this->item->object /* object type */ , $this->item->object_id /* Post ID */ );
//Anchor Attributes
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) || $value === 0 ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
if( $attr === 'href' && ( $custom_url = $this->getSetting( 'custom_url' ) ) ){
$value = do_shortcode( $custom_url );
}
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
//Check if we still have something to print
if( !$title && !$description && !$image && !$icon ){
return '';
}
//Build the Layout
//Get custom pieces
$custom_pieces = array();
extract( apply_filters( 'ubermenu_custom_item_layout_data' , $custom_pieces , $layout , $this->ID , $this->item->object_id ) );
//Gather all the pieces in the layout order into an array
$layout_pieces = compact( $layout_order );
//Output the anchor
if( isset( $this->args->before ) ) $a .= $this->args->before;
$a .= '<'.$tag. $attributes .'>';
if( isset( $this->args->link_before ) ) $a .= $this->args->link_before;
//Add pieces based on layout order
foreach( $layout_pieces as $piece ){
$a.= $piece;
}
if( isset( $this->args->link_after ) ) $a .= $this->args->link_after;
$a .= '</'.$tag.'>';
if( isset( $this->args->after ) ) $a .= $this->args->after;
return $a;
}
/**
* Get the HTML for the image attached to this menu item
*
* Any set img ID will override image src filtering
*
* @return string img HTML
*/
function get_image(){
//Ignore mobile?
if( ( $this->get_menu_op( 'disable_images_mobile' ) == 'on' ) && ubermenu_is_mobile( 'disable_images_mobile' ) ){
return '';
}
//Image
$img = apply_filters( 'ubermenu_item_image' , '' , $this );
if( $img ) return $img;
//Allow ID filtering
$img_id = apply_filters( 'ubermenu_item_image_id' , $this->getSetting( 'item_image' ) , $this );
//Allow src filtering
$img_src = apply_filters( 'ubermenu_item_image_src' , '' , $this );
//Inherit featured image dynamically
if( $this->getSetting( 'inherit_featured_image' ) == 'on' ){
if( $this->item->type == 'post_type' ){
$thumb_id = get_post_thumbnail_id( $this->item->object_id );
if( $thumb_id ) $img_id = $thumb_id;
}
}
if( $img_id || $img_src ){
$atts = array();
$img_srcset = $img_sizes = '';
$atts['class'] = 'ubermenu-image';
//Determine size of image to get
$img_size = $this->getSetting( 'image_size' );
if( $img_size == 'inherit' ){
$img_size = $this->get_menu_op( 'image_size' );
}
//echo '['.$img_size.']';
$atts['class'].= ' ubermenu-image-size-'.$img_size;
//If the img_id is set, get the right image src file
if( $img_id ){
$img_src = wp_get_attachment_image_src( $img_id , $img_size );
if( function_exists( 'wp_get_attachment_image_srcset' ) ){
$img_srcset = wp_get_attachment_image_srcset( $img_id , $img_size );
$img_sizes = wp_get_attachment_image_sizes( $img_id , $img_size );
}
}
//Lazy Load
if( $this->depth > 0 && $this->get_menu_op( 'lazy_load_images' ) == 'on' ){
$atts['class'].= ' ubermenu-image-lazyload';
$atts['data-src'] = $img_src[0];
if( $img_srcset ){
$atts['data-srcset'] = $img_srcset;
if( $img_sizes ) $atts['data-sizes'] = $img_sizes;
}
}
//Normal Load
else{
$atts['src'] = $img_src[0];
if( $img_srcset ){
$atts['srcset'] = $img_srcset;
if( $img_sizes ) $atts['sizes'] = $img_sizes;
}
}
//Determine dimensions
$img_w = '';
$img_h = '';
$dimensions = $this->getSetting( 'image_dimensions' );
switch( $dimensions ){
//Custom Dimensions use Menu Item Settings
case 'custom':
$img_w = $this->getSetting( 'image_width_custom' );
$img_h = $this->getSetting( 'image_height_custom' );
break;
//Inherit settings from main Menu Settings
case 'inherit':
$img_w = $this->get_menu_op( 'image_width' );
$img_h = $this->get_menu_op( 'image_height' );
break;
//Add width and height atts for natural width
case 'natural':
//Done below
break;
default:
break;
}
//Apply natural dimensions if not already set
if( $this->get_menu_op( 'image_set_dimensions' ) ){
if( $img_w == '' && $img_h == '' ){
$img_w = $img_src[1];
$img_h = $img_src[2];
}
}
//Add dimensions as attributes, with pixel units if missing
if( $img_w ){
//if( is_numeric( $img_w ) ) $img_w.='px'; //Should always be numeric only, no units
$atts['width'] = $img_w;
}
if( $img_h ){
//if( is_numeric( $img_h ) ) $img_h.='px'; //Should always be numeric only, no units
$atts['height'] = $img_h;
}
//Add 'alt' & 'title'
if( $img_id ){
$meta = get_post_custom( $img_id );
$alt = isset( $meta['_wp_attachment_image_alt'] ) ? $meta['_wp_attachment_image_alt'][0] : ''; //Alt field
$title = '';
if( $alt == '' ){
$title = get_the_title( $img_id );
$alt = $title;
}
$atts['alt'] = $alt;
if( $this->get_menu_op( 'image_title_attribute' ) == 'on' ){
if( $title == '' ) $title = get_the_title( $img_id );
$atts['title'] = $title;
}
}
//Build attributes string
$atts = apply_filters( 'ubermenu_item_image_attributes' , $atts , $this );
$attributes = '';
foreach( $atts as $name => $val ){
$attributes.= $name . '="'. esc_attr( $val ) .'" ';
}
$img = "<img $attributes />";
//$img = "<span class='ubermenu-image'><img $attributes /></span>";
}
return $img;
}
function get_custom_content(){
$html = '';
$custom_content = $this->getSetting( 'custom_content' );
if( $custom_content ){
$pad_custom_content = $this->getSetting( 'pad_custom_content' ) == 'on' ? 'ubermenu-custom-content-padded' : '' ;
$html.= '<div class="ubermenu-content-block ubermenu-custom-content '.$pad_custom_content.'">';
$html.= do_shortcode( $custom_content );
$html.= '</div>';
}
return $html;
}
function get_widget_area(){
$html = '';
$widget_area_id = $this->getSetting( 'widget_area' );
if( $this->getSetting( 'auto_widget_area' ) ){
$custom_area_id = 'umitem_'.$this->ID;
if( is_active_sidebar( $custom_area_id ) ){
$widget_area_id = $custom_area_id;
}
else{
$notice = __( 'The widget area is empty.' , 'ubermenu' );
$notice.= ' <a target="_blank" href="'.admin_url( 'widgets.php' ).'">'.__( 'Assign a widget' , 'ubermenu' ).'</a>';
global $wp_registered_sidebars;
if( isset( $wp_registered_sidebars[$custom_area_id] ) ){
$sidebar = $wp_registered_sidebars[$custom_area_id];
$notice.= ' to <strong>'.$sidebar['name'].'</strong>';
}
$html.= ubermenu_admin_notice( $notice , false );
return $html;
}
}
//If this is a top level widget and that setting is not enabled, show an admin message
if( $this->depth == 0 && $widget_area_id && ubermenu_op( 'allow_top_level_widgets' , 'general' ) != 'on' ){
$msg = '<strong>[Menu Item: '. $this->item->title . ']</strong> '. __( 'You have assigned a widget area to a top level menu item. If you want the widget to appear in a submenu, please attach it to a child menu item. If you want the widget to appear in the menu bar (always visible), please enable the setting in the UberMenu Control Panel > General Settings > Widgets > Allow Top Level Widgets', 'ubermenu' );
ubermenu_admin_notice( $msg , true ); //Deliberately printed BEFORE the menu rather than within it because the message is so long.
//$html.= ubermenu_admin_notice( $msg , true );
return $html;
}
if( $widget_area_id && is_active_sidebar( $widget_area_id ) ){
global $wp_registered_sidebars;
global $wp_registered_widgets;
//global $_wp_sidebars_widgets;
$sidebars_widgets = wp_get_sidebars_widgets();
$num_widgets = count( $sidebars_widgets[$widget_area_id] );
//Evenly divided
$cols = 'ubermenu-column-1-'.$num_widgets;
if( $num_widgets == 1 ){
$cols = 'ubermenu-column-full';
}
//If col number is set
$widget_area_columns = $this->getSetting( 'widget_area_columns' );
if( is_numeric( $widget_area_columns ) ){
if( $widget_area_columns == 1 ){
$cols = 'ubermenu-column-full';
}
else $cols = 'ubermenu-column-1-'.$widget_area_columns;
}
foreach( $sidebars_widgets[$widget_area_id] as $widget_id ){
$wp_registered_widgets[$widget_id]['classname'].=' '.$cols;
}
//ob_flush();
ob_start();
dynamic_sidebar( $widget_area_id );
$widget_area = ob_get_contents();
//$widget_area = ob_get_clean(); //ob_get_contents();
ob_end_clean();
$html.= '<ul class="ubermenu-content-block ubermenu-widget-area ubermenu-autoclear">'; //ubermenu-row
$html.= $widget_area;
$html.= '</ul>';
}
//No widgets
else if( $widget_area_id ){
global $wp_registered_sidebars;
$notice = __( 'The widget area is empty. ' , 'ubermenu' );
$notice.= '<a target="_blank" href="'.admin_url( 'widgets.php' ).'">'.__( 'Assign a widget' , 'ubermenu' ).'</a>';
if( isset( $wp_registered_sidebars[$widget_area_id] ) ){
$sidebar = $wp_registered_sidebars[$widget_area_id];
$notice.= ' to <strong>'.$sidebar['name'].'</strong>';
}
$html.= ubermenu_admin_notice( $notice , false );
return $html;
}
else{
//Nothing assigned - fine if a normal menu item, but if this is a Widget Area menu item, stop the presses.
if( $this->type == 'widget_area' ){
$notice = __( 'Please enter a name for your Custom Widget Area, or assign a Reusable Widget Area to this menu item.' , 'ubermenu' );
$notice.= ' <strong>Item ID: '.$this->ID.' '.$this->item->title.'</strong>';
$html.= ubermenu_admin_notice( $notice , false );
}
}
return $html;
}
}
/* A Horizontal Rule */
class UberMenuItemDivider extends UberMenuItem{
function get_start_el(){
return '<li class="ubermenu-divider"><hr/>';
}
}
@pfiled
Copy link

pfiled commented Dec 27, 2016

It looks like there are other features and bug fixes mixed in here, I got errors about a submenu_content_align setting not being defined.

Line 203 should be all that is needed to fix the PHP 7.1 bug.

@seanrasmussen
Copy link

pfiled's comment helped me... I just added the one line and it fixed it without introducing other errors...

@zaccety
Copy link

zaccety commented Aug 29, 2019

+1 for pfiled's suggestion.

Nice to see this Premium plugin being actively maintained.

@sevenspark
Copy link
Author

Guys, this is a super old Gist, and not the actual code in the plugin. Just make sure you're up to date with the latest version (currently 3.6.0.1), which is fully compatible all the way up through PHP 7.3. Those undefined notices that came into play with PHP 7.1 were resolved long ago in the official release. Cheers!

@zaccety
Copy link

zaccety commented Aug 29, 2019

Thanks for the update, I was a bit surprised. My client's site has no update notification showing for this plugin so was not aware it wasn't the latest version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment