I need add to my menu extra icon before text. So I read in documentation that I need implement custom Walker_Nav_Menu. After some analyzing, I recognize I could implement my custom walker accord with decorator pattern. I have very small expirience in php especially wordpress. My code works weird. Look at it:
class Walker_nav_menu_Decorator extends Walker_Nav_Menu{
public $menu;
public static $index = 0;
function __construct() {
$menu = new Walker_Nav_Menu();
}
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
if($item->title == "Main Menu"){
$args->before = "TEST";
}
echo $index;
$index+=1;
parent::start_el($output, $item, $depth, $args, $id);
}
}
It doesn't echo $index at all oO. Additionally add extra "TEST" word before each menu item. How should I do it properly and why this version doesn't work?
My class is in my functions.php file and I'm calling my menu here:
wp_nav_menu( array( 'theme_location' => 'main_menu', 'container' => 'nav' ,'container_class' => 'menu', 'walker' => new Walker_nav_menu_Decorator() ) );
your $index is static so don't call it directly but by
echo self::$index;
self::$index+=1;
Related
I have two menus, a primary and secondary, I want to add data-scroll='' attributes to only the main menu. I am sucessfully adding the attribute to all menus with the current code:
function add_data_scroll( $atts, $item, $args ) {
$atts['data-scroll'] = ' ';
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'add_data_scroll', 10, 3 );
How to I add this filter conditionally to my main menu? The main menu is also only used on the front page - so this maybe a good way to target it.
You can look at the example for the wp_nav_menu_args filter on wordpress.
You need to set the theme_location parameter when defining your menu:
<?php wp_nav_menu( array( 'theme_location' => 'primary', 'menu_class' => 'nav-menu' ) ); ?>
In your filter you can then do:
function add_data_scroll( $atts, $item, $args ) {
if( 'primary' == $args['theme_location'] )
{
$atts['data-scroll'] = ' ';
return $atts;
}
}
add_filter( 'nav_menu_link_attributes', 'add_data_scroll', 10, 3 );
I am using the following override in my functions.php
function wp_nav_menu_attributes_filter($var) {
return is_array($var) ? array_intersect($var, array('current-menu-item')) : '';
}
add_filter('nav_menu_css_class', 'wp_nav_menu_attributes_filter', 100, 1);
add_filter('nav_menu_item_id', 'wp_nav_menu_attributes_filter', 100, 1);
add_filter('page_css_class', 'wp_nav_menu_attributes_filter', 100, 1);
This removes the class tag that wordpress adds to a menu item. Now what I need to do is actually put in my own class name into the li tag instead, can anyone fill me in quickly on how to do that, I have scoured google and maybe I am searching for it wrong or what not or I just cannot understand the hook system with the functions.php file....
Using the above make my html output as...
<ul id="menu-homemenu" class="list-group special">
<li>Biography</li>
<li>Selected Works</li>
<li>Contact Us</li>
</ul>
Of course after I posted a comment I figured it out...sigh hate when this takes all evening to get it...this question pointed me in the right direction - How to add custom HTML to wp_nav_menu?
I added this class..
class Custom_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$output .= "<li class='list-group-item'>".esc_attr($item->title)."";
}
function end_el( &$output, $item, $depth = 0, $args = array() ) {
$output .= "</li>\n";
}
}
Then added this to my array where I called my nav inside my template...
<?php wp_nav_menu(array('menu' => 'HomeMenu','menu_class' => 'list-group special','menu_id' => '','walker' => new Custom_Walker_Nav_Menu)); ?>
I just cant fully understand how custom walkers work in worpress:
Code in theme's home.php (actually all code is included from other file to not mess HTML) looks like this:
/**
* Contains wordpress function with array with parameters
* #return string HTML output
*/
function show_main_navigation() {
return wp_nav_menu(
array(
'theme_location' => 'header-menu',
'echo' => false,
'depth' => '-1',
'walker' => new Last_Item_Walker()
)
);
}
Walker looks like this:
class Last_Item_Walker extends Walker_Nav_Menu {
function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= '<li class="spec">title</li>'; // my custom <li>
$output .= "$indent</ul>\n";
}
}
Overwritten method just does not work.
If I try to overwrite another method, for example:
class Last_Item_Walker extends Walker_Nav_Menu {
function end_el( &$output, $item, $depth = 0, $args = array() ) {
$output .= "<br>"; // for demonstration
$output .= "</li>\n";
}
}
This one works, adds br tag but this is not what i want, i want to customize last li before /ul.
Can somebody help me with this?
Ok it was easier to do with filters.
/**
* Hardcodes shop item in navigation
* #param string $items HTML with navigation items
* #param object $args navigation menu arguments
* #return string all navigation items HTML
*/
function new_nav_menu_items($items, $args) {
if($args->theme_location == 'header-menu'){
$shop_item = '<li class="spec">title</li>';
$items = $items . $shop_item;
}
return $items;
}
add_filter('wp_nav_menu_items', 'new_nav_menu_items', 10, 2);
If you're not too worried about IE8 and less, you can use the :last-child selector.
li.spec:last-child{
color: red;
}
If you are bothered about IE8 and less you can use a polyfill to make it work.
I'm trying to mod a wordpress plugin to take custom categories. So when the random_post_link is called, I can add the custom category by using random_post_link('Random Link',3). 3 being the category name.
How does the plugin below create a new object of class Random_Post_Link? I thought you created new objects by doing something like:
$a = new random_post_link;
But I don't see that in the plugin. I think it creates the new object in the init function by using a hook:
add_action('init', array(CLASS, 'jump'));
If that's the case, how can I add parameter to jump function?
I think I know how add_action works, the second parameter should be the function name, how does
" array(CLASS, 'jump')" work?
Here's the full code for the plugin:
function random_post_link($text = 'Random Post',$the_cat = 36) {
printf('%s', get_random_post_url(), $text);
$the_category = $the_cat;
}
function get_random_post_url() {
return trailingslashit(get_bloginfo('url')) . '?' . Random_Post_Link::query_var;
}
class Random_Post_Link {
const query_var = 'random';
const name = 'wp_random_posts';
public $the_category;
function init() {
add_action('init', array(__CLASS__, 'jump'));
// Fire just after post selection
add_action('wp', array(__CLASS__, 'manage_cookie'));
}
// Jump to a random post
function jump() {
if ( ! isset($_GET[self::query_var]) )
return;
$args = apply_filters('random_post_args', array(
'post__not_in' => self::read_cookie(),
));
$args = array_merge($args, array(
'orderby' => 'rand',
'cat' => $the_category,
'showposts' => 1,
));
$posts = get_posts($args);
if ( empty($posts) ) {
self::update_cookie(array());
unset($args['post__not_in']);
$posts = get_posts($args);
}
if ( empty($posts) )
wp_redirect(get_bloginfo('url'));
$id = $posts[0]->ID;
wp_redirect(get_permalink($id));
die;
}
// Collect post ids that the user has already seen
function manage_cookie() {
if ( ! is_single() )
return;
$ids = self::read_cookie();
$id = $GLOBALS['posts'][0]->ID;
if ( count($ids) > 200 )
$ids = array($id);
elseif ( ! in_array($id, $ids) )
$ids[] = $id;
self::update_cookie($ids);
}
private function read_cookie() {
return explode(' ', #$_COOKIE[self::name]);
}
private function update_cookie($ids) {
setcookie(self::name, trim(implode(' ', $ids)), 0, '/');
}
}
Random_Post_Link::init();
Some WordPress authors use the Class structure in PHP to basically reduce global vars. The class is meant as a 'singleton' of sorts, and so it isn't usually instantiated (that code calls Random_Post_Link::init(); at the bottom instead). The class functions are treated as Class members, not instance members, sort of like Math.max() in other languages, for example.
The __CLASS__ php keyword is simply a token for the current class, so when passed, the callable becomes Random_Post_Link::method() or array( 'Random_Post_Link', 'method' )
If you need to unhook, try remove_action( 'init', array( 'Random_Post_Link, 'jump' ) );
(Also note, that methods used that way should be declared static function jump() {...})
P.S. To further clarify:
http://php.net/manual/en/language.types.callable.php
The array('class', 'function') syntax is a PHP thing, while WordPress actions expect a callable which could be any of the PHP callable things.
I'm trying to use a widget within a plugin in wordpress and I'm seeing this error within the widget box:
Warning: extract() [function.extract]: First argument should be an array in /nfs/c03/h04/mnt/57957/domains/rab.qbessi.com/html/wp-content/plugins/register-plus/dash_widget.php on line 24
This is the code from Line 24:
// Output the widget contents
function widget( $args ) {
extract( $args, EXTR_SKIP );
Here's the dash_widget.php code
<?php
if( !class_exists('RegisterPlusWidget') ){
class RegisterPlusWidget{
function RegisterPlusWidget() { //contructor
// Add the widget to the dashboard
add_action( 'wp_dashboard_setup', array($this, 'register_widget') );
add_filter( 'wp_dashboard_widgets', array($this, 'add_widget') );
}
function register_widget() {
wp_register_sidebar_widget( 'regplus_invite_tracking', __( 'Invitation Code Tracking', 'regplus' ), array($this, 'widget'), array( 'settings' => 'options-general.php?page=register-plus' ) );
}
// Modifies the array of dashboard widgets and adds this plugin's
function add_widget( $widgets ) {
global $wp_registered_widgets;
if ( !isset($wp_registered_widgets['regplus_invite_tracking']) ) return $widgets;
array_splice( $widgets, 2, 0, 'regplus_invite_tracking' );
return $widgets;
}
// Output the widget contents
function widget( $args ) {
extract( $args, EXTR_SKIP );
echo $before_widget;
echo $before_title;
echo $widget_name;
echo $after_title;
global $wpdb;
$regplus = get_option( 'register_plus' );
$codes = $regplus['codepass'];
$usercodes = array();
foreach($codes as $code){
$users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key='invite_code' AND meta_value='$code'" );
echo '<h3>' . $code . ': <small style="font-weight:normal">' . count($users) . ' Users Registered.</small></h3>';
}
echo $after_widget;
}
}
} # End Class RegisterPlusWidget
// Start this plugin once all other plugins are fully loaded
add_action( 'plugins_loaded', create_function( '', 'global $regplus_widget; $regplus_widget = new RegisterPlusWidget();' ) );
?>
The widget() function is being called with no parameters. Why, is hard to tell without digging deeply into the plugin. You should ask the plugin's author.
You can try adding
// Output the widget contents
function widget( $args ) {
if (is_array($args)) // Add this
extract( $args, EXTR_SKIP );
and see whether the output still makes sense then. That effectively just suppresses the action that causes the warning. If it's a badly programmed plugin that was developed with warnings turned off, that already may do the trick.
google launched new plugin called site kit, it will make analyzing work much more easier.
https://wordifact.com/google-site-kit/