post

How to Add Custom Background Support to a Genesis Child Theme and Set an Easily Changed Default Background

**UPDATE: Since writing this post, I have updated this code to be a plugin with everything. Please feel free to check it out: Genesis Custom Backgrounds.**

I believe it would be really great if Genesis would support custom backgrounds (forum post). Anyways, the newly developed backgrounds (dark, light), while not part of core, could be easily integrated into ANY child theme.

While I am not sure that this will become part of the Genesis core, and if I had to place a bet, I would bet against me. However, the benefits of this code, are as follows:

  • The code can easily be unhooked and removed
  • The code makes setting defaults easy, which is not part of WordPress, which is perfect for Child Themes
  • A few filters to customize even further

To install the code, simply paste the following in your functions.php, or download the file at the end of the post.

<?php
/**
 * Enables Genesis support of custom backgrounds
 *
 * @author	Travis Smith
 *
 * @uses	add_custom_background()	calls standard, filterable callback
 * @uses	apply_filters()			filters callback
 *
 */
function genesis_custom_background() {
	global $genesis_settings;

	$genesis_settings[ 'cb_default' ] = ''; //assuming this will be placed with the other defaults
	$cb = apply_filters( 'genesis_custom_background_args' , 'genesis_do_theme_background' );
	add_custom_background( $cb );	
}
add_action( 'init' , 'genesis_custom_background' );

/**
 * Outputs custom backgrounds inline
 *
 * @author	Travis Smith
 *
 * @uses	$genesis_settings		for custom background default image
 * @uses	apply_filters()			filters defaults
 *
 */
function genesis_do_theme_background() {
	global $genesis_settings;
	
	$defaults = array(
		'default_img' => ( isset( $genesis_settings['cb_default'] ) ) ? $genesis_settings['cb_default'] : '', //url, e.g., PARENT_URL . "/images/bg/gray/gray-1.png
		'bgimage' => get_background_image(),
		'bgcolor' => get_background_color(),
	);
	$defaults = apply_filters( 'genesis_background_defaults' , $defaults );

	extract( $defaults , EXTR_SKIP );

	// begin output
	$output = "<style type='text/css'>n";

	if( !empty( $bgimage ) ) {
		$background_styles = 'background-image: url('' . get_theme_mod( 'background_image' , '' ) . '');'
		. ' background-repeat: ' . get_theme_mod( 'background_repeat' , 'repeat' ) . ';'
		. ' background-position: top ' . get_theme_mod( 'background_position_x' , 'left' ) .  ';' . 'background-attachment: '. get_theme_mod( 'background_attachment' , 'scroll' );
		$output .= "body { " . $background_styles . "); } n";
	} 
	
	if( !empty( $bgcolor ) ) {
		$output .= "body { background-color: #" . $bgcolor . "; }; n";
	}
	
	// for child themes to set a default bg img
	if( !empty( $default_img ) && empty( $bgcolor ) && empty( $bgimage ) ) {
		$output .= "body { background: url('" . $default_img . "'); }n";
	}
	$output .= "</style>";
	
	echo apply_filters( 'genesis_background_output' , $output , $output, $bgimage , $bgcolor , ( isset( $background_styles ) ) ? $background_styles : '' );
}

This would be used by child themes as such:

<?php
add_filter( 'genesis_background_defaults' , 'genesis_custom_background_childdefault' );
function genesis_custom_background_childdefault( $defaults ) {
	//change the URL to whatever you'd like
	$defaults['default_img'] = CHILD_URL . '/images/bg/gray/gray-1.png';
	
	return $defaults;
}

If you wanted to include the StudioPress backgrounds, they are released to GPL and can be placed in any child theme folder. So feel free to download them (dark, light).

To download this file, click here: Genesis Child Custom Backgrounds (115). Then place it in your child theme folder and include the following in your functions.php file. Assuming you place it in a lib folder within your child theme…

require_once(CHILD_DIR.'/lib/wps-genesis-custom-backgrounds.php');
post

How to Add Menu Descriptions & Featured Images to WordPress Menu Items

sandbox_menu_featimg_descriptions

Recently I read an awesome post by Bill Erickson about customizing WordPress menus. However, there are two things I wanted this class to do that in its original form it doesn’t do.

So since out of the box, WordPress doesn’t intuitively allow you to add descriptions to the menu without requiring some custom code, rather the Walker class extended.

Since Bill has done an excellent job at this I will extend his code to add the options of having a featured image and/or descriptions applied based on depth.

Add this to your functions.php file.

<?php 
class Menu_With_Description extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth, $args) {
        global $wp_query;
		
        $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
 
        $class_names = $value = '';
 
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
 
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
        $class_names = ' class="' . esc_attr( $class_names ) . '"';
 
        $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
 
        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
        $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
        $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
		
		// get user defined attributes for thumbnail images
		$attr_defaults = array( 'class' => 'nav_thumb' , 'alt' => esc_attr( $item->attr_title ) , 'title' => esc_attr( $item->attr_title ) );
		$attr = isset( $args->thumbnail_attr ) ? $args->thumbnail_attr : '';
		$attr = wp_parse_args( $attr , $attr_defaults );
 
        $item_output = $args->before;
		
		// thumbnail image output
		$item_output .= ( isset( $args->thumbnail_link ) && $args->thumbnail_link ) ? '<a' . $attributes . '>' : '';
		$item_output .= apply_filters( 'menu_item_thumbnail' , ( isset( $args->thumbnail ) && $args->thumbnail ) ? get_the_post_thumbnail( $item->object_id , ( isset( $args->thumbnail_size ) ) ? $args->thumbnail_size : 'thumbnail' , $attr ) : '' , $item , $args , $depth );		
		$item_output .= ( isset( $args->thumbnail_link ) && $args->thumbnail_link ) ? '</a>' : '';
		
		// menu link output
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
		
		// menu description output based on depth
        $item_output .= ( $args->desc_depth >= $depth ) ? '<br /><span class="sub">' . $item->description . '</span>' : '';
		
		// close menu link anchor
        $item_output .= '</a>';
        $item_output .= $args->after;
 
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

All Menus

To highjack ALL of your menus, enter this code in your functions.php.

<?php
add_filter( 'wp_nav_menu_args' , 'my_add_menu_descriptions' );
function my_add_menu_descriptions( $args ) {
	$args['walker'] = new Menu_With_Description;
	$args['desc_depth'] = 0;
	$args['thumbnail'] = true;
	$args['thumbnail_link'] = false;
	$args['thumbnail_size'] = 'nav_thumb';
	$args['thumbnail_attr'] = array( 'class' => 'nav_thumb my_thumb' , 'alt' => 'test' , 'title' => 'test' );

	return $args;
}

Menus Based on Location

To highjack a menu based on registered and assigned location, then use this code in your functions.php.

<?php
add_filter( 'wp_nav_menu_args' , 'my_add_menu_descriptions' );
function my_add_menu_descriptions( $args ) {
	if ( $args['theme_location'] == 'primary' ) {
		$args['walker'] = new Menu_With_Description;
		$args['desc_depth'] = 0;
		$args['thumbnail'] = true;
		$args['thumbnail_link'] = false;
		$args['thumbnail_size'] = 'nav_thumb';
		$args['thumbnail_attr'] = array( 'class' => 'nav_thumb my_thumb' , 'alt' => 'test' , 'title' => 'test' );
	}

	return $args;	
}

Menus via WordPress Custom Menu Widget

To highjack a custom menu based menu id that is called using the custom menu widget, or even a manual method (if the menu is being called by a location, you must use ‘theme_location’), then use this code in your functions.php. This will highjack any menu called by the custom menu widget assuming you only have the standard registered theme locations. The example below assumes a standard theme custom menu registered locations for Genesis. Change ‘primary’ and/or ‘secondary’ to whatever your theme adds and add whatever more menus that your theme has to only target the custom menu widget.

<?php
add_filter( 'wp_nav_menu_args' , 'my_add_menu_descriptions' );
function my_add_menu_descriptions( $args ) {
	if ( ( $args['theme_location'] != 'primary' ) && ( $args['theme_location'] != 'secondary' ) ) {
		$args['walker'] = new Menu_With_Description;
		$args['desc_depth'] = 0;
		$args['thumbnail'] = true;
		$args['thumbnail_link'] = false;
		$args['thumbnail_size'] = 'nav_thumb';
		$args['thumbnail_attr'] = array( 'class' => 'nav_thumb my_thumb' , 'alt' => 'test' , 'title' => 'test' );
	}

	return $args;	
}

There is a caveat though. There are certain menu items that may not have a featured image such as custom links, categories, etc. There is a possible work-around that I am trying to work out.

Here is the result of a sandbox description and featured images for all types (not just pages and posts), which I will be posting soon or writing up into a plugin…

Sandbox Genesis Menu with Descriptions and Featured Images

post

How to Get Original Image from a Thumbnail Image in WordPress

Media Library: Insert Into Posts

Recently, in order to dummy proof a metabox that accepts a file upload via Media Library from a user accidentally selecting something other than Original Image like Small, Medium, or Large, I wrote a validation script to check and correct this.
Media Library: Insert Into Posts
This function will change a thumbnail URL (http://domain.com/wp-content/uploads/2011/08/example_2a-158×300.jpg) to the original URL (http://domain.com/wp-content/uploads/2011/08/example_2a.jpg). To use this function, simply:

$url = wps_get_original_image( $url );

Here is the script that can be added to your functions.php:

<!--?php function wps_get_original_image( $url ) { 	global $_wp_additional_image_sizes; 	 	$new_url = $url; 	 	// Get All Image Sizes 	$builtin_sizes = array( 		'large'		=--> array(
			'width' => get_option('large_size_w'),
			'height' => get_option('large_size_h')
		),
		'medium'	=> array(
			'width' => get_option('medium_size_w'),
			'height' => get_option('medium_size_h')
		),
		'thumbnail'	=> array(
			'width' => get_option('thumbnail_size_w'),
			'height' => get_option('thumbnail_size_h')
		)
	);

	$image_sizes = array_merge( $builtin_sizes, $_wp_additional_image_sizes );

	//$url = 'http://webendev.com/review/scheumanndental/wp-content/uploads/2011/08/example_2a-300x158.jpg';

	// Parse URL
	$info = pathinfo( $url );

	// Check to see if it is a post-thumbnail: assuming size < 999x999 so -999x999.jpg = 12chars 	$pos = strrpos($info['basename'], '-', -1); 	$length = strlen( $info['basename'] ); 	if ( ( $length - $pos ) > 12 )
		return $url;

	// Check to see if image is indeed a thumbnail and not example-2.jpg

	// Get image size extensions, e.g. -200x200
	// Get image size width only extensions, e.g., -200x
	// Get image size height only extensions, e.g., x200.
	$image_exts = array();
	$image_exts_width = array();
	$image_exts_height = array();
	foreach ($image_sizes as $image_size) {
		$image_exts[] = '-'.$image_size['width'].'x'.$image_size['height'];
		$image_exts_width[] = '-'.$image_size['width'].'x';
		$image_exts_height[] = 'x'.$image_size['height'];
	}

	// Cycle through image size extensions, e.g. -200x200
	foreach ( $image_exts as $image_ext ) {
		//if found, simply replace with nothing (easy)
		$new_url = str_replace( $image_ext , '' , $url );

		//report changed url
		if ( $new_url != $url )
			break;
	}

	// if a new url hasn't been generated...
	if ( $new_url == $url ) {
		// Cycle through image width only extensions, e.g. -200x
		foreach ( $image_exts_width as $image_ext ) {

			// check for width, e.g., -200x
			$pos1 = strrpos( $info['basename'] , $image_ext , -1 );
			if ( $pos1 ) {
				// strip, & assign new url
				$new_url = $info['dirname'] . '/' . substr( $info['basename'] , 0 , $pos1 ) . '.' . $info['extension'];
			}

			if ( $new_url != $url )
				break;
		}

		// if a new url hasn't been generated...
		if ( $new_url == $url ) {
			// Cycle through image height only extensions, e.g. x200.
			foreach ( $image_exts_height as $image_ext ) {

				// check for height, e.g., x200
				$pos2 = strrpos( $info['basename'] , $image_ext , -1 );

				//example_2a-263x300.jpg -> example_2a.jpg
				if ( $pos2 ) {
					// get position of -, strip, & assign new url
					$pos3 = strrpos( $info['basename'] , '-' , -1 );
					$new_url = $info['dirname'] . '/' . substr( $info['basename'] , 0 , $pos3 ) . '.' . $info['extension'];
				}

				if ( $new_url != $url )
					break;
			}
		}
	}

	if ( $new_url != $url )
		return $new_url;
	else
		return $url;
}
post

Infographic about WP_Query

wp_query Functions

wp_query Functions

post

The Difference between do_action, add_action and add_filter

The Foundation: do_action

do_action creates the hook for things to hang. This is at the core of WordPress and even frameworks like Genesis and many other themes and plugins. do_action is the first domino in the chain of events with hooks. However, alone, it means nothing and does nothing. Simply, it tells WordPress to search to see if any functions are attached to it to fire. So do_actions will look something like this:

<?php do_action( 'my-home' ); 

It can also take and pass variables:

<?php do_action( 'my-home' , $var1 , $var2 ); 

The Difference between add_action and add_filter

The difference is primarily and technically semantic. Technically speaking, you can use them interchangeably, but it wouldn’t follow code common sense or code “mentality” as one writer said. Filters should filter information, thus receiving information/data, applying the filter and returning information/data, and then used. However, filters are still action hooks.

WordPress defines add_filter as “Hooks a function to a specific filter action,” and add_action as “Hooks a function on to a specific action.”

add_action

Now, add_actions are a bit different. They hang items on the do_action hook and $priority determines the order.

Say, for example, you have this in your functions.php file:

<?php
add_action( 'hook' , 'bob' );
add_action( 'hook' , 'andy' );

The general order is “chronological” meaning if action ‘bob’ appears (coded/read by the server) before action ‘andy’, then the action hook ‘bob’ will fire first. However, with $priority, this order can be interrupted and changed. So…

<?php
add_action( 'hook' , 'bob' , 10 );
add_action( 'hook' , 'andy' , 5 );

With add_actions, variables and information may be passed back and forth as needed in the various functions as need. It should also be noted that not all actions are void of arguments or parameters. Some actions do have parameters, so:

<?php add_action( $tag, $function_to_add, $priority, $accepted_args ); ?>

So, it would look something like this:

<?php add_action( 'hook_name' , 'my_function_name' , 10 , 2 ); ?>

Extended Version Example

<?php
function echo_comment_id( $comment_ID ) 
{
   echo "I just received $comment_ID";
}
add_action( 'comment_id_not_found', 'echo_comment_id', 10, 1 );

add_filter

Now WordPress (and my theme) passes much of this page through various filters that check, validate, correct, and even modify various parts. Once it passes through the filter, the information then is applied to an action.

So here is the add_filter function:

<?php add_filter( $tag, $function_to_add, $priority, $accepted_args ); ?>

This generally looks something like this:

<?php 
add_filter( 'filter_name' , 'my_filter_function_name' , 10 , 3 ); 
function filter_name( $val, $attr, $content = null ) { 
//do something
}
?>

Just like add_actions go with do_actions, the same is true for filters logically speaking. With add_filter you must have apply_filters. Without the filter being called or applied then the filter means nothing, logically.

So, logicaly, in our example with filter ‘filter_name’, this would modify content/information that is coded like this:

<?php
// Allow plugins/themes to override the default caption template.
$output = apply_filters( 'filter_name', $output , $val, $attr , $content );
if ( $output != '' )
	return $output;

So, the code is basically saying, “Take the value of the `$output` variable, apply any filters attached to the ‘filter_name’ hook passing the variables $val, $attr, $content to the filter function (whatever that may be and if it accepts them), and assign the filtered value back to the `$output` variable”.

However, technically speaking, PHP is rather forgiving and instead of filtering anything, it can function like add_action, adding the filter to a do_action, not filtering anything, which adds to the confusion. So if you have the following, it will work (though not good form):

</php
do_action( 'my_action' );
add_filter( 'my_action' , 'my_function');
function my_function() {
  //do something
}

Since the add_filter did not have any filters being applied, it worked as an add_action.

post

How to Get WordPress’s Custom Menu Description

So recently, someone wanted to use menu descriptions as a tagline of sorts for a variety of pages, categories, archives, etc. instead of using basic metaboxes on pages (since this would also apply to category pages, etc.). So I wrote up a simple function that I believe may be helpful for others. So here is the code. To use, simply copy the function to your functions.php file and then use the function wherever you’d like.

<?php
function wps_get_menu_description( $args = array() ) {
	global $post;
	
	// Default
	$defaults = array(
		'echo' => false,
		'format' => '',
		'description' => '',
		'location' => 'primary',
		'classes' => 'post-description'
	);
	
	$args = wp_parse_args( $args, $defaults );
	extract( $args , EXTR_SKIP );

	// Get menu
	$menu_locations = get_nav_menu_locations();
	$nav_items = wp_get_nav_menu_items( $menu_locations[ $location ] );
	
	// Cycle through nav items
	foreach ( $nav_items as $nav_item ) {
		
		if ( ( is_page() || is_single() || is_archive() ) && ( $nav_item->object_id == $post->ID ) ) {
			$description = $nav_item->description;
		}
		elseif ( ( is_category() ) && ( $nav_item->object == 'category' ) ) {
			$cat = get_query_var( 'cat' );
			if ( $nav_item->object_id == $cat )
				$description = $nav_item->description;
		}
	}
	
	// Get output formatting
	if ( $format == 'html' )
		$output = apply_filters( 'wps_get_menu_description_output' , '<div class="'. $classes .'">' . $description . '</div>' , $args );
	else
		$output = $description;
	
	// Echo description
	if ($echo)
		echo $output;
		
	// Return description
	return $output;
}

To call the function, you just set the args in an array like this:
wps_get_menu_description( array('echo' => true, 'format'=>'html', 'classes' => 'post-info') );

With most frameworks, like Genesis/Thesis, you may need to call it like this (example reflects Genesis):

<?php
// Add and Customize a Tagline under the Page Title
add_action('genesis_after_post_title', 'my_tagline');
function my_tagline() {
   wps_get_menu_description( array('echo' => true, 'format'=>'html', 'classes' => 'post-info') );
}

Word of Warning: Please check your descriptions, and do not assume that there is nothing there if you didn’t put it there. Your theme or plugins may have inserted content there as I’ve seen the description contain the_content automagically.

Do you see anything that I missed? Is there something else that you wish was added?

post

How to Make a Genesis Grid Archive Template for Tags

To display posts from a specific tag or tags, you need to add a ‘tag’ argument to the $grid_args array.

In the StudioPress tutorial about categories, you are given this example for your home.php.

<?php
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'child_grid_loop_helper' );
/** Add support for Genesis Grid Loop **/
function child_grid_loop_helper() {
    if ( function_exists( 'genesis_grid_loop' ) ) {
        genesis_grid_loop( array(
            'features' => 2,
            'feature_image_size' => 0,
            'feature_image_class' => 'alignleft post-image',
            'feature_content_limit' => 0,
            'grid_image_size' => 'grid-thumbnail',
            'grid_image_class' => 'alignleft post-image',
            'grid_content_limit' => 0,
            'more' => __( '[Continue reading...]', 'genesis' ),
            'posts_per_page' => 6,
            'cat' => '6,7' //enter your category IDs here separated by commas in ' '
        ) );
    } else {
        genesis_standard_loop();
    }
}
 
/** Remove the post meta function for front page only **/
remove_action( 'genesis_after_post_content', 'genesis_post_meta' );
 
genesis();

Simply change the ‘cat’ argument to ‘tag’. And you can have the customization you want. OR, you can grab it dynamically by making the following changes:

<?php
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'child_grid_loop_helper' );
/** Add support for Genesis Grid Loop **/
function child_grid_loop_helper() {
    $term = get_query_var( 'term' );
    if ( function_exists( 'genesis_grid_loop' ) ) {
        genesis_grid_loop( array(
            'features' => 2,
            'feature_image_size' => 0,
            'feature_image_class' => 'alignleft post-image',
            'feature_content_limit' => 0,
            'grid_image_size' => 'grid-thumbnail',
            'grid_image_class' => 'alignleft post-image',
            'grid_content_limit' => 0,
            'more' => __( '[Continue reading...]', 'genesis' ),
            'posts_per_page' => 6,
            'tag' => $term
        ) );
    } else {
        genesis_standard_loop();
    }
}
 
/** Remove the post meta function for front page only **/
remove_action( 'genesis_after_post_content', 'genesis_post_meta' );
 
genesis();

You can save this as tag.php to make all of your tag archives as a grid. Or, you can simply apply this to a single tag by naming it tag-{SLUG}.php or tag-{ID}.php (see WordPress Codex for Tag Templates for more information).