Additional Post Formats For TwentyTen Child Theme, And Post Formats in General

EDIT: I recently found out a better way to add post formats to a Twenty-Ten child theme, scroll to the bottom of the post to check it out!

As we announced yesterday, WordPress 3.1 was released. Hopefully you have all upgraded by now. If not, get to it. Remember to always keep your install up to date with the latest release. Not just for the cool new features, but for security too. Anyway, if you recently upgraded to 3.1, you may be asking yourself the same question as I see others asking. Where are my post formats? WordPress 3.1 promised lots of different post formats, where are they? Let’s answer that question and tell you how to get them going if you don’t have them.

First thing to realize, post formats are a theme feature. Your theme needs to activate theme. So if you are using the TwentyTen theme, the only post formats available to you are Aside and Gallery (and Standard). But this isn’t too hard to remedy. We’re going to add in post format support for themes in general first. Then we will cover adding additional post formats to a twentyten child theme.

First up, the general stuff. Adding post formats to a theme is very easy to do. First visit the codex entry and decide which ones you would like to add from the available list. It’s simply one line of code added to you functions.php file:

//THEME SUPPORT FOR POST FORMATS
add_theme_support( 'post-formats', array( 'aside', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video', 'audio' ) );

You may not need or want them all. Here’s my line of thinking. I activate them all. I can assign posts to them if I want. I don’t have to style them all. But this way they are available. Down the road if I want to style them, my appropriate posts are already assigned to the formats. If I don’t style them, they look like normal posts, so nothing changes. And if I switch to a new theme that has these formats activated and styled, it’s like I planned ahead! Really the ones you activate and use are up to you.

OK, so that was the easy part. Now lets move on to adding additional formats to the twentyten theme by way of a child theme. If you’ve been following along with our customization tutorials so far for twentyten child themes, you know we already have a function set up to customize the header. Mine is called voodoochild_setup in the example, and it runs on after_setup_theme. For some reason just adding in additional post formats to this function doesn’t work. I tried and tried. So we have to do some copying from the twentyten theme here. We need to grab the entire twentyten_setup function from twentyten’s functions.php and copy it to our child theme. So take all this:

function twentyten_setup() {

	// This theme styles the visual editor with editor-style.css to match the theme style.
	add_editor_style();

	// Post Format support. You can also use the legacy "gallery" or "asides" (note the plural) categories.
	add_theme_support( 'post-formats', array( 'aside', 'gallery' ) );

	// This theme uses post thumbnails
	add_theme_support( 'post-thumbnails' );

	// Add default posts and comments RSS feed links to head
	add_theme_support( 'automatic-feed-links' );

	// Make theme available for translation
	// Translations can be filed in the /languages/ directory
	load_theme_textdomain( 'twentyten', TEMPLATEPATH . '/languages' );

	$locale = get_locale();
	$locale_file = TEMPLATEPATH . "/languages/$locale.php";
	if ( is_readable( $locale_file ) )
		require_once( $locale_file );

	// This theme uses wp_nav_menu() in one location.
	register_nav_menus( array(
		'primary' => __( 'Primary Navigation', 'twentyten' ),
	) );

	// This theme allows users to set a custom background
	add_custom_background();

	// Your changeable header business starts here
	if ( ! defined( 'HEADER_TEXTCOLOR' ) )
		define( 'HEADER_TEXTCOLOR', '' );

	// No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
	if ( ! defined( 'HEADER_IMAGE' ) )
		define( 'HEADER_IMAGE', '%s/images/headers/path.jpg' );

	// The height and width of your custom header. You can hook into the theme's own filters to change these values.
	// Add a filter to twentyten_header_image_width and twentyten_header_image_height to change these values.
	define( 'HEADER_IMAGE_WIDTH', apply_filters( 'twentyten_header_image_width', 940 ) );
	define( 'HEADER_IMAGE_HEIGHT', apply_filters( 'twentyten_header_image_height', 198 ) );

	// We'll be using post thumbnails for custom header images on posts and pages.
	// We want them to be 940 pixels wide by 198 pixels tall.
	// Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
	set_post_thumbnail_size( HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true );

	// Don't support text inside the header image.
	if ( ! defined( 'NO_HEADER_TEXT' ) )
		define( 'NO_HEADER_TEXT', true );

	// Add a way for the custom header to be styled in the admin panel that controls
	// custom headers. See twentyten_admin_header_style(), below.
	add_custom_image_header( '', 'twentyten_admin_header_style' );

	// ... and thus ends the changeable header business.

	// Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
	register_default_headers( array(
		'berries' => array(
			'url' => '%s/images/headers/berries.jpg',
			'thumbnail_url' => '%s/images/headers/berries-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Berries', 'twentyten' )
		),
		'cherryblossom' => array(
			'url' => '%s/images/headers/cherryblossoms.jpg',
			'thumbnail_url' => '%s/images/headers/cherryblossoms-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Cherry Blossoms', 'twentyten' )
		),
		'concave' => array(
			'url' => '%s/images/headers/concave.jpg',
			'thumbnail_url' => '%s/images/headers/concave-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Concave', 'twentyten' )
		),
		'fern' => array(
			'url' => '%s/images/headers/fern.jpg',
			'thumbnail_url' => '%s/images/headers/fern-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Fern', 'twentyten' )
		),
		'forestfloor' => array(
			'url' => '%s/images/headers/forestfloor.jpg',
			'thumbnail_url' => '%s/images/headers/forestfloor-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Forest Floor', 'twentyten' )
		),
		'inkwell' => array(
			'url' => '%s/images/headers/inkwell.jpg',
			'thumbnail_url' => '%s/images/headers/inkwell-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Inkwell', 'twentyten' )
		),
		'path' => array(
			'url' => '%s/images/headers/path.jpg',
			'thumbnail_url' => '%s/images/headers/path-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Path', 'twentyten' )
		),
		'sunset' => array(
			'url' => '%s/images/headers/sunset.jpg',
			'thumbnail_url' => '%s/images/headers/sunset-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Sunset', 'twentyten' )
		)
	) );
}

And paste it into your functions.php in your child theme. I put it above my customized function for modifying the header. I recommend you do the same. Now here’s the thing. This is kind of a pain, since we made our custom function to override portions of this very function we are now placing into our child theme. But, this does give you options. Let’s talk about them.

You can just paste this twentyten_setup function in your child functions.php and edit the post formats portion and leave it at that. Your override custom function you made earlier will continue to work. That’s the route I took. Or you can delete your custom function and make those edits directly in the twentyten_setup now that it is in your child theme. You are able to add your default header image and tweak the sizes directly here. It’s up to you. Like I said I kept my custom function and just tweaked the format line.

To add new post formats, just edit line 7 to add in your own. I’m just going to add in a link post format. Here is my final code in my functions.php with twentyten_setup in place, with my post format added to it, and also with my custom voodoochild_setup in place with our previous customizations.

function twentyten_setup() {

	// This theme styles the visual editor with editor-style.css to match the theme style.
	add_editor_style();

	// Post Format support. You can also use the legacy "gallery" or "asides" (note the plural) categories.
	add_theme_support( 'post-formats', array( 'aside', 'gallery', 'link' ) );

	// This theme uses post thumbnails
	add_theme_support( 'post-thumbnails' );

	// Add default posts and comments RSS feed links to head
	add_theme_support( 'automatic-feed-links' );

	// Make theme available for translation
	// Translations can be filed in the /languages/ directory
	load_theme_textdomain( 'twentyten', TEMPLATEPATH . '/languages' );

	$locale = get_locale();
	$locale_file = TEMPLATEPATH . "/languages/$locale.php";
	if ( is_readable( $locale_file ) )
		require_once( $locale_file );

	// This theme uses wp_nav_menu() in one location.
	register_nav_menus( array(
		'primary' => __( 'Primary Navigation', 'twentyten' ),
	) );

	// This theme allows users to set a custom background
	add_custom_background();

	// Your changeable header business starts here
	if ( ! defined( 'HEADER_TEXTCOLOR' ) )
		define( 'HEADER_TEXTCOLOR', '' );

	// No CSS, just IMG call. The %s is a placeholder for the theme template directory URI.
	if ( ! defined( 'HEADER_IMAGE' ) )
		define( 'HEADER_IMAGE', '%s/images/headers/path.jpg' );

	// The height and width of your custom header. You can hook into the theme's own filters to change these values.
	// Add a filter to twentyten_header_image_width and twentyten_header_image_height to change these values.
	define( 'HEADER_IMAGE_WIDTH', apply_filters( 'twentyten_header_image_width', 940 ) );
	define( 'HEADER_IMAGE_HEIGHT', apply_filters( 'twentyten_header_image_height', 198 ) );

	// We'll be using post thumbnails for custom header images on posts and pages.
	// We want them to be 940 pixels wide by 198 pixels tall.
	// Larger images will be auto-cropped to fit, smaller ones will be ignored. See header.php.
	set_post_thumbnail_size( HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT, true );

	// Don't support text inside the header image.
	if ( ! defined( 'NO_HEADER_TEXT' ) )
		define( 'NO_HEADER_TEXT', true );

	// Add a way for the custom header to be styled in the admin panel that controls
	// custom headers. See twentyten_admin_header_style(), below.
	add_custom_image_header( '', 'twentyten_admin_header_style' );

	// ... and thus ends the changeable header business.

	// Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
	register_default_headers( array(
		'berries' => array(
			'url' => '%s/images/headers/berries.jpg',
			'thumbnail_url' => '%s/images/headers/berries-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Berries', 'twentyten' )
		),
		'cherryblossom' => array(
			'url' => '%s/images/headers/cherryblossoms.jpg',
			'thumbnail_url' => '%s/images/headers/cherryblossoms-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Cherry Blossoms', 'twentyten' )
		),
		'concave' => array(
			'url' => '%s/images/headers/concave.jpg',
			'thumbnail_url' => '%s/images/headers/concave-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Concave', 'twentyten' )
		),
		'fern' => array(
			'url' => '%s/images/headers/fern.jpg',
			'thumbnail_url' => '%s/images/headers/fern-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Fern', 'twentyten' )
		),
		'forestfloor' => array(
			'url' => '%s/images/headers/forestfloor.jpg',
			'thumbnail_url' => '%s/images/headers/forestfloor-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Forest Floor', 'twentyten' )
		),
		'inkwell' => array(
			'url' => '%s/images/headers/inkwell.jpg',
			'thumbnail_url' => '%s/images/headers/inkwell-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Inkwell', 'twentyten' )
		),
		'path' => array(
			'url' => '%s/images/headers/path.jpg',
			'thumbnail_url' => '%s/images/headers/path-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Path', 'twentyten' )
		),
		'sunset' => array(
			'url' => '%s/images/headers/sunset.jpg',
			'thumbnail_url' => '%s/images/headers/sunset-thumbnail.jpg',
			/* translators: header image description */
			'description' => __( 'Sunset', 'twentyten' )
		)
	) );
}


// VOODOOCHILD SETUP FUNCTION FOR ADJUSTING HEADER STUFF
function voodoochild_setup(){

// OVERRIDE TWENTYTEN HEADER SIZE
define( 'HEADER_IMAGE_WIDTH', apply_filters( 'twentyten_header_image_width', 1010 ) );
define( 'HEADER_IMAGE_HEIGHT', apply_filters( 'twentyten_header_image_height', 228 ) );

// ADD IN OUR CUSTOM HEADER IMAGES TO DEFAULT
    $voodoochild_dir =    get_bloginfo('stylesheet_directory');
    register_default_headers( array (
        'voodoopress' => array (
            'url' => "$voodoochild_dir/images/voodoopress.jpg",
            'thumbnail_url' => "$voodoochild_dir/images/voodoopressthumb.jpg",
            'description' => __( 'VoodooPress Default', 'voodoochild' )
        )

    ));

}

add_action( 'after_setup_theme', 'voodoochild_setup' );

And that’s it. Our customized headers still work, and we have the link post format added. This is the only way I’ve found so far to make this work. If I find something better in the future, we will revisit this issue. Like I’ve stated before, I want to keep my copying and pasting from the parent theme to a minimum and just use actions, filters, or whatever wherever possible.

Don’t forget our article from a while back about organizing your functions.php. One thing you may want to do with that twentyten_setup is put it in its own file, and just include it near the top of your child functions.php.

Of course this only activates the formats. You still have tonnes of options for using/styling them. I have an article on my blog I wrote before starting VoodooPress explaining what I did. But here on this site, I reall only have edited style.css of my child theme to lend some styling to the formats. You have tonnes of options available which are beyond the scope of this particular article.

Whatever you do, play around, have fun, and we’ll tweak some more real soon!

Add a Meta Box to Use Custom Fields on Front End Post Form

So far this week, we have learned how to post from the front end. And we’ve expanded on that by allowing image uploads from the front end. We are going to go one step further today and add a meta box to our form. This way we can use the meta box to gather data and feed it into a custom field so we can use that data. The data can be just about anything, really use your imagination here. I’ll give some examples of stuff I’m thinking of, let’s get into it!

So I’m still going to be working on my wine rating form. My idea is to set up a 5 star type system. I’m going to offer radio checkboxes where the user picks 1-5 stars. The value of that selection will be fed into the custom field, and then depending on what is picked, an image depicting 1-5 stars will be displayed on the rating post. But that is coming soon. Today I will just use a text field that will take a standard text input. You could use this to gather a site url, a sub-title, anything you can think of. Time to get into some code.

The first thing we need to do is set up the text box. Like I said, mine will be to collect a rating. Here’s my form field:

                            <!-- wine Rating -->
                            <fieldset class="winerating">
                                      <label for="winerating">Your Rating</label>
                                      <input type="text" value="" id="winerating" size="60" tabindex="20" name="winerating">
                            </fieldset>

Obviously you can customize this however you want. The main part here is that I’m calling this winerating. We will be using that in the rest of the code to gather our data and feed it into a custom field. Next up we need to tweak our existing processing code to handle the custom field. Remember I’m working on the form we set up here and here, if your’s is different, you’ll have to accomodate that.

So back on our form, the top bit of code looks like:

// Do some minor form validation to make sure there is content
if (isset ($_POST['title'])) {
        $title =  $_POST['title'];
	} else {
        echo 'Please enter the wine name';
	}
if (isset ($_POST['description'])) {
        $description = $_POST['description'];
	} else {
        echo 'Please enter some notes';
	}
$tags = $_POST['post_tags'];

And I added in my new form field to a variable, which you’ll recall is winerating. I just added it after the last line above, like this:

$tags = $_POST['post_tags'];
$winerating = $_POST['winerating'];

Next up, I tweaked our existing array which looked like this:

// Add the content of the form to $post as an array
$new_post = array(
        'post_title'    => $title,
        'post_content'  => $description,
        'post_category' => array($_POST['cat']),  // Usable for custom taxonomies too
        'tags_input'    => array($tags),
        'post_status'   => 'publish',           // Choose: publish, preview, future, draft, etc.
        'post_type' => 'post'  //'post',page' or use a custom post type if you want to
);

Again right at the bottom I added my code. Don’t forget to add a comma to ‘post’ when adding a new line. So the bottom of that now looks like: This step is not necessary, I’ll explain after the code.

        'post_type' => 'post',  //'post',page' or use a custom post type if you want to
	'winerating' => $winerating
);

When I wrote this tutorial, I didn’t have a full understanding of how everything fit together. I got it working and was happy with that. But here’s one update. This particular step is unnecessary, it doesn’t do a thing! What we can add into the array are parameters used by wp_insert_post. Anything else doesn’t do anything! The rest of this tut works great, I just wanted to update this one misunderstanding I had.

And finally, just after the wp_insert_post line we add some code. If you followed yesterdays tutorial about adding images, I put this line of code after the wp_insert_post and above the foreach loop for the images. Here’s the existing code with the new line added for our meta box.

//save the new post
$pid = wp_insert_post($new_post);

add_post_meta($pid, 'rating', $winerating, true);

And that is all the code you need! Notice in the add_post_meta line above, the second parameter is rating. That is what we call to display our meta box/custom field value. So to display the value in your theme somewhere you just use:

<div class="wineRating">
<?php if( get_post_meta($post->ID, "rating", true) ): ?>
<?php echo get_post_meta($post->ID, "rating", true); ?>
<?php endif; ?>
</div>

There you have it. Now that you have the basics all figured out, you can make a front-end post form, you can allow image uploads, and now you can use meta boxes to gather and display all sorts of other information. Time to go make some sort of fancy post form. Let me know what you come up with!

Tomorrow I will do a quick recap of the past three tutorials, and display my full code for this post form page template from top to bottom for review.

Working With Featured Image in WordPress

I had a request from a reader here on VoodooPress to look into featured image sizes. Recently we had a series of posts on here about posting from the front end, and allowing users to upload their own picture. We even showed you how to set the user uploaded picture as a featured image. Let’s take a deeper look at using the featured images. Maybe assign different sizes to different templates. You don’t have to use this just for user uploaded photos of course. This information is useful for the featured image in general, whether you let users upload them, or you set them in the back end.

You can see an example of this in action on my blog, www.rvoodoo.com. On standard format posts, I use the featured image in a variety of ways. Once it is set, it is used as a small icon next to the post title. It is also used as a larger thumbnail in the body of the post. And if you click through to the single post view, we use a much larger featured image in the post. So let’s go over a variety of things that can be done with the thumbnails.

One thing to note, you may notice when I talk about the featured image, I sometimes also call it just the thumbnail. Please don’t get confused. When the feature was first added to WordPress in version 2.9, it was called the thumbnail. The code for the image refers to it as the thumbnail. Later on the name was changed to featured image. So I am really referring to the same thing. Featured image/thumbnail, whatever you call it, let’s do some work.

If you haven’t read this excellent article, give it a read. It pretty much covers everything I’m going to cover here. That is the article I used to learn how to work with the featured images.

Anyway, the first thing to know is how to turn them on. Featured images don’t just work out of the box on WordPress, the theme must support them. Hopefully by now, pretty much every theme has them. But if yours doesn’t here’s how to fix that:

add_theme_support( 'post-thumbnails' );

That’s it. Add that line to functions.php, and you have thumbnail support! Easy right? Now let’s look at adding the default size. This is the size that will be used if you just call the_post_thumbnail (we’ll get into that in a moment) with no image name.

set_post_thumbnail_size( 75, 75, true );

That right there defines my default thumbnail size as 75 x 75 pixels. The true refers to the crop mode. It can basically be set to true, or left off (which makes it false). To understand the cropping mode a bit better, you can check out what Mark Jaquith has to say on this post, another excellent resource for using featured images.

So now we have turned on the featured image, and we’ve set the default thumbnail size. What if we want more image sizes? Let’s add one:

add_image_size( 'title-image', 50, 27 );

That’s all you need to do. You are now able to call that image size by ‘title-image’ in your theme. You can repeat that as much as you need with different names to add a variety of image sizes to use all over your theme. Here’s what I have over on www.rvoodoo.com for featured images:

	add_theme_support( 'post-thumbnails' );
	set_post_thumbnail_size( 75, 75, true ); // default post thumbnails
	add_image_size( 'index-post-thumb', 75, 75 );
	add_image_size( 'single-post-thumbnail', 150, 150, true ); // Permalink thumbnail size
	add_image_size( 'title-image', 50, 27 ); // Title mini photo
	add_image_size( 'shop-single-image', 700, 999 ); //Shop Single Product Image
	add_image_size( 'member-thumb', 205, 100, true ); // Member Page Image

You can see I have the featured images turned on. I set the default at 75 x 75. I then added on five additional image sizes to use all over my theme. Pretty handy I say!

Now, for a lot of my VoodooPress readers, you are probably using a child theme of twentyten. What then? Featured images are already turned on, and the default image size is set, and being used for a header. What if you want to add more image sizes to a child theme? Well I just add them onto theme setup. If you recall this post, we made our own function called voodoochild_setup which runs on after setup theme. If you have that function, you can drop your add image size in there. That’s how I’ve done it on VoodooPress. If you didn’t follow that, here’s a function for your twentyten child theme that will add image sizes.

// VOODOOCHILD FUNCTION FOR ADDING IMAGE SIZES
function voodoochild_image_sizes(){

add_image_size ( 'admin-thumb', 100, 60, true );
add_image_size( 'single-post-thumbnail', 150, 150, true ); // Permalink thumbnail size
add_image_size( 'title-image', 50, 27 ); // Title mini photo

}

add_action( 'after_setup_theme', 'voodoochild_image_sizes' );

And you just keep on adding whatever sizes you need to that. OK, there’s all the info you should need for adding image sizes. If you followed along earlier and are allowing user uploaded images, now when an image is uploaded, all the sizes you define in functions.php are available for use throughout your theme. Same thing even if you aren’t allowing user uploads. You can set a featured image in the backend, and all the sizes you define are available. Let’s take a look at how to use the images now to actually display them.

The most basic code is this:

<?php the_post_thumbnail(); ?>

How easy is that? That bit of code will call your default thumbnail size. So if you added your own thumbnail support, it’s whatever is defined here:

set_post_thumbnail_size( 75, 75, true );

OK, that’s the default size, lets use our other sizes. You simply drop in whatever you named the image in your add image size code above. So if we have:

add_image_size( 'archive-image', 150, 150, true );

then to display that image size we use:

<?php the_post_thumbnail( 'archive-image' ); ?>

And we just do that over and over for any image size. The code works in pairs. You use add_image_size in functions.php with an image name to define the image size, and then in your template where you want to use the image, you use the_post_thumbnail with the same image name. Pretty simple right? You can use a variety of sizes all over the place now. Just define them in your functions.php, and the call them in your templates.

Let’s look at a few more tricks just for fun.

Maybe we want to display a default image if no thumbnail is set. We can use a conditional for that. Here’s a sample:

	<?php if( has_post_thumbnail() ) : ?>
		<?php the_post_thumbnail(); ?>

	<?php else : ?>
		<img src="<?php bloginfo( 'stylesheet_directory' );?>/images/sample.jpg" alt="Default Icon" title="Default Icon" />
	<?php endif; ?>

That says if there is a thumbnail, use it. If not display the image named sample.jpg in the images directory of my theme.

What if we want the image to link to the article? I use this on any thumbnail I have on my index.php to link to the article.

<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail(); ?>
</a>

You can also add classes to the image of course for styling and whatnot:

<!-- DISPLAY IMAGE WITH CLASS AND ALT -->
<?php the_post_thumbnail( 'thumbnail', array( 'class' => 'class', 'alt' => 'Title' ) ); ?>

And here is another neat trick, good for single.php. I use a lightbox plugin, which needs the rel=”lightbox” added to my images to be able to display them. And I need to link the image to it’s large version. This code does both:

					<a rel="lightbox" href="<?php $image_id = get_post_thumbnail_id();
					$image_url = wp_get_attachment_image_src($image_id,'large', true);
					echo $image_url[0];  ?>">
					<?php the_post_thumbnail('thumbnail'); ?>
					</a>

Even if you don’t use a light box plugin, you may want the image linked to a certain version of the original image. Line 2 here, where I have ‘large’ is the size of the link target image you want the link to go to. Line 4 is the displayed featured image size, you could swap out ‘thumbnail’ for whatever image size you want to use which you have defined in your functions.php with add_image_size.

So that’s a whole bunch of information about working with the_post_thumbnail. I hope this helps some of you. If I forgot anything, or you want to know even more, I’m always open to comments!

How to Post From Your Front End With No Plugin

Lately I’ve been working on another side project. A wine rating site that we hope to launch soon. But one of the requirements for the site was that once a wine rater logged in, they should have access to a form to rate wines. I didn’t want anyone to have to fuss with the back end of WordPress. I just wanted to present them with a simple form to fill out. Let’s look into how that’s done.

The first thing you need to figure out is the details. Sketch out your form, what types of data do you need? Is it just normal post stuff (title, post, categories, keywords), or do you need more? You can use custom fields/meta boxes from the front end. You can also allow thumbnail uploads to set as the featured image, or multiple image uploads. Today we will just look at the basic stuff. Tomorrow we will add image uploads.

After you have your form all filled out you need to figure out some more details. Since the main focus of my site is going to be wine rating, I want to use the standard post as wine rating. I will also use the standard categories to present a dropdown of wine types. And I will use the normal tagging system to allow for keywords. You can follow the same setup, or you can register a new post type, and use custom taxonomies, these things would only require some simple changes in the code I’ll give you, and I’ll point them out.

Now that we have all the details figured out, we need to get into the code. I set up a simple page template first. Now since this is just another form really, I borrowed heavily from my own article here about Contact Form 7. You’ll see a few blocks of code down a setup for a simple page template, it looks like:

<?php
/*
Template Name: Wine Rating Form
*/
get_header(); ?>

        <div id="container">
            <div id="content" role="main">

<?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?>

                <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                    <?php if ( is_front_page() ) { ?>
                        <h2 class="entry-title"><?php the_title(); ?></h2>
                    <?php } else { ?>
                        <h1 class="entry-title"><?php the_title(); ?></h1>
                    <?php } ?>

                    <div class="form-content">
                        <?php the_content(); ?>
                        <?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
                        <?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="edit-link">', '</span>' ); ?>
                    </div><!-- .entry-content -->
                </div><!-- #post-## -->

                <?php comments_template( '', true ); ?>

<?php endwhile; // end of the loop. ?>

            </div><!-- #content -->
        </div><!-- #container -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

You’ll see that the template is the same as on the example in the previous post, except I change the name to Wine Rating Form in the header of the code. So save that as whatever you like, I called it ratewine.php. You’ll see a call to the_content on line 20. I’m going to put my new form directly under that. You can do the same, or you can delete the_content, it’s up to you. I left it in as I may decide later to add some instructions through the normal WP page interface.

You’ll also notice that on line 19, I have div class=form-content rather than the normal entry-content from twenty ten. That is just to avoid having twenty ten’s css play too much on our form. That is explained in this article as well.

Let’s add in our form now! Again looking at the article from before you can see how I like to lay out my forms. I’m going to follow the same format here:

		<!-- WINE RATING FORM -->

		<div class="wpcf7">
		<form id="new_post" name="new_post" method="post" action="" class="wpcf7-form" enctype="multipart/form-data">
			<!-- post name -->
			<fieldset name="name">
				<label for="title">Wine Name:</label>
				<input type="text" id="title" value="" tabindex="5" name="title" />
			</fieldset>

			<!-- post Category -->
			<fieldset class="category">
				<label for="cat">Type:</label>
				<?php wp_dropdown_categories( 'tab_index=10&taxonomy=category&hide_empty=0' ); ?>
			</fieldset>

			<!-- post Content -->
			<fieldset class="content">
				<label for="description">Description and Notes:</label>
				<textarea id="description" tabindex="15" name="description" cols="80" rows="10"></textarea>
			</fieldset>

			<!-- post tags -->
			<fieldset class="tags">
				<label for="post_tags">Additional Keywords (comma separated):</label>
				<input type="text" value="" tabindex="35" name="post_tags" id="post_tags" />
			</fieldset>

			<fieldset class="submit">
				<input type="submit" value="Post Review" tabindex="40" id="submit" name="submit" />
			</fieldset>

			<input type="hidden" name="action" value="new_post" />
			<?php wp_nonce_field( 'new-post' ); ?>
		</form>
		</div> <!-- END WPCF7 -->

You’ll notice I have some tags in there that come from Contact Form 7. we wrap the form in a wpcf7 class, and apply the wpcf7-form class to the actual form. This is not required of course. I just did it because I already have css in place from this tutorial. If I apply the same classes, I can reuse the css with no edits. Keep things simple eh!

The important part is to make sure the name and ID on these inputs match up with what I have. That is because we are using standard inputs. These will save to specific values that go to your database from the block of code I’m about to give you. You will also notice the second block makes use of wp_dropdown_categories, I like the idea of giving a list of categories here, since my cats are wine types. This is one place you could swap in a custom taxonomy. And finally at the bottom you’ll notice a little use of wp_nonce_field again, just a simple verification on where the data is coming from.

So that has our form all built. If you saved it now, and then applied this template to a page you would have your post form. Depending on if you followed this tutorial before, it may or may not be styled. But the big thing you would notice is that the form doesn’t do anything! You can fill it out for sure, but the data does nothing. Let’s fix that!

Way at the top of our template, under the page template header, but above the get_header call, we are going to put some code.

if( 'POST' == $_SERVER['REQUEST_METHOD'] && !empty( $_POST['action'] ) &&  $_POST['action'] == "new_post") {

	// Do some minor form validation to make sure there is content
	if (isset ($_POST['title'])) {
		$title =  $_POST['title'];
	} else {
		echo 'Please enter the wine name';
	}
	if (isset ($_POST['description'])) {
		$description = $_POST['description'];
	} else {
		echo 'Please enter some notes';
	}

	$tags = $_POST['post_tags'];

	// ADD THE FORM INPUT TO $new_post ARRAY
	$new_post = array(
	'post_title'	=>	$title,
	'post_content'	=>	$description,
	'post_category'	=>	array($_POST['cat']),  // Usable for custom taxonomies too
	'tags_input'	=>	array($tags),
	'post_status'	=>	'publish',           // Choose: publish, preview, future, draft, etc.
	'post_type'	=>	'post'  //'post',page' or use a custom post type if you want to
	);

	//SAVE THE POST
	$pid = wp_insert_post($new_post);

             //SET OUR TAGS UP PROPERLY
	wp_set_post_tags($pid, $_POST['post_tags']);

	//REDIRECT TO THE NEW POST ON SAVE
	$link = get_permalink( $pid );
	wp_redirect( $link );

} // END THE IF STATEMENT THAT STARTED THE WHOLE FORM

//POST THE POST YO
do_action('wp_insert_post', 'wp_insert_post');

Up at the top are some instruction to WordPress to use this as a post, and we set up new_post which is what our nonce_field verifies against. After that we do some validation. Just some basic fields we want to require. And then we set up the array which grabs the data from our form and puts it all together to insert into the WordPress database. The wp_redirect line is optional, this redirects the user to their new post once they hit submit. This works great on a wine rating site I thought, take the user right to their post. (redirect threw errors, working on it) I have update the above code again. Everything works splendidly. The redirect block of code is optional or can be edited to redirect where you would like.

I’ve tried to mark with comments in the code where custom post types and custom taxonomies can be swapped out. But that pretty well does it! With this code you can have your own front end post form.

If your form isn’t styled, just take a look at this post, it has the styling I use for Contact Form 7, which if you set up your form using the layout I did above, it will work for this form as well.

Now just save up this page template to your theme and apply it to a page, and you have a post from the front end form available to your users! You probably don’t want this available to just anyone, I keep the access restricted to authors and above on my site.

Notes For Multi Category Select:I haven’t had time to totally sort this out yet, but I’m posting it here for info.
If you replace the wp_dropdown_categories line with this:

		<?php $select_cats = wp_dropdown_categories( array( 'echo' => 0, 'taxonomy' => 'category', 'hide_empty' => 0 ) );
		$select_cats = str_replace( "name='cat' id=", "name='cat[]' multiple='multiple' id=", $select_cats );
		echo $select_cats; ?>

It will allow for multiple category select. However, something needs done with the processing code above to allow that array to be handled.

Around line 16 (of the processing code), where we set up the post tags, I have this

$post_cat = $_POST['cat'];

And then in the array, I replaced the post category line with this

'post_category' =>   $post_cat,

And that was it, I am now able to select and save multiple categories!

UPDATE: If you check out this post, the end review of this form, down at the bottom we have an update with a possible fix to get the validation working properly. If you have a chance to try the fix out and report back if it works, that would be awesome!

UPDATE(2): If you cruise around the site, and search a little, you’ll find that there are a whole variety of posts related to this frontend post form. But here is a couple valuable links – our great VoodooPress readers have been busy! One of our readers provided his technique for editing and deleting these posts from the front end. Another reader got validation working and provided us with that code! That’s a lot of cool stuff! If you have anything to add here, feel free to submit your stuff, or even ask about a guest post! We are well on our way to posting perfection!