Category Archives: WordPress

Posts relating to using or writing code for WordPress.

I’m back in the game baby!


Following the great news that we(my family) will be able to keep the broadband service i decided it’s about time i turn some of my personal plugins into plugins the community can benefit from.

Today i submitted two requests to host plugins on the WordPress.org repository. Two no frills plugins that allow some additional filtering on the administration page that lists your posts, pages or custom types.

PFF(Post Format Filter) will allow you to filter the post list based on post format and will operate with any post type that supports post formats.

PTF(Page Template Filter) will allow you to filter the page list based on page template, and again will operate with any post type that supports page templates.

Less sitting around, more production.. (ie. releasing code that’s useful to the community – after all, the community helped get me where i am today)..

As an aside, i pushed out a new update to the PUT plugin today…  again needing to wrap my head around SVN(amazing how quick you can forget things), which took me longer than writing the code updates(though in honesty i had already written most of the new code in advance).

Yours,

Mark “happy to still be here” Duncan … aka t31os

Advertisements

Tweaking WPSE CSS


Wanted to post an image of what i’m currently running on WPSE in terms of custom CSS.

Ave at ya!..

Warning:
Image is around 1.2mb, so might take some time for people on slower connections(a smaller, lower quality image wouldn’t do the designs any justice).

Conditional tags on init?


I was recently answering a question on WordPress StackExchange and the question of appropriate hooks came up when suggesting where to hook on your styles or scripts when you’re needing to check conditional tags, those such is_page(), is_category, and so on..

http://wordpress.stackexchange.com/questions/8260/loading-scripts-on-specific-pages/

It was my impression, that both wp_print_scripts and wp_print_styles were front facing page actions that occur at a time equivalent to their admin counterparts and a query was raised by Rarst whether this is an appropriate place for enqueues..

The codex also suggests init as appropriate for enqueues.

Warning: You can only use conditional query tags on or after the init action hook in WordPress. For themes, this means the conditional tag will never work properly if you are using it in the body of functions.php, i.e. outside of a function.

I decided to write a PHP class as an example to get the results of hooking onto different actions because i was sure init was too early.

	class conditional_tags_check {
		private $results = array();
		public function __construct() { 
			add_action( 'wp_head',            array( $this, 'conditional_check' ) );
			add_action( 'template_redirect',  array( $this, 'conditional_check' ) );
			add_action( 'wp_enqueue_scripts', array( $this, 'conditional_check' ) );
			add_action( 'wp_print_styles',    array( $this, 'conditional_check' ) );
			add_action( 'wp',                 array( $this, 'conditional_check' ) );
			add_action( 'init',               array( $this, 'conditional_check' ) );
			add_action( 'wp_print_scripts',   array( $this, 'conditional_check' ) );
			add_action( 'wp_footer',          array( $this, 'output' ) );
		}
		public function conditional_check() {
			$action = debug_backtrace();
			$action = $action[2]['args'][0];
			$this->results[] = "$action :" . ( is_page() ? 'yes' : 'no' );
		}
		public function output() {
			echo implode( "\n<br />", $this->results );
		}
	}
	$conditional_tags_check = new conditional_tags_check;

I’ve purposely put the add action calls into a random order so you can see the natural order of the actions appear in the results(naturally the action occuring first will be the first result, and so on..).

The results for me came out as.

init :no
wp :yes
template_redirect :yes
wp_enqueue_scripts :yes
wp_print_styles :yes
wp_print_scripts :yes
wp_head :yes 

Init is the only action that fails the test, and shows “no”, where as all others appear to run late enough to determine the request is for a page(i was of course viewing a page). The above conditional tag could be replaced by any other and replicated to show that under each condition init fires too early to determine the kind of request(page, category, tag, single, etc..).

For reference the actions shown above fire in this order.

  1. init
  2. wp
  3. template_redirect
  4. wp_print_styles
  5. wp_print_scripts
  6. wp_enqueue_scripts
  7. wp_head

Can anybody see any problems with the test code or disagree? Drop me a comment..

What is a Taxonomy and a Term?


Despite the words Taxonomy and Term being quite common, i’ve come to notice very few users know the difference between a Taxonomy and a Term.

Michael Fields made a very cool video using a metaphor to explain what Taxonomies and Terms are, for those of you still unclear on the differences or meaning please see the following video.

Category (Taxonomy)
– My Category One (Term)
– My Category Two (Term)

Post Tag (Taxonomy)
– My Tag One (Term)
– My Tag Two (Term)

Sorry to rant, i just had to get that off my chest..

WordPress plugin translation


Plugin translation has never for me seemed an easy task, i could never quite follow the mish mash of differing information around the web, and none of the guides available ever seemed to answer the specifics of what i needed to know about setting up a plugin for translation.

Well a couple of months have passed since i last put my head down and read up on the translation process, and fortunately for me the persistance in grasping the technique has paid off, i’ve managed (well i hope) to grasp the fundamental points of how to prepare a plugin for translation, and additionally how to run through a translation process.

Those of who would just prefer to see example code can skip straight to the plugin download.

NOTE: This is intended for code literate users, those of you who can already code but just need a quick run down on how to utilise the translation functionality inside a plugin.

Firstly your plugin will need to register a text domain for performing translation tasks, you can read more on that here. Of course the codex entry does leave a little to be desired, not really giving much in the way of an easy to follow example.

However, let’s just run by the parameters for load_plugin_textdomain very briefly.

1. $domain

This is basically the name for your text domain. You’ll have to reference this alot in your plugin, so it certainly helps to make it something easy to remember and quick to type. The name (or domain) declared here will also prefix all translation files used in your plugin, so do try to KISS.

2. $abs_rel_path

We will ignore this parameter because it’s no longer used as of WordPress 2.7, originally you would use this parameter to declare the path to the language files in your plugin, based on the WordPress ABSPATH. I will not be using this parameter for the example, so i’ll stop there.

3. $plugin_rel_path

I think the codex description sums up what this parameter does pretty well (not perfect though).

Relative path to WP_PLUGIN_DIR. This is the preferred argument to use. It takes precendence over $abs_rel_path

Ok, so now the description is out of the way, where should you place the call to load_plugin_textdomain?

As far as i know textdomains should be registered at the init stage, so depending on whether you want to translate front side, admin side or both, will depend where you hook the registration onto, but for the sake of this example i’ve hooked mine onto admin_init.

Inside the main function of my plugin class is a line like so.

				// The action hook
				add_action( 'admin_init' , array( &$this , 'register_plugin_settings' ) );

Various other pieces of code are present in the functions, so to keep this blog trim here’s the line inside the above referenced function that registers the textdomain.

				// How the text domain looks inside the register plugin settings function referenced above
				load_plugin_textdomain(
					$this->l10n_prefix,                        // Plugin text domain reference
					false,                                     // False - deprecated parameter
					basename( dirname( __FILE__ ) ) . '/lang'  // Path to translation files
				);

In the case of my example plugin(at the end of this post) i’ve used a variable to store the name of the textdomain, this means i don’t have to keep remembering the reference name, i simply type in the variable each time i want to make some text translatable.

More information and a very similar example of load_plugin_textdomain can be found here.

Here’s my text domain variable for reference.

			$this->l10n_prefix = 'translatable_demo';

Also note the third parameter used in the text domain registration, this sets where to look for the translation files, you can however (as the codex entry suggests), leave this blank and WordPress will assume they reside in the same folder as your plugin. Of course it’s good to keep things organised, i know i do(just a little), so i’ve opted to have the text domain reference a folder called “lang” (no quotes) inside my plugin’s folder.

Ok you’ve come this far, you’ve registered a text domain, what next?

Next you’ll need to start converting all the strings in your plugin you wish to make translatable, and this is probably the most easiest step in the whole process, and rather then repeat the guides and information already available i’ll simply point you here, and provide a very brief example below based on my example plugin.

Example strings:

$var1 = 'WordPress';
echo 'Hello world';

Translation ready: (remembering the text domain name)

$var1 = __( 'WordPress', 'translatable_demo' ); // __() return value
_e( 'Hello world', 'translatable_demo'); // _e() - echoed value

That’s it as far as making the plugin translation ready, honestly, what more did you expect?

Techinically there is nothing left to do on your part, the plugin can be translated, but a good practice for plugin developers (or so i hear) is to include a .POT file along with the plugin. In the most simple terms this is a base translation file, that will in essence be like any translation of your plugin, but not include a translation for each string, providing a .POT file just means a translator can pick up that file and get translating without having to run your plugin’s folder/files through a translation program (you save them a few minutes, but it’s really very easy, and the process is pretty much identical to that of the translator).

You can download the example plugin here or here(sorry couldn’t host it here, not allowed zips on WordPress.com blogs).
EDIT (02/07/13): New download link(hopefully this one won’t just random expire)

For those of you still interested in learning how to create a .POT file and developing language files read on, i’m going to run down the procedure i followed for creating a .POT file. I’m a windows user, so those of you on another OS, you’ll unfortunately have to look toward existing guides on how to translate. Anyone still with me, read on..

  1. Download and Install Poedit (it’s free).
  2. Open Poedit and click on New Catalog, under File.
  3. Fill in a name for the project, and choose the appropriate language you write in (not required but i tend to do it anyway).
  4. Click on the Paths tab at the top of the box.
  5. Click the second little icon, and put the directory location of your plugin in, for example “C:\Documents and Settings\USER\Desktop\MY_PLUGIN”
  6. Click on the Keywords tab at the top of the box.
  7. Click the second icon, and enter “__” (no quotes, and that’s two underscores).
  8. Click the second icon again, this time entering “_e”
  9. Now click the Ok button.
  10. A save dialog will appear, so enter a name for your POT file and change the extension to .pot
  11. Choose an appropriate place to save the file (you’ll probably want to choose to the language folder inside your plugin).
  12. Click Save.
  13. Various things will happen now and poedit will shows some boxes on the screen. Don’t do anything, this is what a translator will see when he or she is translatin your POT file. Just close the file, job done.

NOTE: It’s most likely a good idea to name your POT file with the same prefix the translation files will require. The prefix is the name you gave you text domain inside your plugin, ie. the first parameter.

Doing translations is the easy part, so i’m leaving that out of my blog for now, but if anyone finds this useful and would like to see an additional “How to make a translation file” or similar, then post a comment, let me know.

If you struggled to keep up with anything covered above, or you think anything above could do with refinement, again feel free to provide feedback, i’m not the world’s best blogger, and my mind can wander when writing, so critique is most definately welcome..

Improving the WordPress.org support forums


Things are really looking up right now, with WP 3.0, the MU merge, and now an improved WordPress.org website on the way, i can’t help but wonder what all you guys are hoping and praying for the new WordPress website to bring.

Jane recently posted here at the WordPress forums, to ask for feedback from the community on what we’d like to see changed or implemented on the WordPress website… quoting from the opening post by Jane..

I think we all know that as helpful as the support forums are in some ways, in other ways there’s much to be desired. As we will be doing some work on improving wordpress.org this summer, let’s hear your suggestions for how we can improve the support experience here on wordpress.org. Thanks!

Ref: http://wordpress.org/support/topic/405965

So i thought i’d open a poll and see if i can grab your attention for a few moments, you can vote and not even say anything, click as many options as you like, or add you own preference at the bottom.

Answers are based on the suggestions in the current forum thread linked above, and a few of my own (and i’ll happily add yours on request).

Go on… it’ll only take you a moment..

If you’d like to post any suggestions, either here or in the thread, i’ll be happy to add them to the poll.

For me, the thread tracking is the most crucial feature… but i’d be most interested to see how you guys (the WordPress community at large) feel about it, and what matters to you..

Until the next blog, that’s me out… 😉

Prevent front and posts page being the same


I’m sure those of you familiar with WordPress will be acustom to the two settings provided under Admin -> Settings -> Reading, known as the Front Page and the Posts Page. Whilst some users find their usage easy, and others find it somewhat confusing, these two settings have never been intended to share a page, in short both should never be set to the same.

The following simple jQuery based plugin will prevent a user from applying the same page to these settings. This could be useful for those of you providing clients with WordPress sites that do not understand such features and attempt to configure these both to the same page.

<?php
/*
Plugin Name: Prevent front and posts page being the same.
Description: Prevents the posts page and front page settings be set to the same page.
*/
add_action( 'admin_head-options-reading.php' , 'postspage_frontpage_not_same' );
function postspage_frontpage_not_same() {
	?>
	<script type="text/javascript">
	//<![CDATA[
	jQuery(document).ready(function($) {		
		// Get the current selected values
		var wp_frontpage = $('#page_on_front option:selected').val();
		var wp_postspage = $('#page_for_posts option:selected').val();
		if( wp_postspage != '' ) {
			$('#page_on_front').find('option[value=' + wp_postspage + ']').attr("disabled","disabled");
		}
		if( wp_frontpage != '' ) {
			$('#page_for_posts').find('option[value=' + wp_frontpage + ']').attr("disabled","disabled");
		}
		// Attach a change function to the front page dropdown
		$('#page_on_front').change(function() {
				// Re-declare the variable for use inside the scope of the function
				var wp_frontpage = $('#page_on_front option:selected').val();
				if( wp_frontpage != '' ) {
					// Find a matching option in posts page dropdown
					$('#page_for_posts').find('option[value=' + wp_frontpage + ']').attr("disabled","disabled");
				}	
				$('#page_for_posts').find('option[value!=' + wp_frontpage + ']:disabled').removeAttr('disabled');
		});
		// Attach a change function to the posts page dropdown
		$('#page_for_posts').change(function() {
				// Re-declare the variable for use inside the scope of the function
				var wp_postspage = $('#page_for_posts option:selected').val();
				if( wp_postspage != '' ) {
					// Find a matching option in the front page dropdown
					$('#page_on_front').find('option[value=' + wp_postspage + ']').attr("disabled","disabled");
				}
				$('#page_on_front').find('option[value!=' + wp_postspage + ']:disabled').removeAttr('disabled');
		});
	});
	//]]>
	</script>
	<?php
}

As always feel free to post a comment, or if you have any suggestions regarding the code, please do share them.