Dynamically Overriding a Page’s Template

It is easy to override the template for a post or page in WordPress in a few ways. For example, the naming of page template files can be used to override a single page’s template:

  • page-{id}.php
  • page-{slug}.php

Or, a page template can be chosen in the Page Attributes section when editing a page:

Choose a Template

This works great when you always want a page template to be used for a particular page. But what if you need to change a page’s template based on something that might change? Like the current user’s role, for example? Well, you can use the template_include filter in WordPress to override the normally-used template in a function.

Start out by attaching a function to the filter:

add_filter( 'template_include', 'dynamic_page_template' );

This can be added to your theme’s functions.php file or to a custom plug-in. In this example, the function called dynamic_page_template will be invoked. This function will accept the parameter, $page_template, which is the $page_template that is to be used. If you want the page template defined in a way above (by the template name or the selected template in the Page Attribute area) to work as normal, simply returning $page_template will accomplish this. However, we can also set $page_template to something different and return that instead. Here is a simple example:

function dynamic_page_template( $page_template ){
 global $post;
 if (100 == $post->ID) :
 $page_template = get_template_directory() . "/page-test.php";
 endif;

return $page_template;
 }

In this example, we are pulling in the $post (or page) information by calling it globally. Then, we can check for the post ID value. If the ID is 100, we are setting the page template dynamically to the page-test.php file in our theme. The get_template_directory call gets us the directory for our theme. Now, even if we have a file named page-100.php, our function will take precedence.

Hiding the categories of a post when it is “uncategorized”

If you’ve ever had some posts on your WordPress blog, you will have noticed that the “Uncategorized” category is displayed with a link to an archive of uncategorized posts.

Uncategorized

The easiest way to solve this, of course, is to categorize every blog post. But, if you don’t want to for some reason, you can use some PHP in your theme to hide the category of these posts. The example below is a customization I did for a theme in Bones but it should be easy to follow for other themes as well. The original line for the display of the categories in Bones is:

<?php printf( __( 'filed under', 'bonestheme' ).': %1$s', get_the_category_list(', ') ); ?>

So, it is just using the WordPress function, get_the_category_list, to list a comma-separated list of categories for the post. How do we hide this if the post is uncategorized? Well, one way to do it is to get a list of categories for the post. If the number of categories is one, and that category is “Uncategorized” then we just won’t use the get_the_category_list display. Here is the code:

$show_categories = true;
$categories = wp_get_post_categories( $post->ID );
// We don't want to show the categories if there is a single category and it is "uncategorized"
if ( count( $categories ) == 1 && in_array( 1, $categories ) ) :
 $show_categories = false;
endif;
if ( has_category( null, $post->ID ) && $show_categories ) :
 echo ' <span class="amp">&amp;</span> ' . __('filed under ', 'bonestheme') . get_the_category_list(', ');
endif;

We start off with the assumption that we’ll display the categories so we set a flag as true to begin with. Then, we retrieve the categories for a post. wp_get_post_categories will return the post’s categories as an array. Terms, or categories, for WordPress are stored in the wp_terms database table. And “Uncategorized” is actually a stored term with the term_id of 1:

Uncategorized term in database

With this knowledge, we check the number of categories of our post (retrieved with wp_get_post_categories) with a count call. If the result is one and the category array contains the “Uncategorized” category (term_id of 1) then we know we don’t have any categories we want to display. So, we’ll set our flag to false.

Finally, we make sure that the post does have categories and that our flag to display categories is set to true. WordPress’s has_category function, if given no category to check against, will just tell us if the post has any categories. If the post has categories and the flag is set to true, then we will use the category display line in our theme and display the post’s categories.

Hiding the WordPress admin bar on certain pages

There may be times when you would like to hide the WordPress admin bar on certain pages. Maybe the admin bar interferes with the design, for example. This can be especially true for things like pages opening up in a lightbox. Fortunately, it is not too difficult to hide the admin bar on certain pages with a filter in WordPress.

There is actually a filter in WordPress named, logically enough, show_admin_bar. This filter will show the admin bar if true is returned but not show the admin bar if the returned value is false. You pass the $bool value in which is WordPress’s own determination if the admin bar should be shown or not. So, in your theme’s functions.php file, you can add the following code:

function my_theme_hide_admin_bar($bool) {
if ( is_page_template( 'page-pop-up.php' ) ) :
return false;
else :
return $bool;
endif;
}
add_filter('show_admin_bar', 'my_theme_hide_admin_bar');

In the code above, we are simply checking to see if the page we’re on is using the template file, page-pop-up.php. This is a theme file that I used to display pages opening up in a lightbox. If the page is using that template, we return false to suppress the showing of the admin bar. If not, we return the usual $bool value set in WordPress and it will act as normal. Of course, the template conditional is just one example. You could also use other WordPress conditionals to turn the admin bar off for a myriad of other circumstances.

Conditional Required Contact Form 7 Fields

Sometimes you may want to have a required field in Contact Form 7 only when another form field has a certain value. For example, if someone has an option to choose their preferred method of contact between email and telephone, you’d want to make the email address field or the phone call field required accordingly. This isn’t too difficult to accomplish in Contact Form 7. You can look at how Contact Form 7 validates text and email fields by viewing its code in:

contact-form-7/modules/text.php

Around line 91, you will see the validation filters defined by Contact Form 7:

add_filter( 'wpcf7_validate_text', 'wpcf7_text_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_text*', 'wpcf7_text_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_email', 'wpcf7_text_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_email*', 'wpcf7_text_validation_filter', 10, 2 );

Then, you can look at the function that handles the validation, wpcf7_text_validation_filter. The function accepts two parameters – $result and $tag. The $tag is the field being validated and the $result is, well, the result of the validation. In other words, did something go wrong?

The user-entered text of the field being checked is assigned to $value. Then, the function checks the current tag type. Is it text? Email? And it will process it accordingly. If a value is empty but the field is required, for example, the result will be invalid:

$result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );

In this case the Contact Form 7 error message for required fields is given as an error (wpcf7_get_message( ‘invalid_required’ )). If $result-invalidate() is called, that field will fail validation and you will get a form error.

We’re not, of course, going to modify the plug-in’s files directly. We want to make our plug-in modifications safe from future plug-in updates so we will tie into the same filters that the plug-in uses. I can put this code in my theme’s functions.php file or put it into a my own plug-in. In my example, I am setting two conditional required fields – email and phone number. So, I will need to set my own custom validations for both text and email fields:

add_filter( 'wpcf7_validate_text', 'my_site_conditional_required', 10, 2 );
add_filter( 'wpcf7_validate_text*', 'my_site_conditional_required', 10, 2 );
add_filter( 'wpcf7_validate_email', 'my_site_conditional_required', 10, 2 );
add_filter( 'wpcf7_validate_email*', 'my_site_conditional_required', 10, 2 );

For both the text (phone) and email fields, I am using the function, my_site_conditional_required, for my own custom validations. Here is my complete function:

function my_site_conditional_required($result, $tag) {
    $tag = new WPCF7_Shortcode( $tag );

    $name = $tag->name;

    $value = isset( $_POST[$name] )
        ? trim( wp_unslash( strtr( (string) $_POST[$name], "\n", " " ) ) )
        : '';

    if ( "phone" == $name && 'Phone' == $_POST['contact-method'] ) :
        if ( '' == $value  ) :
            $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
        endif;
    endif;

    if ( "email" == $name && 'Email' == $_POST['contact-method'] ) :
        if ( '' == $value ) :
            $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
        elseif ( ! wpcf7_is_email( $value ) ) :
            $result->invalidate( $tag, wpcf7_get_message( 'invalid_email' ) );
        endif;
    endif;

    return $result;
}

Here is how it works. I am doing the same thing that Contact Form 7 does with setting the $value. Then, instead of checking the tag type, I want to check the tag name. I specifically want to look for the fields named “phone” or “email.” I also have a dropdown named “contact-form” so I can check the $_POST value of contact-form and use that to see if the field being checked should be required. If $_POST[‘contact-form’] is equal to “Phone,” I want the phone field to be required:

if ( "phone" == $name && 'Phone' == $_POST['contact-method'] ) :
        if ( '' == $value  ) :
            $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
        endif;
endif;

I have an extra check for the email. I don’t just want to require the email address, I want to make sure it is a valid email address as well. Contact Form 7 provides a function to check an email, wpcf7_is_email:

elseif ( ! wpcf7_is_email( $value ) ) :

As you can see, my custom function works very similarly to the code in the plug-in. Finally, you probably want to show the user the field that is required based on their downdown selection. I added empty spans after the field labels that I can use to add and remove informational asterisks from:

<label class="email-label">Email<span class="asterisk"></span></label>

Then, I can use jQuery to add and remove the asterisks:

<script type="text/javascript">
 jQuery(function() {
 add_required_asterisks();
 jQuery("select[name='contact-method']").on('change', function() {
 add_required_asterisks();
 });
 });
 function add_required_asterisks() {
 if ( jQuery("select[name='contact-method']").val() == "Phone" ) {
 jQuery(".phone-label .asterisk").html("*");
 jQuery(".email-label .asterisk").html("");
 }
 else {
 jQuery(".phone-label .asterisk").html("");
 jQuery(".email-label .asterisk").html("*");
 }
 }
 </script>

I created a JavaScript function that will see what my dropdown menu (named “contact-method”) is set to and then, based on that, turn the asterisks on or off. Then, I call that function on page load and, whenever the dropdown changes:

jQuery("select[name='contact-method']").on('change', function() {
add_required_asterisks();
});

Quick WordPress Tip – Upload to a Post Without Switching Tabs

Here is a quick tip for WordPress users out there. When you are adding, say, a Featured Image to a post, you are brought to the Media Library window that includes an “Upload Files” tab. This might lead you to believe that you need to switch to that tab in order to upload a new image file. Actually, though, you can save yourself some clicks by simply dragging a photo onto the Media Library. No need to switch tabs.

Drop to Upload

Changing Posts per Page in WordPress admin

Here’s a quick WordPress tip. One thing that always bugged me about the admin interface is that WordPress shows just 20 posts per page in the admin list leading to a lot of clicking the paging navigation. Well, WordPress allows you to change the number of posts shown per page. Go to the Screen Options dropdown at the top of the page. One of the options is the number of posts. Change it to a larger number and deal less with clicking through pages. I never knew about this handy feature until a coworker of mine pointed it out.

Post per post WordPress

Display the caption of a featured image in WordPress

Have you ever wanted to display the caption of a Featured Image in WordPress? I recently had need to do this and figured out a way to accomplish this.

When you set the Featured Image for a post in WordPress, you can add additional information for the image: Title, Caption, Alt Text and Description.

Set caption for featured image

It makes sense to me that you might want to display the caption for a Featured Image, if entered. My solution to this was to add a function to my functions file to use to display the caption. My function looks like this:

 function my_display_featured_image( ) {
global $post;

$thumbnail_id = get_post_thumbnail_id($post->ID);
$thumbnail_details = get_posts(array('p' => $thumbnail_id, 'post_type' => 'attachment'));
$thumbnail_src = wp_get_attachment_image_src( $thumbnail_id, 'full' );
$thumbnail_width = $thumbnail_src[1];

if ($thumbnail_src && isset($thumbnail_src[0])) {
echo '<div class="featured-image';
if ( !empty( $thumbnail_details[0]->post_excerpt ) ) echo ' wp-caption';
echo '" style="max-width: ' . $thumbnail_width . 'px;">';
if ( !empty( $thumbnail_details[0]->post_excerpt ) ) {
echo '<p class="featured-image-caption">';
echo $thumbnail_details[0]->post_excerpt;
echo '</p>';
}
the_post_thumbnail( $post->ID );
echo '</div>';
}
}

First, we get the information for the post we’re on. We do this by making the $post global. This will give us access to the id of the post we’re on. From there, we can call get_post_thumbnail_id to get the id of the Featured Image. Once we have the id of the Featured Image, or attachment, that we want, we can then use WordPress’s get_posts to grab the record of the Featured Image. The details of the Featured Image are stored in the variable $thumbnail_details using the call:

$thumbnail_details = get_posts(array('p' => $thumbnail_id, 'post_type' => 'attachment'));

get_posts accepts the arguments of WP_Query so, in our example, ‘p’ is the post id (the id of the Featured Image) which we were able to get using get_post_thumbnail_id. This query returns an object which includes the Featured Image’s caption in the ‘post_excerpt’ value and the description is available in the ‘post_content.’

I am also grabbing the source of the attachment image and using the width of the image to set some inline CSS (in my particular case I wanted to float the image so I wanted to set the width). wp_get_attachment_image_src gets the url and image dimensions and returns the values in an array.

So, now I have the image’s URL, dimensions and caption. With this information, we can display the image. To check if there is a caption present, I just need to check the value of the post_excerpt returned by my get_posts call.

if ( !empty( $thumbnail_details[0]->post_excerpt ) ) {
echo '<p class="featured-image-caption">';

Finally, I use the_post_thumbnail to display the featured image. In my template file, if the post has a Featured Image, I call my function to display the Featured Image.

<?php if ( has_post_thumbnail() ) :
my_display_featured_image();
endif; ?>

That is how I display a Featured Image’s caption.

Custom headers and footers in WordPress

Today I wanted to put a custom post inside of a fancyBox popup. So, I wanted to have access to WordPress’s functions, but I didn’t want the usual header and footer from my main template… I just wanted a very basic page that would fit easily inside of fancyBox. I didn’t realize it, but WordPress allows you to load custom headers and footers by name using get_header and get_footer.

The naming structure is pretty simple. I copied header.php and renamed it “header-google_map.php.” Then, I stripped it pretty much bare keeping the wp_head(); function call in place so that I would have access to any scripts and styles used by installed plugins. Then, I called my bare-bones header file in a new template file using:

get_header( 'google_map' );

I did the same thing with the footer and this allowed me to have a simple, no-frills page perfect for displaying within a fancyBox. I could use shortcodes within the page and access all my installed plugins.