Add a parent menu class to wp_nav_menu
Today I needed to define a class for menu items that have a submenu. The menu items were outputted by wp_nav_menu, and I didn't want to use any Javascript.
I found a class filter for when items are being created, and so my first approach was to check if the page had sub pages, which seemed to work at first. I soon realised, however, that just because a page has children, it doesn't mean that it has child menu items, and pages without children can still have child menu items!
So here's my solution. Throw it in your themes functions.php file, and your wp_nav_menu items will receive the class 'parent-menu-item' if they have sub menu items.
function parent_menu_css_class( $classes, $item, $args ) {
$menu_items = wp_get_nav_menu_items( $args->menu );
if ( ! $menu_items && $args->theme_location && ( $locations = get_nav_menu_locations() ) && isset( $locations[ $args->theme_location ] ) ) :
$menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] );
$menu_items = wp_get_nav_menu_items( $menu->term_id );
endif;foreach ( $menu_items as $menu_item ) :
if ( $menu_item->menu_item_parent == $item->ID ) :
$classes[] = 'parent-menu-item';
break;
endif;endforeach;
return $classes;
}
add_filter( 'nav_menu_css_class', 'parent_menu_css_class', 10, 3 );
Including a Google Font in your WordPress theme the right way
Here's the best way to include a Google Font in your WordPress theme.
1. Prepare your font for use on Google Web Fonts. After you've chosen the styles and character sets you would like to include, copy the 'href' attribute of the include code. I'm using the font 'Neuton' in this example.
2. In your theme's functions.php file, include the following code, substituting the red example font details for your own:
function enqueue_fonts() {
wp_register_style( 'neuton-font', 'http://fonts.googleapis.com/css?family=Neuton:300,700,400,400italic,200' );
wp_enqueue_style( 'neuton-font' );
}
add_action( 'init', 'enqueue_fonts' );
3. You're good to go - you can now use the font in your stylesheet, as per Google's instructions.
How to order by post meta item without setting meta_key in WordPress
Problem: I wanted wp_query to sort by a custom meta item, but I also wanted it to include results that don't have that meta item assigned to them! When I use the built in 'orderby => 'meta_value', it requires me to set 'meta_key' => 'something' - and that won't include results that don't have that meta_key assigned.
Solution: I found some query filters that let me edit the SQL of the query, after all my other arguments have been considered. This means I can use an INNER JOIN and a different ORDER BY value to achieve the result I'm after. Here's the poetry:
<?php
add_filter( 'posts_clauses', 'my_custom_order_function', 20, 1 );
function my_custom_order_function( $pieces ) {
$pieces['join'] .= " INNER JOIN (SELECT meta_id, post_id, meta_key, meta_value FROM wp_postmeta ORDER BY CASE meta_key WHEN 'custom_meta' THEN 1 ELSE 2 END ASC, meta_value ASC) AS cm1 ON (wp_posts.ID = cm1.post_id)";
$pieces['orderby'] = "CASE cm1.meta_key WHEN 'custom_meta' THEN 1 ELSE 2 END, cm1.meta_value ASC, wp_posts.post_title ASC";
return $pieces;
}
?>
Okay, so basically what we're doing here as adding a second postmeta table (the first is already added so that wp_query can handle meta queries), but before it's joined, we order it using MySQL's CASE order. This puts the meta_key we're looking for at the top of the JOIN, so if it exists, it will be that meta_key that is linked to our results.
Once we have joined the table, we just need to order by the join - again we do this using CASE, to put the results in the right order - items with our meta_key go first, and everything else second. We also do a secondary ORDER so that the items with the right meta_key also get ordered by meta_value.
It's important that you only use this code in context - pasting it in as is will force it to apply to every single query that is run on each page - and you probably don't want that.
If anyone can suggest a better way of doing it, or if there's something I missed, please let me know in the comments.
