|
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’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&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’s details if necessary.')."</p>\n"; |
|
207 } |
|
208 |
|
209 |
|
210 $authors = $this->get_wp_authors(); |
|
211 echo '<form action="?import=wordpress&step=2&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 ?> |