Using Traits In PHP 5.4

I just read a great article by Shameer C. about traits in PHP 5.4. I’m really looking forward to using this functionality. Basically you can create things called traits, modules if you will, that you can then include into classes that you are writing.

For example if you need to deal with the filesystem, you could load in a filesystem trait that provides you with pre-written functionality. Or if you needed to make remote requests, you could load in a HTTP trait. Classes can only extend a single other class but you can use as many traits as you want.

This will be so useful!

Thanks Mo for sending me the link!

Changing Core WordPress Strings

One of the lesser known filters in WordPress is gettext. All strings that are run through the WordPress translation functions are also run through this filter after being translated thanks to a ticket I opened way back in 2008. That means you can actually use it to change pretty much any string in WordPress, namely in the admin area.

I’ve used this in some plugins I’ve written in the past and it works incredibly well.

My co-worker and one of the lead developers of WordPress Peter Westwood (westi) wrote a really good blog post about this, however I wasn’t completely happy with his code so I’m writing this blog post to share how I would write some code to take advantage of this versatile filter. Don’t get me wrong — he wrote good and valid code, but it’s not exactly the easiest thing for a novice to extend for their own uses.

function youruniqueprefix_filter_gettext( $translated, $original, $domain ) {

	// This is an array of original strings
	// and what they should be replaced with
	$strings = array(
		'View all posts filed under %s' => 'See all articles filed under %s',
		'Howdy, %1$s' => 'Greetings, %1$s!',
		// Add some more strings here
	);

	// See if the current string is in the $strings array
	// If so, replace it's translation
	if ( isset( $strings[$original] ) ) {
		// This accomplishes the same thing as __()
		// but without running it through the filter again
		$translations = &get_translations_for_domain( $domain );
		$translated = $translations->translate( $strings[$original] );
	}

	return $translated;
}

add_filter( 'gettext', 'youruniqueprefix_filter_gettext', 10, 3 );

So as you can see at it’s core it accomplishes the same thing as Peter’s code however my code should be a bit more clear on how to make it translate multiple strings.

Hope someone finds this helpful! 🙂

Easily Create XML In PHP Using A Data Array

I’ve been working with the Google Contacts API lately and needed to construct some XML as a part of that. PHP’s DOMDocument works really great for this, but it can get complicated fast as you need to create lots of variables for all of your elements, children, etc. It can make it quite hard to do dynamically.

An easier method would be to just convert an array into XML, the opposite of simplexml_load_string() if you will. So I wrote some code that does exactly that and I thought I’d share it incase anyone else would find it helpful. 🙂

Start by creating your array of data. I used a numeric array instead of an associative array because you can have duplicate elements in XML while you cannot have duplicate array keys.

$data = array(
	'name' => 'toplevelelement', // "name" required, all else optional
	'attributes' => array(
		'foo' => 'bar',
		'fruit' => 'apple',
	),
	'value' => 'Some random value.',
	array(
		'name' => 'achildelement',
		'value'=> 'Value',
	),
	array(
		'name' => 'anotherchildelement',
		'attributes' => array(
			'some' => 'attr',
		),
		array(
			'name' => 'grandchildelement',
		),
	),
);

An array such as that is easy to dynamically create based on your source data, it’s easy to read, and can be fairly easily manipulated.

name is the only required item of each array and it’s the tag name of the element. attributes is an array of attributes for the element and value is the value. Both of these are optional. Any children arrays are children elements and their structures should be the same.

Now here’s the code I wrote that converts the above array into some XML:

function generate_xml_element( $dom, $data ) {
	if ( empty( $data['name'] ) )
		return false;

	// Create the element
	$element_value = ( ! empty( $data['value'] ) ) ? $data['value'] : null;
	$element = $dom->createElement( $data['name'], $element_value );

	// Add any attributes
	if ( ! empty( $data['attributes'] ) && is_array( $data['attributes'] ) ) {
		foreach ( $data['attributes'] as $attribute_key => $attribute_value ) {
			$element->setAttribute( $attribute_key, $attribute_value );
		}
	}

	// Any other items in the data array should be child elements
	foreach ( $data as $data_key => $child_data ) {
		if ( ! is_numeric( $data_key ) )
			continue;

		$child = generate_xml_element( $dom, $child_data );
		if ( $child )
			$element->appendChild( $child );
	}

	return $element;
}

$doc = new DOMDocument();
$child = generate_xml_element( $doc, $data );
if ( $child )
	$doc->appendChild( $child );
$doc->formatOutput = true; // Add whitespace to make easier to read XML
$xml = $doc->saveXML();

You first create a blank canvas by creating a new instance of the DOMDocument class and then you pass the class instance (needed for creating elements in the correct character set and such) and the data array to the generate_xml_element() function. This function will create the top level element and then recursively call itself on any child elements until it’s gone through the whole array.

Once it’s done, you’ll need to append the element to the DOM using the inherited appendChild() function. Then calling saveXML will give you the XML output. The above example data array will give you something like this (maybe or maybe not nicely formatted with whitespace depending on what mood DOMDocument is in):

<?xml version="1.0"?>
<toplevelelement foo="bar" fruit="apple">
	Some random value.
	<achildelement>Value</achildelement>
	<anotherchildelement some="attr">
		<grandchildelement></grandchildelement>
	</anotherchildelement>
</toplevelelement>

And there you have it!

WordPress: Using Filters With get_posts()

Something I just learned and thought I’d share to save others the trouble: if you’re attempting to filter the results of get_posts(), for example with the posts_where filter, you need to disable suppress_filters.

For example, here’s how to fetch some posts from within the past 30 days (based on an example from the Codex):

<?php

function last_thirty_days( $where = '' ) {
	global $wpdb;

	$where .= $wpdb->prepare( " AND post_date > %s", date( 'Y-m-d', strtotime('-30 days') ) );

	return $where;
}

add_filter( 'posts_where', 'last_thirty_days' );

$some_posts = get_posts( array( 'suppress_filters' => false ) );

// Important to avoid modifying other queries
remove_filter( 'posts_where', 'last_thirty_days' );

?>