File: /home/globfdxw/www/wp-content/plugins/ubermenu/includes/UberMenuWalker.class.php
<?php
/**
* Create HTML list of nav menu items.
*
* @package WordPress
* @since 3.0.0
* @uses Walker
*/
class UberMenuWalker extends Walker_Nav_Menu
{
var $item_stack = array();
var $current_umitem;
var $setting_defaults;
var $auto_child = '';
var $trashbin = array();
var $ignore_items = array(); //Don't print these items
var $ignore_children = array();
var $detached_content = array();
var $detached = false;
var $detached_context = 0;
var $offset_depth = 0;
/**
* What the class handles.
*
* @see Walker::$tree_type
* @since 3.0.0
* @var string
*/
var $tree_type = array('post_type', 'taxonomy', 'custom');
/**
* Database fields to use.
*
* @see Walker::$db_fields
* @since 3.0.0
* @todo Decouple this.
* @var array
*/
var $db_fields = array('parent' => 'menu_item_parent', 'id' => 'db_id');
function __construct()
{
$this->setting_defaults = ubermenu_menu_item_setting_defaults();
$this->setting_defaults['submenu_type_calc'] = 'unk'; //Unknown
$this->setting_defaults['item_display_calc'] = 'unk'; //Unknown
}
/* Recursive function to remove all children */
function clear_children(&$children_elements, $id)
{
if (empty($children_elements[$id]))
return;
foreach ($children_elements[$id] as $child) {
$this->clear_children($children_elements, $child->ID);
}
unset($children_elements[$id]);
}
function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output)
{
if (!$element)
return;
//Offset Depth
$original_depth = $depth;
$depth = $depth + $this->offset_depth;
$id_field = $this->db_fields['id'];
$el_id = $element->$id_field;
if (isset($element->duplicate) && $element->duplicate)
$el_id = $element->ID; // Use the altered ID if this is a duplicate element so that we get the child index correct
if ($this->get_ignore($element->$id_field)) {
unset($children_elements[$element->$id_field]);
return;
}
//Automatically add rows!
if (isset($children_elements[$el_id]) && count($children_elements[$el_id]) > 0) {
$has_row = false;
$has_nonrow = false;
//if( $element->$id_field == 65 ) uberp( $children_elements[ $element->$id_field ] , 3 );
foreach ($children_elements[$el_id] as $child_el) {
//If we find a [Row] child, flag
if (isset($child_el->type_label) && $child_el->type_label == '[UberMenu Row]') {
$has_row = true;
}
//Menu Segment can't reliably determine rows.
//If we find a menu segment, we need to check its children
// else if( $child_el->object == 'ubermenu-custom' && $child_el->type_label == '[UberMenu Menu Segment]' ){
// foreach( $children_elements[$child_el->ID] as $grandchild_el ){
// if( $grandchild_el->type_label == '[UberMenu Row]' ){
// $has_row = true;
// }
// else{
// $has_nonrow = true;
// }
// }
// }
//Flag that one child is not a row
else {
$has_nonrow = true;
}
}
if ($has_row) {
$element->classes[] = 'advanced-sub';
//If user hasn't added rows, we need to add them
if ($has_nonrow) {
$row_count = 0;
$current_row = false;
$current_row_id = 0;
$id = $element->$id_field;
$my_children = $children_elements[$id];
$children_elements[$id] = array();
//Loop through items, wrap in rows
foreach ($my_children as $k => $child_el) {
//If this is a row, reset current vals
if ($child_el->type_label == '[UberMenu Row]') {
$current_row = false;
$current_row_id = 0;
$children_elements[$id][] = $child_el;
}
//If this isn't a row, wrap it in a row
else {
//If we don't have a current row, make one
if (!$current_row_id) {
$row_count++;
$current_row_id = $element->$id_field . '_auto_' . $row_count;
$current_row = new UberMenu_dummy_item($current_row_id, 'row', 'Dummy Row', $element->$id_field);
$children_elements[$current_row_id] = array();
//Insert row in appropriate spot.
$children_elements[$id][] = $current_row;
}
//Add Children to Row
$children_elements[$current_row_id][] = $child_el;
//Remove Children from Sub?
//unset( $children_elements[$id][$k] ); // No because we reset array above
}
}
}
}
}
//Walker_Nav_Menu::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
//display this element - wp-includes/class-wp-walker.php
$has_children = !empty($children_elements[$el_id]);
if (isset($args[0]) && is_array($args[0])) {
$args[0]['has_children'] = $has_children;
}
$cb_args = array_merge(array(&$output, $element, $depth), $args);
$id = $element->$id_field; // Moved up
// Setup UberMenuItem object
$umitem_obect_class = apply_filters('ubermenu_item_object_class', 'UberMenuItemDefault', $element, $id, $this->auto_child);
//echo '<br/><br/>'.str_repeat(" ", $depth*5).'['. $id .'] '. $umitem_obect_class . ' :: <strong>' . $element->title.'</strong>';
//echo $element->$id_field . ' :: ' .$umitem_obect_class.'<br/>';
$umitem = new $umitem_obect_class($output, $element, $depth, $cb_args[3], $id, $this, $has_children); //The $args that get passed to start_el are $cb[3] -- i.e. the 4the element in the array merged above
//Ignoring? Check again after initialization so that item can disable itself
if ($this->get_ignore($element->$id_field)) {
unset($children_elements[$element->$id_field]);
return;
}
//Disabled?
$display_on = $umitem->display_on();
//If this item is not yet disabled, allow its status to be filtered
if ($display_on) {
$display_on = apply_filters('ubermenu_display_item', true, $this, $element, $max_depth, $depth, $args, $umitem);
}
//If the item is disabled, kill its children, Lannister-style
if (!$display_on) {
$this->clear_children($children_elements, $id);
return;
}
//If submenu disabled, clear children but don't return
if ($umitem->getSetting('disable_submenu_on_mobile') == 'on') {
if (ubermenu_is_mobile('disable_submenu_on_mobile')) {
$this->clear_children($children_elements, $id);
$umitem->disable_children();
}
}
//Filter
// Manipulate Structure
if ($umitem->alter_structure()) {
$umitem->alter($children_elements);
}
$this->push_item($umitem);
call_user_func_array(array($this, 'start_el'), $cb_args);
//Check if we are ignoring children
if (!$this->get_ignore_children($id)) {
// descend only when the depth is right and there are childrens for this element
// uberp( "ID: $id" );
// uberp( "Getting children of $el_id" );
// uberp_childmap( [ $el_id => $children_elements[$el_id]]);
if (($max_depth == 0 || $max_depth > $depth + 1) && isset($children_elements[$el_id])) {
foreach ($children_elements[$el_id] as $child) {
$this->auto_child = $umitem->getAutoChild();
if (!isset($newlevel)) {
$newlevel = true;
//start the child delimiter
$cb_args = array_merge(array(&$output, $depth), $args);
call_user_func_array(array($this, 'start_lvl'), $cb_args);
}
$this->display_element($child, $children_elements, $max_depth, $depth + 1, $args, $output);
$this->auto_child = '';
}
//Unset this item's children elements
unset($children_elements[$el_id]); //TODO!!!
}
}
if (isset($newlevel) && $newlevel) {
//end the child delimiter
$cb_args = array_merge(array(&$output, $depth), $args);
call_user_func_array(array($this, 'end_lvl'), $cb_args);
}
//end this element
$cb_args = array_merge(array(&$output, $element, $depth), $args);
call_user_func_array(array($this, 'end_el'), $cb_args);
//Cleanup when we hit top level items (original depth/without offset matters for menu segments)
if ($depth == 0 || $original_depth == 0) {
//Make sure we don't print trash - actually, these elements don't exist, just child indexes
foreach ($this->trashbin as $_trash_id => $on) {
//echo '<br/>$$unset '.$_trash_id.'<br/>';
unset($children_elements[$_trash_id]);
}
if ($depth == 0)
$this->trashbin = array(); //reset trashbin only at very top
}
}
/**
* Starts the list before the elements are added.
*
* @see Walker::start_lvl()
*
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
function start_lvl(&$output, $depth = 0, $args = array())
{
//$indent = str_repeat("\t", $depth);
$this->current_umitem->start_lvl();
}
/**
* Ends the list of after the elements are added.
*
* @see Walker::end_lvl()
*
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
function end_lvl(&$output, $depth = 0, $args = array())
{
//$indent = str_repeat("\t", $depth);
$this->current_umitem->end_lvl();
}
/**
* Start the element output.
*
* @see Walker::start_el()
*
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param array $args An array of arguments. @see wp_nav_menu()
* @param int $id Current item ID.
*/
function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0)
{
$this->current_umitem->start_el();
}
/**
* Ends the element output, if needed.
*
* @see Walker::end_el()
*
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Page data object. Not used.
* @param int $depth Depth of page. Not Used.
* @param array $args An array of arguments. @see wp_nav_menu()
*/
function end_el(&$output, $item, $depth = 0, $args = array())
{
$this->current_umitem->end_el();
$this->pop_item();
}
function feed_trash_collector($index)
{
if (isset($this->trashbin[$index]) && $this->trashbin[$index]) {
return true;
}
$this->trashbin[$index] = true;
return false;
}
function push_item($umitem)
{
$this->item_stack[] = $umitem;
$this->current_umitem = $umitem;
}
function pop_item()
{
$umitem = array_pop($this->item_stack);
$this->current_umitem = $this->current_item();
}
function current_item()
{
return end($this->item_stack);
}
function parent_item()
{
return isset($this->item_stack[count($this->item_stack) - 2]) ?
$this->item_stack[count($this->item_stack) - 2] :
false;
}
function grandparent_item()
{
return isset($this->item_stack[count($this->item_stack) - 3]) ?
$this->item_stack[count($this->item_stack) - 3] :
false;
}
function ancestor_item($k)
{
return isset($this->item_stack[count($this->item_stack) - $k]) ?
$this->item_stack[count($this->item_stack) - $k] :
false;
}
function closest_item_type($type)
{
for ($k = count($this->item_stack) - 1; $k >= 0; $k--) {
if ($this->item_stack[$k]->getType() == $type) {
return $this->item_stack[$k];
}
}
}
/* Traverse until an ancestor returns a term ID, otherwise return -1 */
function find_parent_term()
{
//up( $this->item_stack , 1 );
for ($k = count($this->item_stack) - 1; $k >= 0; $k--) {
$term_id = $this->item_stack[$k]->get_term_id();
if ($term_id)
return $term_id;
}
return -1;
}
/* Traverse until an ancestor returns a post ID, otherwise return -1 */
function find_parent_post()
{
for ($k = count($this->item_stack) - 1; $k >= 0; $k--) {
$post = $this->item_stack[$k]->get_post_id();
if ($post)
return $post;
}
return -1;
}
function find_inherited_setting($setting_id, $ignore = '', $offset = 0)
{
for ($k = count($this->item_stack) - ($offset + 1); $k >= 0; $k--) {
$item = $this->item_stack[$k];
$settings = $item->get_settings();
if (isset($settings[$setting_id]) && $settings[$setting_id] !== $ignore) {
return $settings[$setting_id];
}
}
return $this->setting_defaults[$setting_id];
}
function alert_dynamic_alter($id, $source_id, $umitem, &$children)
{
for ($k = count($this->item_stack) - 1; $k >= 0; $k--) {
if ($this->item_stack[$k]->dynamic_alter($id, $source_id, $umitem, $children)) {
return;
}
}
return -1;
}
function setAutoChild($auto_child)
{
$this->auto_child = $auto_child;
}
function getAutoChild()
{
return $this->auto_child;
}
function set_ignore($id, $ignore = true)
{
$this->ignore_items[$id] = $ignore;
}
function get_ignore($id)
{
if (isset($this->ignore_items[$id]) && $this->ignore_items[$id]) {
return true;
}
return false;
}
function set_ignore_children($id, $ignore = true)
{
$this->ignore_children[$id] = $ignore;
}
function get_ignore_children($id)
{
if (isset($this->ignore_children[$id]) && $this->ignore_children[$id]) {
return true;
}
return false;
}
function set_offset_depth($depth)
{
$this->offset_depth = $depth;
}
function get_offset_depth()
{
return $this->offset_depth;
}
//passed Key (ID of item) may not be unique if any ancestors
//are Dynamic Terms or Dynamic Posts
function unique_path_key($key = '')
{
//$key = ;
for ($k = count($this->item_stack) - 1; $k >= 0; $k--) {
$term = $this->item_stack[$k]->get_term_id();
if ($term)
$key .= '_t' . $term;
$post = $this->item_stack[$k]->get_post_id();
if ($post)
$key .= '_p' . $post;
}
return $key;
}
}
// function ubermenu_child_map( $map, $el ){
// $arr = [];
// foreach( $map as $parent_id => $kids ){
// $list = [];
// foreach( $kids as $kid ){
// $list[$kid->ID] = $kid->post_title; // . '['.$kid->ID.']';
// }
// $arr[$parent_id] = $list;
// }
// echo '<h3>UberMenu Child Map</h3>';
// uberp($el->post_title);
// uberp( $arr , 2 );
// }