I'm trying to add a last item to the wordpress primary menu. So here is my question:
I have a code in functions.php that works well:
function add_last_nav_item($items) {
return $items .= '<li><a href="#" >Contact</a></li>';
}
add_filter('wp_nav_menu_items','add_last_nav_item');
I need to replace which is inside the <li> tags with this:
<li><?php if(function_exists(wp_forecast)) { wp_forecast( wp_forecast("A") ); } ?></li>
I tried but it doesn't work.
Try this:
function add_last_nav_item($items) {
ob_start();
echo '<li>';
if (function_exists('wp_forecast')) {
wp_forecast( wp_forecast("A") );
}
echo '</li>';
$end = ob_get_clean();
$items = $items . $end;
return $items;
}
add_filter('wp_nav_menu_items','add_last_nav_item');
Related
This class is designed to iterate over a WordPress menu structure (nested arrays/objects) to produce a finished menu. While the source of my data is WordPress, I feel this question belongs on SO instead of WP.SO because the issue is rooted more in PHP (applies to anyone attempting a recursion).
For some reason, I'm seeing duplicate results in the hierarchy. Also, I'm noticing that certain HTML elements are not closing properly. It seems like I've nested everything properly, but the result is what you see here.
To assist with debugging, I've added some * to impact the markup visually. Maybe you guys know something I don't. Fingers crossed and thanks in advance for your input!
My class
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$output = $this->build_output($this->nested_nav);
$output_formatted = $format->HTML($output);
// echo $output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$output = '**';
$output.= $this->recurse_menu($menu, $output);
return $output;
}
private function recurse_menu( $menu = array(), $output )
{
global $post;
if( !empty($menu) && !empty($output) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$output.= '<li>' . $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= $this->recurse_menu($menu_val->children, $output);
}
// process list items
$output.= '</li>';
}
// process list wrappers
$output.= '</ul>';
}
return $output;
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu');
The resulting output
****
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three**
<ul class="depth-1">
<li>
One**
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
WordPress menu in the backend
If someone knows the reason why, I'd be willing to know, so I'll reserve choosing an answer for now. My guess is some kind of odd namespacing/scope issue for the variable $output. Who knows, I'm kinda tired right now.
The fix to get a legit structure was this...
Class
class Nav_Menu
{
public $wp_nav;
public $nested_nav;
public $recursion_depth = 0;
public $output = '';
function __construct( $menu, $args = array() )
{
$format = new Format;
if( $menu )
{
$this->wp_nav = wp_get_nav_menu_items($menu, $args);
$this->nested_nav = $this->build_tree($this->wp_nav);
$this->build_output($this->nested_nav);
$output_formatted = $format->HTML($this->output);
// echo $this->output;
echo $output_formatted;
}
}
private function build_output( $menu = array() )
{
$this->recurse_menu($menu);
}
private function recurse_menu( $menu = array() )
{
global $post;
if( !empty($menu) )
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// process list wrappers
$this->output.= '<ul class="' . $this->process_classes($classes_ul) . '">';
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// process list items
$this->output.= '<li>';
$this->output.= $menu_val->title;
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$this->recurse_menu($menu_val->children);
}
// process list items
$this->output.= '</li>';
}
// process list wrappers
$this->output.= '</ul>';
}
}
private function process_classes($classes = array())
{
if( !$classes )
{
return;
}
return trim(implode(' ', $classes));
}
private function build_tree( $elements = array(), $parent_id = 0 )
{
$branch = array();
foreach($elements as $element)
{
if ($element->menu_item_parent == $parent_id)
{
$children = $this->build_tree($elements, $element->ID);
if ($children)
{
$element->children = $children;
}
$branch[] = $element;
}
}
return $branch;
}
}
$mynav = new Nav_Menu('Test Menu'); exit;
Resulting output
<ul class="depth-1">
<li>
One
<ul class="sub-menu depth-2">
<li>
Sub One
</li>
<li>
Sub Two
</li>
<li>
Sub Three
</li>
</ul>
</li>
<li>
Two
</li>
<li>
Three
<ul class="sub-menu depth-3">
<li>
Sub One
</li>
<li>
Sub Two
</li>
</ul>
</li>
<li>
Four
</li>
</ul>
I just created a private variable for the class, and each time I need to reference it as a storage location, I just append to it. Same as before, but no more having to pass $output down some crazy method chain.
If anyone has any other ideas that could help the community, please share!
Update your build_output method as below:
private function build_output( $menu = array() )
{
$output = '<ul>';
$output = $this->recurse_menu($menu, $output);
$output.= '</ul>';
return $output;
}
Update your recurse_menu method as below:
private function recurse_menu( $menu = array(), $output = '')
{
global $post;
if( !empty($menu))
{
$this->recursion_depth++;
// ul classes
$classes_ul = array();
$classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
$classes_ul[] = 'depth-' . $this->recursion_depth;
// loop through menu items
foreach( $menu as $menu_key => $menu_val )
{
// if necessary, handle children and recurse
if( !empty($menu_val->children) )
{
// recurse, and call this again
$output.= '<li>'.$menu_val->title.'<ul class="' . $this->process_classes($classes_ul) . '">'.$this->recurse_menu($menu_val->children).'</ul></li>';
}
else {
$output.= '<li>'.$menu_val->title.'</li>';
}
}
}
return $output;
}
NOTE: I have tested it with more further sub-level and it is working fine.
Ok have a question did some research and got it to work so I can put spans in my li's which work great but in the span I have a data-hover tag and inside it I want to put the title of the page but cant figure out how.
As well it shows all the pages when I just want to show the childs of the parent which I have done before but when changing the echo $pages to echo$children it works and shows all the children but then removes my span info.
Can anyone help heres the code...
{ if($post->post_parent)
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
if ($children) { ?>
<ul class="cl-effect-2" id="cl-effect-2">
<?php
$pages = wp_list_pages('echo=0&title_li=');
$pages = str_replace('">', '"><span data-hover="PAGETITLEHERE">', $pages);
$pages = str_replace('<span data-hover="PAGETITLEHERE"><a', '<a', $pages);
$pages = str_replace('</a>', '</span></a>', $pages);
echo $pages;
?>
</ul>
<?php } ?> }
You replaces the $pages variable with str_replace, try to use the $children variable instead.
{ if($post->post_parent)
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
if ($children) { ?>
<ul class="cl-effect-2" id="cl-effect-2">
<?php
$pages = wp_list_pages('echo=0&title_li=');
$children = str_replace('">', '"><span data-hover="PAGETITLEHERE">', $pages);
$children = str_replace('<span data-hover="PAGETITLEHERE"><a', '<a', $pages);
$children = str_replace('</a>', '</span></a>', $pages);
echo $children;
?>
</ul>
<?php } ?> }
I have an answer
in funktion.php i put hook
add_filter( 'wp_list_pages', 'wp_list_pages_hook', 11, 2 );
function wp_list_pages_hook( $output, $r ){
if( ! is_front_page() ){
$output = preg_replace('~<a([^>]+)>(.*?)</a>~', '<a $1 > <span data-hover="$2">$2</span></a>', $output);
}
return $output;
}
In header.php now I can use a simple
<?php wp_list_pages('exclude=41&title_li='); ?>
I am making a breadcrumb for my codeigniter using bootstrap but would like to know how to get the current url and so it show the page on my breadcrumbs current_url() not sure how to use this
Displayed On Controller Index
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->lang->line('language_key'),
'href' => $this->url->link
);
Displayed On View
<div class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><?php echo $breadcrumb['text']; ?></li>
<?php } ?>
</div>
Working now
Controller file
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->lang->line('heading_title'),
'href' => $this->uri->uri_string()
);
View File
<div class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><?php echo $breadcrumb['text']; ?></li>
<?php } ?>
</div>
yep for example what i would do is create a helper "breadcrumb_helper.php" and place it in your helpers folder (application/helpers/breadcrumb_helper.php). Load it with the auto load config file so that it is loaded via the entire site and can be called inside a view file.
<?php
/* This is breadcrumb_helper.php */
function breadcrumbs() {
//get codeigniter instance as object
$ci =& get_instance();
$linkBuild = '';
$breadcrumbs = '';
//http://ellislab.com/codeigniter/user-guide/libraries/uri.html
//the uri class is loaded by the system automatically
$count = 1;
$segs = $ci->uri->segment_array();
//no need to run this on the main page and only show a link to the main page.
if(count($segs) >= 1) :
$breadcrumbs .= '<ol class="breadcrumb">';
$breadcrumbs .= '<li class="home"><i class="fa fa-home"></i></li>';
foreach ($segs as $segment)
{
$linkBuild .= $ci->uri->segment($count) . '/';
if($count <= count($segs)) :
$breadcrumbs .= '<li>' . $segment . '</li>';
else :
$breadcrumbs .= '<li>' . $segment . '</li>';
$count++;
endif;
}
$breadcrumbs .= '</ol>';
endif;
return $breadcrumbs;
}
Then in your view file you would just need to run the function like this:
<?= breadcrumbs(); ?>
And this will give you the current breadcrumb to the page you are on.
Here are my costume functions that I wrote for the menu and submenu in my wordpress theme, but after I tested it the submenu disappeared when I clicked on a submenu, because wordpress doesnt separate categories from subcategories, so the parameter for them is "cat", which means that when I click on a submenu then the function that creates the submenu checks if cat=id in the url has child categories but it doesnt becasue it is a child category, I am new into wordpress and I dont know how to deal with it:
function costume_menu() {
$categories = get_categories('hide_empty=0&style=none&parent=0');
foreach ($categories as $category) {
(is_category($category->term_id)) ? $active = 'class="active_menu"' : $active = '';
$nav = '<li>';
$nav .= '<a '.$active.'href="'.get_category_link($category->term_id).'">'.strtoupper($category->cat_name).'</a>';
$nav .= '</li>';
echo $nav;
}
}
function costume_submenu($cat) {
$categories = get_categories("child_of=$cat&hide_empty=0");
foreach ($categories as $category) {
(is_category($category->term_id)) ? $active = 'class="active_menu"' : $active = '';
$nav = '<li>';
$nav .= '<a '.$active.'href="'.get_category_link($category->term_id).'">'.strtoupper($category->cat_name).'</a>';
$nav .= '</li>';
echo $nav;
}
}
Try the function like this:
function costume_submenu($cat) {
$current_cat=get_category($cat);
if($current_cat->parent==0)
$parent_cat=$cat;
else
$parent_cat=$current_cat->parent;
$categories = get_categories("child_of=$parent_cat&hide_empty=0");
foreach ($categories as $category) {
(is_category($category->term_id)) ? $active = 'class="active_menu"' : $active = '';
$nav = '<li>';
$nav .= '<a '.$active.'href="'.get_category_link($category->term_id).'">'.strtoupper($category->cat_name).'</a>';
$nav .= '</li>';
echo $nav;
}
}
I have written a function for a multilevel wordpress menu, but I'd like it to work for any number of levels, at the moment it is written to work for 3 levels.
//only gets the top level items
$top_level_pages = get_pages('parent=0&sort_column=menu_order&exclude=129,2,13');
foreach($top_level_pages as $page){
//print_r($top_level_pages);
$p_id = $page->ID;
// gets all pages and subpages in one array
$children = get_pages("child_of=$p_id&sort_column=menu_order");
$immediate_children = get_pages("child_of=$p_id&parent=$p_id&sort_column=menu_order");
//print_r($immediate_children);
if($children) {
print '<li class="page_item page-item-'.$page->ID.'"><span class="first-level">'.$page->post_title;
print '</span><ul>';
foreach($immediate_children as $child){
$c_id = $child->ID;
//gets a preformatted menu
$grandchildren = wp_list_pages('depth=1&echo=0&parent='.$c_id.'&sort_column=menu_order&title_li=');
if($grandchildren) {
print '<li class="page_item page-item-'.$child->ID.'"><span class="second-level">'.$child->post_title;
print '</span><ul>';
print $grandchildren;
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$child->ID.'">'.$child->post_title.'</li>';
}
}
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$page->ID.'">'.$page->post_title.'</li>';
}
}
All we need to do to make your function recursive is move most of the loop into a recursive function:
<?php
//only gets the top level items
$top_level_pages = get_pages('parent=0&sort_column=menu_order&exclude=129,2,13');
foreach($top_level_pages as $page) {
//print_r($top_level_pages);
$p_id = $page->ID;
recursiveFunction($p_id);
}
function recursiveFunction($p_id){
$children = get_pages("child_of=$p_id&sort_column=menu_order");
$immediate_children = get_pages("child_of=$p_id&parent=$p_id&sort_column=menu_order");
//print_r($immediate_children);
if($children) {
print '<li class="page_item page-item-'.$page->ID.'"><span class="first-level">'.$page->post_title;
print '</span><ul>';
foreach($immediate_children as $child) {
recursiveFunction($child->ID);
}
print '</ul></li>';
}
else {
print '<li class="page_item page-item-'.$page->ID.'">'.$page->post_title.'</li>';
}
}
?>
The hard part is making the "first-level", "second-level" stuff work. I'd just change it "level-1", "level-2", etc. And then you can just start with $x = 1; and pass $x+1 each time you call the function recursively.
Something like this should probably do the trik (written in the stackoverflow textbox and untested).
function listChildren($parentID, &$menu)
{
static $options = 'parent=0&sort_column=menu_order&exclude=129,2,13';
static $level = 1;
foreach(get_pages(sprintf('child_of=%d&%s', $parentID, $options ) as $page)
{
$menu .= sprintf('<li class="level-%d">%s',
$level
get_page_link($page->ID),
$page->post_title);
if ($page->hasChildrenOrWhateverWPUses())
{
$level ++;
$menu .= sprintf('<ul class="menu-level-%d">', $level);
listChildren($page->ID, $menu);
$menu .= '</ul>';
$level --;
}
$menu .="</li>"
}
}
used like:
$menu = '<ul class="menu-tree">';
listChildren($rootPageID, $menu);
$menu .= '</ul>';
echo $menu;