Eventhough WordPress 2.3 hasn't yet been released to the general public at the moment I'm writing this, I'd like to do one or more posts on some of the new features that went into 2.3. Although tagging is propably the biggest new addition, everybody is already blogging about it, or will be. So I'll be concentrating one some smaller, but still very usefull new features.

In this post, that will be Importer Plugins. What are Importer Plugins? As most of you know, WordPress comes with a set of importers which can be used to import data from other formats/blogs into your blog. (Think DotClear, Blogger and many more) But there are many more systems out there which don't have importers that are build into WordPress. That's where plugins come in. A plugin can be used to extend the default WordPress behaviour and starting with 2.3 can also be used to add your own importer to WordPress.

So how do you create such a Importer Plugin? Let's build one step by step. We start with an empty plugin template. (For basic information on writing plugins I recommend reading the Codex Writing a Plugin article or this tutorial by Leonid Mamchenkov)

  1. <?php
  2. /*
  3. Plugin Name: Importer Plugin
  4. Version: 0.1
  5. Plugin URI: http://wordpress.nazgul.nu/
  6. Description: Example of an importer plugin.
  7. Author: Nazgul
  8. Author URI: http://nazgul.nu/
  9. */
  11. /* Copyright 2007 Nazgul
  13.   This program is free software; you can redistribute it and/or modify
  14.   it under the terms of the GNU General Public License as published by
  15.   the Free Software Foundation; either version 2 of the License, or
  16.   (at your option) any later version.
  18.   This program is distributed in the hope that it will be useful,
  19.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.   GNU General Public License for more details.
  23.   You should have received a copy of the GNU General Public License
  24.   along with this program; if not, write to the Free Software
  25.   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. ?>

So how do we turn this into an importer? We create a class which will do the importing for us. I based this class on the bundled importers, as they almost all use this form, but stripped out the fluff for now.

  1. // The importer
  2. class Test_Import {
  3. var $importer_code = 'importerplugin';
  4. var $importer_name = 'Importer Plugin';
  5. var $importer_desc = 'Import stuff';
  7. // Function that will handle the wizard-like behaviour
  8. function dispatch() {
  9. if (empty ($_GET['step']))
  10. $step = 0;
  11. else
  12. $step = (int) $_GET['step'];
  14. switch ($step) {
  15. case 0 :
  16. wp_import_upload_form('admin.php?import='.$this->importer_code.'&step=1');
  17. break;
  18. case 1 :
  19. check_admin_referer('import-upload');
  20. $this->import();
  21. break;
  22. }
  23. }
  25. // Function that does the actual importing
  26. function import() {
  27. $file = wp_import_handle_upload();
  28. if ( isset($file['error']) ) {
  29. echo '< p>Sorry, there has been an error.< /p>';
  30. echo '< p><strong>' . $file['error'] . '</strong>< /p>';
  31. return;
  32. }
  33. $this->file = $file['file'];
  34. $this->id = (int) $file['id'];
  36. // TODO: Write import code
  37. }
  39. // Default constructor
  40. function Test_Import() {
  41. // Nothing.
  42. }
  43. }

What we see is a class with a constructor which does nothing, 2 functions and a couple of variables. Let's start with those variables. importer_code is the name which WordPress will be using to identify the importer internally. importer_name is the human readable name which will be shown on the Importer screen end importer_desc is the description which is displayed on that same page.

The importers are wizards. That means they can have multiple screens during various stages of the import process. That's where our dispatch function comes in. It shows the different screens based on the step in the wizard where you currently are. Currently the first step (0) shows an upload form and the second step does some security checking and runs the actual import by means of the import function.

So now that we have an importer, how do we let WordPress know it exists? We register it using the register_importer function. That function is part of wp-admin/includes/import.php which isn't loaded by default, so we'll have to do that as well.

  1. // Instantiate and register the importer
  2. include_once(ABSPATH . 'wp-admin/includes/import.php');
  3. if(function_exists('register_importer')) {
  4. $test_import = new Test_Import();
  5. register_importer($test_import->importer_code, $test_import->importer_name,
  6. $test_import->importer_desc, array ($test_import, 'dispatch'));
  7. }

We use include_once and function_exists because we don't want to kill the blog if the inclusion fails for some reason. (It will on pre 2.3 version because the import.php was located elsewhere) Next we instantiate our importer and register it, passing in our plugin code, name, description and dispatch function. That's all there is to building an Importer Plugin. I admit that this plugin doesn't actually import anything, but I'll leave that up as an exercise for the reader. :)

One last thing I'd like to include is some sort of protection. As stated, this behaviour is new to 2.3 and this plugin therefore won't work on older versions. Let's make sure people who try this plugin on older versions can't accidentally activate this plugin.

  1. add_action('activate_'.plugin_basename(__FILE__), 'importerplugin_activate');
  3. function importerplugin_activate() {
  4. global $wp_db_version;
  6. // Deactivate on pre 2.3 blogs
  7. if($wp_db_version<6075) {
  8. $current = get_settings('active_plugins');
  9. array_splice($current, array_search( plugin_basename(__FILE__), $current), 1 );
  10. update_option('active_plugins', $current);
  11. do_action('deactivate_'.plugin_basename(__FILE__));
  12. }
  13. }

You can download the complete sourcecode for the plugin here.

That's it for now. Stay tuned for more posts about new 2.3 features.