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