How to stop post duplication when using multiple WP_Query() requests

Filed February 12th, 2012 under Tutorial, WordPress

On my site SalaciousSound I have two selections of articles: five ‘featured’ posts which appear at the top of my index, above the fold, and ten more of my most recent articles.

I wanted to exclude the featured articles from appearing in the regular articles section, and I did so by using the WP_Query() parameter ‘post__not_in’.

The reason for writing this article is that collecting the post IDs from my first WP_Query and passing them to the second was, for me, non-trivial because the five featured articles appear in my header.php file and the ten regular articles appear in index.php.

In order to achieve my desired result I had to set a php variable in my functions.php file, and then declare it as a global variable in my header.php file and index.php file.

Here’s how the relevant code looks:

from functions.php
$featIDs = array();
from header.php
global $featIDs;
$feats_query = new WP_Query('category_name=Features&posts_per_page=5');
while ($feats_query->have_posts()) : $feats_query->the_post();
	array_push($featIDs, $post->ID);
from index.php
global $featIDs;
$index_query = new WP_Query(array(
	'posts_per_page' => 10,
	'post__not_in' => $featIDs
));
Comment! (2)

How to use WP_Query() with pagination

Filed February 12th, 2012 under Tutorial, WordPress

It turns out using WP_Query() AND paginating your results properly is not entirely straightforward. The WordPress Codex documentation and information on the help forums is also pretty bad.

This article explains how to make custom queries using WP_Query() AND still allow for pagination.

My use case is: a custom query on my index page which excludes certain posts, and wp_pagenavi for paginating my archives.

I explain in detail why I am using WP_Query() instead of the regular WordPress loop in my next article ‘How to stop post duplication when using multiple WP_Query() requests‘.

In short, WP_Query doesn’t know what page you’re on like the regular WordPress loop does – you need to tell it which page of posts to ask for (and, in addition, how many posts per page you want it to retrieve).

Here’s the relevant code:

$pagedNum = get_query_var('paged');
$index_query = new WP_Query(
	array(
		'posts_per_page' => 10,
		'paged' => $pagedNum
	));
Comment! (0)

Add TinyMCE WYSIWYG Editor and HTML Capabilities to WordPress User Bios

Filed September 13th, 2011 under Resources, WordPress

I’m at the end of another project here and as usual I’ve had to modify the WordPress core slightly to give my client some CMS functionality that vanilla WordPress lacks. Specifically, by default you are not able to add any html to the ‘Biographical Info’ field on user profile, much less use the WYSIWYG editor bundled with the post editor on that field – any html is automatically stripped out when you ‘Update Profile’.

So there are two ways that you can achieve what I wanted to do, and both utilize the functions.php file.

Strategy One – just allow for html (no TinyMCE)
remove_filter('pre_user_description','wp_filter_kses');
Strategy Two – add TinyMCE to the User ‘Biographical Info’ field

Use the above code AND the code below

function biographical_info_tinymce() {
	if ( basename($_SERVER['PHP_SELF']) == 'profile.php' || basename($_SERVER['PHP_SELF']) == 'user-edit.php' && function_exists('wp_tiny_mce') ) {
		wp_admin_css();
		wp_enqueue_script('utils');
		wp_enqueue_script('editor');
		do_action('admin_print_scripts');
		do_action("admin_print_styles-post-php");
		do_action('admin_print_styles');
		remove_all_filters('mce_external_plugins');

		add_filter( 'teeny_mce_before_init', create_function( '$a', '
			$a["theme"] = "advanced";
			$a["skin"] = "wp_theme";
			$a["height"] = "300";
			$a["width"] = "440";
			$a["onpageload"] = "";
			$a["mode"] = "exact";
			$a["elements"] = "description";
			$a["theme_advanced_buttons1"] = "formatselect, bold, italic, pastetext, pasteword, bullist, numlist, link, unlink, outdent, indent, charmap, removeformat, spellchecker, fullscreen, wp_help";
			$a["theme_advanced_blockformats"] = "p,h2,h3,h4,h5,h6";
			$a["theme_advanced_disable"] = "strikethrough,underline,forecolor,justifyfull";
			return $a;' ) );

		wp_tiny_mce( true );
	}
}
add_action('admin_head', 'biographical_info_tinymce');
Comment! (2)

WPAudio WordPress Plugin Crashes Safari Browser When Song is Played From Post

Filed July 3rd, 2011 under Tutorial, WordPress

I encountered a problem on my music blog SalaciousSound today. I use a plugin called wpaudio, which uses javascript and the soundmanager2 library (with flash fallback) to play mp3 audio files. I was finding that, on a particular post, whenever I played an mp3 the browser would crash. The plugin was working fine on all other posts, so I knew that this had something to do with the number of mp3 files on this particular post.

How to reproduce the crash

Create a post with more than 20+ mp3s to play, or go to a page (archive for example) where more than 20+ players are present – it doesn’t matter if they’re all inline or each have their own wpaudio markup, you just need more than twenty players. The crash was occurring in Safari. Chrome was working ok. I didn’t test Firefox or Internet Explorer.

I have a monthly series that I run called the Monthly Best of the Blogosphere, wherein I post 25-30 tracks that have been really popular that month. Only on these posts was the browser crash occurring.

How to fix the crash

You have to edit the wpaudio.js (or wpaudio.min.js file, depending on what you use – I use the minified wpaudio.min.js file myself). You have to change two lines of code in this file, and add an additional one. It’s pretty easy, and if you follow my instructions carefully you can do this with minimal coding knowledge.

Find this function:

function WpaudioHTML5 (parent) {
			...
}

Find these two lines – they are sequential:

start = player.seekable.start();
end = player.seekable.end();

Change them to this:

start = player.buffered.start();
end = player.buffered.end();

Next, find these two lines:

player.src = parent.getUrl();
player.volume = 1;

And add this line after them:

player.preload = "none";

Voila! Problem solved!

Comment! (0)

How to Use WordPress Multisite Subdomain Install With Real Subdomains

Filed January 10th, 2011 under Tutorial, WordPress

TL;DR: I added the VirtualHost record for specialsubdomain.mysite.com BEFORE the mysite.com record, and inserted the “Include /var/www/vhosts/mysite.com/conf/vhost.conf” statement in to the last line of the mysite.com VirtualHost record (just before the closing tag).

My frustrating learning experience

I just sorted out an issue with wordpress multisite, and it took quite a bit of searching and reading to uncover what is ostensibly a very simple solution. Admittedly, I didn’t know anything about the httpd.include or vhost.conf files before I set out a few weeks ago, nor the ServerAlias tag the VirtualHost tag or how dns entries, including the wildcard (*) are parsed.

The problem was this: wordpress multisite is installed with a subdomain install. That means every site created gets a new subdomain, and as a result you need a way to tell your server that any traffic that goes to that subdomain should ask the main site for information and files.

The practical solution is to use a wildcard dns (*) entry when setting up wordpress multisite – indeed this is the definitive proscribed solution. Unfortunately, this can cause some headaches if applied incorrectly, as has been well documented in this discussion thread.

What was supposed to happen

1. People can visit mysite.com
2. I can create a new site (a subdomain) in the mysite.com backend, and people can automatically access newsubdomain.mysite.com
3. People can access my subdomain community.mysite.com which is NOT a wordpress multisite blog, and any other special subdomains that I might like to define separately from the mysite.com wpms install (ie community is vanilla forums, and I might want to add some kind of mail redirect to google apps email mail.mysite.com)

What was happening when I included the vhost.conf file

1. I followed the instructions to add a line to my httpd.include file which includes a vhost.conf file. Incidentally, this is ALSO required for domain mapping, which I am also doing:

<VirtualHost xxx.xxx.xxx.xxx:80>
   ServerName   mysite.com:80
   ...
   Include /var/www/vhosts/mysite.com/conf/vhost.conf
</VirtualHost>

2. Because the vhost.conf file was included INSIDE the VirtualHost tag, the VirtualHost tag was NOT required in the vhost.conf file. All I required was one line: ServerAlias *.mysite.com
3. I could visit mysite.com
4. I could visit my wpms subdomains
5. I couldn’t visit community.mysite.com – I would be redirected to a page telling me that registration is closed (and presumably I would have been redirected to a signup page, were I to enable that feature)

What was happening when I took out the vhost.conf file

1. I could visit mysite.com
2. I could visit community.mysite.com
3. I couldn’t visit any of my wpms subdomains

The solution, and why

It took a minute, but when I paid attention to the details of the discussion thread the answer was pretty clear.

The way these dns redirects work is in order – the text file is just parsed, and apache takes the first valid option it finds. “Cool!” I thought, “that just means that I need to order my file properly!” Sure enough, once I added the VirtualHost record for community.mysite.com BEFORE the mysite.com record, and put the include vhost.conf statement in to the mysite.com VirtualHost record, things worked fine!

Voila:

<VirtualHost xxx.xxx.xxx.xxx:80>
   ServerName   specialsubdomain.mysite.com:80
   ...
</VirtualHost>
<VirtualHost xxx.xxx.xxx.xxx:80>
   ServerName   mysite.com:80
   ...
   Include /var/www/vhosts/mysite.com/conf/vhost.conf
</VirtualHost>

I hope this helps even one person, because I was seriously going nuts with this problem. Please feel free to comment if there is any confusion over what I’ve described here, but keep in mind that I am still a novice with Apache… but I’ll try my best! :)

Comment! (1)

5 Creative Uses of WordPress

Filed August 27th, 2010 under Web Technologies, WordPress

I‘ve been working with WordPress since 2005, way back in its version 2.0 days. Back then, endlessly tinkering with CSS selectors I didn’t quite understand was about the limit of what I could do with the platform.

So it’s interesting to me to reflect on where WordPress has come from in that time. From introducing the WYSISWG editor and post previews to custom post types, taxonomies, and on-the-fly menus. It’s come from being a basic blogging platform, to being the starting point for ideas big and small.

But the WordPress core itself is a slow-moving beast. And rightfully so – it’s a mature environment now, and integrating features into the core has to be methodical and well planned. With that in mind, much of the true innovation comes in the form of the theme and plugin market.

I’ve gathered a collection of these resources over the past few months, and I’d thought I’d share them here.

Social Networking: BuddyPress

BuddyPress.org

Dubbed Social networking in a box, BuddyPress is a plugin that sits on top of an existing WordPress installation. By default, it provides activity streams, extended profiles, friend connections, private messaging, WordPress blogging, extensible groups, and discussion forums.

Documentation and Collaboration: WordPress Wiki

If you’ve ever played with the official Wikimedia platform, you know that creating an easy-to-use Wiki is a pain in the ass. WordPress Wiki gives you the core functionality of a knowledge database with minimal trouble.

Ticket Tracking: Quality Control

Ticket tracking is hugely important for project management and customer service. And everyone in the web design/development community deals with on tickets on some level. But just like the Mediawiki platform, most ticket tracking environments are either complete overkill or get a “please gouge my eyes out” rating on the difficulty scale. Quality Control gives you an extremely lightweight ticket tracking system, and you get to keep your sanity.

Classified Ads: Yellooh!

Yellooh! is one of a few different examples of using WordPress as classified ads board. It stands out for its low cost and nice design. Users are able to add new entries from a front-end form (saving the trouble of logging into the WordPress backend), Google Maps is tightly integrated, and it even features PayPal integration if you’re looking to charges users to post ads.

Customer Support: Instant Q&A

Instant Q&A provides an easy to use Q&A forum perfect for customer support.

Comment! (1)

How to Easily Hide Admin Panels in WordPress

Filed August 21st, 2010 under WordPress

The WordPress admin back end can be overwhelming. Combine a default installation with a handful of custom-post types and plugins, and you’ve got yourself 15 or 16 options panels – many of which an end user (i.e. a client) will never use.

It’s easy to forget that this sort of clutter confuses users. That’s why hiding some of these panels can often be a good idea. Luckily, there’s an easy to do that.

The CSS Technique

Every admin panel in the WordPress backend is identified as #menu-title in the HTML formatting. If we want to hide a particular administration panel that’s natively displayed for a particular user class, we just need to declare display:none; as a CSS attribute of the ID.

If we want to hide the Plugins panel from users, we simply add the following to functions.php:

<?php
add_action('admin_head', 'hide_menus');

function hide_menus() {
	global $current_user;
	get_currentuserinfo();

	If($current_user->user_login != 'admin') {
		?>
		<style>
		   #menu-plugins{
		        display:none;
		   }
		</style>
		<?php
	}
}
?>

Let’s break this down.

The function hide_menus queries the user info for the currently logged in user. If the user isn’t an administrator, then the content in the <style> attribute is embedded in the backend. In this case, display:none; is applied to #menu-plugins, and the Plugins panel is hidden from the user’s browser.

Changing which option panel is hidden, or hiding additional panels, is simply a case of modifying which #menu-title is defined in the <style> attribute.

This technique doesn’t disable or modify actual user permissions, but simply modifies the way browsers display the backend. It’s not a secure solution, but it’s not meant to be – it’s just a quick and dirty way of modifying the administrative UI for end users.

Plugin Alternatives

There are a number of plugins that reproduce the CSS technique, without the need to manually edit functions.php.

Hide Admin Panels enjoys fairly robust support for recent versions of WordPress, and is updated regularly.

Credits

Kudos to Brian Williams for his article and source code for this technique.

Comment! (2)

4 Ways to Create Page and Post Specific Sidebars in WordPress

Filed August 11th, 2010 under WordPress

One of the challenges with using WordPress as a CMS is the lack of truly robust sidebar control.

Sidebars can be widgetized, and template files can be assigned different sidebars (i.e. pages, posts, archives) – but assigning specific sidebars to individual pages and posts isn’t exactly painless.

Let’s say that I’m creating a WordPress-based site with three pages: About Us, Services and Contact – all of which are generated using page.php. On each page, I’d like to have a different (widgetized) sidebar. There are three basic ways to accomplish this.

Multiple template files

I could create three different page template files (i.e. about.php, services.php, and contact.php) and include three different sidebars. For example, in about.php I could include:

<?php include ('sidebar-about.php'); ?>

While in services.php I could include:

<?php include ('sidebar-services.php'); ?>

Then within each sidebar template file I could define a widgetized structure. This is fine with only a few separate pages requiring individual sidebars, but it quickly becomes an annoying task with a large site. Furthermore, if you’re developing a product for a client, it’s not exactly easy to use.

Custom values

This is a pretty clever approach, and definitely makes it easier to use. In your template files, you define get_sidebar based on custom post meta. This lets you associate particular posts and pages with various sidebars on the fly:

<?php $sidebar = get_post_meta($post->ID, "sidebar", true);
get_sidebar($sidebar);
?>

So now if I create a new page, I enter a custom field with a value of the name of the sidebar I wish to associate it with (i.e. “sidebar-about”).

But I’m still going to be limited if I’m dealing with a complex information structure. I’m going to have to create individual sidebar.php files for every sidebar I want to include on the site. Doing this is both messy and near impossible for non-technical end users.

Conditional awareness

I can use

<div id="sidebar">
if (is_home()) {
echo "<ul>";
wp_list_cats('children=0');
echo "</ul>
";
} elseif (is_category()) {
echo "<ul>";
wp_list_cats('children=1');
echo "</ul>
";
} elseif (is_single()) {
} elseif (is_page()) {
if (is_page('About')) {
echo "
This is my about page!
";
} elseif (is_page('Colophon')) {
echo "
This is my colophon page, running on WordPress " . bloginfo('version') . "
";
} else {
echo "
Vote for Pedro!
";
}
} else {
echo "
Pedro offers you his protection.
";
}
?&gt;
</div>

But wait…

You can define specific widgetized sidebars in each conditional statement, eliminating the need for separate page.php or single.php template files (i.e. about.php and services.php), but an end user will still have to register the sidebar in functions.php and in a conditional statement when creating a new page with a unique sidebar.

A better alternative!

Well, it’s better in a lot of ways at least. It’s called Core Sidebars. It’s a plugin written by Daniel from Nexterous LLC. Unfortunately, it doesn’t appear to be actively supported anymore – with the last update being from 2008. That said, I can confirm that it works with WordPress 3.0.1.

Basically, Core Sidebars enables you to give end users really robust control over widgetized sidebars. Users can create page or post specific sidebars on the fly simply by clicking “Add Widgets” in a column that’s added to the Page/Post list in WordPress. Core Sidebars registers and creates a widgetized sidebar specifically associated with the page/post on which it was created.

It’s pretty easy to set up too. After installing and activating the plugin, simply post the following wherever the sidebars are going to appear:

$sboptions = array(
     'order' => 'title-content-widgets',
     'before_title' => '',
     'after_title' => '',
     'before_content' => '',
     'after_content' => '');
coresidebar($sboptions);

Do you use a trick or technique I haven’t covered here? Let me know with a comment!

Comment! (0)

How to Remove the Category Base URL in WordPress

Filed July 13th, 2010 under WordPress

One of the difficulties with using WordPress as a CMS is that the out-of-the-box URL construction is limited. In this respect, categories have particularly poor control.

By default, WordPress constructs category URLs as http://domain/category/category-name and post URLs as http://domain/date/post-name. While you can control most aspects of the post URLs (whether or not to display the month of the post, for example), the only customization available for category URLs is the base name following the domain in which all categories reside (http://domain/series/category-name, for example).

But this can lead to counterintuitive URLs.

For example, if I file a post about about the Godather under a category called Film, the post URL will read http://domain/2010/01/01/the-godfather while the category URL will read http://domain/category/film. This might work well for a blog format, but for large-scale content management, intuitive URLs are a big deal.

Thankfully, we can get WordPress to do our bidding with a simple hack – and it even works with WordPress 3.0!

Let’s say I want to create post URLs in the form http://domain/category/post-name and category URLs in the form http://domain/category-name. Makes sense right? Well here’s how we do that.

Step One: Edit the Post Permalink

Open up WordPress administration panel, and navigate to the Permalinks options screen. Under Common settings, click Custom Structure and enter /%category%/%postname%/ into the field.

Step Two: Edit Functions.php

To edit the category URL structure we have to go into the functions.php file in our WordPress theme. Before the closing PHP bracket, enter the following:

add_filter('user_trailingslashit', 'remcat_function');
function remcat_function($link) {
	return str_replace("/category/", "/", $link);
}

add_action('init', 'remcat_flush_rules');
function remcat_flush_rules() {
	global $wp_rewrite;
	$wp_rewrite->flush_rules();
}

add_filter('generate_rewrite_rules', 'remcat_rewrite');
function remcat_rewrite($wp_rewrite) {
	$new_rules = array('(.+)/page/(.+)/?' => 'index.php?category_name='.$wp_rewrite->preg_index(1).'&paged='.$wp_rewrite->preg_index(2));
	$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}

Make sure to save functions.php and upload it to the theme directory.

Now, to go back to the Godfather example, category URLs will look like http://domain/film and post URLs will appear as http://domain/film/the-godfather. Cool eh?

There are other ways of doing this using .htaccess but this is a cleaner approach in that it modifies how WordPress generates URLs, instead of modifying how the server interprets them.

Comment! (6)

How To Make Timthumb Get Youtube and Vimeo Video Thumbnails, Add Default Thumbnail When No Images Are Present

Filed July 6th, 2010 under Tutorial, WordPress

One of our main portfolio pieces is a music blog called SalaciousSound that I started about 2 years back. I’ve been using timthumb on the site for about 6 months, though when I first added it I wasn’t able to grab thumbnails for videos, and it also didn’t handle posts without images well. I’ve added two pieces of functionality to the function that calls timthumb, catch_that_image(), which resides in my theme’s functions.php file. The former grabs thumbs from videos as the title describes, and the latter just adds a default image that I have defined if the function can not find an image or a video to get a thumbnail from.

function catch_that_image() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
$output = preg_match_all('//i', $post-&gt;post_content, $matches);
$first_img = $matches [1] [0];
if ( $first_img != '' ) {
return urlencode($first_img);
}
/*
$match = array();
preg_match("/http://www.youtube.com/v/([^"][a-zA-Z0-9-_]+)[&amp;"]/siU",$post-&gt;post_content,$match);
if ( $match[1] != '' ) {
return 'http://img.youtube.com/vi/'.$match[1].'/0.jpg';
}
$vimmatch = array();
preg_match('@vimeo.com/[^"&amp;d]*([^"&amp;]+)@i', $post-&gt;post_content, $vimmatch);
if ($vimmatch[1] != '') {
$vimhash = unserialize (file_get_contents ("http://vimeo.com/api/v2/video/".$vimmatch[1].".php"));
return $vimhash[0]['thumbnail_medium'];
}
*/
else { return 'http://url.com/wp-content/themes/themefolder/images/defaultimage.png'; }

}
Comment! (2)