Close

WordPress Code Snippets

How to Add Featured Images to Your WordPress RSS Feed

If you want to add featured images to your WordPress RSS feed (as enclosures), here’s what to do. First, you need to hook into the RSS feed as each item is built. This hook will do that:

<?php
add_action( ‘rss2_item’, ‘rss_add_featured_image’ );

Next, in our callback function, we need to check if the current post has a featured image. We’ll use has_post_thumbnail() for that:

<?php
if ( function_exists( ‘has_post_thumbnail’ ) && has_post_thumbnail( $post->ID ) ) {
// do stuff here
}

No, we need to get the URL of the featured image if it does exist. Here, we’ll need to run through a couple steps like this:

<?php
$attachment_id = get_post_thumbnail_id($post->ID);
$featured_image = wp_get_attachment_image_src( $attachment_id, ‘post-thumbnail’ );
$url = $featured_image[0];

Enclosures require you set not only the URL, but also the length of the file (in bytes) and the MIME type. Here’s how to do that:

<?php
$length = filesize(get_attached_file($attachment_id));
$type = get_post_mime_type($attachment_id);

And, finally, we can out put the enclosure using printf():

<?php
printf(‘<enclosure url=”%s” length=”%s” type=”%s” />’, $url, $length, $type);

This can all be inside a plugin or in your theme’s functions.php file. Although, I’d recommend using a plugin so if you change themes, you don’t have to transfers this code over to your new theme. And, if you’re ready to get serious about building WordPress plugins, then enroll in my WordPress plugin course. Inside, you build a contact form plugin, but, more importantly, you’ll learn fundamental WordPress plugin-building skills like creating custom post types, adding shortcodes, adding custom columns to the post table and more. You can learn more here.

April 24, 2018

Build a Grid Layout For WordPress Using WP_Query

Here’s how to build a grid layout for WordPress via shortcodes and WP_Query:

A lot of WordPress developers immediately rush to query_posts in order to create custom loops.

But, query_posts is meant for altering the main loop of a WordPress page/post (actually, it’s not even recommended for that anymore).

Using get_posts() is okay… but, if you want that real WordPress flavor using WP_Query is the way to go.

In the video above, I show you how to use WP_Query to create a custom loop inside WordPress in order to build a Pinterest-style grid layout.

Here’s the code I used in the video:

<?php
/*
Plugin Name: John Morris Grid
Plugin URI: http://johnmorrisonline.com/
Description: Demo plugin that displays posts in a grid format via shortcode
Version: 1.0.1
Author: John Morris
Author URI: http://johnmorrisonline.com
Text Domain: johnmorris-grid
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Domain Path: /lang
*/

if ( ! class_exists( 'John_Morris_Grid' ) ) {
class John_Morris_Grid {
/**
* Init
*
* Initializes the plugin
*/
public function init() {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
add_image_size( 'jmogrid', 220, 220, true );
add_shortcode( 'jmogrid', array( $this, 'shortcode_handler' ) );
}

/**
* Enqueue Scripts and Styles
*
* Enqueues styles and scripts used throughout the plugin
*/
public function enqueue() {
wp_enqueue_style('jmogrid', plugins_url( '/css/style.css', __FILE__) );
}

/**
* Shortcode Handler
*
* Handles shortcode processing
*/
public function shortcode_handler($atts) {
$atts = shortcode_atts(
array(
'posts_per_page' => 100
), $atts, 'jmogrid'
);

return $this->grid($atts);
}

/**
* Grid Builder
*
* Builds the grid
*
* @param array $args Query argumenst passed to WP_Query
*
* @return string $html The HTML output
*/
public function grid($args) {
$grid = new WP_Query($args);

ob_start(); ?>

<div id="jmogrid">

<?php $count = 1; if ( $grid->have_posts() ) : while( $grid->have_posts() ) : $grid->the_post(); ?>
<?php
$modulus = $count % 5;

if ( $modulus == 1 ) {
$class = 'first';
} elseif ( $modulus == 0 ) {
$class = 'last';
}
?>
<div class="jmogrid-item <?php echo $class; ?>">
<?php if ( has_post_thumbnail() ) : ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('jmogrid'); ?>
</a>
<?php endif; ?>
<h4>
<a href="<?php the_permalink(); ?>"><?php echo wp_trim_words(get_the_title(), 6); ?></a>
</h4>
<p class="jmogrid-meta">
<?php _e( 'Written by', 'johnmorris-grid' ); ?> <?php the_author(); ?><br />
<?php echo get_the_date( get_option( 'date_format' ) ); ?>
</p>
<p><?php echo wp_trim_words( get_the_content(), 10); ?></p>
</div>

<?php unset($class); $count++; endwhile; wp_reset_postdata(); endif; ?>

</div>

<?php return ob_get_clean();
}
}

// Instantiate Class
$JohnMorrisGrid = new John_Morris_Grid;

// Hook in
add_action( 'init', array( $JohnMorrisGrid, 'init' ) );
}

/* John Morris Grid CSS */

#jmogrid {
overflow: hidden;
clear: both;
}

.jmogrid-item {
overflow: hidden;
box-sizing: border-box;
width: 18%;
float: left;
margin: 20px 1%;
border: 1px solid #e4e4e4;
border-radius: 3px;
}

.jmogrid-item.first {
width: 19%;
margin-left: 0;
}

.jmogrid-item.last {
width: 19%;
margin-right: 0;
}

.jmogrid-item h4,
.jmogrid-item p {
margin: 0;
padding: 20px;
}

.jmogrid-item h4 {
padding-bottom: 0;
}

.jmogrid-item p {
font-size: 1.5rem;
}

p.jmogrid-meta {
font-size: 1.2rem;
color: #777;
padding-bottom:0;
padding-top: 5px;
}

If you get value from this code snippet, please consider sharing it with another developer or group who could benefit from it.

July 16, 2015

Force a Single (2, 3, 4…) Column Dashboard Layout in WordPress 3.8

Bring back single column

Prior to WordPress 3.8, you had the option to select the number of columns you wanted on your admin dashboard. Personally, I prefer 2.

However, in version 3.8… that option is gone. Here’s a handy little code snippet to bring it back:

function jmo_screen_layout_columns($columns) {
$columns['dashboard'] = 2;

return $columns;
}

add_filter('screen_layout_columns', 'jmo_screen_layout_columns');

function jmo_screen_layout_dashboard() {
return 2;
}

add_filter('get_user_option_screen_layout_dashboard', 'jmo_screen_layout_dashboard');

Just change all instances of “2” to the number of columns you’d like your admin dashboard to have and drop the code into your theme’s functions.php file and you’re all set.

December 27, 2013

How to Get the Post Thumbnail Source URL in WordPress

Often, when working with WordPress, you’ll find the need to grab a post’s thumbnail source URL. Unfortunately, the_post_thumbnail() and get_the_post_thumbnail() only return the entire image tag.

How to Get a Post Thumbnail Source URL in WordPress

This handy little WordPress code snippet takes care of it for you, though:

function wp_get_thumb_src($post = false, $size = 'thumbnail') {
if ( ! $post ) {
global $post;
}

$thumb = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), $size );
$url = $thumb['0'];

return $url;
}

As you can see, you can post in a $post object or let it use the globalized $post object… depending on your needs. You can also pass in the image size you’re after. By default, it uses the “thumbnail” size.

Hopefully, you find it useful.

December 25, 2013

How to Add a Login/Logout Link to WordPress Menus

In my last post, I talked about how to add a custom meta box with a custom link to WordPress navigation menus. Several times, I mentioned how I needed to add a specific class to that link for WishList Login 2.0, so that I could find that link later and do stuff with it.

This is the part where we “do stuff” with that link. Specifically, we’re going to hook into the navigation menu before it displays, find our link and change its display based on the current user’s login status. Here’s what it looks like:

Adding a Login/Logout Link

So, if they’re logged in, we’re going to change it to a logout link. If they’re not logged, then we’ll leave it alone. Here’s the code to do that:

if ( !class_exists( 'HijackMe' ) ) {
class HijackMe {
public function hijack_menu($objects) {
/**
* If user isn't logged in, we return the link as normal
*/
if ( !is_user_logged_in() ) {
return $objects;
}
/**
* If they are logged in, we search through the objects for items with the
* class wl-login-pop and we change the text and url into a logout link
*/
foreach ( $objects as $k=>$object ) {
if ( in_array( 'wl-login-pop', $object->classes ) ) {
$objects[$k]->title = 'Logout';
$objects[$k]->url = wp_logout_url();
$remove_key = array_search( 'wl-login-pop', $object->classes );
unset($objects[$k]->classes[$remove_key]);
}
}

return $objects;
}
}
}

$hijackme = new HijackMe;

add_filter('wp_nav_menu_objects', array($hijackme, 'hijack_menu'), 10, 2);

Here’s a run-down of what’s happening:

  1. We’re hooking in using the wp_nav_menu_objects filter.
  2. If the user is logged out, we just return the link as it is since by default it’s a login link.
  3. If the user is logged in, we then loop through the items and search the “classes” array element for our class.
  4. If the class exists in an item object, then we alter the “title” and “url” of that link and we unset our target class from the object.
  5. Then, we simply return the new objects array.

There’s definitely some customization and abstraction you could do with this:

1. Edit only the menu for a certain theme location. You’ll notice in the hook, I have 2 arguments being sent to the callback function, but I’m only actually using the first one. That’s to show you that there are actually 2 arguments available. The second one is the $args array which will contain information about that menu… including the theme location.

You would simply run a check on that array to see if the current theme location is the one you want to edit. This is especially important if you don’t want to touch widget menus at all… since, the Custom Menu widget uses the same back-end functionality as regular menus.

In our case, we wanted to hijack every instance of a link that contained our special class… even in a widget… so, we didn’t run any such check.

2. Abstract the target class. In our function, the target class we search for is hard-coded. In this instance, it’s fine because there’s no reason to have an option to change that class. You may have a scenario where it does make sense to allow users to change that class. In this case, you’d want to abstract that out by creating an admin option. You could then use get_option() to retrieve the target class and alter your menu accordingly.

So, that’s it. It’s a pretty straight-forward way to hook in and alter navigation menus how you’d like. And, IMHO, a hell of a lot easier than dealing with wp_nav_menu_items() and futzing with parsing HTML, and so on.

March 26, 2013

How to Add a Fully Functional Custom Meta Box to WordPress Navigation Menus

When I created WishList Login 2.0, I wanted to an easy way for users to add a dynamic login/logout link to their navigation menus. As simple as it sounds, it’s not something you can do natively in WordPress and we can requests for this kind of thing all the time.

In WishList Login 1.0, I had added an entire admin interface in the plugin settings that had all the necessary options for creating the link, editing its text, setting its position, and so on.

Of course, this was before WordPress added menus, so I didn’t have much choice… but, now WITH WordPress’ menus, it seemed silly to create a redundant interface… especially when the WordPress menus handled all the things need to added a menu link in a much clear way than my original interface did.

All that led me to figure out how to add my own meta box to the WordPress navigation menu interface with (important) the ability to add a custom link that contained certain parameters I needed in order to hijack the link’s display on the front-end.

Here’s what it looks like in the admin:

WordPress Custom Meta Box

Notice the CSS class. This was really the most important part because it’s what allows me to identify this link later and change it to a login link if the user is logged out and a logout link if the user is logged in.

Here’s a look at the code to make this happen:

if ( !class_exists('JMO_Custom_Nav')) {
class JMO_Custom_Nav {
public function add_nav_menu_meta_boxes() {
add_meta_box(
'wl_login_nav_link',
__('WishList Login'),
array( $this, 'nav_menu_link'),
'nav-menus',
'side',
'low'
);
}

public function nav_menu_link() {?>
<div id="posttype-wl-login" class="posttypediv">
<div id="tabs-panel-wishlist-login" class="tabs-panel tabs-panel-active">
<ul id ="wishlist-login-checklist" class="categorychecklist form-no-clear">
<li>
<label class="menu-item-title">
<input type="checkbox" class="menu-item-checkbox" name="menu-item[-1][menu-item-object-id]" value="-1"> Login/Logout Link
</label>
<input type="hidden" class="menu-item-type" name="menu-item[-1][menu-item-type]" value="custom">
<input type="hidden" class="menu-item-title" name="menu-item[-1][menu-item-title]" value="Login">
<input type="hidden" class="menu-item-url" name="menu-item[-1][menu-item-url]" value="<?php bloginfo('wpurl'); ?>/wp-login.php">
<input type="hidden" class="menu-item-classes" name="menu-item[-1][menu-item-classes]" value="wl-login-pop">
</li>
</ul>
</div>
<p class="button-controls">
<span class="list-controls">
<a href="/wordpress/wp-admin/nav-menus.php?page-tab=all&amp;selectall=1#posttype-page" class="select-all">Select All</a>
</span>
<span class="add-to-menu">
<input type="submit" class="button-secondary submit-add-to-menu right" value="Add to Menu" name="add-post-type-menu-item" id="submit-posttype-wl-login">
<span class="spinner"></span>
</span>
</p>
</div>
<?php }
}
}

$custom_nav = new JMO_Custom_Nav;

add_action('admin_init', array($custom_nav, 'add_nav_menu_meta_boxes'));

Most of this is pretty straight-forward.

  1. You hook into WordPress using the “add_nav_menu_meta_boxes” hook.
  2. You call add_meta_box() in your callback function setting “nav-menus” as the $post_type parameter.
  3. Finally, in your callback function for add_meta_box() you lay out your meta box HTML.

It’s that last part that can get tricky in order to make the adding of your custom link item to the nav menu… so, we’ll look at this more in-depth.

1. First, you need to make sure your HTML is set up correctly. The JavaScript that actually processes the adding of the link to the menu selects your link item in a specific way… so altering the HTML can break it. The above works. I’d recommend copying it and then just altering the small bits you need to.

Or, you can do what I did which is to copy the Category meta box native in WordPress and change what I needed.

2. Next, you need to adjust the main container div ID and the submit button ID so they match. This is part of how the jQuery works. You need to change these so they are unique and you need to make them match.

In the example code, you’ll notice the name of the container div ID is “posttype-wl-login” and the name of the submit button ID is “submit-posttype-wl-login”. This is the kind of relationship these two items need to have.

3. Finally, you’ll edit the inputs in the un-ordered list. These are the bare minimum I needed for everything to work. You can alter the values of these to what you’d like to display be default. You can also check other native meta boxes to see what inputs are available. The important one in our case was the “menu-item-classes”. This sets the CSS classes the link item will have by default and is what I used to hijack the menu later on.

And, that’s it. Once you have that all set up. Your users will be able to add your custom link item from your custom meta box to any of their menus and it’ll have the information pre-loaded in it that you may need later on when displaying menus.

Later, I’ll write up a tutorial on how to hijack menu items when you display the menus, so you can alter your custom link as you need.

March 22, 2013

How to Create a Custom Loop in WordPress Using WP_Query

In this tutorial, I’ll show you how to create a custom loop in WordPress using WP_Query. Plus, I’ll explain why you want to use this instead of query_posts when creating custom loops like these.

<?php
/*** Custom Loop ***/
function demo_loop() {
$args = array(
'cat' => 3,
'posts_per_page' => 1
);

$demo_posts = new WP_Query($args);

if ( $demo_posts->have_posts() ) {
while( $demo_posts->have_posts() ) {
$demo_posts->the_post();

$output .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
}
}

return $output;
}

add_shortcode( 'demo_custom_loop', 'demo_loop' );

February 11, 2013