web/wp-admin/import/wordpress.php
branchwordpress
changeset 109 03b0d1493584
child 132 4d4862461b8d
equal deleted inserted replaced
-1:000000000000 109:03b0d1493584
       
     1 <?php
       
     2 /**
       
     3  * WordPress Importer
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Importer
       
     7  */
       
     8 
       
     9 /**
       
    10  * WordPress Importer
       
    11  *
       
    12  * Will process the WordPress eXtended RSS files that you upload from the export
       
    13  * file.
       
    14  *
       
    15  * @since unknown
       
    16  */
       
    17 class WP_Import {
       
    18 
       
    19 	var $post_ids_processed = array ();
       
    20 	var $orphans = array ();
       
    21 	var $file;
       
    22 	var $id;
       
    23 	var $mtnames = array ();
       
    24 	var $newauthornames = array ();
       
    25 	var $allauthornames = array ();
       
    26 
       
    27 	var $author_ids = array ();
       
    28 	var $tags = array ();
       
    29 	var $categories = array ();
       
    30 
       
    31 	var $j = -1;
       
    32 	var $fetch_attachments = false;
       
    33 	var $url_remap = array ();
       
    34 
       
    35 	function header() {
       
    36 		echo '<div class="wrap">';
       
    37 		screen_icon();
       
    38 		echo '<h2>'.__('Import WordPress').'</h2>';
       
    39 	}
       
    40 
       
    41 	function footer() {
       
    42 		echo '</div>';
       
    43 	}
       
    44 
       
    45 	function unhtmlentities($string) { // From php.net for < 4.3 compat
       
    46 		$trans_tbl = get_html_translation_table(HTML_ENTITIES);
       
    47 		$trans_tbl = array_flip($trans_tbl);
       
    48 		return strtr($string, $trans_tbl);
       
    49 	}
       
    50 
       
    51 	function greet() {
       
    52 		echo '<div class="narrow">';
       
    53 		echo '<p>'.__('Howdy! Upload your WordPress eXtended RSS (WXR) file and we&#8217;ll import the posts, pages, comments, custom fields, categories, and tags into this blog.').'</p>';
       
    54 		echo '<p>'.__('Choose a WordPress WXR file to upload, then click Upload file and import.').'</p>';
       
    55 		wp_import_upload_form("admin.php?import=wordpress&amp;step=1");
       
    56 		echo '</div>';
       
    57 	}
       
    58 
       
    59 	function get_tag( $string, $tag ) {
       
    60 		global $wpdb;
       
    61 		preg_match("|<$tag.*?>(.*?)</$tag>|is", $string, $return);
       
    62 		$return = preg_replace('|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1]);
       
    63 		$return = $wpdb->escape( trim( $return ) );
       
    64 		return $return;
       
    65 	}
       
    66 
       
    67 	function has_gzip() {
       
    68 		return is_callable('gzopen');
       
    69 	}
       
    70 
       
    71 	function fopen($filename, $mode='r') {
       
    72 		if ( $this->has_gzip() )
       
    73 			return gzopen($filename, $mode);
       
    74 		return fopen($filename, $mode);
       
    75 	}
       
    76 
       
    77 	function feof($fp) {
       
    78 		if ( $this->has_gzip() )
       
    79 			return gzeof($fp);
       
    80 		return feof($fp);
       
    81 	}
       
    82 
       
    83 	function fgets($fp, $len=8192) {
       
    84 		if ( $this->has_gzip() )
       
    85 			return gzgets($fp, $len);
       
    86 		return fgets($fp, $len);
       
    87 	}
       
    88 
       
    89 	function fclose($fp) {
       
    90 		if ( $this->has_gzip() )
       
    91 			return gzclose($fp);
       
    92 		return fclose($fp);
       
    93 	}
       
    94 
       
    95 	function get_entries($process_post_func=NULL) {
       
    96 		set_magic_quotes_runtime(0);
       
    97 
       
    98 		$doing_entry = false;
       
    99 		$is_wxr_file = false;
       
   100 
       
   101 		$fp = $this->fopen($this->file, 'r');
       
   102 		if ($fp) {
       
   103 			while ( !$this->feof($fp) ) {
       
   104 				$importline = rtrim($this->fgets($fp));
       
   105 
       
   106 				// this doesn't check that the file is perfectly valid but will at least confirm that it's not the wrong format altogether
       
   107 				if ( !$is_wxr_file && preg_match('|xmlns:wp="http://wordpress[.]org/export/\d+[.]\d+/"|', $importline) )
       
   108 					$is_wxr_file = true;
       
   109 
       
   110 				if ( false !== strpos($importline, '<wp:base_site_url>') ) {
       
   111 					preg_match('|<wp:base_site_url>(.*?)</wp:base_site_url>|is', $importline, $url);
       
   112 					$this->base_url = $url[1];
       
   113 					continue;
       
   114 				}
       
   115 				if ( false !== strpos($importline, '<wp:category>') ) {
       
   116 					preg_match('|<wp:category>(.*?)</wp:category>|is', $importline, $category);
       
   117 					$this->categories[] = $category[1];
       
   118 					continue;
       
   119 				}
       
   120 				if ( false !== strpos($importline, '<wp:tag>') ) {
       
   121 					preg_match('|<wp:tag>(.*?)</wp:tag>|is', $importline, $tag);
       
   122 					$this->tags[] = $tag[1];
       
   123 					continue;
       
   124 				}
       
   125 				if ( false !== strpos($importline, '<item>') ) {
       
   126 					$this->post = '';
       
   127 					$doing_entry = true;
       
   128 					continue;
       
   129 				}
       
   130 				if ( false !== strpos($importline, '</item>') ) {
       
   131 					$doing_entry = false;
       
   132 					if ($process_post_func)
       
   133 						call_user_func($process_post_func, $this->post);
       
   134 					continue;
       
   135 				}
       
   136 				if ( $doing_entry ) {
       
   137 					$this->post .= $importline . "\n";
       
   138 				}
       
   139 			}
       
   140 
       
   141 			$this->fclose($fp);
       
   142 		}
       
   143 
       
   144 		return $is_wxr_file;
       
   145 
       
   146 	}
       
   147 
       
   148 	function get_wp_authors() {
       
   149 		// We need to find unique values of author names, while preserving the order, so this function emulates the unique_value(); php function, without the sorting.
       
   150 		$temp = $this->allauthornames;
       
   151 		$authors[0] = array_shift($temp);
       
   152 		$y = count($temp) + 1;
       
   153 		for ($x = 1; $x < $y; $x ++) {
       
   154 			$next = array_shift($temp);
       
   155 			if (!(in_array($next, $authors)))
       
   156 				array_push($authors, "$next");
       
   157 		}
       
   158 
       
   159 		return $authors;
       
   160 	}
       
   161 
       
   162 	function get_authors_from_post() {
       
   163 		global $current_user;
       
   164 
       
   165 		// this will populate $this->author_ids with a list of author_names => user_ids
       
   166 
       
   167 		foreach ( $_POST['author_in'] as $i => $in_author_name ) {
       
   168 
       
   169 			if ( !empty($_POST['user_select'][$i]) ) {
       
   170 				// an existing user was selected in the dropdown list
       
   171 				$user = get_userdata( intval($_POST['user_select'][$i]) );
       
   172 				if ( isset($user->ID) )
       
   173 					$this->author_ids[$in_author_name] = $user->ID;
       
   174 			}
       
   175 			elseif ( $this->allow_create_users() ) {
       
   176 				// nothing was selected in the dropdown list, so we'll use the name in the text field
       
   177 
       
   178 				$new_author_name = trim($_POST['user_create'][$i]);
       
   179 				// if the user didn't enter a name, assume they want to use the same name as in the import file
       
   180 				if ( empty($new_author_name) )
       
   181 					$new_author_name = $in_author_name;
       
   182 
       
   183 				$user_id = username_exists($new_author_name);
       
   184 				if ( !$user_id ) {
       
   185 					$user_id = wp_create_user($new_author_name, wp_generate_password());
       
   186 				}
       
   187 
       
   188 				$this->author_ids[$in_author_name] = $user_id;
       
   189 			}
       
   190 
       
   191 			// failsafe: if the user_id was invalid, default to the current user
       
   192 			if ( empty($this->author_ids[$in_author_name]) ) {
       
   193 				$this->author_ids[$in_author_name] = intval($current_user->ID);
       
   194 			}
       
   195 		}
       
   196 
       
   197 	}
       
   198 
       
   199 	function wp_authors_form() {
       
   200 ?>
       
   201 <?php screen_icon(); ?>
       
   202 <h2><?php _e('Assign Authors'); ?></h2>
       
   203 <p><?php _e('To make it easier for you to edit and save the imported posts and drafts, you may want to change the name of the author of the posts. For example, you may want to import all the entries as <code>admin</code>s entries.'); ?></p>
       
   204 <?php
       
   205 	if ( $this->allow_create_users() ) {
       
   206 		echo '<p>'.__('If a new user is created by WordPress, a password will be randomly generated. Manually change the user&#8217;s details if necessary.')."</p>\n";
       
   207 	}
       
   208 
       
   209 
       
   210 		$authors = $this->get_wp_authors();
       
   211 		echo '<form action="?import=wordpress&amp;step=2&amp;id=' . $this->id . '" method="post">';
       
   212 		wp_nonce_field('import-wordpress');
       
   213 		echo '<ol id="authors">';
       
   214 		$j = -1;
       
   215 		foreach ($authors as $author) {
       
   216 			++ $j;
       
   217 			echo '<li>'.__('Import author:').' <strong>'.$author.'</strong><br />';
       
   218 			$this->users_form($j, $author);
       
   219 			echo '</li>';
       
   220 		}
       
   221 
       
   222 		if ( $this->allow_fetch_attachments() ) {
       
   223 ?>
       
   224 </ol>
       
   225 <?php screen_icon(); ?>
       
   226 <h2><?php _e('Import Attachments'); ?></h2>
       
   227 <p>
       
   228 	<input type="checkbox" value="1" name="attachments" id="import-attachments" />
       
   229 	<label for="import-attachments"><?php _e('Download and import file attachments') ?></label>
       
   230 </p>
       
   231 
       
   232 <?php
       
   233 		}
       
   234 
       
   235 		echo '<p class="submit">';
       
   236 		echo '<input type="submit" class="button" value="'. esc_attr__('Submit') .'" />'.'<br />';
       
   237 		echo '</p>';
       
   238 		echo '</form>';
       
   239 
       
   240 	}
       
   241 
       
   242 	function users_form($n, $author) {
       
   243 
       
   244 		if ( $this->allow_create_users() ) {
       
   245 			printf('<label>'.__('Create user %1$s or map to existing'), ' <input type="text" value="'. esc_attr($author) .'" name="'.'user_create['.intval($n).']'.'" maxlength="30" /></label> <br />');
       
   246 		}
       
   247 		else {
       
   248 			echo __('Map to existing').'<br />';
       
   249 		}
       
   250 
       
   251 		// keep track of $n => $author name
       
   252 		echo '<input type="hidden" name="author_in['.intval($n).']" value="' . esc_attr($author).'" />';
       
   253 
       
   254 		$users = get_users_of_blog();
       
   255 ?><select name="user_select[<?php echo $n; ?>]">
       
   256 	<option value="0"><?php _e('- Select -'); ?></option>
       
   257 	<?php
       
   258 		foreach ($users as $user) {
       
   259 			echo '<option value="'.$user->user_id.'">'.$user->user_login.'</option>';
       
   260 		}
       
   261 ?>
       
   262 	</select>
       
   263 	<?php
       
   264 	}
       
   265 
       
   266 	function select_authors() {
       
   267 		$is_wxr_file = $this->get_entries(array(&$this, 'process_author'));
       
   268 		if ( $is_wxr_file ) {
       
   269 			$this->wp_authors_form();
       
   270 		}
       
   271 		else {
       
   272 			echo '<h2>'.__('Invalid file').'</h2>';
       
   273 			echo '<p>'.__('Please upload a valid WXR (WordPress eXtended RSS) export file.').'</p>';
       
   274 		}
       
   275 	}
       
   276 
       
   277 	// fetch the user ID for a given author name, respecting the mapping preferences
       
   278 	function checkauthor($author) {
       
   279 		global $current_user;
       
   280 
       
   281 		if ( !empty($this->author_ids[$author]) )
       
   282 			return $this->author_ids[$author];
       
   283 
       
   284 		// failsafe: map to the current user
       
   285 		return $current_user->ID;
       
   286 	}
       
   287 
       
   288 
       
   289 
       
   290 	function process_categories() {
       
   291 		global $wpdb;
       
   292 
       
   293 		$cat_names = (array) get_terms('category', 'fields=names');
       
   294 
       
   295 		while ( $c = array_shift($this->categories) ) {
       
   296 			$cat_name = trim($this->get_tag( $c, 'wp:cat_name' ));
       
   297 
       
   298 			// If the category exists we leave it alone
       
   299 			if ( in_array($cat_name, $cat_names) )
       
   300 				continue;
       
   301 
       
   302 			$category_nicename	= $this->get_tag( $c, 'wp:category_nicename' );
       
   303 			$category_description = $this->get_tag( $c, 'wp:category_description' );
       
   304 			$posts_private		= (int) $this->get_tag( $c, 'wp:posts_private' );
       
   305 			$links_private		= (int) $this->get_tag( $c, 'wp:links_private' );
       
   306 
       
   307 			$parent = $this->get_tag( $c, 'wp:category_parent' );
       
   308 
       
   309 			if ( empty($parent) )
       
   310 				$category_parent = '0';
       
   311 			else
       
   312 				$category_parent = category_exists($parent);
       
   313 
       
   314 			$catarr = compact('category_nicename', 'category_parent', 'posts_private', 'links_private', 'posts_private', 'cat_name', 'category_description');
       
   315 
       
   316 			$cat_ID = wp_insert_category($catarr);
       
   317 		}
       
   318 	}
       
   319 
       
   320 	function process_tags() {
       
   321 		global $wpdb;
       
   322 
       
   323 		$tag_names = (array) get_terms('post_tag', 'fields=names');
       
   324 
       
   325 		while ( $c = array_shift($this->tags) ) {
       
   326 			$tag_name = trim($this->get_tag( $c, 'wp:tag_name' ));
       
   327 
       
   328 			// If the category exists we leave it alone
       
   329 			if ( in_array($tag_name, $tag_names) )
       
   330 				continue;
       
   331 
       
   332 			$slug = $this->get_tag( $c, 'wp:tag_slug' );
       
   333 			$description = $this->get_tag( $c, 'wp:tag_description' );
       
   334 
       
   335 			$tagarr = compact('slug', 'description');
       
   336 
       
   337 			$tag_ID = wp_insert_term($tag_name, 'post_tag', $tagarr);
       
   338 		}
       
   339 	}
       
   340 
       
   341 	function process_author($post) {
       
   342 		$author = $this->get_tag( $post, 'dc:creator' );
       
   343 		if ($author)
       
   344 			$this->allauthornames[] = $author;
       
   345 	}
       
   346 
       
   347 	function process_posts() {
       
   348 		echo '<ol>';
       
   349 
       
   350 		$this->get_entries(array(&$this, 'process_post'));
       
   351 
       
   352 		echo '</ol>';
       
   353 
       
   354 		wp_import_cleanup($this->id);
       
   355 		do_action('import_done', 'wordpress');
       
   356 
       
   357 		echo '<h3>'.sprintf(__('All done.').' <a href="%s">'.__('Have fun!').'</a>', get_option('home')).'</h3>';
       
   358 	}
       
   359 
       
   360 	function process_post($post) {
       
   361 		global $wpdb;
       
   362 
       
   363 		$post_ID = (int) $this->get_tag( $post, 'wp:post_id' );
       
   364   		if ( $post_ID && !empty($this->post_ids_processed[$post_ID]) ) // Processed already
       
   365 			return 0;
       
   366 
       
   367 		set_time_limit( 60 );
       
   368 
       
   369 		// There are only ever one of these
       
   370 		$post_title     = $this->get_tag( $post, 'title' );
       
   371 		$post_date      = $this->get_tag( $post, 'wp:post_date' );
       
   372 		$post_date_gmt  = $this->get_tag( $post, 'wp:post_date_gmt' );
       
   373 		$comment_status = $this->get_tag( $post, 'wp:comment_status' );
       
   374 		$ping_status    = $this->get_tag( $post, 'wp:ping_status' );
       
   375 		$post_status    = $this->get_tag( $post, 'wp:status' );
       
   376 		$post_name      = $this->get_tag( $post, 'wp:post_name' );
       
   377 		$post_parent    = $this->get_tag( $post, 'wp:post_parent' );
       
   378 		$menu_order     = $this->get_tag( $post, 'wp:menu_order' );
       
   379 		$post_type      = $this->get_tag( $post, 'wp:post_type' );
       
   380 		$post_password  = $this->get_tag( $post, 'wp:post_password' );
       
   381 		$guid           = $this->get_tag( $post, 'guid' );
       
   382 		$post_author    = $this->get_tag( $post, 'dc:creator' );
       
   383 
       
   384 		$post_excerpt = $this->get_tag( $post, 'excerpt:encoded' );
       
   385 		$post_excerpt = preg_replace_callback('|<(/?[A-Z]+)|', create_function('$match', 'return "<" . strtolower($match[1]);'), $post_excerpt);
       
   386 		$post_excerpt = str_replace('<br>', '<br />', $post_excerpt);
       
   387 		$post_excerpt = str_replace('<hr>', '<hr />', $post_excerpt);
       
   388 
       
   389 		$post_content = $this->get_tag( $post, 'content:encoded' );
       
   390 		$post_content = preg_replace_callback('|<(/?[A-Z]+)|', create_function('$match', 'return "<" . strtolower($match[1]);'), $post_content);
       
   391 		$post_content = str_replace('<br>', '<br />', $post_content);
       
   392 		$post_content = str_replace('<hr>', '<hr />', $post_content);
       
   393 
       
   394 		preg_match_all('|<category domain="tag">(.*?)</category>|is', $post, $tags);
       
   395 		$tags = $tags[1];
       
   396 
       
   397 		$tag_index = 0;
       
   398 		foreach ($tags as $tag) {
       
   399 			$tags[$tag_index] = $wpdb->escape($this->unhtmlentities(str_replace(array ('<![CDATA[', ']]>'), '', $tag)));
       
   400 			$tag_index++;
       
   401 		}
       
   402 
       
   403 		preg_match_all('|<category>(.*?)</category>|is', $post, $categories);
       
   404 		$categories = $categories[1];
       
   405 
       
   406 		$cat_index = 0;
       
   407 		foreach ($categories as $category) {
       
   408 			$categories[$cat_index] = $wpdb->escape($this->unhtmlentities(str_replace(array ('<![CDATA[', ']]>'), '', $category)));
       
   409 			$cat_index++;
       
   410 		}
       
   411 
       
   412 		$post_exists = post_exists($post_title, '', $post_date);
       
   413 
       
   414 		if ( $post_exists ) {
       
   415 			echo '<li>';
       
   416 			printf(__('Post <em>%s</em> already exists.'), stripslashes($post_title));
       
   417 			$comment_post_ID = $post_id = $post_exists;
       
   418 		} else {
       
   419 
       
   420 			// If it has parent, process parent first.
       
   421 			$post_parent = (int) $post_parent;
       
   422 			if ($post_parent) {
       
   423 				// if we already know the parent, map it to the local ID
       
   424 				if ( $parent = $this->post_ids_processed[$post_parent] ) {
       
   425 					$post_parent = $parent;  // new ID of the parent
       
   426 				}
       
   427 				else {
       
   428 					// record the parent for later
       
   429 					$this->orphans[intval($post_ID)] = $post_parent;
       
   430 				}
       
   431 			}
       
   432 
       
   433 			echo '<li>';
       
   434 
       
   435 			$post_author = $this->checkauthor($post_author); //just so that if a post already exists, new users are not created by checkauthor
       
   436 
       
   437 			$postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_excerpt', 'post_title', 'post_status', 'post_name', 'comment_status', 'ping_status', 'guid', 'post_parent', 'menu_order', 'post_type', 'post_password');
       
   438 			$postdata['import_id'] = $post_ID;
       
   439 			if ($post_type == 'attachment') {
       
   440 				$remote_url = $this->get_tag( $post, 'wp:attachment_url' );
       
   441 				if ( !$remote_url )
       
   442 					$remote_url = $guid;
       
   443 
       
   444 				$comment_post_ID = $post_id = $this->process_attachment($postdata, $remote_url);
       
   445 				if ( !$post_id or is_wp_error($post_id) )
       
   446 					return $post_id;
       
   447 			}
       
   448 			else {
       
   449 				printf(__('Importing post <em>%s</em>...'), stripslashes($post_title));
       
   450 				$comment_post_ID = $post_id = wp_insert_post($postdata);
       
   451 			}
       
   452 
       
   453 			if ( is_wp_error( $post_id ) )
       
   454 				return $post_id;
       
   455 
       
   456 			// Memorize old and new ID.
       
   457 			if ( $post_id && $post_ID ) {
       
   458 				$this->post_ids_processed[intval($post_ID)] = intval($post_id);
       
   459 			}
       
   460 
       
   461 			// Add categories.
       
   462 			if (count($categories) > 0) {
       
   463 				$post_cats = array();
       
   464 				foreach ($categories as $category) {
       
   465 					if ( '' == $category )
       
   466 						continue;
       
   467 					$slug = sanitize_term_field('slug', $category, 0, 'category', 'db');
       
   468 					$cat = get_term_by('slug', $slug, 'category');
       
   469 					$cat_ID = 0;
       
   470 					if ( ! empty($cat) )
       
   471 						$cat_ID = $cat->term_id;
       
   472 					if ($cat_ID == 0) {
       
   473 						$category = $wpdb->escape($category);
       
   474 						$cat_ID = wp_insert_category(array('cat_name' => $category));
       
   475 						if ( is_wp_error($cat_ID) )
       
   476 							continue;
       
   477 					}
       
   478 					$post_cats[] = $cat_ID;
       
   479 				}
       
   480 				wp_set_post_categories($post_id, $post_cats);
       
   481 			}
       
   482 
       
   483 			// Add tags.
       
   484 			if (count($tags) > 0) {
       
   485 				$post_tags = array();
       
   486 				foreach ($tags as $tag) {
       
   487 					if ( '' == $tag )
       
   488 						continue;
       
   489 					$slug = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
       
   490 					$tag_obj = get_term_by('slug', $slug, 'post_tag');
       
   491 					$tag_id = 0;
       
   492 					if ( ! empty($tag_obj) )
       
   493 						$tag_id = $tag_obj->term_id;
       
   494 					if ( $tag_id == 0 ) {
       
   495 						$tag = $wpdb->escape($tag);
       
   496 						$tag_id = wp_insert_term($tag, 'post_tag');
       
   497 						if ( is_wp_error($tag_id) )
       
   498 							continue;
       
   499 						$tag_id = $tag_id['term_id'];
       
   500 					}
       
   501 					$post_tags[] = intval($tag_id);
       
   502 				}
       
   503 				wp_set_post_tags($post_id, $post_tags);
       
   504 			}
       
   505 		}
       
   506 
       
   507 		// Now for comments
       
   508 		preg_match_all('|<wp:comment>(.*?)</wp:comment>|is', $post, $comments);
       
   509 		$comments = $comments[1];
       
   510 		$num_comments = 0;
       
   511 		if ( $comments) { foreach ($comments as $comment) {
       
   512 			$comment_author       = $this->get_tag( $comment, 'wp:comment_author');
       
   513 			$comment_author_email = $this->get_tag( $comment, 'wp:comment_author_email');
       
   514 			$comment_author_IP    = $this->get_tag( $comment, 'wp:comment_author_IP');
       
   515 			$comment_author_url   = $this->get_tag( $comment, 'wp:comment_author_url');
       
   516 			$comment_date         = $this->get_tag( $comment, 'wp:comment_date');
       
   517 			$comment_date_gmt     = $this->get_tag( $comment, 'wp:comment_date_gmt');
       
   518 			$comment_content      = $this->get_tag( $comment, 'wp:comment_content');
       
   519 			$comment_approved     = $this->get_tag( $comment, 'wp:comment_approved');
       
   520 			$comment_type         = $this->get_tag( $comment, 'wp:comment_type');
       
   521 			$comment_parent       = $this->get_tag( $comment, 'wp:comment_parent');
       
   522 
       
   523 			// if this is a new post we can skip the comment_exists() check
       
   524 			if ( !$post_exists || !comment_exists($comment_author, $comment_date) ) {
       
   525 				$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_approved', 'comment_type', 'comment_parent');
       
   526 				wp_insert_comment($commentdata);
       
   527 				$num_comments++;
       
   528 			}
       
   529 		} }
       
   530 
       
   531 		if ( $num_comments )
       
   532 			printf(' '._n('(%s comment)', '(%s comments)', $num_comments), $num_comments);
       
   533 
       
   534 		// Now for post meta
       
   535 		preg_match_all('|<wp:postmeta>(.*?)</wp:postmeta>|is', $post, $postmeta);
       
   536 		$postmeta = $postmeta[1];
       
   537 		if ( $postmeta) { foreach ($postmeta as $p) {
       
   538 			$key   = $this->get_tag( $p, 'wp:meta_key' );
       
   539 			$value = $this->get_tag( $p, 'wp:meta_value' );
       
   540 			$value = stripslashes($value); // add_post_meta() will escape.
       
   541 
       
   542 			$this->process_post_meta($post_id, $key, $value);
       
   543 
       
   544 		} }
       
   545 
       
   546 		do_action('import_post_added', $post_id);
       
   547 		print "</li>\n";
       
   548 	}
       
   549 
       
   550 	function process_post_meta($post_id, $key, $value) {
       
   551 		// the filter can return false to skip a particular metadata key
       
   552 		$_key = apply_filters('import_post_meta_key', $key);
       
   553 		if ( $_key ) {
       
   554 			add_post_meta( $post_id, $_key, $value );
       
   555 			do_action('import_post_meta', $post_id, $_key, $value);
       
   556 		}
       
   557 	}
       
   558 
       
   559 	function process_attachment($postdata, $remote_url) {
       
   560 		if ($this->fetch_attachments and $remote_url) {
       
   561 			printf( __('Importing attachment <em>%s</em>... '), htmlspecialchars($remote_url) );
       
   562 
       
   563 			// If the URL is absolute, but does not contain http, upload it assuming the base_site_url variable
       
   564 			if ( preg_match('/^\/[\w\W]+$/', $remote_url) )
       
   565 				$remote_url = rtrim($this->base_url,'/').$remote_url;
       
   566 
       
   567 			$upload = $this->fetch_remote_file($postdata, $remote_url);
       
   568 			if ( is_wp_error($upload) ) {
       
   569 				printf( __('Remote file error: %s'), htmlspecialchars($upload->get_error_message()) );
       
   570 				return $upload;
       
   571 			}
       
   572 			else {
       
   573 				print '('.size_format(filesize($upload['file'])).')';
       
   574 			}
       
   575 
       
   576 			if ( $info = wp_check_filetype($upload['file']) ) {
       
   577 				$postdata['post_mime_type'] = $info['type'];
       
   578 			}
       
   579 			else {
       
   580 				print __('Invalid file type');
       
   581 				return;
       
   582 			}
       
   583 
       
   584 			$postdata['guid'] = $upload['url'];
       
   585 
       
   586 			// as per wp-admin/includes/upload.php
       
   587 			$post_id = wp_insert_attachment($postdata, $upload['file']);
       
   588 			wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );
       
   589 
       
   590 			// remap the thumbnail url.  this isn't perfect because we're just guessing the original url.
       
   591 			if ( preg_match('@^image/@', $info['type']) && $thumb_url = wp_get_attachment_thumb_url($post_id) ) {
       
   592 				$parts = pathinfo($remote_url);
       
   593 				$ext = $parts['extension'];
       
   594 				$name = basename($parts['basename'], ".{$ext}");
       
   595 				$this->url_remap[$parts['dirname'] . '/' . $name . '.thumbnail.' . $ext] = $thumb_url;
       
   596 			}
       
   597 
       
   598 			return $post_id;
       
   599 		}
       
   600 		else {
       
   601 			printf( __('Skipping attachment <em>%s</em>'), htmlspecialchars($remote_url) );
       
   602 		}
       
   603 	}
       
   604 
       
   605 	function fetch_remote_file($post, $url) {
       
   606 		$upload = wp_upload_dir($post['post_date']);
       
   607 
       
   608 		// extract the file name and extension from the url
       
   609 		$file_name = basename($url);
       
   610 
       
   611 		// get placeholder file in the upload dir with a unique sanitized filename
       
   612 		$upload = wp_upload_bits( $file_name, 0, '', $post['post_date']);
       
   613 		if ( $upload['error'] ) {
       
   614 			echo $upload['error'];
       
   615 			return new WP_Error( 'upload_dir_error', $upload['error'] );
       
   616 		}
       
   617 
       
   618 		// fetch the remote url and write it to the placeholder file
       
   619 		$headers = wp_get_http($url, $upload['file']);
       
   620 
       
   621 		//Request failed
       
   622 		if ( ! $headers ) {
       
   623 			@unlink($upload['file']);
       
   624 			return new WP_Error( 'import_file_error', __('Remote server did not respond') );
       
   625 		}
       
   626 
       
   627 		// make sure the fetch was successful
       
   628 		if ( $headers['response'] != '200' ) {
       
   629 			@unlink($upload['file']);
       
   630 			return new WP_Error( 'import_file_error', sprintf(__('Remote file returned error response %1$d %2$s'), $headers['response'], get_status_header_desc($headers['response']) ) );
       
   631 		}
       
   632 		elseif ( isset($headers['content-length']) && filesize($upload['file']) != $headers['content-length'] ) {
       
   633 			@unlink($upload['file']);
       
   634 			return new WP_Error( 'import_file_error', __('Remote file is incorrect size') );
       
   635 		}
       
   636 
       
   637 		$max_size = $this->max_attachment_size();
       
   638 		if ( !empty($max_size) and filesize($upload['file']) > $max_size ) {
       
   639 			@unlink($upload['file']);
       
   640 			return new WP_Error( 'import_file_error', sprintf(__('Remote file is too large, limit is %s', size_format($max_size))) );
       
   641 		}
       
   642 
       
   643 		// keep track of the old and new urls so we can substitute them later
       
   644 		$this->url_remap[$url] = $upload['url'];
       
   645 		// if the remote url is redirected somewhere else, keep track of the destination too
       
   646 		if ( $headers['x-final-location'] != $url )
       
   647 			$this->url_remap[$headers['x-final-location']] = $upload['url'];
       
   648 
       
   649 		return $upload;
       
   650 
       
   651 	}
       
   652 
       
   653 	// sort by strlen, longest string first
       
   654 	function cmpr_strlen($a, $b) {
       
   655 		return strlen($b) - strlen($a);
       
   656 	}
       
   657 
       
   658 	// update url references in post bodies to point to the new local files
       
   659 	function backfill_attachment_urls() {
       
   660 
       
   661 		// make sure we do the longest urls first, in case one is a substring of another
       
   662 		uksort($this->url_remap, array(&$this, 'cmpr_strlen'));
       
   663 
       
   664 		global $wpdb;
       
   665 		foreach ($this->url_remap as $from_url => $to_url) {
       
   666 			// remap urls in post_content
       
   667 			$wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, '%s', '%s')", $from_url, $to_url) );
       
   668 			// remap enclosure urls
       
   669 			$result = $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, '%s', '%s') WHERE meta_key='enclosure'", $from_url, $to_url) );
       
   670 		}
       
   671 	}
       
   672 
       
   673 	// update the post_parent of orphans now that we know the local id's of all parents
       
   674 	function backfill_parents() {
       
   675 		global $wpdb;
       
   676 
       
   677 		foreach ($this->orphans as $child_id => $parent_id) {
       
   678 			$local_child_id = $this->post_ids_processed[$child_id];
       
   679 			$local_parent_id = $this->post_ids_processed[$parent_id];
       
   680 			if ($local_child_id and $local_parent_id) {
       
   681 				$wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_parent = %d WHERE ID = %d", $local_parent_id, $local_child_id));
       
   682 			}
       
   683 		}
       
   684 	}
       
   685 
       
   686 	function is_valid_meta_key($key) {
       
   687 		// skip attachment metadata since we'll regenerate it from scratch
       
   688 		if ( $key == '_wp_attached_file' || $key == '_wp_attachment_metadata' )
       
   689 			return false;
       
   690 		return $key;
       
   691 	}
       
   692 
       
   693 	// give the user the option of creating new users to represent authors in the import file?
       
   694 	function allow_create_users() {
       
   695 		return apply_filters('import_allow_create_users', true);
       
   696 	}
       
   697 
       
   698 	// give the user the option of downloading and importing attached files
       
   699 	function allow_fetch_attachments() {
       
   700 		return apply_filters('import_allow_fetch_attachments', true);
       
   701 	}
       
   702 
       
   703 	function max_attachment_size() {
       
   704 		// can be overridden with a filter - 0 means no limit
       
   705 		return apply_filters('import_attachment_size_limit', 0);
       
   706 	}
       
   707 
       
   708 	function import_start() {
       
   709 		wp_defer_term_counting(true);
       
   710 		wp_defer_comment_counting(true);
       
   711 		do_action('import_start');
       
   712 	}
       
   713 
       
   714 	function import_end() {
       
   715 		do_action('import_end');
       
   716 
       
   717 		// clear the caches after backfilling
       
   718 		foreach ($this->post_ids_processed as $post_id)
       
   719 			clean_post_cache($post_id);
       
   720 
       
   721 		wp_defer_term_counting(false);
       
   722 		wp_defer_comment_counting(false);
       
   723 	}
       
   724 
       
   725 	function import($id, $fetch_attachments = false) {
       
   726 		$this->id = (int) $id;
       
   727 		$this->fetch_attachments = ($this->allow_fetch_attachments() && (bool) $fetch_attachments);
       
   728 
       
   729 		add_filter('import_post_meta_key', array($this, 'is_valid_meta_key'));
       
   730 		$file = get_attached_file($this->id);
       
   731 		$this->import_file($file);
       
   732 	}
       
   733 
       
   734 	function import_file($file) {
       
   735 		$this->file = $file;
       
   736 
       
   737 		$this->import_start();
       
   738 		$this->get_authors_from_post();
       
   739 		wp_suspend_cache_invalidation(true);
       
   740 		$this->get_entries();
       
   741 		$this->process_categories();
       
   742 		$this->process_tags();
       
   743 		$result = $this->process_posts();
       
   744 		wp_suspend_cache_invalidation(false);
       
   745 		$this->backfill_parents();
       
   746 		$this->backfill_attachment_urls();
       
   747 		$this->import_end();
       
   748 
       
   749 		if ( is_wp_error( $result ) )
       
   750 			return $result;
       
   751 	}
       
   752 
       
   753 	function handle_upload() {
       
   754 		$file = wp_import_handle_upload();
       
   755 		if ( isset($file['error']) ) {
       
   756 			echo '<p>'.__('Sorry, there has been an error.').'</p>';
       
   757 			echo '<p><strong>' . $file['error'] . '</strong></p>';
       
   758 			return false;
       
   759 		}
       
   760 		$this->file = $file['file'];
       
   761 		$this->id = (int) $file['id'];
       
   762 		return true;
       
   763 	}
       
   764 
       
   765 	function dispatch() {
       
   766 		if (empty ($_GET['step']))
       
   767 			$step = 0;
       
   768 		else
       
   769 			$step = (int) $_GET['step'];
       
   770 
       
   771 		$this->header();
       
   772 		switch ($step) {
       
   773 			case 0 :
       
   774 				$this->greet();
       
   775 				break;
       
   776 			case 1 :
       
   777 				check_admin_referer('import-upload');
       
   778 				if ( $this->handle_upload() )
       
   779 					$this->select_authors();
       
   780 				break;
       
   781 			case 2:
       
   782 				check_admin_referer('import-wordpress');
       
   783 				$result = $this->import( $_GET['id'], $_POST['attachments'] );
       
   784 				if ( is_wp_error( $result ) )
       
   785 					echo $result->get_error_message();
       
   786 				break;
       
   787 		}
       
   788 		$this->footer();
       
   789 	}
       
   790 
       
   791 	function WP_Import() {
       
   792 		// Nothing.
       
   793 	}
       
   794 }
       
   795 
       
   796 /**
       
   797  * Register WordPress Importer
       
   798  *
       
   799  * @since unknown
       
   800  * @var WP_Import
       
   801  * @name $wp_import
       
   802  */
       
   803 $wp_import = new WP_Import();
       
   804 
       
   805 register_importer('wordpress', 'WordPress', __('Import <strong>posts, pages, comments, custom fields, categories, and tags</strong> from a WordPress export file.'), array ($wp_import, 'dispatch'));
       
   806 
       
   807 ?>