Overriding Options and Meta

Photo by 900hp

One of my favorite “under-the-hood” features of WordPress and Genesis is the ability to override almost any kind of option/meta: site options, post meta, user meta, term meta….

Make sure you are careful with these filters though. Themes and plugins will expect certain options/meta to be returned when they call a core function, and if you’re not careful you could break them. Make sure you only return your changes in the very specific instances in which you want them.

Here’s a few common use cases:

  1. Change the admin email on certain pages (site option)
  2. Change the default layout of the homepage (site option)
  3. Force a layout on the homepage (post meta)
  4. Turn the Genesis Author Box on automatically for author archives (user meta)
  5. Specify a default title for term archives (term meta)

Site Options

Site options are anything stored in the wp_options database, and you typically access them using the get_option() function.

WordPress provides a filter for these options, called pre_option_($key) (see wp-includes/option.php, line 36 in WP 3.4.1).

Example 1: Change the admin email on certain pages

As a simple example, let’s say you had an email link in your footer, and you wanted to modify the ‘admin_email’ option on blog posts to use the blog post’s author email (I probably wouldn’t use this approach, but it shows you how to use the filter).

<?php
/**
* Add "Email Us" link to footer
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*/
function be_email_us() {
echo '<p><a href="mailto:' . get_option( 'admin_email' ) . '">Email Us</a></p>';
}
add_action( 'wp_footer', 'be_email_us' );
/**
* Modify Author Email option on Single Posts
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string $email
* @return string
*/
function be_post_author_email( $email ) {
global $post;
if( is_single() )
$email = get_the_author_meta( 'user_email', $post->post_author );
return $email;
}
add_filter( 'pre_option_admin_email', 'be_post_author_email' );
view raw functions.php hosted with ❤ by GitHub

Genesis has a lot of options, but instead of storing them all as individual entries in the database, it stores them as a single serialized array. This is great for performance, but it makes using the above filter difficult. So Genesis provides a filter for Genesis options and any other options that use the Genesis Settings API.

Example 2: Change the default layout of the homepage

You can set the site-wide default layout in Genesis > Theme Settings, which sets the Genesis option ‘site_layout’. But on the homepage you might want to have a different default layout. We’ll set this using the genesis_pre_get_option_($key) filter (see lib/functions/options, line 57 in Genesis 1.8.2).

<?php
/**
* Use Full Width Content on Homepage
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string $layout
* @return string
*/
function be_home_layout( $layout ) {
return 'full-width-content';
}
add_filter( 'genesis_pre_get_option_site_layout', 'be_home_layout' );
view raw front-page.php hosted with ❤ by GitHub

Since this is such a popular use, Genesis has already made functions that return all the built-in layouts, and you can see a list of them at the end of this post. We can replace the code above with this:

<?php
/**
* Use Full Width Content on Homepage
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string $layout
* @return string
*/
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
view raw front-page.php hosted with ❤ by GitHub

Please note that both the above code snippets are to be placed in front-page.php or home.php — whichever template file is responsible for your homepage.

Post Meta

WordPress provides a filter called get_post_metadata (see wp-includes/meta.php, line 274 in WP 3.4.1) for modifying post meta.

Example 3: Force a layout on the homepage

The Genesis function that determines the page layout first checks the post’s meta field ‘_genesis_layout’, and if none is specified it uses the sitewide default (which is what we overwrote in the previous example). The code below overrides the post meta, so the user can’t change the layout on this page:

<?php
/**
* Force Full Width Layout
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string/array $meta_value
* @param int $post_id
* @param string $meta_key
* @param bool $single
* @return string/array $meta_value
*/
function be_home_full_layout( $meta_value, $post_id, $meta_key, $single ) {
if( '_genesis_layout' == $meta_key )
$meta_value = 'full-width-content';
return $meta_value;
}
add_filter( 'get_post_metadata', 'be_home_full_layout', 10, 4 );
view raw front-page.php hosted with ❤ by GitHub

Again, this code is running in front-page.php or home.php — whatever is responsible for your homepage. Since the filter passes the $post_id, we could also run this in functions.php like so:

<?php
/**
* Force Full Width Layout
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string/array $meta_value
* @param int $post_id
* @param string $meta_key
* @param bool $single
* @return string/array $meta_value
*/
function be_home_full_layout( $meta_value, $post_id, $meta_key, $single ) {
if( get_option( 'page_on_front' ) == $post_id && '_genesis_layout' == $meta_key )
$meta_value = 'full-width-content';
return $meta_value;
}
add_filter( 'get_post_metadata', 'be_home_full_layout', 10, 4 );
view raw functions.php hosted with ❤ by GitHub

We’re now making sure the $meta_key matches the one we want AND we’re making sure $post_id is the page set to the front page in General > Reading. If you wanted this on your blog page instead, you could check $post_id against get_option( 'page_for_posts' ).

User Meta

WordPress provides a filter called get_the_author_($key) (see wp-includes/author-template.php, line 112 in WP 3.4.1) for modifying author meta. You can use this to override any of the author meta from WP Core, and also any author meta added by themes and plugins.

Example 4: Turn the Genesis Author Box on automatically for author archives

If you have the Genesis theme installed and go to Users > Your Profile, there’s a checkbox that lets you specify if an author box should show up on your author profile and/or at the bottom of all your posts. These update the user meta fields genesis_author_box_archive and genesis_author_box_single, respectively.

This code will make genesis_author_box_archive always return true, so the author box it automatically shows up on all author archive pages:

<?php
/**
* Display Author Box on all author archives
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param bool $option
* @return bool
*/
add_filter( 'get_the_author_genesis_author_box_archive', '__return_true' );
view raw functions.php hosted with ❤ by GitHub

You’ll notice I’m using a function called __return_true(), but that I didn’t create that function. This is one of the WordPress core helper functions. See the end of this post for a list of more helper functions.

Term Meta

WordPress doesn’t have term meta, which is one of the few things it is lacking as a CMS. Genesis needed term meta for all its SEO and layout options, so it created term meta using the options table.

Genesis also added a filter, genesis_term_meta_($key) (see lib/functions/options.php, line 228 in Genesis 1.8.2), used for modifying this meta.

Example 5: Specify a default title for term archives

On my photography blog, I have a taxonomy called “people” that I use for tagging people in photos. For taxonomy archives, Genesis has term meta for an Archive Headline and Description. I wanted to display a headline at the top of all the term archive pages, but didn’t want to manually create them.

Here’s a simple function I wrote that first checks to see if a headline has been provided, and if it hasn’t it uses “Photos of [person’s name]”.

<?php
/**
* Person Intro
* Displays "Photos of .. " name on term archive of people taxonomy
*
* @author Bill Erickson
* @link http://www.billerickson.net/overriding-options-and-meta
*
* @param string $headline
* @param object $term
* @return string $headline
*/
function be_person_intro( $headline, $term ) {
if( !is_tax( 'people' ) || !empty( $headline ) )
return $headline;
return 'Photos of ' . $term->name;
}
add_filter( 'genesis_term_meta_headline', 'be_person_intro', 10, 2 );
view raw gistfile1.aw hosted with ❤ by GitHub

Relevant filters:

  • WP: pre_option_($key) in wp-includes/option.php, line 36
  • WP: get_the_author_($key) in wp-includes/author-template.php, line 112
  • WP: get_post_metadata in wp-includes/meta.php, line 274
  • Genesis: genesis_pre_get_option_($key) in lib/functions/options.php, line 57
  • Genesis: genesis_term_meta_($key) in lib/functions/options.php, line 228

Helper Functions:

  • WP: __return_true() – returns the Boolean state of true
  • WP: __return_false() – returns the Boolean state of false
  • WP: __return_zero() – returns a value of zero (0)
  • WP: __return_empty_array() – returns an empty array, as in array()
  • WP: __return_null() – returns null (or void)
  • Genesis: __genesis_return_full_width_content() – returns ‘full-width-content’
  • Genesis: __genesis_return_content_sidebar() – returns ‘content-sidebar’
  • Genesis: __genesis_return_sidebar_content() – returns ‘sidebar-content’
  • Genesis: __genesis_return_content_sidebar_sidebar() – returns ‘content-sidebar-sidebar’
  • Genesis: __genesis_return_sidebar_content_sidebar() – returns ‘sidebar-content-sidebar’
  • Genesis: __genesis_return_sidebar_sidebar_content() – returns ‘sidebar-sidebar-content’

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. Tim Osborn says

    I really like Example 5! I use Yoast’s SEO plugin generally, which doesn’t offer as much flexibility as this… Still finding the best way to do ‘term head pages’ (I’d love to see a post in that in future!)

    • Tim Osborn says

      I was looking to implement example 5, but I can’t for the life of me find the filter ‘genesis_term_meta_headline’ anywhere in my project (genesis 1.8.2 and bones for genesis)… Any clues on what I’m missing?

      • Bill Erickson says

        There’s not a filter called ‘genesis_term_meta_headline’. There’s a dynamic filter called ‘genesis_term_meta_’ . $field, which can be found in /genesis/lib/functions/options.php on line 228.

        Every term meta field passes through this filter before it is returned, so once you know the field id (ex: ‘headline’) you can figure out the filter.

  2. Josh Stauffer says

    I had no idea about some of the helper functions. Learned something new. Thanks, Bill!