From mboxrd@z Thu Jan 1 00:00:00 1970
Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org)
by finch.gentoo.org with esmtp (Exim 4.60)
(envelope-from )
id 1PxSpp-0005up-IN
for garchives@archives.gentoo.org; Wed, 09 Mar 2011 23:30:33 +0000
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
by pigeon.gentoo.org (Postfix) with SMTP id DB0321C029;
Wed, 9 Mar 2011 23:30:21 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
by pigeon.gentoo.org (Postfix) with ESMTP id 59F441C029
for ; Wed, 9 Mar 2011 23:30:21 +0000 (UTC)
Received: from pelican.gentoo.org (unknown [66.219.59.40])
(using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits))
(No client certificate requested)
by smtp.gentoo.org (Postfix) with ESMTPS id 713551B40DE
for ; Wed, 9 Mar 2011 23:30:20 +0000 (UTC)
Received: from localhost.localdomain (localhost [127.0.0.1])
by pelican.gentoo.org (Postfix) with ESMTP id AC8E88006A
for ; Wed, 9 Mar 2011 23:30:19 +0000 (UTC)
From: "Theo Chatzimichos"
To: gentoo-commits@lists.gentoo.org
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Theo Chatzimichos"
Message-ID: <3ed191998d4c870d0a39fbe96ecf0b4eba4dc396.tampakrap@gentoo>
Subject: [gentoo-commits] proj/blogs-gentoo:master commit in: plugins/wordpress-importer/, plugins/wordpress-importer/languages/
X-VCS-Repository: proj/blogs-gentoo
X-VCS-Files: plugins/wordpress-importer/languages/wordpress-importer.pot plugins/wordpress-importer/parsers.php plugins/wordpress-importer/readme.txt plugins/wordpress-importer/wordpress-importer.php
X-VCS-Directories: plugins/wordpress-importer/ plugins/wordpress-importer/languages/
X-VCS-Committer: tampakrap
X-VCS-Committer-Name: Theo Chatzimichos
X-VCS-Revision: 3ed191998d4c870d0a39fbe96ecf0b4eba4dc396
Date: Wed, 9 Mar 2011 23:30:19 +0000 (UTC)
Precedence: bulk
List-Post:
List-Help:
List-Unsubscribe:
List-Subscribe:
List-Id: Gentoo Linux mail
X-BeenThere: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: quoted-printable
X-Archives-Salt:
X-Archives-Hash: a6cae9292f854fd05ef4b94b1ca10d46
commit: 3ed191998d4c870d0a39fbe96ecf0b4eba4dc396
Author: Theo Chatzimichos gentoo org>
AuthorDate: Wed Mar 9 23:30:01 2011 +0000
Commit: Theo Chatzimichos gentoo org>
CommitDate: Wed Mar 9 23:30:01 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/blogs-gentoo.=
git;a=3Dcommit;h=3D3ed19199
Add wordpress importer
---
.../languages/wordpress-importer.pot | 231 +++++
plugins/wordpress-importer/parsers.php | 601 +++++++++++
plugins/wordpress-importer/readme.txt | 41 +
plugins/wordpress-importer/wordpress-importer.php | 1060 ++++++++++++++=
++++++
4 files changed, 1933 insertions(+), 0 deletions(-)
diff --git a/plugins/wordpress-importer/languages/wordpress-importer.pot =
b/plugins/wordpress-importer/languages/wordpress-importer.pot
new file mode 100644
index 0000000..8dae6cf
--- /dev/null
+++ b/plugins/wordpress-importer/languages/wordpress-importer.pot
@@ -0,0 +1,231 @@
+# Copyright (C) 2011 WordPress Importer
+# This file is distributed under the same license as the WordPress Impor=
ter package.
+msgid ""
+msgstr ""
+"Project-Id-Version: WordPress Importer 0.3\n"
+"Report-Msgid-Bugs-To: http://wordpress.org/tag/wordpress-importer\n"
+"POT-Creation-Date: 2011-02-21 21:07:12+00:00\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=3DUTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2010-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+
+#: parsers.php:42 parsers.php:63
+msgid "There was an error when reading this WXR file"
+msgstr ""
+
+#: parsers.php:43
+msgid ""
+"Details are shown above. The importer will now try again with a differe=
nt "
+"parser..."
+msgstr ""
+
+#: parsers.php:67 parsers.php:72 parsers.php:248 parsers.php:430
+msgid ""
+"This does not appear to be a WXR file, missing/invalid WXR version numb=
er"
+msgstr ""
+
+#: wordpress-importer.php:133 wordpress-importer.php:142
+#: wordpress-importer.php:193 wordpress-importer.php:201
+msgid "Sorry, there has been an error."
+msgstr ""
+
+#: wordpress-importer.php:134
+msgid "The file does not exist, please try again."
+msgstr ""
+
+#: wordpress-importer.php:177
+msgid "All done."
+msgstr ""
+
+#: wordpress-importer.php:177
+msgid "Have fun!"
+msgstr ""
+
+#: wordpress-importer.php:178
+msgid "Remember to update the passwords and roles of imported users."
+msgstr ""
+
+#: wordpress-importer.php:209
+msgid ""
+"This WXR file (version %s) may not be supported by this version of the =
"
+"importer. Please consider updating."
+msgstr ""
+
+#: wordpress-importer.php:234
+msgid ""
+"Failed to import author %s. Their posts will be attributed to the curre=
nt "
+"user."
+msgstr ""
+
+#: wordpress-importer.php:260
+msgid "Assign Authors"
+msgstr ""
+
+#: wordpress-importer.php:261
+msgid ""
+"To make it easier for you to edit and save the imported content, you ma=
y "
+"want to reassign the author of the imported item to an existing user of=
this "
+"site. For example, you may want to import all the entries as admi=
n"
+"code>s entries."
+msgstr ""
+
+#: wordpress-importer.php:263
+msgid ""
+"If a new user is created by WordPress, a new password will be randomly =
"
+"generated and the new user’s role will be set as %s. Manually cha=
nging "
+"the new user’s details will be necessary."
+msgstr ""
+
+#: wordpress-importer.php:273
+msgid "Import Attachments"
+msgstr ""
+
+#: wordpress-importer.php:276
+msgid "Download and import file attachments"
+msgstr ""
+
+#: wordpress-importer.php:280
+msgid "Submit"
+msgstr ""
+
+#: wordpress-importer.php:293
+msgid "Import author:"
+msgstr ""
+
+#: wordpress-importer.php:304
+msgid "or create new user with login name:"
+msgstr ""
+
+#: wordpress-importer.php:307
+msgid "as a new user:"
+msgstr ""
+
+#: wordpress-importer.php:315
+msgid "assign posts to an existing user:"
+msgstr ""
+
+#: wordpress-importer.php:317
+msgid "or assign posts to an existing user:"
+msgstr ""
+
+#: wordpress-importer.php:318
+msgid "- Select -"
+msgstr ""
+
+#: wordpress-importer.php:366
+msgid ""
+"Failed to create new user for %s. Their posts will be attributed to the=
"
+"current user."
+msgstr ""
+
+#: wordpress-importer.php:413
+msgid "Failed to import category %s"
+msgstr ""
+
+#: wordpress-importer.php:449
+msgid "Failed to import post tag %s"
+msgstr ""
+
+#: wordpress-importer.php:491 wordpress-importer.php:603
+msgid "Failed to import %s %s"
+msgstr ""
+
+#: wordpress-importer.php:513
+msgid "Failed to import “%s”: Invalid post type %s"
+msgstr ""
+
+#: wordpress-importer.php:534
+msgid "%s “%s” already exists."
+msgstr ""
+
+#: wordpress-importer.php:575
+msgid "Failed to import %s “%s”"
+msgstr ""
+
+#: wordpress-importer.php:712
+msgid "Menu item skipped due to missing menu slug"
+msgstr ""
+
+#: wordpress-importer.php:719
+msgid "Menu item skipped due to invalid menu slug: %s"
+msgstr ""
+
+#: wordpress-importer.php:782
+msgid "Fetching attachments is not enabled"
+msgstr ""
+
+#: wordpress-importer.php:795
+msgid "Invalid file type"
+msgstr ""
+
+#: wordpress-importer.php:838
+msgid "Remote server did not respond"
+msgstr ""
+
+#: wordpress-importer.php:844
+msgid "Remote server returned error response %1$d %2$s"
+msgstr ""
+
+#: wordpress-importer.php:851
+msgid "Remote file is incorrect size"
+msgstr ""
+
+#: wordpress-importer.php:856
+msgid "Zero size file downloaded"
+msgstr ""
+
+#: wordpress-importer.php:862
+msgid "Remote file is too large, limit is %s"
+msgstr ""
+
+#: wordpress-importer.php:961
+msgid "Import WordPress"
+msgstr ""
+
+#: wordpress-importer.php:968
+msgid ""
+"A new version of this importer is available. Please update to version %=
s to "
+"ensure compatibility with newer export files."
+msgstr ""
+
+#: wordpress-importer.php:983
+msgid ""
+"Howdy! Upload your WordPress eXtended RSS (WXR) file and we’ll im=
port "
+"the posts, pages, comments, custom fields, categories, and tags into th=
is "
+"site."
+msgstr ""
+
+#: wordpress-importer.php:984
+msgid "Choose a WXR file to upload, then click Upload file and import."
+msgstr ""
+
+#: wordpress-importer.php:1058
+msgid ""
+"Import posts, pages, comments, custom fields, categories, and t=
ags"
+"strong> from a WordPress export file."
+msgstr ""
+
+#. Plugin Name of the plugin/theme
+msgid "WordPress Importer"
+msgstr ""
+
+#. Plugin URI of the plugin/theme
+msgid "http://wordpress.org/extend/plugins/wordpress-importer/"
+msgstr ""
+
+#. Description of the plugin/theme
+msgid ""
+"Import posts, pages, comments, custom fields, categories, tags and more=
from "
+"a WordPress export file."
+msgstr ""
+
+#. Author of the plugin/theme
+msgid "wordpressdotorg"
+msgstr ""
+
+#. Author URI of the plugin/theme
+msgid "http://wordpress.org/"
+msgstr ""
diff --git a/plugins/wordpress-importer/parsers.php b/plugins/wordpress-i=
mporter/parsers.php
new file mode 100644
index 0000000..1724729
--- /dev/null
+++ b/plugins/wordpress-importer/parsers.php
@@ -0,0 +1,601 @@
+parse( $file );
+
+ // If SimpleXML succeeds or this is an invalid WXR file then return t=
he results
+ if ( ! is_wp_error( $result ) || 'SimpleXML_parse_error' !=3D $result=
->get_error_code() )
+ return $result;
+ } else if ( extension_loaded( 'xml' ) ) {
+ $parser =3D new WXR_Parser_XML;
+ $result =3D $parser->parse( $file );
+
+ // If XMLParser succeeds or this is an invalid WXR file then return t=
he results
+ if ( ! is_wp_error( $result ) || 'XML_parse_error' !=3D $result->get_=
error_code() )
+ return $result;
+ }
+
+ // We have a malformed XML file, so display the error and fallthrough =
to regex
+ if ( isset($result) && defined('IMPORT_DEBUG') && IMPORT_DEBUG ) {
+ echo '';
+ if ( 'SimpleXML_parse_error' =3D=3D $result->get_error_code() ) {
+ foreach ( $result->get_error_data() as $error )
+ echo $error->line . ':' . $error->column . ' ' . esc_html( $error->=
message ) . "\n";
+ } else if ( 'XML_parse_error' =3D=3D $result->get_error_code() ) {
+ $error =3D $result->get_error_data();
+ echo $error[0] . ':' . $error[1] . ' ' . esc_html( $error[2] );
+ }
+ echo ' ';
+ echo '' . __( 'There was an error when reading this WXR fi=
le', 'wordpress-importer' ) . ' ';
+ echo __( 'Details are shown above. The importer will now try again wi=
th a different parser...', 'wordpress-importer' ) . '
';
+ }
+
+ // use regular expressions if nothing else available or this is bad XM=
L
+ $parser =3D new WXR_Parser_Regex;
+ return $parser->parse( $file );
+ }
+}
+
+/**
+ * WXR Parser that makes use of the SimpleXML PHP extension.
+ */
+class WXR_Parser_SimpleXML {
+ function parse( $file ) {
+ $authors =3D $posts =3D $categories =3D $tags =3D $terms =3D array();
+
+ $internal_errors =3D libxml_use_internal_errors(true);
+ $xml =3D simplexml_load_file( $file );
+ // halt if loading produces an error
+ if ( ! $xml )
+ return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error=
when reading this WXR file', 'wordpress-importer' ), libxml_get_errors()=
);
+
+ $wxr_version =3D $xml->xpath('/rss/channel/wp:wxr_version');
+ if ( ! $wxr_version )
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to =
be a WXR file, missing/invalid WXR version number', 'wordpress-importer' =
) );
+
+ $wxr_version =3D (string) trim( $wxr_version[0] );
+ // confirm that we are dealing with the correct file format
+ if ( ! preg_match( '/^\d+\.\d+$/', $wxr_version ) )
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to =
be a WXR file, missing/invalid WXR version number', 'wordpress-importer' =
) );
+
+ $base_url =3D $xml->xpath('/rss/channel/wp:base_site_url');
+ $base_url =3D (string) trim( $base_url[0] );
+
+ $namespaces =3D $xml->getDocNamespaces();
+ if ( ! isset( $namespaces['wp'] ) )
+ $namespaces['wp'] =3D 'http://wordpress.org/export/1.1/';
+ if ( ! isset( $namespaces['excerpt'] ) )
+ $namespaces['excerpt'] =3D 'http://wordpress.org/export/1.1/excerpt/'=
;
+
+ // grab authors
+ foreach ( $xml->xpath('/rss/channel/wp:author') as $author_arr ) {
+ $a =3D $author_arr->children( $namespaces['wp'] );
+ $login =3D (string) $a->author_login;
+ $authors[$login] =3D array(
+ 'author_id' =3D> (int) $a->author_id,
+ 'author_login' =3D> $login,
+ 'author_email' =3D> (string) $a->author_email,
+ 'author_display_name' =3D> (string) $a->author_display_name,
+ 'author_first_name' =3D> (string) $a->author_first_name,
+ 'author_last_name' =3D> (string) $a->author_last_name
+ );
+ }
+
+ // grab cats, tags and terms
+ foreach ( $xml->xpath('/rss/channel/wp:category') as $term_arr ) {
+ $t =3D $term_arr->children( $namespaces['wp'] );
+ $categories[] =3D array(
+ 'term_id' =3D> (int) $t->term_id,
+ 'category_nicename' =3D> (string) $t->category_nicename,
+ 'category_parent' =3D> (string) $t->category_parent,
+ 'cat_name' =3D> (string) $t->cat_name,
+ 'category_description' =3D> (string) $t->category_description
+ );
+ }
+
+ foreach ( $xml->xpath('/rss/channel/wp:tag') as $term_arr ) {
+ $t =3D $term_arr->children( $namespaces['wp'] );
+ $tags[] =3D array(
+ 'term_id' =3D> (int) $t->term_id,
+ 'tag_slug' =3D> (string) $t->tag_slug,
+ 'tag_name' =3D> (string) $t->tag_name,
+ 'tag_description' =3D> (string) $t->tag_description
+ );
+ }
+
+ foreach ( $xml->xpath('/rss/channel/wp:term') as $term_arr ) {
+ $t =3D $term_arr->children( $namespaces['wp'] );
+ $terms[] =3D array(
+ 'term_id' =3D> (int) $t->term_id,
+ 'term_taxonomy' =3D> (string) $t->term_taxonomy,
+ 'slug' =3D> (string) $t->term_slug,
+ 'term_parent' =3D> (string) $t->term_parent,
+ 'term_name' =3D> (string) $t->term_name,
+ 'term_description' =3D> (string) $t->term_description
+ );
+ }
+
+ // grab posts
+ foreach ( $xml->channel->item as $item ) {
+ $post =3D array(
+ 'post_title' =3D> (string) $item->title,
+ 'guid' =3D> (string) $item->guid,
+ );
+
+ $dc =3D $item->children( 'http://purl.org/dc/elements/1.1/' );
+ $post['post_author'] =3D (string) $dc->creator;
+
+ $content =3D $item->children( 'http://purl.org/rss/1.0/modules/conten=
t/' );
+ $excerpt =3D $item->children( $namespaces['excerpt'] );
+ $post['post_content'] =3D (string) $content->encoded;
+ $post['post_excerpt'] =3D (string) $excerpt->encoded;
+
+ $wp =3D $item->children( $namespaces['wp'] );
+ $post['post_id'] =3D (int) $wp->post_id;
+ $post['post_date'] =3D (string) $wp->post_date;
+ $post['post_date_gmt'] =3D (string) $wp->post_date_gmt;
+ $post['comment_status'] =3D (string) $wp->comment_status;
+ $post['ping_status'] =3D (string) $wp->ping_status;
+ $post['post_name'] =3D (string) $wp->post_name;
+ $post['status'] =3D (string) $wp->status;
+ $post['post_parent'] =3D (int) $wp->post_parent;
+ $post['menu_order'] =3D (int) $wp->menu_order;
+ $post['post_type'] =3D (string) $wp->post_type;
+ $post['post_password'] =3D (string) $wp->post_password;
+ $post['is_sticky'] =3D (int) $wp->is_sticky;
+
+ foreach ( $item->category as $c ) {
+ $att =3D $c->attributes();
+ if ( isset( $att['nicename'] ) )
+ $post['terms'][] =3D array(
+ 'name' =3D> (string) $c,
+ 'slug' =3D> (string) $att['nicename'],
+ 'domain' =3D> (string) $att['domain']
+ );
+ }
+
+ foreach ( $wp->postmeta as $meta ) {
+ $post['postmeta'][] =3D array(
+ 'key' =3D> (string) $meta->meta_key,
+ 'value' =3D> (string) $meta->meta_value,
+ );
+ }
+
+ foreach ( $wp->comment as $comment ) {
+ $post['comments'][] =3D array(
+ 'comment_id' =3D> (int) $comment->comment_id,
+ 'comment_author' =3D> (string) $comment->comment_author,
+ 'comment_author_email' =3D> (string) $comment->comment_author_email=
,
+ 'comment_author_IP' =3D> (string) $comment->comment_author_IP,
+ 'comment_author_url' =3D> (string) $comment->comment_author_url,
+ 'comment_date' =3D> (string) $comment->comment_date,
+ 'comment_date_gmt' =3D> (string) $comment->comment_date_gmt,
+ 'comment_content' =3D> (string) $comment->comment_content,
+ 'comment_approved' =3D> (string) $comment->comment_approved,
+ 'comment_type' =3D> (string) $comment->comment_type,
+ 'comment_parent' =3D> (string) $comment->comment_parent,
+ 'comment_user_id' =3D> (int) $comment->comment_user_id,
+ );
+ }
+
+ $posts[] =3D $post;
+ }
+
+ return array(
+ 'authors' =3D> $authors,
+ 'posts' =3D> $posts,
+ 'categories' =3D> $categories,
+ 'tags' =3D> $tags,
+ 'terms' =3D> $terms,
+ 'base_url' =3D> $base_url,
+ 'version' =3D> $wxr_version
+ );
+ }
+}
+
+/**
+ * WXR Parser that makes use of the XML Parser PHP extension.
+ */
+class WXR_Parser_XML {
+ var $wp_tags =3D array(
+ 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status',=
'wp:ping_status',
+ 'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:po=
st_type', 'wp:post_password',
+ 'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_par=
ent', 'wp:cat_name', 'wp:category_description',
+ 'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy'=
, 'wp:term_parent',
+ 'wp:term_name', 'wp:term_description', 'wp:author_id', 'wp:author_logi=
n', 'wp:author_email', 'wp:author_display_name',
+ 'wp:author_first_name', 'wp:author_last_name',
+ );
+ var $wp_sub_tags =3D array(
+ 'wp:comment_id', 'wp:comment_author', 'wp:comment_author_email', 'wp:c=
omment_author_url',
+ 'wp:comment_author_IP', 'wp:comment_date', 'wp:comment_date_gmt', 'wp:=
comment_content',
+ 'wp:comment_approved', 'wp:comment_type', 'wp:comment_parent', 'wp:com=
ment_user_id',
+ );
+
+ function parse( $file ) {
+ $this->wxr_version =3D $this->in_post =3D $this->cdata =3D $this->data=
=3D $this->sub_data =3D $this->in_tag =3D $this->in_sub_tag =3D false;
+ $this->authors =3D $this->posts =3D $this->term =3D $this->category =3D=
$this->tag =3D array();
+
+ $xml =3D xml_parser_create( 'UTF-8' );
+ xml_parser_set_option( $xml, XML_OPTION_SKIP_WHITE, 1 );
+ xml_parser_set_option( $xml, XML_OPTION_CASE_FOLDING, 0 );
+ xml_set_object( $xml, $this );
+ xml_set_character_data_handler( $xml, 'cdata' );
+ xml_set_element_handler( $xml, 'tag_open', 'tag_close' );
+
+ if ( ! xml_parse( $xml, file_get_contents( $file ), true ) ) {
+ $current_line =3D xml_get_current_line_number( $xml );
+ $current_column =3D xml_get_current_column_number( $xml );
+ $error_code =3D xml_get_error_code( $xml );
+ $error_string =3D xml_error_string( $error_code );
+ return new WP_Error( 'XML_parse_error', 'There was an error when read=
ing this WXR file', array( $current_line, $current_column, $error_string =
) );
+ }
+ xml_parser_free( $xml );
+
+ if ( ! preg_match( '/^\d+\.\d+$/', $this->wxr_version ) )
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to =
be a WXR file, missing/invalid WXR version number', 'wordpress-importer' =
) );
+
+ return array(
+ 'authors' =3D> $this->authors,
+ 'posts' =3D> $this->posts,
+ 'categories' =3D> $this->category,
+ 'tags' =3D> $this->tag,
+ 'terms' =3D> $this->term,
+ 'base_url' =3D> $this->base_url,
+ 'version' =3D> $this->wxr_version
+ );
+ }
+
+ function tag_open( $parse, $tag, $attr ) {
+ if ( in_array( $tag, $this->wp_tags ) ) {
+ $this->in_tag =3D substr( $tag, 3 );
+ return;
+ }
+
+ if ( in_array( $tag, $this->wp_sub_tags ) ) {
+ $this->in_sub_tag =3D substr( $tag, 3 );
+ return;
+ }
+
+ switch ( $tag ) {
+ case 'category':
+ if ( isset($attr['domain'], $attr['nicename']) ) {
+ $this->sub_data['domain'] =3D $attr['domain'];
+ $this->sub_data['slug'] =3D $attr['nicename'];
+ }
+ break;
+ case 'item': $this->in_post =3D true;
+ case 'title': if ( $this->in_post ) $this->in_tag =3D 'post_title'; b=
reak;
+ case 'guid': $this->in_tag =3D 'guid'; break;
+ case 'dc:creator': $this->in_tag =3D 'post_author'; break;
+ case 'content:encoded': $this->in_tag =3D 'post_content'; break;
+ case 'excerpt:encoded': $this->in_tag =3D 'post_excerpt'; break;
+
+ case 'wp:term_slug': $this->in_tag =3D 'slug'; break;
+ case 'wp:meta_key': $this->in_sub_tag =3D 'key'; break;
+ case 'wp:meta_value': $this->in_sub_tag =3D 'value'; break;
+ }
+ }
+
+ function cdata( $parser, $cdata ) {
+ if ( ! trim( $cdata ) )
+ return;
+
+ $this->cdata .=3D trim( $cdata );
+ }
+
+ function tag_close( $parser, $tag ) {
+ switch ( $tag ) {
+ case 'wp:comment':
+ if ( ! empty( $this->sub_data ) )
+ $this->data['comments'][] =3D $this->sub_data;
+ $this->sub_data =3D false;
+ break;
+ case 'category':
+ if ( ! empty( $this->sub_data ) ) {
+ $this->sub_data['name'] =3D $this->cdata;
+ $this->data['terms'][] =3D $this->sub_data;
+ }
+ $this->sub_data =3D false;
+ break;
+ case 'wp:postmeta':
+ if ( ! empty( $this->sub_data ) )
+ $this->data['postmeta'][] =3D $this->sub_data;
+ $this->sub_data =3D false;
+ break;
+ case 'item':
+ $this->posts[] =3D $this->data;
+ $this->data =3D false;
+ break;
+ case 'wp:category':
+ case 'wp:tag':
+ case 'wp:term':
+ $n =3D substr( $tag, 3 );
+ array_push( $this->$n, $this->data );
+ $this->data =3D false;
+ break;
+ case 'wp:author':
+ if ( ! empty($this->data['author_login']) )
+ $this->authors[$this->data['author_login']] =3D $this->data;
+ $this->data =3D false;
+ break;
+ case 'wp:base_site_url':
+ $this->base_url =3D $this->cdata;
+ break;
+ case 'wp:wxr_version':
+ $this->wxr_version =3D $this->cdata;
+ break;
+
+ default:
+ if ( $this->in_sub_tag ) {
+ $this->sub_data[$this->in_sub_tag] =3D ! empty( $this->cdata ) ? $t=
his->cdata : '';
+ $this->in_sub_tag =3D false;
+ } else if ( $this->in_tag ) {
+ $this->data[$this->in_tag] =3D ! empty( $this->cdata ) ? $this->cda=
ta : '';
+ $this->in_tag =3D false;
+ }
+ }
+
+ $this->cdata =3D false;
+ }
+}
+
+/**
+ * WXR Parser that uses regular expressions. Fallback for installs witho=
ut an XML parser.
+ */
+class WXR_Parser_Regex {
+ var $authors =3D array();
+ var $posts =3D array();
+ var $categories =3D array();
+ var $tags =3D array();
+ var $terms =3D array();
+ var $base_url =3D '';
+
+ function WXR_Parser_Regex() {
+ $this->__construct();
+ }
+
+ function __construct() {
+ $this->has_gzip =3D is_callable( 'gzopen' );
+ }
+
+ function parse( $file ) {
+ $wxr_version =3D $in_post =3D false;
+
+ $fp =3D $this->fopen( $file, 'r' );
+ if ( $fp ) {
+ while ( ! $this->feof( $fp ) ) {
+ $importline =3D rtrim( $this->fgets( $fp ) );
+
+ if ( ! $wxr_version && preg_match( '|(\d+\.\d+)|', $importline, $version ) )
+ $wxr_version =3D $version[1];
+
+ if ( false !=3D=3D strpos( $importline, '' ) ) {
+ preg_match( '|(.*?) |is', $impo=
rtline, $url );
+ $this->base_url =3D $url[1];
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '' ) ) {
+ preg_match( '|(.*?) |is', $importline, $c=
ategory );
+ $this->categories[] =3D $this->process_category( $category[1] );
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '' ) ) {
+ preg_match( '|(.*?) |is', $importline, $tag );
+ $this->tags[] =3D $this->process_tag( $tag[1] );
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '' ) ) {
+ preg_match( '|(.*?) |is', $importline, $term );
+ $this->terms[] =3D $this->process_term( $term[1] );
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '' ) ) {
+ preg_match( '|(.*?) |is', $importline, $autho=
r );
+ $a =3D $this->process_author( $author[1] );
+ $this->authors[$a['author_login']] =3D $a;
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '- ' ) ) {
+ $post =3D '';
+ $in_post =3D true;
+ continue;
+ }
+ if ( false !=3D=3D strpos( $importline, '
' ) ) {
+ $in_post =3D false;
+ $this->posts[] =3D $this->process_post( $post );
+ continue;
+ }
+ if ( $in_post ) {
+ $post .=3D $importline . "\n";
+ }
+ }
+
+ $this->fclose($fp);
+ }
+
+ if ( ! $wxr_version )
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to =
be a WXR file, missing/invalid WXR version number', 'wordpress-importer' =
) );
+
+ return array(
+ 'authors' =3D> $this->authors,
+ 'posts' =3D> $this->posts,
+ 'categories' =3D> $this->categories,
+ 'tags' =3D> $this->tags,
+ 'terms' =3D> $this->terms,
+ 'base_url' =3D> $this->base_url,
+ 'version' =3D> $wxr_version
+ );
+ }
+
+ function get_tag( $string, $tag ) {
+ global $wpdb;
+ preg_match( "|<$tag.*?>(.*?)$tag>|is", $string, $return );
+ if ( isset( $return[1] ) ) {
+ $return =3D preg_replace( '|^$|s', '$1', $return[=
1] );
+ $return =3D $wpdb->escape( trim( $return ) );
+ } else {
+ $return =3D '';
+ }
+ return $return;
+ }
+
+ function process_category( $c ) {
+ return array(
+ 'term_id' =3D> $this->get_tag( $c, 'wp:term_id' ),
+ 'cat_name' =3D> $this->get_tag( $c, 'wp:cat_name' ),
+ 'category_nicename' =3D> $this->get_tag( $c, 'wp:category_nicename' )=
,
+ 'category_parent' =3D> $this->get_tag( $c, 'wp:category_parent' ),
+ 'category_description' =3D> $this->get_tag( $c, 'wp:category_descript=
ion' ),
+ );
+ }
+
+ function process_tag( $t ) {
+ return array(
+ 'term_id' =3D> $this->get_tag( $t, 'wp:term_id' ),
+ 'tag_name' =3D> $this->get_tag( $t, 'wp:tag_name' ),
+ 'tag_slug' =3D> $this->get_tag( $t, 'wp:tag_slug' ),
+ 'tag_description' =3D> $this->get_tag( $t, 'wp:tag_description' ),
+ );
+ }
+
+ function process_term( $t ) {
+ return array(
+ 'term_id' =3D> $this->get_tag( $t, 'wp:term_id' ),
+ 'term_taxonomy' =3D> $this->get_tag( $t, 'wp:term_taxonomy' ),
+ 'slug' =3D> $this->get_tag( $t, 'wp:term_slug' ),
+ 'term_parent' =3D> $this->get_tag( $t, 'wp:term_parent' ),
+ 'term_name' =3D> $this->get_tag( $t, 'wp:term_name' ),
+ 'term_description' =3D> $this->get_tag( $t, 'wp:term_description' ),
+ );
+ }
+
+ function process_author( $a ) {
+ return array(
+ 'author_id' =3D> $this->get_tag( $a, 'wp:author_id' ),
+ 'author_login' =3D> $this->get_tag( $a, 'wp:author_login' ),
+ 'author_email' =3D> $this->get_tag( $a, 'wp:author_email' ),
+ 'author_display_name' =3D> $this->get_tag( $a, 'wp:author_display_nam=
e' ),
+ 'author_first_name' =3D> $this->get_tag( $a, 'wp:author_first_name' )=
,
+ 'author_last_name' =3D> $this->get_tag( $a, 'wp:author_last_name' ),
+ );
+ }
+
+ function process_post( $post ) {
+ $post_id =3D $this->get_tag( $post, 'wp:post_id' );
+ $post_title =3D $this->get_tag( $post, 'title' );
+ $post_date =3D $this->get_tag( $post, 'wp:post_date' );
+ $post_date_gmt =3D $this->get_tag( $post, 'wp:post_date_gmt' );
+ $comment_status =3D $this->get_tag( $post, 'wp:comment_status' );
+ $ping_status =3D $this->get_tag( $post, 'wp:ping_status' );
+ $status =3D $this->get_tag( $post, 'wp:status' );
+ $post_name =3D $this->get_tag( $post, 'wp:post_name' );
+ $post_parent =3D $this->get_tag( $post, 'wp:post_parent' );
+ $menu_order =3D $this->get_tag( $post, 'wp:menu_order' );
+ $post_type =3D $this->get_tag( $post, 'wp:post_type' );
+ $post_password =3D $this->get_tag( $post, 'wp:post_password' );
+ $is_sticky =3D $this->get_tag( $post, 'wp:is_sticky' );
+ $guid =3D $this->get_tag( $post, 'guid' );
+ $post_author =3D $this->get_tag( $post, 'dc:creator' );
+
+ $post_excerpt =3D $this->get_tag( $post, 'excerpt:encoded' );
+ $post_excerpt =3D preg_replace_callback( '|<(/?[A-Z]+)|', array( &$thi=
s, '_normalize_tag' ), $post_excerpt );
+ $post_excerpt =3D str_replace( ' ', ' ', $post_excerpt );
+ $post_excerpt =3D str_replace( ' ', ' ', $post_excerpt );
+
+ $post_content =3D $this->get_tag( $post, 'content:encoded' );
+ $post_content =3D preg_replace_callback( '|<(/?[A-Z]+)|', array( &$thi=
s, '_normalize_tag' ), $post_content );
+ $post_content =3D str_replace( ' ', ' ', $post_content );
+ $post_content =3D str_replace( ' ', ' ', $post_content );
+
+ $postdata =3D compact( 'post_id', 'post_author', 'post_date', 'post_da=
te_gmt', 'post_content', 'post_excerpt',
+ 'post_title', 'status', 'post_name', 'comment_status', 'ping_status',=
'guid', 'post_parent',
+ 'menu_order', 'post_type', 'post_password', 'is_sticky'
+ );
+
+ preg_match_all( '|=
(.+?) |is', $post, $terms, PREG_SET_ORDER );
+ foreach ( $terms as $t ) {
+ $post_terms[] =3D array(
+ 'slug' =3D> $t[2],
+ 'domain' =3D> $t[1],
+ 'name' =3D> str_replace( array( '' ), '', $t[3] ),
+ );
+ }
+ if ( ! empty( $post_terms ) ) $postdata['terms'] =3D $post_terms;
+
+ preg_match_all( '|(.+?) |is', $post, $comments=
);
+ $comments =3D $comments[1];
+ if ( $comments ) {
+ foreach ( $comments as $comment ) {
+ $post_comments[] =3D array(
+ 'comment_id' =3D> $this->get_tag( $comment, 'wp:comment_id' ),
+ 'comment_author' =3D> $this->get_tag( $comment, 'wp:comment_author'=
),
+ 'comment_author_email' =3D> $this->get_tag( $comment, 'wp:comment_a=
uthor_email' ),
+ 'comment_author_IP' =3D> $this->get_tag( $comment, 'wp:comment_auth=
or_IP' ),
+ 'comment_author_url' =3D> $this->get_tag( $comment, 'wp:comment_aut=
hor_url' ),
+ 'comment_date' =3D> $this->get_tag( $comment, 'wp:comment_date' ),
+ 'comment_date_gmt' =3D> $this->get_tag( $comment, 'wp:comment_date_=
gmt' ),
+ 'comment_content' =3D> $this->get_tag( $comment, 'wp:comment_conten=
t' ),
+ 'comment_approved' =3D> $this->get_tag( $comment, 'wp:comment_appro=
ved' ),
+ 'comment_type' =3D> $this->get_tag( $comment, 'wp:comment_type' ),
+ 'comment_parent' =3D> $this->get_tag( $comment, 'wp:comment_parent'=
),
+ );
+ }
+ }
+ if ( ! empty( $post_comments ) ) $postdata['comments'] =3D $post_comme=
nts;
+
+ preg_match_all( '|(.+?) |is', $post, $postme=
ta );
+ $postmeta =3D $postmeta[1];
+ if ( $postmeta ) {
+ foreach ( $postmeta as $p ) {
+ $post_postmeta[] =3D array(
+ 'key' =3D> $this->get_tag( $p, 'wp:meta_key' ),
+ 'value' =3D> $this->get_tag( $p, 'wp:meta_value' ),
+ );
+ }
+ }
+ if ( ! empty( $post_postmeta ) ) $postdata['postmeta'] =3D $post_postm=
eta;
+
+ return $postdata;
+ }
+
+ function _normalize_tag( $matches ) {
+ return '<' . strtolower( $matches[1] );
+ }
+
+ function fopen( $filename, $mode =3D 'r' ) {
+ if ( $this->has_gzip )
+ return gzopen( $filename, $mode );
+ return fopen( $filename, $mode );
+ }
+
+ function feof( $fp ) {
+ if ( $this->has_gzip )
+ return gzeof( $fp );
+ return feof( $fp );
+ }
+
+ function fgets( $fp, $len =3D 8192 ) {
+ if ( $this->has_gzip )
+ return gzgets( $fp, $len );
+ return fgets( $fp, $len );
+ }
+
+ function fclose( $fp ) {
+ if ( $this->has_gzip )
+ return gzclose( $fp );
+ return fclose( $fp );
+ }
+}
diff --git a/plugins/wordpress-importer/readme.txt b/plugins/wordpress-im=
porter/readme.txt
new file mode 100644
index 0000000..06689a0
--- /dev/null
+++ b/plugins/wordpress-importer/readme.txt
@@ -0,0 +1,41 @@
+=3D=3D=3D Plugin Name =3D=3D=3D
+Contributors: wordpressdotorg
+Donate link:=20
+Tags: importer, wordpress
+Requires at least: 3.0
+Tested up to: 3.1
+Stable tag: 0.2
+
+Import posts, pages, comments, custom fields, categories, tags and more =
from a WordPress export file.
+
+=3D=3D Description =3D=3D
+
+Import posts, pages, comments, custom fields, categories, tags and more =
from a WordPress export file.
+
+=3D=3D Installation =3D=3D
+
+1. Upload the `wordpress-importer` folder to the `/wp-content/plugins/` =
directory
+1. Activate the plugin through the 'Plugins' menu in WordPress
+1. Go to the Tools -> Import screen, click on WordPress
+
+=3D=3D Changelog =3D=3D
+
+=3D 0.3 =3D
+* Use an XML Parser if possible
+* Proper import support for nav menus
+* ... and more, see [Trac ticket #15197](http://core.trac.wordpress.org/=
ticket/15197)
+
+=3D 0.1 =3D
+* Initial release
+
+=3D=3D Upgrade Notice =3D=3D
+
+=3D 0.3 =3D
+Upgrade for a more robust and reliable experience when importing WordPre=
ss export files, and for compatibility with WordPress 3.1.
+
+=3D=3D Filters =3D=3D
+
+The importer has a couple of filters to allow you to completely enable/b=
lock certain features:
+* `import_allow_create_users`: return false if you only want to allow ma=
pping to existing users
+* `import_allow_fetch_attachments`: return false if you do not wish to a=
llow importing and downloading of attachments
+* `import_attachment_size_limit`: return an integer value for the maximu=
m file size in bytes to save (default is 0, which is unlimited)
diff --git a/plugins/wordpress-importer/wordpress-importer.php b/plugins/=
wordpress-importer/wordpress-importer.php
new file mode 100644
index 0000000..36285e2
--- /dev/null
+++ b/plugins/wordpress-importer/wordpress-importer.php
@@ -0,0 +1,1060 @@
+header();
+
+ $step =3D empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
+ switch ( $step ) {
+ case 0:
+ $this->greet();
+ break;
+ case 1:
+ check_admin_referer( 'import-upload' );
+ if ( $this->handle_upload() )
+ $this->import_options();
+ break;
+ case 2:
+ check_admin_referer( 'import-wordpress' );
+ $this->fetch_attachments =3D ( ! empty( $_POST['fetch_attachments'] =
) && $this->allow_fetch_attachments() );
+ $this->id =3D (int) $_POST['import_id'];
+ $file =3D get_attached_file( $this->id );
+ set_time_limit(0);
+ $this->import( $file );
+ break;
+ }
+
+ $this->footer();
+ }
+
+ /**
+ * The main controller for the actual import stage.
+ *
+ * @param string $file Path to the WXR file for importing
+ */
+ function import( $file ) {
+ add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' =
) );
+
+ $this->import_start( $file );
+
+ $this->get_author_mapping();
+
+ wp_suspend_cache_invalidation( true );
+ $this->process_categories();
+ $this->process_tags();
+ $this->process_terms();
+ $this->process_posts();
+ wp_suspend_cache_invalidation( false );
+
+ // update incorrect/missing information in the DB
+ $this->backfill_parents();
+ $this->backfill_attachment_urls();
+ $this->remap_featured_images();
+
+ $this->import_end();
+ }
+
+ /**
+ * Parses the WXR file and prepares us for the task of processing parse=
d data
+ *
+ * @param string $file Path to the WXR file for importing
+ */
+ function import_start( $file ) {
+ if ( ! is_file($file) ) {
+ echo '' . __( 'Sorry, there has been an error.', 'wordpres=
s-importer' ) . ' ';
+ echo __( 'The file does not exist, please try again.', 'wordpress-imp=
orter' ) . '
';
+ $this->footer();
+ die();
+ }
+
+ $import_data =3D $this->parse( $file );
+
+ if ( is_wp_error( $import_data ) ) {
+ echo '' . __( 'Sorry, there has been an error.', 'wordpres=
s-importer' ) . ' ';
+ echo esc_html( $import_data->get_error_message() ) . '
';
+ $this->footer();
+ die();
+ }
+
+ $this->version =3D $import_data['version'];
+ $this->get_authors_from_import( $import_data );
+ $this->posts =3D $import_data['posts'];
+ $this->terms =3D $import_data['terms'];
+ $this->categories =3D $import_data['categories'];
+ $this->tags =3D $import_data['tags'];
+ $this->base_url =3D esc_url( $import_data['base_url'] );
+
+ wp_defer_term_counting( true );
+ wp_defer_comment_counting( true );
+
+ do_action( 'import_start' );
+ }
+
+ /**
+ * Performs post-import cleanup of files and the cache
+ */
+ function import_end() {
+ wp_import_cleanup( $this->id );
+
+ wp_cache_flush();
+ foreach ( get_taxonomies() as $tax ) {
+ delete_option( "{$tax}_children" );
+ _get_term_hierarchy( $tax );
+ }
+
+ wp_defer_term_counting( false );
+ wp_defer_comment_counting( false );
+
+ echo '' . __( 'All done.', 'wordpress-importer' ) . ' ' . __( 'Have fun!', 'wordpress-importer' ) . ' ' .=
'
';
+ echo '' . __( 'Remember to update the passwords and roles of import=
ed users.', 'wordpress-importer' ) . '
';
+
+ do_action( 'import_end' );
+ }
+
+ /**
+ * Handles the WXR upload and initial parsing of the file to prepare fo=
r
+ * displaying author import options
+ *
+ * @return bool False if error uploading or invalid file, true otherwis=
e
+ */
+ function handle_upload() {
+ $file =3D wp_import_handle_upload();
+
+ if ( isset( $file['error'] ) ) {
+ echo '' . __( 'Sorry, there has been an error.', 'wordpres=
s-importer' ) . ' ';
+ echo esc_html( $file['error'] ) . '
';
+ return false;
+ }
+
+ $this->id =3D (int) $file['id'];
+ $import_data =3D $this->parse( $file['file'] );
+ if ( is_wp_error( $import_data ) ) {
+ echo '' . __( 'Sorry, there has been an error.', 'wordpres=
s-importer' ) . ' ';
+ echo esc_html( $import_data->get_error_message() ) . '
';
+ return false;
+ }
+
+ $this->version =3D $import_data['version'];
+ if ( $this->version > $this->max_wxr_version ) {
+ echo '';
+ printf( __( 'This WXR file (version %s) may not be supported by this =
version of the importer. Please consider updating.', 'wordpress-importer'=
), esc_html($import_data['version']) );
+ echo '
';
+ }
+
+ $this->get_authors_from_import( $import_data );
+
+ return true;
+ }
+
+ /**
+ * Retrieve authors from parsed WXR data
+ *
+ * Uses the provided author information from WXR 1.1 files
+ * or extracts info from each post for WXR 1.0 files
+ *
+ * @param array $import_data Data returned by a WXR parser
+ */
+ function get_authors_from_import( $import_data ) {
+ if ( ! empty( $import_data['authors'] ) ) {
+ $this->authors =3D $import_data['authors'];
+ // no author information, grab it from the posts
+ } else {
+ foreach ( $import_data['posts'] as $post ) {
+ $login =3D sanitize_user( $post['post_author'], true );
+ if ( empty( $login ) ) {
+ printf( __( 'Failed to import author %s. Their posts will be attrib=
uted to the current user.', 'wordpress-importer' ), esc_html( $post['post=
_author'] ) );
+ echo ' ';
+ continue;
+ }
+
+ if ( ! isset($this->authors[$login]) )
+ $this->authors[$login] =3D array(
+ 'author_login' =3D> $login,
+ 'author_display_name' =3D> $post['post_author']
+ );
+ }
+ }
+ }
+
+ /**
+ * Display pre-import options, author importing/mapping and option to
+ * fetch attachments
+ */
+ function import_options() {
+ $j =3D 0;
+?>
+
s entries.', 'wordpress-importer' ); ?>
+allow_create_users() ) : ?>
+ =
p>
+
+
+authors as $author ) : ?>
+ author_select( $j++, $author ); ?>
+
+
+
+
+allow_fetch_attachments() ) : ?>
+
+
+
+
+
+
+
+ " />
+
+' . esc_html( $author['author_display_name'] );
+ if ( $this->version !=3D '1.0' ) echo ' (' . esc_html( $author['author=
_login'] ) . ')';
+ echo ' ';
+
+ if ( $this->version !=3D '1.0' )
+ echo '';
+
+ $create_users =3D $this->allow_create_users();
+ if ( $create_users ) {
+ if ( $this->version !=3D '1.0' ) {
+ _e( 'or create new user with login name:', 'wordpress-importer' );
+ $value =3D '';
+ } else {
+ _e( 'as a new user:', 'wordpress-importer' );
+ $value =3D esc_attr( sanitize_user( $author['author_login'], true ) =
);
+ }
+
+ echo ' ';
+ }
+
+ if ( ! $create_users && $this->version =3D=3D '1.0' )
+ _e( 'assign posts to an existing user:', 'wordpress-importer' );
+ else
+ _e( 'or assign posts to an existing user:', 'wordpress-importer' );
+ wp_dropdown_users( array( 'name' =3D> "user_map[$n]", 'multi' =3D> tru=
e, 'show_option_all' =3D> __( '- Select -', 'wordpress-importer' ) ) );
+ echo ' ';
+
+ if ( $this->version !=3D '1.0' )
+ echo '
';
+ }
+
+ /**
+ * Map old author logins to local user IDs based on decisions made
+ * in import options form. Can map to an existing user, create a new us=
er
+ * or falls back to the current user in case of error with either of th=
e previous
+ */
+ function get_author_mapping() {
+ if ( ! isset( $_POST['imported_authors'] ) )
+ return;
+
+ $create_users =3D $this->allow_create_users();
+
+ foreach ( (array) $_POST['imported_authors'] as $i =3D> $old_login ) {
+ $old_id =3D isset( $this->authors[$old_login]['author_id'] ) ? intval=
($this->authors[$old_login]['author_id']) : false;
+
+ if ( ! empty( $_POST['user_map'][$i] ) ) {
+ $user =3D get_userdata( intval($_POST['user_map'][$i]) );
+ if ( isset( $user->ID ) ) {
+ if ( $old_id )
+ $this->processed_authors[$old_id] =3D $user->ID;
+ $this->author_mapping[$old_login] =3D $user->ID;
+ }
+ } else if ( $create_users ) {
+ if ( ! empty($_POST['user_new'][$i]) ) {
+ $user_id =3D wp_create_user( $_POST['user_new'][$i], wp_generate_pa=
ssword() );
+ } else if ( $this->version !=3D '1.0' ) {
+ $user_data =3D array(
+ 'user_login' =3D> $old_login,
+ 'user_pass' =3D> wp_generate_password(),
+ 'user_email' =3D> isset( $this->authors[$old_login]['author_email'=
] ) ? $this->authors[$old_login]['author_email'] : '',
+ 'display_name' =3D> $this->authors[$old_login]['author_display_nam=
e'],
+ 'first_name' =3D> isset( $this->authors[$old_login]['author_first_=
name'] ) ? $this->authors[$old_login]['author_first_name'] : '',
+ 'last_name' =3D> isset( $this->authors[$old_login]['author_last_na=
me'] ) ? $this->authors[$old_login]['author_last_name'] : '',
+ );
+ $user_id =3D wp_insert_user( $user_data );
+ }
+
+ if ( ! is_wp_error( $user_id ) ) {
+ if ( $old_id )
+ $this->processed_authors[$old_id] =3D $user_id;
+ $this->author_mapping[$old_login] =3D $user_id;
+ } else {
+ printf( __( 'Failed to create new user for %s. Their posts will be =
attributed to the current user.', 'wordpress-importer' ), esc_html($this-=
>authors[$old_login]['author_display_name']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ' ' . $user_id->get_error_message();
+ echo ' ';
+ }
+ }
+
+ // failsafe: if the user_id was invalid, default to the current user
+ if ( ! isset( $this->author_mapping[$old_login] ) ) {
+ if ( $old_id )
+ $this->processed_authors[$old_id] =3D (int) get_current_user_id();
+ $this->author_mapping[$old_login] =3D (int) get_current_user_id();
+ }
+ }
+ }
+
+ /**
+ * Create new categories based on import information
+ *
+ * Doesn't create a new category if its slug already exists
+ */
+ function process_categories() {
+ if ( empty( $this->categories ) )
+ return;
+
+ foreach ( $this->categories as $cat ) {
+ // if the category already exists leave it alone
+ $term_id =3D term_exists( $cat['category_nicename'], 'category' );
+ if ( $term_id ) {
+ if ( is_array($term_id) ) $term_id =3D $term_id['term_id'];
+ $this->processed_terms[intval($cat['term_id'])] =3D (int) $term_id;
+ continue;
+ }
+
+ $category_parent =3D empty( $cat['category_parent'] ) ? 0 : category_=
exists( $cat['category_parent'] );
+ $category_description =3D isset( $cat['category_description'] ) ? $ca=
t['category_description'] : '';
+ $catarr =3D array(
+ 'category_nicename' =3D> $cat['category_nicename'],
+ 'category_parent' =3D> $category_parent,
+ 'cat_name' =3D> $cat['cat_name'],
+ 'category_description' =3D> $category_description
+ );
+
+ $id =3D wp_insert_category( $catarr );
+ if ( ! is_wp_error( $id ) ) {
+ $this->processed_terms[intval($cat['term_id'])] =3D $id;
+ } else {
+ printf( __( 'Failed to import category %s', 'wordpress-importer' ), =
esc_html($cat['category_nicename']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ': ' . $id->get_error_message();
+ echo ' ';
+ continue;
+ }
+ }
+
+ unset( $this->categories );
+ }
+
+ /**
+ * Create new post tags based on import information
+ *
+ * Doesn't create a tag if its slug already exists
+ */
+ function process_tags() {
+ if ( empty( $this->tags ) )
+ return;
+
+ foreach ( $this->tags as $tag ) {
+ // if the tag already exists leave it alone
+ $term_id =3D term_exists( $tag['tag_slug'], 'post_tag' );
+ if ( $term_id ) {
+ if ( is_array($term_id) ) $term_id =3D $term_id['term_id'];
+ $this->processed_terms[intval($tag['term_id'])] =3D (int) $term_id;
+ continue;
+ }
+
+ $tag_desc =3D isset( $tag['tag_description'] ) ? $tag['tag_descriptio=
n'] : '';
+ $tagarr =3D array( 'slug' =3D> $tag['tag_slug'], 'description' =3D> $=
tag_desc );
+
+ $id =3D wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr );
+ if ( ! is_wp_error( $id ) ) {
+ $this->processed_terms[intval($tag['term_id'])] =3D $id['term_id'];
+ } else {
+ printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), =
esc_html($tag['tag_name']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ': ' . $id->get_error_message();
+ echo ' ';
+ continue;
+ }
+ }
+
+ unset( $this->tags );
+ }
+
+ /**
+ * Create new terms based on import information
+ *
+ * Doesn't create a term its slug already exists
+ */
+ function process_terms() {
+ if ( empty( $this->terms ) )
+ return;
+
+ foreach ( $this->terms as $term ) {
+ // if the term already exists in the correct taxonomy leave it alone
+ $term_id =3D term_exists( $term['slug'], $term['term_taxonomy'] );
+ if ( $term_id ) {
+ if ( is_array($term_id) ) $term_id =3D $term_id['term_id'];
+ $this->processed_terms[intval($term['term_id'])] =3D (int) $term_id;
+ continue;
+ }
+
+ if ( empty( $term['term_parent'] ) ) {
+ $parent =3D 0;
+ } else {
+ $parent =3D term_exists( $term['term_parent'], $term['term_taxonomy'=
] );
+ if ( is_array( $parent ) ) $parent =3D $parent['term_id'];
+ }
+ $description =3D isset( $term['term_description'] ) ? $term['term_des=
cription'] : '';
+ $termarr =3D array( 'slug' =3D> $term['slug'], 'description' =3D> $de=
scription, 'parent' =3D> intval($parent) );
+
+ $id =3D wp_insert_term( $term['term_name'], $term['term_taxonomy'], $=
termarr );
+ if ( ! is_wp_error( $id ) ) {
+ $this->processed_terms[intval($term['term_id'])] =3D $id['term_id'];
+ } else {
+ printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_ht=
ml($term['term_taxonomy']), esc_html($term['term_name']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ': ' . $id->get_error_message();
+ echo ' ';
+ continue;
+ }
+ }
+
+ unset( $this->terms );
+ }
+
+ /**
+ * Create new posts based on import information
+ *
+ * Posts marked as having a parent which doesn't exist will become top =
level items.
+ * Doesn't create a new post if: the post type doesn't exist, the given=
post ID
+ * is already noted as imported or a post with the same title and date =
already exists.
+ * Note that new/updated terms, comments and meta are imported for the =
last of the above.
+ */
+ function process_posts() {
+ foreach ( $this->posts as $post ) {
+ if ( ! post_type_exists( $post['post_type'] ) ) {
+ printf( __( 'Failed to import “%s”: Invalid post type %s=
', 'wordpress-importer' ),
+ esc_html($post['post_title']), esc_html($post['post_type']) );
+ echo ' ';
+ continue;
+ }
+
+ if ( isset( $this->processed_posts[$post['post_id']] ) )
+ continue;
+
+ if ( $post['status'] =3D=3D 'auto-draft' )
+ continue;
+
+ if ( 'nav_menu_item' =3D=3D $post['post_type'] ) {
+ $this->process_menu_item( $post );
+ continue;
+ }
+
+ $post_type_object =3D get_post_type_object( $post['post_type'] );
+
+ $post_exists =3D post_exists( $post['post_title'], '', $post['post_da=
te'] );
+ if ( $post_exists ) {
+ printf( __('%s “%s” already exists.', 'wordpress-importe=
r'), $post_type_object->labels->singular_name, esc_html($post['post_title=
']) );
+ echo ' ';
+ $comment_post_ID =3D $post_id =3D $post_exists;
+ } else {
+ $post_parent =3D (int) $post['post_parent'];
+ if ( $post_parent ) {
+ // if we already know the parent, map it to the new local ID
+ if ( isset( $this->processed_posts[$post_parent] ) ) {
+ $post_parent =3D $this->processed_posts[$post_parent];
+ // otherwise record the parent for later
+ } else {
+ $this->post_orphans[intval($post['post_id'])] =3D $post_parent;
+ $post_parent =3D 0;
+ }
+ }
+
+ // map the post author
+ $author =3D sanitize_user( $post['post_author'], true );
+ if ( isset( $this->author_mapping[$author] ) )
+ $author =3D $this->author_mapping[$author];
+ else
+ $author =3D (int) get_current_user_id();
+
+ $postdata =3D array(
+ 'import_id' =3D> $post['post_id'], 'post_author' =3D> $author, 'pos=
t_date' =3D> $post['post_date'],
+ 'post_date_gmt' =3D> $post['post_date_gmt'], 'post_content' =3D> $p=
ost['post_content'],
+ 'post_excerpt' =3D> $post['post_excerpt'], 'post_title' =3D> $post[=
'post_title'],
+ 'post_status' =3D> $post['status'], 'post_name' =3D> $post['post_na=
me'],
+ 'comment_status' =3D> $post['comment_status'], 'ping_status' =3D> $=
post['ping_status'],
+ 'guid' =3D> $post['guid'], 'post_parent' =3D> $post_parent, 'menu_o=
rder' =3D> $post['menu_order'],
+ 'post_type' =3D> $post['post_type'], 'post_password' =3D> $post['po=
st_password']
+ );
+
+ if ( 'attachment' =3D=3D $postdata['post_type'] ) {
+ $remote_url =3D ! empty($post['attachment_url']) ? $post['attachmen=
t_url'] : $post['guid'];
+ $comment_post_ID =3D $post_id =3D $this->process_attachment( $postd=
ata, $remote_url );
+ } else {
+ $comment_post_ID =3D $post_id =3D wp_insert_post( $postdata, true )=
;
+ }
+
+ if ( is_wp_error( $post_id ) ) {
+ printf( __( 'Failed to import %s “%s”', 'wordpress-impo=
rter' ),
+ $post_type_object->labels->singular_name, esc_html($post['post_tit=
le']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ': ' . $post_id->get_error_message();
+ echo ' ';
+ continue;
+ }
+
+ if ( $post['is_sticky'] =3D=3D 1 )
+ stick_post( $post_id );
+ }
+
+ // map pre-import ID to local ID
+ $this->processed_posts[intval($post['post_id'])] =3D (int) $post_id;
+
+ // add categories, tags and other terms
+ if ( ! empty( $post['terms'] ) ) {
+ $terms_to_set =3D array();
+ foreach ( $post['terms'] as $term ) {
+ // back compat with WXR 1.0 map 'tag' to 'post_tag'
+ $taxonomy =3D ( 'tag' =3D=3D $term['domain'] ) ? 'post_tag' : $term=
['domain'];
+ $term_exists =3D term_exists( $term['slug'], $taxonomy );
+ $term_id =3D is_array( $term_exists ) ? $term_exists['term_id'] : $=
term_exists;
+ if ( ! $term_id ) {
+ $t =3D wp_insert_term( $term['name'], $taxonomy, array( 'slug' =3D=
> $term['slug'] ) );
+ if ( ! is_wp_error( $t ) ) {
+ $term_id =3D $t['term_id'];
+ } else {
+ printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc=
_html($taxonomy), esc_html($term['name']) );
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
+ echo ': ' . $t->get_error_message();
+ echo ' ';
+ continue;
+ }
+ }
+ $terms_to_set[$taxonomy][] =3D intval( $term_id );
+ }
+
+ foreach ( $terms_to_set as $tax =3D> $ids ) {
+ $tt_ids =3D wp_set_post_terms( $post_id, $ids, $tax );
+ }
+ unset( $post['terms'], $terms_to_set );
+ }
+
+ // add/update comments
+ if ( ! empty( $post['comments'] ) ) {
+ $num_comments =3D 0;
+ $inserted_comments =3D array();
+ foreach ( $post['comments'] as $comment ) {
+ $comment_id =3D $comment['comment_id'];
+ $newcomments[$comment_id]['comment_post_ID'] =3D $comment_post=
_ID;
+ $newcomments[$comment_id]['comment_author'] =3D $comment['com=
ment_author'];
+ $newcomments[$comment_id]['comment_author_email'] =3D $comment['com=
ment_author_email'];
+ $newcomments[$comment_id]['comment_author_IP'] =3D $comment['com=
ment_author_IP'];
+ $newcomments[$comment_id]['comment_author_url'] =3D $comment['com=
ment_author_url'];
+ $newcomments[$comment_id]['comment_date'] =3D $comment['com=
ment_date'];
+ $newcomments[$comment_id]['comment_date_gmt'] =3D $comment['com=
ment_date_gmt'];
+ $newcomments[$comment_id]['comment_content'] =3D $comment['com=
ment_content'];
+ $newcomments[$comment_id]['comment_approved'] =3D $comment['com=
ment_approved'];
+ $newcomments[$comment_id]['comment_type'] =3D $comment['com=
ment_type'];
+ $newcomments[$comment_id]['comment_parent'] =3D $comment['commen=
t_parent'];
+ }
+ ksort( $newcomments );
+
+ foreach ( $newcomments as $key =3D> $comment ) {
+ // if this is a new post we can skip the comment_exists() check
+ if ( ! $post_exists || ! comment_exists( $comment['comment_author']=
, $comment['comment_date'] ) ) {
+ if ( isset( $inserted_comments[$comment['comment_parent']] ) )
+ $comment['comment_parent'] =3D $inserted_comments[$comment['comme=
nt_parent']];
+ $comment =3D wp_filter_comment( $comment );
+ $inserted_comments[$key] =3D wp_insert_comment( $comment );
+ $num_comments++;
+ }
+ }
+ unset( $newcomments, $inserted_comments, $post['comments'] );
+ }
+
+ // add/update post meta
+ if ( isset( $post['postmeta'] ) ) {
+ foreach ( $post['postmeta'] as $meta ) {
+ $key =3D apply_filters( 'import_post_meta_key', $meta['key'] );
+ $value =3D false;
+
+ if ( '_edit_last' =3D=3D $key ) {
+ if ( isset( $this->processed_authors[intval($meta['value'])] ) )
+ $value =3D $this->processed_authors[intval($meta['value'])];
+ else
+ $key =3D false;
+ }
+
+ if ( $key ) {
+ // export gets meta straight from the DB so could have a serialize=
d string
+ if ( ! $value )
+ $value =3D maybe_unserialize( $meta['value'] );
+
+ update_post_meta( $post_id, $key, $value );
+ do_action( 'import_post_meta', $post_id, $key, $value );
+
+ // if the post has a featured image, take note of this in case of =
remap
+ if ( '_thumbnail_id' =3D=3D $key )
+ $this->featured_images[$post_id] =3D (int) $value;
+ }
+ }
+ }
+ }
+
+ unset( $this->posts );
+ }
+
+ /**
+ * Attempt to create a new menu item from import data
+ *
+ * Fails for draft, orphaned menu items and those without an associated=
nav_menu
+ * or an invalid nav_menu term. If the post type or term object which t=
he menu item
+ * represents doesn't exist then the menu item will not be imported (wa=
its until the
+ * end of the import to retry again before discarding).
+ *
+ * @param array $item Menu item details from WXR file
+ */
+ function process_menu_item( $item ) {
+ // skip draft, orphaned menu items
+ if ( 'draft' =3D=3D $item['status'] )
+ return;
+
+ $menu_slug =3D false;
+ if ( isset($item['terms']) ) {
+ // loop through terms, assume first nav_menu term is correct menu
+ foreach ( $item['terms'] as $term ) {
+ if ( 'nav_menu' =3D=3D $term['domain'] ) {
+ $menu_slug =3D $term['slug'];
+ break;
+ }
+ }
+ }
+
+ // no nav_menu term associated with this menu item
+ if ( ! $menu_slug ) {
+ _e( 'Menu item skipped due to missing menu slug', 'wordpress-importer=
' );
+ echo ' ';
+ return;
+ }
+
+ $menu_id =3D term_exists( $menu_slug, 'nav_menu' );
+ if ( ! $menu_id ) {
+ printf( __( 'Menu item skipped due to invalid menu slug: %s', 'wordpr=
ess-importer' ), esc_html( $menu_slug ) );
+ echo ' ';
+ return;
+ } else {
+ $menu_id =3D is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
+ }
+
+ foreach ( $item['postmeta'] as $meta )
+ $$meta['key'] =3D $meta['value'];
+
+ if ( 'taxonomy' =3D=3D $_menu_item_type && isset( $this->processed_ter=
ms[intval($_menu_item_object_id)] ) ) {
+ $_menu_item_object_id =3D $this->processed_terms[intval($_menu_item_o=
bject_id)];
+ } else if ( 'post_type' =3D=3D $_menu_item_type && isset( $this->proce=
ssed_posts[intval($_menu_item_object_id)] ) ) {
+ $_menu_item_object_id =3D $this->processed_posts[intval($_menu_item_o=
bject_id)];
+ } else if ( 'custom' !=3D $_menu_item_type ) {
+ // associated object is missing or not imported yet, we'll retry late=
r
+ $this->missing_menu_items[] =3D $item;
+ return;
+ }
+
+ if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_p=
arent)] ) ) {
+ $_menu_item_menu_item_parent =3D $this->processed_menu_items[intval($=
_menu_item_menu_item_parent)];
+ } else if ( $_menu_item_menu_item_parent ) {
+ $this->menu_item_orphans[intval($item['post_id'])] =3D (int) $_menu_i=
tem_menu_item_parent;
+ $_menu_item_menu_item_parent =3D 0;
+ }
+
+ // wp_update_nav_menu_item expects CSS classes as a space separated st=
ring
+ $_menu_item_classes =3D maybe_unserialize( $_menu_item_classes );
+ if ( is_array( $_menu_item_classes ) )
+ $_menu_item_classes =3D implode( ' ', $_menu_item_classes );
+
+ $args =3D array(
+ 'menu-item-object-id' =3D> $_menu_item_object_id,
+ 'menu-item-object' =3D> $_menu_item_object,
+ 'menu-item-parent-id' =3D> $_menu_item_menu_item_parent,
+ 'menu-item-position' =3D> intval( $item['menu_order'] ),
+ 'menu-item-type' =3D> $_menu_item_type,
+ 'menu-item-title' =3D> $item['post_title'],
+ 'menu-item-url' =3D> $_menu_item_url,
+ 'menu-item-description' =3D> $item['post_content'],
+ 'menu-item-attr-title' =3D> $item['post_excerpt'],
+ 'menu-item-target' =3D> $_menu_item_target,
+ 'menu-item-classes' =3D> $_menu_item_classes,
+ 'menu-item-xfn' =3D> $_menu_item_xfn,
+ 'menu-item-status' =3D> $item['status']
+ );
+
+ $id =3D wp_update_nav_menu_item( $menu_id, 0, $args );
+ if ( $id && ! is_wp_error( $id ) )
+ $this->processed_menu_items[intval($item['post_id'])] =3D (int) $id;
+ }
+
+ /**
+ * If fetching attachments is enabled then attempt to create a new atta=
chment
+ *
+ * @param array $post Attachment post details from WXR
+ * @param string $url URL to fetch attachment from
+ * @return int|WP_Error Post ID on success, WP_Error otherwise
+ */
+ function process_attachment( $post, $url ) {
+ if ( ! $this->fetch_attachments )
+ return new WP_Error( 'attachment_processing_error',
+ __( 'Fetching attachments is not enabled', 'wordpress-importer' ) );
+
+ // if the URL is absolute, but does not contain address, then upload i=
t assuming base_site_url
+ if ( preg_match( '|^/[\w\W]+$|', $url ) )
+ $url =3D rtrim( $this->base_url, '/' ) . $url;
+
+ $upload =3D $this->fetch_remote_file( $url, $post );
+ if ( is_wp_error( $upload ) )
+ return $upload;
+
+ if ( $info =3D wp_check_filetype( $upload['file'] ) )
+ $post['post_mime_type'] =3D $info['type'];
+ else
+ return new WP_Error( 'attachment_processing_error', __('Invalid file =
type', 'wordpress-importer') );
+
+ $post['guid'] =3D $upload['url'];
+
+ // as per wp-admin/includes/upload.php
+ $post_id =3D wp_insert_attachment( $post, $upload['file'] );
+ wp_update_attachment_metadata( $post_id, wp_generate_attachment_metada=
ta( $post_id, $upload['file'] ) );
+
+ // remap the thumbnail url. this isn't perfect because we're just gue=
ssing the original url.
+ if ( preg_match( '@^image/@', $info['type'] ) && $thumb_url =3D wp_get=
_attachment_thumb_url( $post_id ) ) {
+ $parts =3D pathinfo( $url );
+ $ext =3D $parts['extension'];
+ $name =3D basename($parts['basename'], ".{$ext}");
+ $this->url_remap[$parts['dirname'] . '/' . $name . '.thumbnail.' . $e=
xt] =3D $thumb_url;
+ }
+
+ return $post_id;
+ }
+
+ /**
+ * Attempt to download a remote file attachment
+ *
+ * @param string $url URL of item to fetch
+ * @param array $post Attachment details
+ * @return array|WP_Error Local file location details on success, WP_Er=
ror otherwise
+ */
+ function fetch_remote_file( $url, $post ) {
+ add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeo=
ut' ) );
+
+ // extract the file name and extension from the url
+ $file_name =3D basename( $url );
+
+ // get placeholder file in the upload dir with a unique, sanitized fil=
ename
+ $upload =3D wp_upload_bits( $file_name, 0, '', $post['post_date'] );
+ if ( $upload['error'] )
+ return new WP_Error( 'upload_dir_error', $upload['error'] );
+
+ // fetch the remote url and write it to the placeholder file
+ $headers =3D wp_get_http( $url, $upload['file'] );
+
+ // request failed
+ if ( ! $headers ) {
+ @unlink( $upload['file'] );
+ return new WP_Error( 'import_file_error', __('Remote server did not r=
espond', 'wordpress-importer') );
+ }
+
+ // make sure the fetch was successful
+ if ( $headers['response'] !=3D '200' ) {
+ @unlink( $upload['file'] );
+ return new WP_Error( 'import_file_error', sprintf( __('Remote server =
returned error response %1$d %2$s', 'wordpress-importer'), esc_html($head=
ers['response']), get_status_header_desc($headers['response']) ) );
+ }
+
+ $filesize =3D filesize( $upload['file'] );
+
+ if ( isset( $headers['content-length'] ) && $filesize !=3D $headers['c=
ontent-length'] ) {
+ @unlink( $upload['file'] );
+ return new WP_Error( 'import_file_error', __('Remote file is incorrec=
t size', 'wordpress-importer') );
+ }
+
+ if ( 0 =3D=3D $filesize ) {
+ @unlink( $upload['file'] );
+ return new WP_Error( 'import_file_error', __('Zero size file download=
ed', 'wordpress-importer') );
+ }
+
+ $max_size =3D (int) $this->max_attachment_size();
+ if ( ! empty( $max_size ) && $filesize > $max_size ) {
+ @unlink( $upload['file'] );
+ return new WP_Error( 'import_file_error', sprintf(__('Remote file is =
too large, limit is %s', 'wordpress-importer'), size_format($max_size) ) =
);
+ }
+
+ // keep track of the old and new urls so we can substitute them later
+ $this->url_remap[$url] =3D $upload['url'];
+ $this->url_remap[$post['guid']] =3D $upload['url'];
+ // if the remote url is redirected somewhere else, keep track of the d=
estination too
+ if ( isset($headers['x-final-location']) && $headers['x-final-location=
'] !=3D $url )
+ $this->url_remap[$headers['x-final-location']] =3D $upload['url'];
+
+ return $upload;
+ }
+
+ /**
+ * Attempt to associate posts and menu items with previously missing pa=
rents
+ *
+ * An imported post's parent may not have been imported when it was fir=
st created
+ * so try again. Similarly for child menu items and menu items which we=
re missing
+ * the object (e.g. post) they represent in the menu
+ */
+ function backfill_parents() {
+ global $wpdb;
+
+ // find parents for post orphans
+ foreach ( $this->post_orphans as $child_id =3D> $parent_id ) {
+ $local_child_id =3D $local_parent_id =3D false;
+ if ( isset( $this->processed_posts[$child_id] ) )
+ $local_child_id =3D $this->processed_posts[$child_id];
+ if ( isset( $this->processed_posts[$parent_id] ) )
+ $local_parent_id =3D $this->processed_posts[$parent_id];
+
+ if ( $local_child_id && $local_parent_id )
+ $wpdb->update( $wpdb->posts, array( 'post_parent' =3D> $local_parent=
_id ), array( 'ID' =3D> $local_child_id ), '%d', '%d' );
+ }
+
+ // all other posts/terms are imported, retry menu items with missing a=
ssociated object
+ $missing_menu_items =3D $this->missing_menu_items;
+ foreach ( $missing_menu_items as $item )
+ $this->process_menu_item( $item );
+
+ // find parents for menu item orphans
+ foreach ( $this->menu_item_orphans as $child_id =3D> $parent_id ) {
+ $local_child_id =3D $local_parent_id =3D 0;
+ if ( isset( $this->processed_menu_items[$child_id] ) )
+ $local_child_id =3D $this->processed_menu_items[$child_id];
+ if ( isset( $this->processed_menu_items[$parent_id] ) )
+ $local_parent_id =3D $this->processed_menu_items[$parent_id];
+
+ if ( $local_child_id && $local_parent_id )
+ update_post_meta( $local_child_id, '_menu_item_menu_item_parent', (i=
nt) $local_parent_id );
+ }
+ }
+
+ /**
+ * Use stored mapping information to update old attachment URLs
+ */
+ function backfill_attachment_urls() {
+ global $wpdb;
+ // make sure we do the longest urls first, in case one is a substring =
of another
+ uksort( $this->url_remap, array(&$this, 'cmpr_strlen') );
+
+ foreach ( $this->url_remap as $from_url =3D> $to_url ) {
+ // remap urls in post_content
+ $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content =
=3D REPLACE(post_content, %s, %s)", $from_url, $to_url) );
+ // remap enclosure urls
+ $result =3D $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SE=
T meta_value =3D REPLACE(meta_value, %s, %s) WHERE meta_key=3D'enclosure'=
", $from_url, $to_url) );
+ }
+ }
+
+ /**
+ * Update _thumbnail_id meta to new, imported attachment IDs
+ */
+ function remap_featured_images() {
+ // cycle through posts that have a featured image
+ foreach ( $this->featured_images as $post_id =3D> $value ) {
+ if ( isset( $this->processed_posts[$value] ) ) {
+ $new_id =3D $this->processed_posts[$value];
+ // only update if there's a difference
+ if ( $new_id !=3D $value )
+ update_post_meta( $post_id, '_thumbnail_id', $new_id );
+ }
+ }
+ }
+
+ /**
+ * Parse a WXR file
+ *
+ * @param string $file Path to WXR file for parsing
+ * @return array Information gathered from the WXR file
+ */
+ function parse( $file ) {
+ $parser =3D new WXR_Parser();
+ return $parser->parse( $file );
+ }
+
+ // Display import page title
+ function header() {
+ echo '';
+ screen_icon();
+ echo '
' . __( 'Import WordPress', 'wordpress-importer' ) . ' '=
;
+
+ $updates =3D get_plugin_updates();
+ $basename =3D plugin_basename(__FILE__);
+ if ( isset( $updates[$basename] ) ) {
+ $update =3D $updates[$basename];
+ echo '
';
+ printf( __( 'A new version of this importer is available. Please upda=
te to version %s to ensure compatibility with newer export files.', 'word=
press-importer' ), $update->update->new_version );
+ echo '
';
+ }
+ }
+
+ // Close div.wrap
+ function footer() {
+ echo '
';
+ }
+
+ /**
+ * Display introductory text and file upload form
+ */
+ function greet() {
+ echo '';
+ echo '
'.__( 'Howdy! Upload your WordPress eXtended RSS (WXR) file a=
nd we’ll import the posts, pages, comments, custom fields, categori=
es, and tags into this site.', 'wordpress-importer' ).'
';
+ echo '
'.__( 'Choose a WXR file to upload, then click Upload file an=
d import.', 'wordpress-importer' ).'
';
+ wp_import_upload_form( 'admin.php?import=3Dwordpress&step=3D1' );
+ echo '
';
+ }
+
+ /**
+ * Decide if the given meta key maps to information we will want to imp=
ort
+ *
+ * @param string $key The meta key to check
+ * @return string|bool The key if we do want to import, false if not
+ */
+ function is_valid_meta_key( $key ) {
+ // skip attachment metadata since we'll regenerate it from scratch
+ // skip _edit_lock as not relevant for import
+ if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metad=
ata', '_edit_lock' ) ) )
+ return false;
+ return $key;
+ }
+
+ /**
+ * Decide whether or not the importer is allowed to create users.
+ * Default is true, can be filtered via import_allow_create_users
+ *
+ * @return bool True if creating users is allowed
+ */
+ function allow_create_users() {
+ return apply_filters( 'import_allow_create_users', true );
+ }
+
+ /**
+ * Decide whether or not the importer should attempt to download attach=
ment files.
+ * Default is true, can be filtered via import_allow_fetch_attachments.=
The choice
+ * made at the import options screen must also be true, false here hide=
s that checkbox.
+ *
+ * @return bool True if downloading attachments is allowed
+ */
+ function allow_fetch_attachments() {
+ return apply_filters( 'import_allow_fetch_attachments', true );
+ }
+
+ /**
+ * Decide what the maximum file size for downloaded attachments is.
+ * Default is 0 (unlimited), can be filtered via import_attachment_size=
_limit
+ *
+ * @return int Maximum attachment file size to import
+ */
+ function max_attachment_size() {
+ return apply_filters( 'import_attachment_size_limit', 0 );
+ }
+
+ /**
+ * Added to http_request_timeout filter to force timeout at 60 seconds =
during import
+ * @return int 60
+ */
+ function bump_request_timeout() {
+ return 60;
+ }
+
+ // return the difference in length between two strings
+ function cmpr_strlen( $a, $b ) {
+ return strlen($b) - strlen($a);
+ }
+}
+
+} // class_exists( 'WP_Importer' )
+
+function wordpress_importer_init() {
+ load_plugin_textdomain( 'wordpress-importer', false, dirname( plugin_ba=
sename( __FILE__ ) ) . '/languages' );
+
+ /**
+ * WordPress Importer object for registering the import callback
+ * @global WP_Import $wp_import
+ */
+ $GLOBALS['wp_import'] =3D new WP_Import();
+ register_importer( 'wordpress', 'WordPress', __('Import posts, =
pages, comments, custom fields, categories, and tags from a Word=
Press export file.', 'wordpress-importer'), array( $GLOBALS['wp_import'],=
'dispatch' ) );
+}
+add_action( 'admin_init', 'wordpress_importer_init' );