WordPress Importer - Version 0.4

Version Description

  • Map comment user_id where possible
  • Import attachments from wp:attachment_url
  • Upload attachments to correct directory
  • Remap resized image URLs correctly
Download this release

Release Info

Developer duck_
Plugin Icon 128x128 WordPress Importer
Version 0.4
Comparing to
See all releases

Code changes from version 0.3 to 0.4

Files changed (3) hide show
  1. parsers.php +9 -1
  2. readme.txt +46 -3
  3. wordpress-importer.php +42 -18
parsers.php CHANGED
@@ -157,6 +157,9 @@ class WXR_Parser_SimpleXML {
157
  $post['post_password'] = (string) $wp->post_password;
158
  $post['is_sticky'] = (int) $wp->is_sticky;
159
 
 
 
 
160
  foreach ( $item->category as $c ) {
161
  $att = $c->attributes();
162
  if ( isset( $att['nicename'] ) )
@@ -211,7 +214,7 @@ class WXR_Parser_SimpleXML {
211
  */
212
  class WXR_Parser_XML {
213
  var $wp_tags = array(
214
- 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status', 'wp:ping_status',
215
  'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:post_type', 'wp:post_password',
216
  'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_parent', 'wp:cat_name', 'wp:category_description',
217
  'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy', 'wp:term_parent',
@@ -525,6 +528,10 @@ class WXR_Parser_Regex {
525
  'menu_order', 'post_type', 'post_password', 'is_sticky'
526
  );
527
 
 
 
 
 
528
  preg_match_all( '|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER );
529
  foreach ( $terms as $t ) {
530
  $post_terms[] = array(
@@ -551,6 +558,7 @@ class WXR_Parser_Regex {
551
  'comment_approved' => $this->get_tag( $comment, 'wp:comment_approved' ),
552
  'comment_type' => $this->get_tag( $comment, 'wp:comment_type' ),
553
  'comment_parent' => $this->get_tag( $comment, 'wp:comment_parent' ),
 
554
  );
555
  }
556
  }
157
  $post['post_password'] = (string) $wp->post_password;
158
  $post['is_sticky'] = (int) $wp->is_sticky;
159
 
160
+ if ( isset($wp->attachment_url) )
161
+ $post['attachment_url'] = (string) $wp->attachment_url;
162
+
163
  foreach ( $item->category as $c ) {
164
  $att = $c->attributes();
165
  if ( isset( $att['nicename'] ) )
214
  */
215
  class WXR_Parser_XML {
216
  var $wp_tags = array(
217
+ 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status', 'wp:ping_status', 'wp:attachment_url',
218
  'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:post_type', 'wp:post_password',
219
  'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_parent', 'wp:cat_name', 'wp:category_description',
220
  'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy', 'wp:term_parent',
528
  'menu_order', 'post_type', 'post_password', 'is_sticky'
529
  );
530
 
531
+ $attachment_url = $this->get_tag( $post, 'wp:attachment_url' );
532
+ if ( $attachment_url )
533
+ $postdata['attachment_url'] = $attachment_url;
534
+
535
  preg_match_all( '|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER );
536
  foreach ( $terms as $t ) {
537
  $post_terms[] = array(
558
  'comment_approved' => $this->get_tag( $comment, 'wp:comment_approved' ),
559
  'comment_type' => $this->get_tag( $comment, 'wp:comment_type' ),
560
  'comment_parent' => $this->get_tag( $comment, 'wp:comment_parent' ),
561
+ 'comment_user_id' => $this->get_tag( $comment, 'wp:comment_user_id' ),
562
  );
563
  }
564
  }
readme.txt CHANGED
@@ -4,38 +4,81 @@ Donate link:
4
  Tags: importer, wordpress
5
  Requires at least: 3.0
6
  Tested up to: 3.1
7
- Stable tag: 0.2
8
 
9
  Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
10
 
11
  == Description ==
12
 
13
- Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
 
 
 
 
 
 
 
 
14
 
15
  == Installation ==
16
 
 
 
 
 
 
 
 
 
 
17
  1. Upload the `wordpress-importer` folder to the `/wp-content/plugins/` directory
18
  1. Activate the plugin through the 'Plugins' menu in WordPress
19
  1. Go to the Tools -> Import screen, click on WordPress
20
 
21
  == Changelog ==
22
 
 
 
 
 
 
 
23
  = 0.3 =
24
  * Use an XML Parser if possible
25
  * Proper import support for nav menus
26
- * ... and more, see [Trac ticket #15197](http://core.trac.wordpress.org/ticket/15197)
27
 
28
  = 0.1 =
29
  * Initial release
30
 
31
  == Upgrade Notice ==
32
 
 
 
 
33
  = 0.3 =
34
  Upgrade for a more robust and reliable experience when importing WordPress export files, and for compatibility with WordPress 3.1.
35
 
 
 
 
 
 
 
 
 
 
 
 
36
  == Filters ==
37
 
38
  The importer has a couple of filters to allow you to completely enable/block certain features:
 
39
  * `import_allow_create_users`: return false if you only want to allow mapping to existing users
40
  * `import_allow_fetch_attachments`: return false if you do not wish to allow importing and downloading of attachments
41
  * `import_attachment_size_limit`: return an integer value for the maximum file size in bytes to save (default is 0, which is unlimited)
 
 
 
 
 
4
  Tags: importer, wordpress
5
  Requires at least: 3.0
6
  Tested up to: 3.1
7
+ Stable tag: 0.4
8
 
9
  Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
10
 
11
  == Description ==
12
 
13
+ The WordPress Importer will import the following content from a WordPress export file:
14
+
15
+ * Posts, pages and other custom post types
16
+ * Comments
17
+ * Custom fields and post meta
18
+ * Categories, tags and terms from custom taxonomies
19
+ * Authors
20
+
21
+ For further information and instructions please see the [Codex page on Importing Content](http://codex.wordpress.org/Importing_Content#WordPress)
22
 
23
  == Installation ==
24
 
25
+ The quickest method for installing the importer is:
26
+
27
+ 1. Visit Tools -> Import in the WordPress dashboard
28
+ 1. Click on the WordPress link in the list of importers
29
+ 1. Click "Install Now"
30
+ 1. Finally click "Activate Plugin & Run Importer"
31
+
32
+ If you would prefer to do things manually then follow these instructions:
33
+
34
  1. Upload the `wordpress-importer` folder to the `/wp-content/plugins/` directory
35
  1. Activate the plugin through the 'Plugins' menu in WordPress
36
  1. Go to the Tools -> Import screen, click on WordPress
37
 
38
  == Changelog ==
39
 
40
+ = 0.4 =
41
+ * Map comment user_id where possible
42
+ * Import attachments from `wp:attachment_url`
43
+ * Upload attachments to correct directory
44
+ * Remap resized image URLs correctly
45
+
46
  = 0.3 =
47
  * Use an XML Parser if possible
48
  * Proper import support for nav menus
49
+ * ... and much more, see [Trac ticket #15197](http://core.trac.wordpress.org/ticket/15197)
50
 
51
  = 0.1 =
52
  * Initial release
53
 
54
  == Upgrade Notice ==
55
 
56
+ = 0.4 =
57
+ Bug fixes for attachment importing and other small enhancements.
58
+
59
  = 0.3 =
60
  Upgrade for a more robust and reliable experience when importing WordPress export files, and for compatibility with WordPress 3.1.
61
 
62
+ == Frequently Asked Questions ==
63
+
64
+ = Help! I'm getting out of memory errors or a blank screen. =
65
+ If your exported file is very large, the import script may run into your host's configured memory limit for PHP.
66
+
67
+ A message like "Fatal error: Allowed memory size of 8388608 bytes exhausted" indicates that the script can't successfully import your XML file under the current PHP memory limit. If you have access to the php.ini file, you can manually increase the limit; if you do not (your WordPress installation is hosted on a shared server, for instance), you might have to break your exported XML file into several smaller pieces and run the import script one at a time.
68
+
69
+ For those with shared hosting, the best alternative may be to consult hosting support to determine the safest approach for running the import. A host may be willing to temporarily lift the memory limit and/or run the process directly from their end.
70
+
71
+ -- [WordPress Codex: Importing Content](http://codex.wordpress.org/Importing_Content#Before_Importing)
72
+
73
  == Filters ==
74
 
75
  The importer has a couple of filters to allow you to completely enable/block certain features:
76
+
77
  * `import_allow_create_users`: return false if you only want to allow mapping to existing users
78
  * `import_allow_fetch_attachments`: return false if you do not wish to allow importing and downloading of attachments
79
  * `import_attachment_size_limit`: return an integer value for the maximum file size in bytes to save (default is 0, which is unlimited)
80
+
81
+ There are also a few actions available to hook into:
82
+
83
+ * `import_start`: occurs after the export file has been uploaded and author import settings have been chosen
84
+ * `import_end`: called after the last output from the importer
wordpress-importer.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://wordpress.org/extend/plugins/wordpress-importer/
5
  Description: Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
6
  Author: wordpressdotorg
7
  Author URI: http://wordpress.org/
8
- Version: 0.3
9
  Text Domain: wordpress-importer
10
  License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
11
  */
@@ -103,6 +103,7 @@ class WP_Import extends WP_Importer {
103
  */
104
  function import( $file ) {
105
  add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
 
106
 
107
  $this->import_start( $file );
108
 
@@ -393,7 +394,8 @@ class WP_Import extends WP_Importer {
393
  $term_id = term_exists( $cat['category_nicename'], 'category' );
394
  if ( $term_id ) {
395
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
396
- $this->processed_terms[intval($cat['term_id'])] = (int) $term_id;
 
397
  continue;
398
  }
399
 
@@ -408,7 +410,8 @@ class WP_Import extends WP_Importer {
408
 
409
  $id = wp_insert_category( $catarr );
410
  if ( ! is_wp_error( $id ) ) {
411
- $this->processed_terms[intval($cat['term_id'])] = $id;
 
412
  } else {
413
  printf( __( 'Failed to import category %s', 'wordpress-importer' ), esc_html($cat['category_nicename']) );
414
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
@@ -435,7 +438,8 @@ class WP_Import extends WP_Importer {
435
  $term_id = term_exists( $tag['tag_slug'], 'post_tag' );
436
  if ( $term_id ) {
437
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
438
- $this->processed_terms[intval($tag['term_id'])] = (int) $term_id;
 
439
  continue;
440
  }
441
 
@@ -444,7 +448,8 @@ class WP_Import extends WP_Importer {
444
 
445
  $id = wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr );
446
  if ( ! is_wp_error( $id ) ) {
447
- $this->processed_terms[intval($tag['term_id'])] = $id['term_id'];
 
448
  } else {
449
  printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), esc_html($tag['tag_name']) );
450
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
@@ -471,7 +476,8 @@ class WP_Import extends WP_Importer {
471
  $term_id = term_exists( $term['slug'], $term['term_taxonomy'] );
472
  if ( $term_id ) {
473
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
474
- $this->processed_terms[intval($term['term_id'])] = (int) $term_id;
 
475
  continue;
476
  }
477
 
@@ -486,7 +492,8 @@ class WP_Import extends WP_Importer {
486
 
487
  $id = wp_insert_term( $term['term_name'], $term['term_taxonomy'], $termarr );
488
  if ( ! is_wp_error( $id ) ) {
489
- $this->processed_terms[intval($term['term_id'])] = $id['term_id'];
 
490
  } else {
491
  printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($term['term_taxonomy']), esc_html($term['term_name']) );
492
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
@@ -566,6 +573,20 @@ class WP_Import extends WP_Importer {
566
 
567
  if ( 'attachment' == $postdata['post_type'] ) {
568
  $remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
  $comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url );
570
  } else {
571
  $comment_post_ID = $post_id = wp_insert_post( $postdata, true );
@@ -633,6 +654,8 @@ class WP_Import extends WP_Importer {
633
  $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved'];
634
  $newcomments[$comment_id]['comment_type'] = $comment['comment_type'];
635
  $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent'];
 
 
636
  }
637
  ksort( $newcomments );
638
 
@@ -667,7 +690,7 @@ class WP_Import extends WP_Importer {
667
  if ( ! $value )
668
  $value = maybe_unserialize( $meta['value'] );
669
 
670
- update_post_meta( $post_id, $key, $value );
671
  do_action( 'import_post_meta', $post_id, $key, $value );
672
 
673
  // if the post has a featured image, take note of this in case of remap
@@ -800,12 +823,15 @@ class WP_Import extends WP_Importer {
800
  $post_id = wp_insert_attachment( $post, $upload['file'] );
801
  wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );
802
 
803
- // remap the thumbnail url. this isn't perfect because we're just guessing the original url.
804
- if ( preg_match( '@^image/@', $info['type'] ) && $thumb_url = wp_get_attachment_thumb_url( $post_id ) ) {
805
  $parts = pathinfo( $url );
806
- $ext = $parts['extension'];
807
- $name = basename($parts['basename'], ".{$ext}");
808
- $this->url_remap[$parts['dirname'] . '/' . $name . '.thumbnail.' . $ext] = $thumb_url;
 
 
 
809
  }
810
 
811
  return $post_id;
@@ -819,13 +845,11 @@ class WP_Import extends WP_Importer {
819
  * @return array|WP_Error Local file location details on success, WP_Error otherwise
820
  */
821
  function fetch_remote_file( $url, $post ) {
822
- add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );
823
-
824
  // extract the file name and extension from the url
825
  $file_name = basename( $url );
826
 
827
  // get placeholder file in the upload dir with a unique, sanitized filename
828
- $upload = wp_upload_bits( $file_name, 0, '', $post['post_date'] );
829
  if ( $upload['error'] )
830
  return new WP_Error( 'upload_dir_error', $upload['error'] );
831
 
@@ -864,8 +888,8 @@ class WP_Import extends WP_Importer {
864
 
865
  // keep track of the old and new urls so we can substitute them later
866
  $this->url_remap[$url] = $upload['url'];
867
- $this->url_remap[$post['guid']] = $upload['url'];
868
- // if the remote url is redirected somewhere else, keep track of the destination too
869
  if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url )
870
  $this->url_remap[$headers['x-final-location']] = $upload['url'];
871
 
5
  Description: Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
6
  Author: wordpressdotorg
7
  Author URI: http://wordpress.org/
8
+ Version: 0.4
9
  Text Domain: wordpress-importer
10
  License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
11
  */
103
  */
104
  function import( $file ) {
105
  add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
106
+ add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );
107
 
108
  $this->import_start( $file );
109
 
394
  $term_id = term_exists( $cat['category_nicename'], 'category' );
395
  if ( $term_id ) {
396
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
397
+ if ( isset($cat['term_id']) )
398
+ $this->processed_terms[intval($cat['term_id'])] = (int) $term_id;
399
  continue;
400
  }
401
 
410
 
411
  $id = wp_insert_category( $catarr );
412
  if ( ! is_wp_error( $id ) ) {
413
+ if ( isset($cat['term_id']) )
414
+ $this->processed_terms[intval($cat['term_id'])] = $id;
415
  } else {
416
  printf( __( 'Failed to import category %s', 'wordpress-importer' ), esc_html($cat['category_nicename']) );
417
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
438
  $term_id = term_exists( $tag['tag_slug'], 'post_tag' );
439
  if ( $term_id ) {
440
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
441
+ if ( isset($tag['term_id']) )
442
+ $this->processed_terms[intval($tag['term_id'])] = (int) $term_id;
443
  continue;
444
  }
445
 
448
 
449
  $id = wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr );
450
  if ( ! is_wp_error( $id ) ) {
451
+ if ( isset($tag['term_id']) )
452
+ $this->processed_terms[intval($tag['term_id'])] = $id['term_id'];
453
  } else {
454
  printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), esc_html($tag['tag_name']) );
455
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
476
  $term_id = term_exists( $term['slug'], $term['term_taxonomy'] );
477
  if ( $term_id ) {
478
  if ( is_array($term_id) ) $term_id = $term_id['term_id'];
479
+ if ( isset($term['term_id']) )
480
+ $this->processed_terms[intval($term['term_id'])] = (int) $term_id;
481
  continue;
482
  }
483
 
492
 
493
  $id = wp_insert_term( $term['term_name'], $term['term_taxonomy'], $termarr );
494
  if ( ! is_wp_error( $id ) ) {
495
+ if ( isset($term['term_id']) )
496
+ $this->processed_terms[intval($term['term_id'])] = $id['term_id'];
497
  } else {
498
  printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($term['term_taxonomy']), esc_html($term['term_name']) );
499
  if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
573
 
574
  if ( 'attachment' == $postdata['post_type'] ) {
575
  $remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
576
+
577
+ // try to use _wp_attached file for upload folder placement to ensure the same location as the export site
578
+ // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
579
+ $postdata['upload_date'] = $post['post_date'];
580
+ if ( isset( $post['postmeta'] ) ) {
581
+ foreach( $post['postmeta'] as $meta ) {
582
+ if ( $meta['key'] == '_wp_attached_file' ) {
583
+ if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) )
584
+ $postdata['upload_date'] = $matches[0];
585
+ break;
586
+ }
587
+ }
588
+ }
589
+
590
  $comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url );
591
  } else {
592
  $comment_post_ID = $post_id = wp_insert_post( $postdata, true );
654
  $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved'];
655
  $newcomments[$comment_id]['comment_type'] = $comment['comment_type'];
656
  $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent'];
657
+ if ( isset( $this->processed_authors[$comment['comment_user_id']] ) )
658
+ $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']];
659
  }
660
  ksort( $newcomments );
661
 
690
  if ( ! $value )
691
  $value = maybe_unserialize( $meta['value'] );
692
 
693
+ add_post_meta( $post_id, $key, $value );
694
  do_action( 'import_post_meta', $post_id, $key, $value );
695
 
696
  // if the post has a featured image, take note of this in case of remap
823
  $post_id = wp_insert_attachment( $post, $upload['file'] );
824
  wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );
825
 
826
+ // remap resized image URLs, works by stripping the extension and remapping the URL stub.
827
+ if ( preg_match( '!^image/!', $info['type'] ) ) {
828
  $parts = pathinfo( $url );
829
+ $name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2
830
+
831
+ $parts_new = pathinfo( $upload['url'] );
832
+ $name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
833
+
834
+ $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
835
  }
836
 
837
  return $post_id;
845
  * @return array|WP_Error Local file location details on success, WP_Error otherwise
846
  */
847
  function fetch_remote_file( $url, $post ) {
 
 
848
  // extract the file name and extension from the url
849
  $file_name = basename( $url );
850
 
851
  // get placeholder file in the upload dir with a unique, sanitized filename
852
+ $upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] );
853
  if ( $upload['error'] )
854
  return new WP_Error( 'upload_dir_error', $upload['error'] );
855
 
888
 
889
  // keep track of the old and new urls so we can substitute them later
890
  $this->url_remap[$url] = $upload['url'];
891
+ $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
892
+ // keep track of the destination if the remote url is redirected somewhere else
893
  if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url )
894
  $this->url_remap[$headers['x-final-location']] = $upload['url'];
895