|
1 <?php |
|
2 /* |
|
3 Plugin Name: WordPress Importer |
|
4 Plugin URI: http://wordpress.org/extend/plugins/wordpress-importer/ |
|
5 Description: Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file. |
|
6 Author: wordpressdotorg |
|
7 Author URI: http://wordpress.org/ |
|
8 Version: 0.6.1 |
|
9 Text Domain: wordpress-importer |
|
10 License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|
11 */ |
|
12 |
|
13 if ( ! defined( 'WP_LOAD_IMPORTERS' ) ) |
|
14 return; |
|
15 |
|
16 /** Display verbose errors */ |
|
17 define( 'IMPORT_DEBUG', false ); |
|
18 |
|
19 // Load Importer API |
|
20 require_once ABSPATH . 'wp-admin/includes/import.php'; |
|
21 |
|
22 if ( ! class_exists( 'WP_Importer' ) ) { |
|
23 $class_wp_importer = ABSPATH . 'wp-admin/includes/class-wp-importer.php'; |
|
24 if ( file_exists( $class_wp_importer ) ) |
|
25 require $class_wp_importer; |
|
26 } |
|
27 |
|
28 // include WXR file parsers |
|
29 require dirname( __FILE__ ) . '/parsers.php'; |
|
30 |
|
31 /** |
|
32 * WordPress Importer class for managing the import process of a WXR file |
|
33 * |
|
34 * @package WordPress |
|
35 * @subpackage Importer |
|
36 */ |
|
37 if ( class_exists( 'WP_Importer' ) ) { |
|
38 class WP_Import extends WP_Importer { |
|
39 var $max_wxr_version = 1.2; // max. supported WXR version |
|
40 |
|
41 var $id; // WXR attachment ID |
|
42 |
|
43 // information to import from WXR file |
|
44 var $version; |
|
45 var $authors = array(); |
|
46 var $posts = array(); |
|
47 var $terms = array(); |
|
48 var $categories = array(); |
|
49 var $tags = array(); |
|
50 var $base_url = ''; |
|
51 |
|
52 // mappings from old information to new |
|
53 var $processed_authors = array(); |
|
54 var $author_mapping = array(); |
|
55 var $processed_terms = array(); |
|
56 var $processed_posts = array(); |
|
57 var $post_orphans = array(); |
|
58 var $processed_menu_items = array(); |
|
59 var $menu_item_orphans = array(); |
|
60 var $missing_menu_items = array(); |
|
61 |
|
62 var $fetch_attachments = false; |
|
63 var $url_remap = array(); |
|
64 var $featured_images = array(); |
|
65 |
|
66 function WP_Import() { /* nothing */ } |
|
67 |
|
68 /** |
|
69 * Registered callback function for the WordPress Importer |
|
70 * |
|
71 * Manages the three separate stages of the WXR import process |
|
72 */ |
|
73 function dispatch() { |
|
74 $this->header(); |
|
75 |
|
76 $step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step']; |
|
77 switch ( $step ) { |
|
78 case 0: |
|
79 $this->greet(); |
|
80 break; |
|
81 case 1: |
|
82 check_admin_referer( 'import-upload' ); |
|
83 if ( $this->handle_upload() ) |
|
84 $this->import_options(); |
|
85 break; |
|
86 case 2: |
|
87 check_admin_referer( 'import-wordpress' ); |
|
88 $this->fetch_attachments = ( ! empty( $_POST['fetch_attachments'] ) && $this->allow_fetch_attachments() ); |
|
89 $this->id = (int) $_POST['import_id']; |
|
90 $file = get_attached_file( $this->id ); |
|
91 set_time_limit(0); |
|
92 $this->import( $file ); |
|
93 break; |
|
94 } |
|
95 |
|
96 $this->footer(); |
|
97 } |
|
98 |
|
99 /** |
|
100 * The main controller for the actual import stage. |
|
101 * |
|
102 * @param string $file Path to the WXR file for importing |
|
103 */ |
|
104 function import( $file ) { |
|
105 add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) ); |
|
106 add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) ); |
|
107 |
|
108 $this->import_start( $file ); |
|
109 |
|
110 $this->get_author_mapping(); |
|
111 |
|
112 wp_suspend_cache_invalidation( true ); |
|
113 $this->process_categories(); |
|
114 $this->process_tags(); |
|
115 $this->process_terms(); |
|
116 $this->process_posts(); |
|
117 wp_suspend_cache_invalidation( false ); |
|
118 |
|
119 // update incorrect/missing information in the DB |
|
120 $this->backfill_parents(); |
|
121 $this->backfill_attachment_urls(); |
|
122 $this->remap_featured_images(); |
|
123 |
|
124 $this->import_end(); |
|
125 } |
|
126 |
|
127 /** |
|
128 * Parses the WXR file and prepares us for the task of processing parsed data |
|
129 * |
|
130 * @param string $file Path to the WXR file for importing |
|
131 */ |
|
132 function import_start( $file ) { |
|
133 if ( ! is_file($file) ) { |
|
134 echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />'; |
|
135 echo __( 'The file does not exist, please try again.', 'wordpress-importer' ) . '</p>'; |
|
136 $this->footer(); |
|
137 die(); |
|
138 } |
|
139 |
|
140 $import_data = $this->parse( $file ); |
|
141 |
|
142 if ( is_wp_error( $import_data ) ) { |
|
143 echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />'; |
|
144 echo esc_html( $import_data->get_error_message() ) . '</p>'; |
|
145 $this->footer(); |
|
146 die(); |
|
147 } |
|
148 |
|
149 $this->version = $import_data['version']; |
|
150 $this->get_authors_from_import( $import_data ); |
|
151 $this->posts = $import_data['posts']; |
|
152 $this->terms = $import_data['terms']; |
|
153 $this->categories = $import_data['categories']; |
|
154 $this->tags = $import_data['tags']; |
|
155 $this->base_url = esc_url( $import_data['base_url'] ); |
|
156 |
|
157 wp_defer_term_counting( true ); |
|
158 wp_defer_comment_counting( true ); |
|
159 |
|
160 do_action( 'import_start' ); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Performs post-import cleanup of files and the cache |
|
165 */ |
|
166 function import_end() { |
|
167 wp_import_cleanup( $this->id ); |
|
168 |
|
169 wp_cache_flush(); |
|
170 foreach ( get_taxonomies() as $tax ) { |
|
171 delete_option( "{$tax}_children" ); |
|
172 _get_term_hierarchy( $tax ); |
|
173 } |
|
174 |
|
175 wp_defer_term_counting( false ); |
|
176 wp_defer_comment_counting( false ); |
|
177 |
|
178 echo '<p>' . __( 'All done.', 'wordpress-importer' ) . ' <a href="' . admin_url() . '">' . __( 'Have fun!', 'wordpress-importer' ) . '</a>' . '</p>'; |
|
179 echo '<p>' . __( 'Remember to update the passwords and roles of imported users.', 'wordpress-importer' ) . '</p>'; |
|
180 |
|
181 do_action( 'import_end' ); |
|
182 } |
|
183 |
|
184 /** |
|
185 * Handles the WXR upload and initial parsing of the file to prepare for |
|
186 * displaying author import options |
|
187 * |
|
188 * @return bool False if error uploading or invalid file, true otherwise |
|
189 */ |
|
190 function handle_upload() { |
|
191 $file = wp_import_handle_upload(); |
|
192 |
|
193 if ( isset( $file['error'] ) ) { |
|
194 echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />'; |
|
195 echo esc_html( $file['error'] ) . '</p>'; |
|
196 return false; |
|
197 } else if ( ! file_exists( $file['file'] ) ) { |
|
198 echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />'; |
|
199 printf( __( 'The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', 'wordpress-importer' ), esc_html( $file['file'] ) ); |
|
200 echo '</p>'; |
|
201 return false; |
|
202 } |
|
203 |
|
204 $this->id = (int) $file['id']; |
|
205 $import_data = $this->parse( $file['file'] ); |
|
206 if ( is_wp_error( $import_data ) ) { |
|
207 echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />'; |
|
208 echo esc_html( $import_data->get_error_message() ) . '</p>'; |
|
209 return false; |
|
210 } |
|
211 |
|
212 $this->version = $import_data['version']; |
|
213 if ( $this->version > $this->max_wxr_version ) { |
|
214 echo '<div class="error"><p><strong>'; |
|
215 printf( __( 'This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'wordpress-importer' ), esc_html($import_data['version']) ); |
|
216 echo '</strong></p></div>'; |
|
217 } |
|
218 |
|
219 $this->get_authors_from_import( $import_data ); |
|
220 |
|
221 return true; |
|
222 } |
|
223 |
|
224 /** |
|
225 * Retrieve authors from parsed WXR data |
|
226 * |
|
227 * Uses the provided author information from WXR 1.1 files |
|
228 * or extracts info from each post for WXR 1.0 files |
|
229 * |
|
230 * @param array $import_data Data returned by a WXR parser |
|
231 */ |
|
232 function get_authors_from_import( $import_data ) { |
|
233 if ( ! empty( $import_data['authors'] ) ) { |
|
234 $this->authors = $import_data['authors']; |
|
235 // no author information, grab it from the posts |
|
236 } else { |
|
237 foreach ( $import_data['posts'] as $post ) { |
|
238 $login = sanitize_user( $post['post_author'], true ); |
|
239 if ( empty( $login ) ) { |
|
240 printf( __( 'Failed to import author %s. Their posts will be attributed to the current user.', 'wordpress-importer' ), esc_html( $post['post_author'] ) ); |
|
241 echo '<br />'; |
|
242 continue; |
|
243 } |
|
244 |
|
245 if ( ! isset($this->authors[$login]) ) |
|
246 $this->authors[$login] = array( |
|
247 'author_login' => $login, |
|
248 'author_display_name' => $post['post_author'] |
|
249 ); |
|
250 } |
|
251 } |
|
252 } |
|
253 |
|
254 /** |
|
255 * Display pre-import options, author importing/mapping and option to |
|
256 * fetch attachments |
|
257 */ |
|
258 function import_options() { |
|
259 $j = 0; |
|
260 ?> |
|
261 <form action="<?php echo admin_url( 'admin.php?import=wordpress&step=2' ); ?>" method="post"> |
|
262 <?php wp_nonce_field( 'import-wordpress' ); ?> |
|
263 <input type="hidden" name="import_id" value="<?php echo $this->id; ?>" /> |
|
264 |
|
265 <?php if ( ! empty( $this->authors ) ) : ?> |
|
266 <h3><?php _e( 'Assign Authors', 'wordpress-importer' ); ?></h3> |
|
267 <p><?php _e( 'To make it easier for you to edit and save the imported content, you may want to reassign the author of the imported item to an existing user of this site. For example, you may want to import all the entries as <code>admin</code>s entries.', 'wordpress-importer' ); ?></p> |
|
268 <?php if ( $this->allow_create_users() ) : ?> |
|
269 <p><?php printf( __( 'If a new user is created by WordPress, a new password will be randomly generated and the new user’s role will be set as %s. Manually changing the new user’s details will be necessary.', 'wordpress-importer' ), esc_html( get_option('default_role') ) ); ?></p> |
|
270 <?php endif; ?> |
|
271 <ol id="authors"> |
|
272 <?php foreach ( $this->authors as $author ) : ?> |
|
273 <li><?php $this->author_select( $j++, $author ); ?></li> |
|
274 <?php endforeach; ?> |
|
275 </ol> |
|
276 <?php endif; ?> |
|
277 |
|
278 <?php if ( $this->allow_fetch_attachments() ) : ?> |
|
279 <h3><?php _e( 'Import Attachments', 'wordpress-importer' ); ?></h3> |
|
280 <p> |
|
281 <input type="checkbox" value="1" name="fetch_attachments" id="import-attachments" /> |
|
282 <label for="import-attachments"><?php _e( 'Download and import file attachments', 'wordpress-importer' ); ?></label> |
|
283 </p> |
|
284 <?php endif; ?> |
|
285 |
|
286 <p class="submit"><input type="submit" class="button" value="<?php esc_attr_e( 'Submit', 'wordpress-importer' ); ?>" /></p> |
|
287 </form> |
|
288 <?php |
|
289 } |
|
290 |
|
291 /** |
|
292 * Display import options for an individual author. That is, either create |
|
293 * a new user based on import info or map to an existing user |
|
294 * |
|
295 * @param int $n Index for each author in the form |
|
296 * @param array $author Author information, e.g. login, display name, email |
|
297 */ |
|
298 function author_select( $n, $author ) { |
|
299 _e( 'Import author:', 'wordpress-importer' ); |
|
300 echo ' <strong>' . esc_html( $author['author_display_name'] ); |
|
301 if ( $this->version != '1.0' ) echo ' (' . esc_html( $author['author_login'] ) . ')'; |
|
302 echo '</strong><br />'; |
|
303 |
|
304 if ( $this->version != '1.0' ) |
|
305 echo '<div style="margin-left:18px">'; |
|
306 |
|
307 $create_users = $this->allow_create_users(); |
|
308 if ( $create_users ) { |
|
309 if ( $this->version != '1.0' ) { |
|
310 _e( 'or create new user with login name:', 'wordpress-importer' ); |
|
311 $value = ''; |
|
312 } else { |
|
313 _e( 'as a new user:', 'wordpress-importer' ); |
|
314 $value = esc_attr( sanitize_user( $author['author_login'], true ) ); |
|
315 } |
|
316 |
|
317 echo ' <input type="text" name="user_new['.$n.']" value="'. $value .'" /><br />'; |
|
318 } |
|
319 |
|
320 if ( ! $create_users && $this->version == '1.0' ) |
|
321 _e( 'assign posts to an existing user:', 'wordpress-importer' ); |
|
322 else |
|
323 _e( 'or assign posts to an existing user:', 'wordpress-importer' ); |
|
324 wp_dropdown_users( array( 'name' => "user_map[$n]", 'multi' => true, 'show_option_all' => __( '- Select -', 'wordpress-importer' ) ) ); |
|
325 echo '<input type="hidden" name="imported_authors['.$n.']" value="' . esc_attr( $author['author_login'] ) . '" />'; |
|
326 |
|
327 if ( $this->version != '1.0' ) |
|
328 echo '</div>'; |
|
329 } |
|
330 |
|
331 /** |
|
332 * Map old author logins to local user IDs based on decisions made |
|
333 * in import options form. Can map to an existing user, create a new user |
|
334 * or falls back to the current user in case of error with either of the previous |
|
335 */ |
|
336 function get_author_mapping() { |
|
337 if ( ! isset( $_POST['imported_authors'] ) ) |
|
338 return; |
|
339 |
|
340 $create_users = $this->allow_create_users(); |
|
341 |
|
342 foreach ( (array) $_POST['imported_authors'] as $i => $old_login ) { |
|
343 // Multisite adds strtolower to sanitize_user. Need to sanitize here to stop breakage in process_posts. |
|
344 $santized_old_login = sanitize_user( $old_login, true ); |
|
345 $old_id = isset( $this->authors[$old_login]['author_id'] ) ? intval($this->authors[$old_login]['author_id']) : false; |
|
346 |
|
347 if ( ! empty( $_POST['user_map'][$i] ) ) { |
|
348 $user = get_userdata( intval($_POST['user_map'][$i]) ); |
|
349 if ( isset( $user->ID ) ) { |
|
350 if ( $old_id ) |
|
351 $this->processed_authors[$old_id] = $user->ID; |
|
352 $this->author_mapping[$santized_old_login] = $user->ID; |
|
353 } |
|
354 } else if ( $create_users ) { |
|
355 if ( ! empty($_POST['user_new'][$i]) ) { |
|
356 $user_id = wp_create_user( $_POST['user_new'][$i], wp_generate_password() ); |
|
357 } else if ( $this->version != '1.0' ) { |
|
358 $user_data = array( |
|
359 'user_login' => $old_login, |
|
360 'user_pass' => wp_generate_password(), |
|
361 'user_email' => isset( $this->authors[$old_login]['author_email'] ) ? $this->authors[$old_login]['author_email'] : '', |
|
362 'display_name' => $this->authors[$old_login]['author_display_name'], |
|
363 'first_name' => isset( $this->authors[$old_login]['author_first_name'] ) ? $this->authors[$old_login]['author_first_name'] : '', |
|
364 'last_name' => isset( $this->authors[$old_login]['author_last_name'] ) ? $this->authors[$old_login]['author_last_name'] : '', |
|
365 ); |
|
366 $user_id = wp_insert_user( $user_data ); |
|
367 } |
|
368 |
|
369 if ( ! is_wp_error( $user_id ) ) { |
|
370 if ( $old_id ) |
|
371 $this->processed_authors[$old_id] = $user_id; |
|
372 $this->author_mapping[$santized_old_login] = $user_id; |
|
373 } else { |
|
374 printf( __( 'Failed to create new user for %s. Their posts will be attributed to the current user.', 'wordpress-importer' ), esc_html($this->authors[$old_login]['author_display_name']) ); |
|
375 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
376 echo ' ' . $user_id->get_error_message(); |
|
377 echo '<br />'; |
|
378 } |
|
379 } |
|
380 |
|
381 // failsafe: if the user_id was invalid, default to the current user |
|
382 if ( ! isset( $this->author_mapping[$santized_old_login] ) ) { |
|
383 if ( $old_id ) |
|
384 $this->processed_authors[$old_id] = (int) get_current_user_id(); |
|
385 $this->author_mapping[$santized_old_login] = (int) get_current_user_id(); |
|
386 } |
|
387 } |
|
388 } |
|
389 |
|
390 /** |
|
391 * Create new categories based on import information |
|
392 * |
|
393 * Doesn't create a new category if its slug already exists |
|
394 */ |
|
395 function process_categories() { |
|
396 $this->categories = apply_filters( 'wp_import_categories', $this->categories ); |
|
397 |
|
398 if ( empty( $this->categories ) ) |
|
399 return; |
|
400 |
|
401 foreach ( $this->categories as $cat ) { |
|
402 // if the category already exists leave it alone |
|
403 $term_id = term_exists( $cat['category_nicename'], 'category' ); |
|
404 if ( $term_id ) { |
|
405 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
406 if ( isset($cat['term_id']) ) |
|
407 $this->processed_terms[intval($cat['term_id'])] = (int) $term_id; |
|
408 continue; |
|
409 } |
|
410 |
|
411 $category_parent = empty( $cat['category_parent'] ) ? 0 : category_exists( $cat['category_parent'] ); |
|
412 $category_description = isset( $cat['category_description'] ) ? $cat['category_description'] : ''; |
|
413 $catarr = array( |
|
414 'category_nicename' => $cat['category_nicename'], |
|
415 'category_parent' => $category_parent, |
|
416 'cat_name' => $cat['cat_name'], |
|
417 'category_description' => $category_description |
|
418 ); |
|
419 |
|
420 $id = wp_insert_category( $catarr ); |
|
421 if ( ! is_wp_error( $id ) ) { |
|
422 if ( isset($cat['term_id']) ) |
|
423 $this->processed_terms[intval($cat['term_id'])] = $id; |
|
424 } else { |
|
425 printf( __( 'Failed to import category %s', 'wordpress-importer' ), esc_html($cat['category_nicename']) ); |
|
426 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
427 echo ': ' . $id->get_error_message(); |
|
428 echo '<br />'; |
|
429 continue; |
|
430 } |
|
431 } |
|
432 |
|
433 unset( $this->categories ); |
|
434 } |
|
435 |
|
436 /** |
|
437 * Create new post tags based on import information |
|
438 * |
|
439 * Doesn't create a tag if its slug already exists |
|
440 */ |
|
441 function process_tags() { |
|
442 $this->tags = apply_filters( 'wp_import_tags', $this->tags ); |
|
443 |
|
444 if ( empty( $this->tags ) ) |
|
445 return; |
|
446 |
|
447 foreach ( $this->tags as $tag ) { |
|
448 // if the tag already exists leave it alone |
|
449 $term_id = term_exists( $tag['tag_slug'], 'post_tag' ); |
|
450 if ( $term_id ) { |
|
451 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
452 if ( isset($tag['term_id']) ) |
|
453 $this->processed_terms[intval($tag['term_id'])] = (int) $term_id; |
|
454 continue; |
|
455 } |
|
456 |
|
457 $tag_desc = isset( $tag['tag_description'] ) ? $tag['tag_description'] : ''; |
|
458 $tagarr = array( 'slug' => $tag['tag_slug'], 'description' => $tag_desc ); |
|
459 |
|
460 $id = wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr ); |
|
461 if ( ! is_wp_error( $id ) ) { |
|
462 if ( isset($tag['term_id']) ) |
|
463 $this->processed_terms[intval($tag['term_id'])] = $id['term_id']; |
|
464 } else { |
|
465 printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), esc_html($tag['tag_name']) ); |
|
466 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
467 echo ': ' . $id->get_error_message(); |
|
468 echo '<br />'; |
|
469 continue; |
|
470 } |
|
471 } |
|
472 |
|
473 unset( $this->tags ); |
|
474 } |
|
475 |
|
476 /** |
|
477 * Create new terms based on import information |
|
478 * |
|
479 * Doesn't create a term its slug already exists |
|
480 */ |
|
481 function process_terms() { |
|
482 $this->terms = apply_filters( 'wp_import_terms', $this->terms ); |
|
483 |
|
484 if ( empty( $this->terms ) ) |
|
485 return; |
|
486 |
|
487 foreach ( $this->terms as $term ) { |
|
488 // if the term already exists in the correct taxonomy leave it alone |
|
489 $term_id = term_exists( $term['slug'], $term['term_taxonomy'] ); |
|
490 if ( $term_id ) { |
|
491 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
492 if ( isset($term['term_id']) ) |
|
493 $this->processed_terms[intval($term['term_id'])] = (int) $term_id; |
|
494 continue; |
|
495 } |
|
496 |
|
497 if ( empty( $term['term_parent'] ) ) { |
|
498 $parent = 0; |
|
499 } else { |
|
500 $parent = term_exists( $term['term_parent'], $term['term_taxonomy'] ); |
|
501 if ( is_array( $parent ) ) $parent = $parent['term_id']; |
|
502 } |
|
503 $description = isset( $term['term_description'] ) ? $term['term_description'] : ''; |
|
504 $termarr = array( 'slug' => $term['slug'], 'description' => $description, 'parent' => intval($parent) ); |
|
505 |
|
506 $id = wp_insert_term( $term['term_name'], $term['term_taxonomy'], $termarr ); |
|
507 if ( ! is_wp_error( $id ) ) { |
|
508 if ( isset($term['term_id']) ) |
|
509 $this->processed_terms[intval($term['term_id'])] = $id['term_id']; |
|
510 } else { |
|
511 printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($term['term_taxonomy']), esc_html($term['term_name']) ); |
|
512 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
513 echo ': ' . $id->get_error_message(); |
|
514 echo '<br />'; |
|
515 continue; |
|
516 } |
|
517 } |
|
518 |
|
519 unset( $this->terms ); |
|
520 } |
|
521 |
|
522 /** |
|
523 * Create new posts based on import information |
|
524 * |
|
525 * Posts marked as having a parent which doesn't exist will become top level items. |
|
526 * Doesn't create a new post if: the post type doesn't exist, the given post ID |
|
527 * is already noted as imported or a post with the same title and date already exists. |
|
528 * Note that new/updated terms, comments and meta are imported for the last of the above. |
|
529 */ |
|
530 function process_posts() { |
|
531 $this->posts = apply_filters( 'wp_import_posts', $this->posts ); |
|
532 |
|
533 foreach ( $this->posts as $post ) { |
|
534 $post = apply_filters( 'wp_import_post_data_raw', $post ); |
|
535 |
|
536 if ( ! post_type_exists( $post['post_type'] ) ) { |
|
537 printf( __( 'Failed to import “%s”: Invalid post type %s', 'wordpress-importer' ), |
|
538 esc_html($post['post_title']), esc_html($post['post_type']) ); |
|
539 echo '<br />'; |
|
540 do_action( 'wp_import_post_exists', $post ); |
|
541 continue; |
|
542 } |
|
543 |
|
544 if ( isset( $this->processed_posts[$post['post_id']] ) && ! empty( $post['post_id'] ) ) |
|
545 continue; |
|
546 |
|
547 if ( $post['status'] == 'auto-draft' ) |
|
548 continue; |
|
549 |
|
550 if ( 'nav_menu_item' == $post['post_type'] ) { |
|
551 $this->process_menu_item( $post ); |
|
552 continue; |
|
553 } |
|
554 |
|
555 $post_type_object = get_post_type_object( $post['post_type'] ); |
|
556 |
|
557 $post_exists = post_exists( $post['post_title'], '', $post['post_date'] ); |
|
558 if ( $post_exists && get_post_type( $post_exists ) == $post['post_type'] ) { |
|
559 printf( __('%s “%s” already exists.', 'wordpress-importer'), $post_type_object->labels->singular_name, esc_html($post['post_title']) ); |
|
560 echo '<br />'; |
|
561 $comment_post_ID = $post_id = $post_exists; |
|
562 } else { |
|
563 $post_parent = (int) $post['post_parent']; |
|
564 if ( $post_parent ) { |
|
565 // if we already know the parent, map it to the new local ID |
|
566 if ( isset( $this->processed_posts[$post_parent] ) ) { |
|
567 $post_parent = $this->processed_posts[$post_parent]; |
|
568 // otherwise record the parent for later |
|
569 } else { |
|
570 $this->post_orphans[intval($post['post_id'])] = $post_parent; |
|
571 $post_parent = 0; |
|
572 } |
|
573 } |
|
574 |
|
575 // map the post author |
|
576 $author = sanitize_user( $post['post_author'], true ); |
|
577 if ( isset( $this->author_mapping[$author] ) ) |
|
578 $author = $this->author_mapping[$author]; |
|
579 else |
|
580 $author = (int) get_current_user_id(); |
|
581 |
|
582 $postdata = array( |
|
583 'import_id' => $post['post_id'], 'post_author' => $author, 'post_date' => $post['post_date'], |
|
584 'post_date_gmt' => $post['post_date_gmt'], 'post_content' => $post['post_content'], |
|
585 'post_excerpt' => $post['post_excerpt'], 'post_title' => $post['post_title'], |
|
586 'post_status' => $post['status'], 'post_name' => $post['post_name'], |
|
587 'comment_status' => $post['comment_status'], 'ping_status' => $post['ping_status'], |
|
588 'guid' => $post['guid'], 'post_parent' => $post_parent, 'menu_order' => $post['menu_order'], |
|
589 'post_type' => $post['post_type'], 'post_password' => $post['post_password'] |
|
590 ); |
|
591 |
|
592 $original_post_ID = $post['post_id']; |
|
593 $postdata = apply_filters( 'wp_import_post_data_processed', $postdata, $post ); |
|
594 |
|
595 if ( 'attachment' == $postdata['post_type'] ) { |
|
596 $remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid']; |
|
597 |
|
598 // try to use _wp_attached file for upload folder placement to ensure the same location as the export site |
|
599 // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload() |
|
600 $postdata['upload_date'] = $post['post_date']; |
|
601 if ( isset( $post['postmeta'] ) ) { |
|
602 foreach( $post['postmeta'] as $meta ) { |
|
603 if ( $meta['key'] == '_wp_attached_file' ) { |
|
604 if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) ) |
|
605 $postdata['upload_date'] = $matches[0]; |
|
606 break; |
|
607 } |
|
608 } |
|
609 } |
|
610 |
|
611 $comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url ); |
|
612 } else { |
|
613 $comment_post_ID = $post_id = wp_insert_post( $postdata, true ); |
|
614 do_action( 'wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post ); |
|
615 } |
|
616 |
|
617 if ( is_wp_error( $post_id ) ) { |
|
618 printf( __( 'Failed to import %s “%s”', 'wordpress-importer' ), |
|
619 $post_type_object->labels->singular_name, esc_html($post['post_title']) ); |
|
620 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
621 echo ': ' . $post_id->get_error_message(); |
|
622 echo '<br />'; |
|
623 continue; |
|
624 } |
|
625 |
|
626 if ( $post['is_sticky'] == 1 ) |
|
627 stick_post( $post_id ); |
|
628 } |
|
629 |
|
630 // map pre-import ID to local ID |
|
631 $this->processed_posts[intval($post['post_id'])] = (int) $post_id; |
|
632 |
|
633 if ( ! isset( $post['terms'] ) ) |
|
634 $post['terms'] = array(); |
|
635 |
|
636 $post['terms'] = apply_filters( 'wp_import_post_terms', $post['terms'], $post_id, $post ); |
|
637 |
|
638 // add categories, tags and other terms |
|
639 if ( ! empty( $post['terms'] ) ) { |
|
640 $terms_to_set = array(); |
|
641 foreach ( $post['terms'] as $term ) { |
|
642 // back compat with WXR 1.0 map 'tag' to 'post_tag' |
|
643 $taxonomy = ( 'tag' == $term['domain'] ) ? 'post_tag' : $term['domain']; |
|
644 $term_exists = term_exists( $term['slug'], $taxonomy ); |
|
645 $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists; |
|
646 if ( ! $term_id ) { |
|
647 $t = wp_insert_term( $term['name'], $taxonomy, array( 'slug' => $term['slug'] ) ); |
|
648 if ( ! is_wp_error( $t ) ) { |
|
649 $term_id = $t['term_id']; |
|
650 do_action( 'wp_import_insert_term', $t, $term, $post_id, $post ); |
|
651 } else { |
|
652 printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($taxonomy), esc_html($term['name']) ); |
|
653 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
654 echo ': ' . $t->get_error_message(); |
|
655 echo '<br />'; |
|
656 do_action( 'wp_import_insert_term_failed', $t, $term, $post_id, $post ); |
|
657 continue; |
|
658 } |
|
659 } |
|
660 $terms_to_set[$taxonomy][] = intval( $term_id ); |
|
661 } |
|
662 |
|
663 foreach ( $terms_to_set as $tax => $ids ) { |
|
664 $tt_ids = wp_set_post_terms( $post_id, $ids, $tax ); |
|
665 do_action( 'wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post ); |
|
666 } |
|
667 unset( $post['terms'], $terms_to_set ); |
|
668 } |
|
669 |
|
670 if ( ! isset( $post['comments'] ) ) |
|
671 $post['comments'] = array(); |
|
672 |
|
673 $post['comments'] = apply_filters( 'wp_import_post_comments', $post['comments'], $post_id, $post ); |
|
674 |
|
675 // add/update comments |
|
676 if ( ! empty( $post['comments'] ) ) { |
|
677 $num_comments = 0; |
|
678 $inserted_comments = array(); |
|
679 foreach ( $post['comments'] as $comment ) { |
|
680 $comment_id = $comment['comment_id']; |
|
681 $newcomments[$comment_id]['comment_post_ID'] = $comment_post_ID; |
|
682 $newcomments[$comment_id]['comment_author'] = $comment['comment_author']; |
|
683 $newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email']; |
|
684 $newcomments[$comment_id]['comment_author_IP'] = $comment['comment_author_IP']; |
|
685 $newcomments[$comment_id]['comment_author_url'] = $comment['comment_author_url']; |
|
686 $newcomments[$comment_id]['comment_date'] = $comment['comment_date']; |
|
687 $newcomments[$comment_id]['comment_date_gmt'] = $comment['comment_date_gmt']; |
|
688 $newcomments[$comment_id]['comment_content'] = $comment['comment_content']; |
|
689 $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved']; |
|
690 $newcomments[$comment_id]['comment_type'] = $comment['comment_type']; |
|
691 $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent']; |
|
692 $newcomments[$comment_id]['commentmeta'] = isset( $comment['commentmeta'] ) ? $comment['commentmeta'] : array(); |
|
693 if ( isset( $this->processed_authors[$comment['comment_user_id']] ) ) |
|
694 $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']]; |
|
695 } |
|
696 ksort( $newcomments ); |
|
697 |
|
698 foreach ( $newcomments as $key => $comment ) { |
|
699 // if this is a new post we can skip the comment_exists() check |
|
700 if ( ! $post_exists || ! comment_exists( $comment['comment_author'], $comment['comment_date'] ) ) { |
|
701 if ( isset( $inserted_comments[$comment['comment_parent']] ) ) |
|
702 $comment['comment_parent'] = $inserted_comments[$comment['comment_parent']]; |
|
703 $comment = wp_filter_comment( $comment ); |
|
704 $inserted_comments[$key] = wp_insert_comment( $comment ); |
|
705 do_action( 'wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post ); |
|
706 |
|
707 foreach( $comment['commentmeta'] as $meta ) { |
|
708 $value = maybe_unserialize( $meta['value'] ); |
|
709 add_comment_meta( $inserted_comments[$key], $meta['key'], $value ); |
|
710 } |
|
711 |
|
712 $num_comments++; |
|
713 } |
|
714 } |
|
715 unset( $newcomments, $inserted_comments, $post['comments'] ); |
|
716 } |
|
717 |
|
718 if ( ! isset( $post['postmeta'] ) ) |
|
719 $post['postmeta'] = array(); |
|
720 |
|
721 $post['postmeta'] = apply_filters( 'wp_import_post_meta', $post['postmeta'], $post_id, $post ); |
|
722 |
|
723 // add/update post meta |
|
724 if ( ! empty( $post['postmeta'] ) ) { |
|
725 foreach ( $post['postmeta'] as $meta ) { |
|
726 $key = apply_filters( 'import_post_meta_key', $meta['key'], $post_id, $post ); |
|
727 $value = false; |
|
728 |
|
729 if ( '_edit_last' == $key ) { |
|
730 if ( isset( $this->processed_authors[intval($meta['value'])] ) ) |
|
731 $value = $this->processed_authors[intval($meta['value'])]; |
|
732 else |
|
733 $key = false; |
|
734 } |
|
735 |
|
736 if ( $key ) { |
|
737 // export gets meta straight from the DB so could have a serialized string |
|
738 if ( ! $value ) |
|
739 $value = maybe_unserialize( $meta['value'] ); |
|
740 |
|
741 add_post_meta( $post_id, $key, $value ); |
|
742 do_action( 'import_post_meta', $post_id, $key, $value ); |
|
743 |
|
744 // if the post has a featured image, take note of this in case of remap |
|
745 if ( '_thumbnail_id' == $key ) |
|
746 $this->featured_images[$post_id] = (int) $value; |
|
747 } |
|
748 } |
|
749 } |
|
750 } |
|
751 |
|
752 unset( $this->posts ); |
|
753 } |
|
754 |
|
755 /** |
|
756 * Attempt to create a new menu item from import data |
|
757 * |
|
758 * Fails for draft, orphaned menu items and those without an associated nav_menu |
|
759 * or an invalid nav_menu term. If the post type or term object which the menu item |
|
760 * represents doesn't exist then the menu item will not be imported (waits until the |
|
761 * end of the import to retry again before discarding). |
|
762 * |
|
763 * @param array $item Menu item details from WXR file |
|
764 */ |
|
765 function process_menu_item( $item ) { |
|
766 // skip draft, orphaned menu items |
|
767 if ( 'draft' == $item['status'] ) |
|
768 return; |
|
769 |
|
770 $menu_slug = false; |
|
771 if ( isset($item['terms']) ) { |
|
772 // loop through terms, assume first nav_menu term is correct menu |
|
773 foreach ( $item['terms'] as $term ) { |
|
774 if ( 'nav_menu' == $term['domain'] ) { |
|
775 $menu_slug = $term['slug']; |
|
776 break; |
|
777 } |
|
778 } |
|
779 } |
|
780 |
|
781 // no nav_menu term associated with this menu item |
|
782 if ( ! $menu_slug ) { |
|
783 _e( 'Menu item skipped due to missing menu slug', 'wordpress-importer' ); |
|
784 echo '<br />'; |
|
785 return; |
|
786 } |
|
787 |
|
788 $menu_id = term_exists( $menu_slug, 'nav_menu' ); |
|
789 if ( ! $menu_id ) { |
|
790 printf( __( 'Menu item skipped due to invalid menu slug: %s', 'wordpress-importer' ), esc_html( $menu_slug ) ); |
|
791 echo '<br />'; |
|
792 return; |
|
793 } else { |
|
794 $menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id; |
|
795 } |
|
796 |
|
797 foreach ( $item['postmeta'] as $meta ) |
|
798 $$meta['key'] = $meta['value']; |
|
799 |
|
800 if ( 'taxonomy' == $_menu_item_type && isset( $this->processed_terms[intval($_menu_item_object_id)] ) ) { |
|
801 $_menu_item_object_id = $this->processed_terms[intval($_menu_item_object_id)]; |
|
802 } else if ( 'post_type' == $_menu_item_type && isset( $this->processed_posts[intval($_menu_item_object_id)] ) ) { |
|
803 $_menu_item_object_id = $this->processed_posts[intval($_menu_item_object_id)]; |
|
804 } else if ( 'custom' != $_menu_item_type ) { |
|
805 // associated object is missing or not imported yet, we'll retry later |
|
806 $this->missing_menu_items[] = $item; |
|
807 return; |
|
808 } |
|
809 |
|
810 if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_parent)] ) ) { |
|
811 $_menu_item_menu_item_parent = $this->processed_menu_items[intval($_menu_item_menu_item_parent)]; |
|
812 } else if ( $_menu_item_menu_item_parent ) { |
|
813 $this->menu_item_orphans[intval($item['post_id'])] = (int) $_menu_item_menu_item_parent; |
|
814 $_menu_item_menu_item_parent = 0; |
|
815 } |
|
816 |
|
817 // wp_update_nav_menu_item expects CSS classes as a space separated string |
|
818 $_menu_item_classes = maybe_unserialize( $_menu_item_classes ); |
|
819 if ( is_array( $_menu_item_classes ) ) |
|
820 $_menu_item_classes = implode( ' ', $_menu_item_classes ); |
|
821 |
|
822 $args = array( |
|
823 'menu-item-object-id' => $_menu_item_object_id, |
|
824 'menu-item-object' => $_menu_item_object, |
|
825 'menu-item-parent-id' => $_menu_item_menu_item_parent, |
|
826 'menu-item-position' => intval( $item['menu_order'] ), |
|
827 'menu-item-type' => $_menu_item_type, |
|
828 'menu-item-title' => $item['post_title'], |
|
829 'menu-item-url' => $_menu_item_url, |
|
830 'menu-item-description' => $item['post_content'], |
|
831 'menu-item-attr-title' => $item['post_excerpt'], |
|
832 'menu-item-target' => $_menu_item_target, |
|
833 'menu-item-classes' => $_menu_item_classes, |
|
834 'menu-item-xfn' => $_menu_item_xfn, |
|
835 'menu-item-status' => $item['status'] |
|
836 ); |
|
837 |
|
838 $id = wp_update_nav_menu_item( $menu_id, 0, $args ); |
|
839 if ( $id && ! is_wp_error( $id ) ) |
|
840 $this->processed_menu_items[intval($item['post_id'])] = (int) $id; |
|
841 } |
|
842 |
|
843 /** |
|
844 * If fetching attachments is enabled then attempt to create a new attachment |
|
845 * |
|
846 * @param array $post Attachment post details from WXR |
|
847 * @param string $url URL to fetch attachment from |
|
848 * @return int|WP_Error Post ID on success, WP_Error otherwise |
|
849 */ |
|
850 function process_attachment( $post, $url ) { |
|
851 if ( ! $this->fetch_attachments ) |
|
852 return new WP_Error( 'attachment_processing_error', |
|
853 __( 'Fetching attachments is not enabled', 'wordpress-importer' ) ); |
|
854 |
|
855 // if the URL is absolute, but does not contain address, then upload it assuming base_site_url |
|
856 if ( preg_match( '|^/[\w\W]+$|', $url ) ) |
|
857 $url = rtrim( $this->base_url, '/' ) . $url; |
|
858 |
|
859 $upload = $this->fetch_remote_file( $url, $post ); |
|
860 if ( is_wp_error( $upload ) ) |
|
861 return $upload; |
|
862 |
|
863 if ( $info = wp_check_filetype( $upload['file'] ) ) |
|
864 $post['post_mime_type'] = $info['type']; |
|
865 else |
|
866 return new WP_Error( 'attachment_processing_error', __('Invalid file type', 'wordpress-importer') ); |
|
867 |
|
868 $post['guid'] = $upload['url']; |
|
869 |
|
870 // as per wp-admin/includes/upload.php |
|
871 $post_id = wp_insert_attachment( $post, $upload['file'] ); |
|
872 wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) ); |
|
873 |
|
874 // remap resized image URLs, works by stripping the extension and remapping the URL stub. |
|
875 if ( preg_match( '!^image/!', $info['type'] ) ) { |
|
876 $parts = pathinfo( $url ); |
|
877 $name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2 |
|
878 |
|
879 $parts_new = pathinfo( $upload['url'] ); |
|
880 $name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" ); |
|
881 |
|
882 $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new; |
|
883 } |
|
884 |
|
885 return $post_id; |
|
886 } |
|
887 |
|
888 /** |
|
889 * Attempt to download a remote file attachment |
|
890 * |
|
891 * @param string $url URL of item to fetch |
|
892 * @param array $post Attachment details |
|
893 * @return array|WP_Error Local file location details on success, WP_Error otherwise |
|
894 */ |
|
895 function fetch_remote_file( $url, $post ) { |
|
896 // extract the file name and extension from the url |
|
897 $file_name = basename( $url ); |
|
898 |
|
899 // get placeholder file in the upload dir with a unique, sanitized filename |
|
900 $upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] ); |
|
901 if ( $upload['error'] ) |
|
902 return new WP_Error( 'upload_dir_error', $upload['error'] ); |
|
903 |
|
904 // fetch the remote url and write it to the placeholder file |
|
905 $headers = wp_get_http( $url, $upload['file'] ); |
|
906 |
|
907 // request failed |
|
908 if ( ! $headers ) { |
|
909 @unlink( $upload['file'] ); |
|
910 return new WP_Error( 'import_file_error', __('Remote server did not respond', 'wordpress-importer') ); |
|
911 } |
|
912 |
|
913 // make sure the fetch was successful |
|
914 if ( $headers['response'] != '200' ) { |
|
915 @unlink( $upload['file'] ); |
|
916 return new WP_Error( 'import_file_error', sprintf( __('Remote server returned error response %1$d %2$s', 'wordpress-importer'), esc_html($headers['response']), get_status_header_desc($headers['response']) ) ); |
|
917 } |
|
918 |
|
919 $filesize = filesize( $upload['file'] ); |
|
920 |
|
921 if ( isset( $headers['content-length'] ) && $filesize != $headers['content-length'] ) { |
|
922 @unlink( $upload['file'] ); |
|
923 return new WP_Error( 'import_file_error', __('Remote file is incorrect size', 'wordpress-importer') ); |
|
924 } |
|
925 |
|
926 if ( 0 == $filesize ) { |
|
927 @unlink( $upload['file'] ); |
|
928 return new WP_Error( 'import_file_error', __('Zero size file downloaded', 'wordpress-importer') ); |
|
929 } |
|
930 |
|
931 $max_size = (int) $this->max_attachment_size(); |
|
932 if ( ! empty( $max_size ) && $filesize > $max_size ) { |
|
933 @unlink( $upload['file'] ); |
|
934 return new WP_Error( 'import_file_error', sprintf(__('Remote file is too large, limit is %s', 'wordpress-importer'), size_format($max_size) ) ); |
|
935 } |
|
936 |
|
937 // keep track of the old and new urls so we can substitute them later |
|
938 $this->url_remap[$url] = $upload['url']; |
|
939 $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed? |
|
940 // keep track of the destination if the remote url is redirected somewhere else |
|
941 if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url ) |
|
942 $this->url_remap[$headers['x-final-location']] = $upload['url']; |
|
943 |
|
944 return $upload; |
|
945 } |
|
946 |
|
947 /** |
|
948 * Attempt to associate posts and menu items with previously missing parents |
|
949 * |
|
950 * An imported post's parent may not have been imported when it was first created |
|
951 * so try again. Similarly for child menu items and menu items which were missing |
|
952 * the object (e.g. post) they represent in the menu |
|
953 */ |
|
954 function backfill_parents() { |
|
955 global $wpdb; |
|
956 |
|
957 // find parents for post orphans |
|
958 foreach ( $this->post_orphans as $child_id => $parent_id ) { |
|
959 $local_child_id = $local_parent_id = false; |
|
960 if ( isset( $this->processed_posts[$child_id] ) ) |
|
961 $local_child_id = $this->processed_posts[$child_id]; |
|
962 if ( isset( $this->processed_posts[$parent_id] ) ) |
|
963 $local_parent_id = $this->processed_posts[$parent_id]; |
|
964 |
|
965 if ( $local_child_id && $local_parent_id ) |
|
966 $wpdb->update( $wpdb->posts, array( 'post_parent' => $local_parent_id ), array( 'ID' => $local_child_id ), '%d', '%d' ); |
|
967 } |
|
968 |
|
969 // all other posts/terms are imported, retry menu items with missing associated object |
|
970 $missing_menu_items = $this->missing_menu_items; |
|
971 foreach ( $missing_menu_items as $item ) |
|
972 $this->process_menu_item( $item ); |
|
973 |
|
974 // find parents for menu item orphans |
|
975 foreach ( $this->menu_item_orphans as $child_id => $parent_id ) { |
|
976 $local_child_id = $local_parent_id = 0; |
|
977 if ( isset( $this->processed_menu_items[$child_id] ) ) |
|
978 $local_child_id = $this->processed_menu_items[$child_id]; |
|
979 if ( isset( $this->processed_menu_items[$parent_id] ) ) |
|
980 $local_parent_id = $this->processed_menu_items[$parent_id]; |
|
981 |
|
982 if ( $local_child_id && $local_parent_id ) |
|
983 update_post_meta( $local_child_id, '_menu_item_menu_item_parent', (int) $local_parent_id ); |
|
984 } |
|
985 } |
|
986 |
|
987 /** |
|
988 * Use stored mapping information to update old attachment URLs |
|
989 */ |
|
990 function backfill_attachment_urls() { |
|
991 global $wpdb; |
|
992 // make sure we do the longest urls first, in case one is a substring of another |
|
993 uksort( $this->url_remap, array(&$this, 'cmpr_strlen') ); |
|
994 |
|
995 foreach ( $this->url_remap as $from_url => $to_url ) { |
|
996 // remap urls in post_content |
|
997 $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url) ); |
|
998 // remap enclosure urls |
|
999 $result = $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url) ); |
|
1000 } |
|
1001 } |
|
1002 |
|
1003 /** |
|
1004 * Update _thumbnail_id meta to new, imported attachment IDs |
|
1005 */ |
|
1006 function remap_featured_images() { |
|
1007 // cycle through posts that have a featured image |
|
1008 foreach ( $this->featured_images as $post_id => $value ) { |
|
1009 if ( isset( $this->processed_posts[$value] ) ) { |
|
1010 $new_id = $this->processed_posts[$value]; |
|
1011 // only update if there's a difference |
|
1012 if ( $new_id != $value ) |
|
1013 update_post_meta( $post_id, '_thumbnail_id', $new_id ); |
|
1014 } |
|
1015 } |
|
1016 } |
|
1017 |
|
1018 /** |
|
1019 * Parse a WXR file |
|
1020 * |
|
1021 * @param string $file Path to WXR file for parsing |
|
1022 * @return array Information gathered from the WXR file |
|
1023 */ |
|
1024 function parse( $file ) { |
|
1025 $parser = new WXR_Parser(); |
|
1026 return $parser->parse( $file ); |
|
1027 } |
|
1028 |
|
1029 // Display import page title |
|
1030 function header() { |
|
1031 echo '<div class="wrap">'; |
|
1032 screen_icon(); |
|
1033 echo '<h2>' . __( 'Import WordPress', 'wordpress-importer' ) . '</h2>'; |
|
1034 |
|
1035 $updates = get_plugin_updates(); |
|
1036 $basename = plugin_basename(__FILE__); |
|
1037 if ( isset( $updates[$basename] ) ) { |
|
1038 $update = $updates[$basename]; |
|
1039 echo '<div class="error"><p><strong>'; |
|
1040 printf( __( 'A new version of this importer is available. Please update to version %s to ensure compatibility with newer export files.', 'wordpress-importer' ), $update->update->new_version ); |
|
1041 echo '</strong></p></div>'; |
|
1042 } |
|
1043 } |
|
1044 |
|
1045 // Close div.wrap |
|
1046 function footer() { |
|
1047 echo '</div>'; |
|
1048 } |
|
1049 |
|
1050 /** |
|
1051 * Display introductory text and file upload form |
|
1052 */ |
|
1053 function greet() { |
|
1054 echo '<div class="narrow">'; |
|
1055 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 site.', 'wordpress-importer' ).'</p>'; |
|
1056 echo '<p>'.__( 'Choose a WXR (.xml) file to upload, then click Upload file and import.', 'wordpress-importer' ).'</p>'; |
|
1057 wp_import_upload_form( 'admin.php?import=wordpress&step=1' ); |
|
1058 echo '</div>'; |
|
1059 } |
|
1060 |
|
1061 /** |
|
1062 * Decide if the given meta key maps to information we will want to import |
|
1063 * |
|
1064 * @param string $key The meta key to check |
|
1065 * @return string|bool The key if we do want to import, false if not |
|
1066 */ |
|
1067 function is_valid_meta_key( $key ) { |
|
1068 // skip attachment metadata since we'll regenerate it from scratch |
|
1069 // skip _edit_lock as not relevant for import |
|
1070 if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) ) |
|
1071 return false; |
|
1072 return $key; |
|
1073 } |
|
1074 |
|
1075 /** |
|
1076 * Decide whether or not the importer is allowed to create users. |
|
1077 * Default is true, can be filtered via import_allow_create_users |
|
1078 * |
|
1079 * @return bool True if creating users is allowed |
|
1080 */ |
|
1081 function allow_create_users() { |
|
1082 return apply_filters( 'import_allow_create_users', true ); |
|
1083 } |
|
1084 |
|
1085 /** |
|
1086 * Decide whether or not the importer should attempt to download attachment files. |
|
1087 * Default is true, can be filtered via import_allow_fetch_attachments. The choice |
|
1088 * made at the import options screen must also be true, false here hides that checkbox. |
|
1089 * |
|
1090 * @return bool True if downloading attachments is allowed |
|
1091 */ |
|
1092 function allow_fetch_attachments() { |
|
1093 return apply_filters( 'import_allow_fetch_attachments', true ); |
|
1094 } |
|
1095 |
|
1096 /** |
|
1097 * Decide what the maximum file size for downloaded attachments is. |
|
1098 * Default is 0 (unlimited), can be filtered via import_attachment_size_limit |
|
1099 * |
|
1100 * @return int Maximum attachment file size to import |
|
1101 */ |
|
1102 function max_attachment_size() { |
|
1103 return apply_filters( 'import_attachment_size_limit', 0 ); |
|
1104 } |
|
1105 |
|
1106 /** |
|
1107 * Added to http_request_timeout filter to force timeout at 60 seconds during import |
|
1108 * @return int 60 |
|
1109 */ |
|
1110 function bump_request_timeout() { |
|
1111 return 60; |
|
1112 } |
|
1113 |
|
1114 // return the difference in length between two strings |
|
1115 function cmpr_strlen( $a, $b ) { |
|
1116 return strlen($b) - strlen($a); |
|
1117 } |
|
1118 } |
|
1119 |
|
1120 } // class_exists( 'WP_Importer' ) |
|
1121 |
|
1122 function wordpress_importer_init() { |
|
1123 load_plugin_textdomain( 'wordpress-importer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); |
|
1124 |
|
1125 /** |
|
1126 * WordPress Importer object for registering the import callback |
|
1127 * @global WP_Import $wp_import |
|
1128 */ |
|
1129 $GLOBALS['wp_import'] = new WP_Import(); |
|
1130 register_importer( 'wordpress', 'WordPress', __('Import <strong>posts, pages, comments, custom fields, categories, and tags</strong> from a WordPress export file.', 'wordpress-importer'), array( $GLOBALS['wp_import'], 'dispatch' ) ); |
|
1131 } |
|
1132 add_action( 'admin_init', 'wordpress_importer_init' ); |