How to Use the WordPress HTTP API

How to Use the WordPress HTTP API

WordPress provides a way for developers to fetch other web pages. It’s called the HTTP API. If you’re using things like file_get_contents or some other PHP functions in your WordPress theme or plugin, you’re doing it wrong.

HTTP API Applications

You could use the HTTP API to…

  • Interact with other APIs (facebook, twitter, etc)
  • To screen scrape other sites or create some sort of aggregation site
  • Create your own plugin repository

There are a lot of potential uses, but this tutorial will focus the first. We’ll create a shortcode that displays the number of likes a given Facebook page has.

Step 1: Registering the Shortcode

First we need to register the shortcode. This is done via the add_shortcode function. It takes too arguments: first, the name of the shortcode (the stuff between the square brackets) and a the call back function that displays the shortcode.

// Hook in after wordpress has started so the add_shortcode function is available
add_action( 'init', 'cdhttp_register_shortcode' );
function cdhttp_register_shortcode()
{
	add_shortcode( 'fbcount', 'cdhttp_fbcount' );
}

Step 2: Displaying the Shortcode

Next we need to create a function with the same name as the second argument of add_shortcode call. This function gets passed up to three arguments, but we only need the first: the attributes passed into the shortcode. If we had this, [fbcount page="classicalguitarblog"], then page="classicalguitarblog" would be the attribute.

function cdhttp_fbcount( $atts )
{
	extract(
		shortcode_atts(
			array(
				'page'	=> 'classicalguitarblog'
			),
			$atts
		)
	);
	// Make sure the $page attribute is clean
	$page = esc_attr( strip_tags( $page ) );
}

shortcode_atts compairs an array of defaults and the actual atts passed into the shortcode. If any of the passed in attributes are not in the default array, they are removed. In other words, in the shortcode [fbcount page="classicalguitarblog" x="1213"], x=”1213″ would be removed by shortcode_atts because x is not a valid attribute (its not in the array of defaults).

If a user fails to specify one of the attributes, it will be replaced by the defaults.

Step 3: Actually using the HTTP API

Alright, with the housekeeping and shortcode creating out of the way, we can add some more stuff to our function that actually displays the Facebook count.

First we build a URL to pass into the http api function wp_remote_get. For this, we’ll use the facebook graph api. Since WordPress doesn’t handle https:// urls, we have to use the non-secure version of the graph api URL.

$url = 'http://graph.facebook.com/' . $page;

Now onto opening the page. We’ll use a function called wp_remote_get which, as the name implies, fetches the url passed in as its argument via a standard get request. wp_remote_get returns an associative array with the headers, response body, response codes and messages, and the cookies.

$response = wp_remote_get( $url );

By far the coolest part about the HTTP api is that if the GET request fails in some way, WordPress will return a WP_Error. Which means you can check for that via is_wp_error, and bail if something goes wrong. While we’re at it, we’ll also check to make sure the response was a 200 status code and the site loaded correctly.

if( is_wp_error( $response ) || $response['response']['code'] != 200 ) return;

So far, our shortcode function looks like this:

function cdhttp_fbcount( $atts )
{
	extract(
		shortcode_atts(
			array(
				'page'	=> 'classicalguitarblog'
			),
			$atts
		)
	);

	$page = esc_attr( strip_tags( $page ) );

	// Frist we construct a url for our wp_remote_get
	$url = 'http://graph.facebook.com/' . $page;

	// Fetch the page with wp_remote_get
	$response = wp_remote_get( $url );

	// Bail if wp_remote_get fails or the response code is anything but 200
	if( is_wp_error( $response ) || $response['response']['code'] != 200 ) return;

When using shortcodes, your callback function does not echo anything out. Instead you have to return the values you wish to display. The Facebook Graph API returns a JSON, found at $response['body']; we’ll use the json_decode PHP function to interpret it. Then we’ll return the number of likes wrapped in a paragraph tag.

// Facebook returns a JSON, so let's decode it. the body of the page is in $response['body']
$body = json_decode( $response['body'] );

// Return out value!
return '<p class="fb-count">' . $body->likes . ' Fans</p>';

Finally, our entire shortcode callback function:

function cdhttp_fbcount( $atts )
{
	extract(
		shortcode_atts(
			array(
				'page'	=> 'classicalguitarblog'
			),
			$atts
		)
	);

	$page = esc_attr( strip_tags( $page ) );

	// Frist we construct a url for our wp_remote_get
	$url = 'http://graph.facebook.com/' . $page;

	// Fetch the page with wp_remote_get
	$response = wp_remote_get( $url );

	// Bail if wp_remote_get fails or the response code is anything but 200
	if( is_wp_error( $response ) || $response['response']['code'] != 200 ) return;

	// Facebook returns a JSON, so let's decode it. the body of the page is in $response['body']
	$body = json_decode( $response['body'] );

	// Return out value!
	return '<p class="fb-count">' . $body->likes . ' Fans</p>';
}

Wrap Up

You can download this code in the form of a plugin here. The HTTP API is much more than the simple example here. You can do just about anything with it: change the headers you send, make POST requests, use other functions that only retrieve the response body or headers, and more.

The bottom line: if your WordPress site or plugin is requesting data from an external URL without using the HTTP API, you’re doing it wrong.

WordPress HTTP API Example

How to Use the WordPress HTTP API

Excluding Single Posts From Your WordPress Blog Index

There are a lot of really nice plugins for excluding entire categories from the hope page. I use simply exclude and it works great. A few extra characters in your query arguments also accomplishes the same thing.

Excluding a single post, however, is more difficult. You could use the post__not_in wp query argument, but that’s not extremely flexible. What about excluding posts on the fly: you write a post and don’t want it showing up on the home page. Or you’re buying content and you don’t want to put all that on the home page either.

The Solution

First off, we need to add a meta box to our post screens. Just a little box for the user to check if they don’t want the post showing up on the home page.

<?php
add_action( 'admin_init', 'meta_box' );
function meta_box()
{
     add_meta_box( 'my-metabox-id', 'My Metabox Title', 'my_meta_box_cb', 'post', 'side', 'low' );
}
?>

You can read more about add_meta_box here. The first argument is the html ID attribute of the metabox itself (handy for styling), the second is the title, and the third is a call back function: the thing that actual displays the box. post tells the function we want to put this meta box on the post editing page, while side puts the box off to the side (not below the content editor) and low tells wordpress to put the box last.

Also notice we didn’t call add_meta_box directly: we hooked it into the admin_init action hook.

Now lets build the metabox call back function.

<?php
function my_meta_box_cb()
{
      global $post;
      $on = get_post_meta( $post->ID, 'my_meta_exclude', true);
      ?>
      <input type="hidden" name="my_meta_nonce" value="<?php echo wp_create_nonce( 'my_meta_nonce' ); ?>" />
      <input type="checkbox"> name="my_meta_exclude" id="my_meta_exclude" <?php checked( $on, 'yes' ); ?> />
      <label for="my_meta_exclude">Check to Exlcude this Post</label>
      <?php
}
?>

First, we include a nonce to use for validating the data later on. Next is just a standard input and label html elements. We don’t need to include form tags or a submit button because that’s taken care of by the post screen itself.

Which brings us to the hard part: actually saving the data. Fortunately wordpress gives us the save_post hook to use.

<?php
add_action( 'save_post', 'my_meta_save' );
function my_meta_save( $post_id )
{
     // if our nonce isn't verified or the current user can't edit this post get out of here
     if( !wp_verify_nonce( $_POST['my_meta_nonce'], 'my_meta_nonce' ) || !current_user_can( 'edit_posts' ) ) return;

     // if our value is set (the box is checked), set our value to 'yes' otherwise, set it to 'no'
     $value = isset( $_POST['my_meta_exclude'] ) ? 'yes' : 'no';

     // Save our value to the wp_postmeta table with the meta key my_meta_exclude
     update_post_meta( $post_id, 'my_meta_exclude', $value );
}
?>

Changing the Loop

Now that each post getting saved has this meta value, we can test for it on the front end. So find the loop:

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

Now we’re to add a small if statement after the while loop starts…

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

// Check to see if our post has a my_meta_exclude value of yes, and jump to the next post if it does.
if( get_post_meta( $post->ID, 'my_meta_exclude', true ) == 'yes' ) continue;
?>

That’s it! The downside is this method could really screw up your pagination/posts per page.

The complete admin code. You could put this in one file or class and only include if the admin area is loaded (via is_admin() ).

<?php
add_action( 'admin_init', 'meta_box' );
function meta_box()
{
     add_meta_box( 'my-metabox-id', 'My Metabox Title', 'my_meta_box_cb', 'post', 'side', 'low' );
}

function my_meta_box_cb()
{
      global $post;
      $on = get_post_meta( $post->ID, 'my_meta_exclude', true);
      ?>
      <input type="hidden" name="my_meta_nonce" value="<?php echo wp_create_nonce( 'my_meta_nonce' ); ?>" />
      <input type="checkbox"> name="my_meta_exclude" id="my_meta_exclude" <?php checked( $on, 'yes' ); ?> />
      <label for="my_meta_exclude">Check to Exlcude this Post</label>
      <?php
}

add_action( 'save_post', 'my_meta_save' );
function my_meta_save( $post_id )
{
     // if our nonce isn't verified or the current user can't edit this post get out of here
     if( !wp_verify_nonce( $_POST['my_meta_nonce'], 'my_meta_nonce' ) || !current_user_can( 'edit_posts' ) ) return;

     // if our POST data for our meta box is set (the box is checked), set our value to 'yes' otherwise, set it to 'no'
     $value = isset( $_POST['my_meta_exclude'] ) ? 'yes' : 'no';

     // Save our value to the wp_postmeta table with the meta key my_meta_exclude
     update_post_meta( $post_id, 'my_meta_exclude', $value );
}
?>

Python Script for Checking Links

Sometimes there are links to your website that you want to check on every now and again. You could do this manually or you could use a little program to do it for you.

I wrote something in Python to do this. It’s probably not at all good (I’m new to python), but here it is. The code is commented, so you should be able to see what’s going on. First it grabs a list of urls from a file you define in an argument variable. Then it runs through each url, first checking for status code, whether the link is found, whether is nofollowed, and the fetches the anchor text. Mostly it’s a lot of string manipulation that’s probably easier accomplished with something like Scrapy. But, as I mentioned, I’m new to this, and it was fun.

Grab the Script – You’ll have to change the filename to .py

Usage

I use a mac. Windows and Linux people, you’re on your own.

  1. Create a .txt file and put in the urls you’d like to check for a given link. There should be one URL per line. Put this file in the same directory as urls.py
  2. Open the url.py and set the url_to_find variable to the url you’d like to find. This is right at the top.
  3. Open up terminal and navigate to the directory where you put the urls.py file.
  4. Enter this: python urls.py your_url_list.txt. your_url_list.txt is the file you created in step one.

Issues

Because the anchor text thing is really just string manipulation, if there’s any html or commas or tabs within that anchor text (the contents of <a> and </a>) it will show up in your output file.

Output

The script creates a file called link_results_YYYY-MM-DD.txt. Where YYYY-MM-DD is replaced with the current date in ISO standard format. You should be able to open this file with excel or some other spreadsheet program.

Help me out!

I’d love to hear some feedback from Python savvy people!

Updating Custom Fields for All WordPress Posts

The situation: a client moves to a new theme. Their old wordpress theme used custom fields to create thumbnails.

As of WordPress 2.9, support for post thumbnails is built in, but many themes still create nice, pretty custom field write panels in the add/edit post areas. The result is still that thumbnail urls get stored in custom fields, which are then stored in the wp_postmeta table in the database.

Basically what I needed to do was get the contents of every custom field with the key thumb_img and move it to the custom field with the key image. In other words, I had all the thumbnails I needed, but they were stored with the wrong custom field key.

So I wrote a plugin:

function update_image_meta() {
    $allposts = get_posts('numberposts=-1&post_type=post&post_status=any');
    foreach ($allposts as $postinfo) {
        $image_url = get_post_meta($postinfo->ID, 'thumb_img', true);
        update_post_meta($postinfo->ID,'image', $image_url);
     }
}

The $allposts variable stores all wordpress posts (numberpost=-1 accomplishes this) within an array that we then step through with the foreach ($allposts as $postinfo).

So for each post we store the contents of the thumb_img custom field, fetched with get post meta, in the $image_url variable.

Then we do an update post meta on the image custom field, insert the value stored in $image_url.

Next step is initiating the function:

add_action('save_post', 'update_image_meta');

Then you just go in a save a post. All the custom fields are updated, and you’re done.

The Full Plugin

<?php
/*
Plugin Name: Update Images in Posts
Plugin URI: http://www.christopherguitar.net
Description: Updates custom fields
Author: Christopher Davis
Author URI: http://www.christopherguitar.net
*/
add_action('save_post', 'update_image_meta');

function update_image_meta() {
	$allposts = get_posts('numberposts=-1&post_type=post&post_status=any');
	foreach ($allposts as $postinfo) {
		$image_url = get_post_meta($postinfo->ID, 'thumb_img', true);
		update_post_meta($postinfo->ID,'image', $image_url);
	}
}

?>

This is probably not the best solution, and if you’re MySQL savvy, you should probably do it that way.

Classical Guitar Concert in Quincy, Illinois – April 7, 2011

Playing at Quincy College.

Concert starts with the Quincy University Guitar Ensemble at 7:30pm. I’ll follow them. There’s also a masterclass during the afternoon before the concert

Classical Guitar Concert in Macomb, Illinois – April 10, 2011

This is part of the Western Illinois Guitar Festival. I’ll be performing along with Tom Clippert, Brad DeRoche, Guilherme Vincens and Virginia Broffett.

Concert starts at 7:30pm in COFAC, Western Illinois University‘s concert hall.

Classical Music: A Positional Good

“Positional goods are products and services whose value is mostly (if not exclusively) a function of their ranking in desirability by others, in comparison to substitutes. The extent to which a good’s value depends on such a ranking is referred to as its positionality.”
(source: wikipedia)

Let’s talk about what art music really is to almost everyone who listens to or plays it: art music a positional good. It’s a way for the listeners to be different. Not everyone can listen to classical music and understand it. And being able to do just that is a way to be different from the unwashed masses.

Those people who don’t like it? Well, they just don’t get it. They’re not “enlightened”.

Do You Really Want a Bigger Audience?

That’s why I find it interesting when people talk about growing the audience for classical music or fine art. Yes, it does need to be done, but the same people who are working to do it don’t want a bigger audience.

More people in the in crowd? That would make the value of their ability to enjoy/understand art music less valuable.

Manipulate the Crowd

And of course, if you run an arts organization, you can use this sort of thinking to your advantage. You can make the rebel sell to convince people that your organization or group is worth more.

Indie musicians do this all the time. It’s massively popular right now to release recordings on limited edition vinyl or some sort of exclusive package. These things are more expensive, and only made available in limited in quantities. In other words, not just anyone can have one. Since an indie musician’s audience is most likely already small — being a fan of so-and-so is already a positional good, in other words — buying the limited edition run is an extra way to set yourself apart as a fan and person.

Is it Right?

Who knows. My point with this little article was not to pass judgement, just to make you aware of some things.

A Few Fernando Sor Etudes

Fernando Sor: Opus 60, Number 5

http://www.christopherguitar.net/audio/sor-number5.mp3

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Fernando Sor: Opus 60, Number 13

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

A few quick recordings I did tonight. I’ve been teaching opus 60 a lot these past few months. Great little pieces with a lot of depth and plenty of musical stuff to work on.

Photo: Masterclass with Laura Young

Laura was in town for the Guitar Fort Worth concert series.

Analysis Project: Mouton – “Corde et animo”

Many people suggest that analysis is basically accounting for all the notes on the page. That is, fitting those notes into the abstract structures defined by harmony or melodic devices or motivic development. The next step — the one that gets skipped — is figuring out what the composer meant by the stuff on the page.

This is really easy to do when there’s text. Why? Because the poem literally tells you what the song (or in this case, Motet) is about. It’s just a matter of looking at the music and see how the composer uses the musical elements imply things.

I often take the approach of looking for something interesting. So when I find it, I examine that section and focus on it. In the piece above, the section 1:48 – 2:24 is very interesting to me. Below is a bit of what I wrote about the piece.

Here Mouton repeats a three measure musical idea three times: each voice repeats the same three measures three times. In addition, the cantus imitates the soprano for the measures, and, again, the closely spaced imitation dissolves to homophony by the end of the third measure.

The text at this point translates as, “With peaceful joy let us celebrate the Nativity of Blessed Mary.” Two important things stand out in the text/music relationship. First, the portion where the narrator discusses peace and joy is set to the repeating fragment. And indeed, the musical effect of this section is strikingly peaceful — the contrapuntal drive heard in the previous sections is lost and the section seems to be in stasis. Second, on the celebremus (celebrate) Mouton abandons three-measure fragment creating a sort of musical celebration. Here the forward momentum returns, driving to the first cadence in all voices without textual overlap in measure 67.