|
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 |
|
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 if ( empty( $this->categories ) ) |
|
397 return; |
|
398 |
|
399 foreach ( $this->categories as $cat ) { |
|
400 // if the category already exists leave it alone |
|
401 $term_id = term_exists( $cat['category_nicename'], 'category' ); |
|
402 if ( $term_id ) { |
|
403 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
404 if ( isset($cat['term_id']) ) |
|
405 $this->processed_terms[intval($cat['term_id'])] = (int) $term_id; |
|
406 continue; |
|
407 } |
|
408 |
|
409 $category_parent = empty( $cat['category_parent'] ) ? 0 : category_exists( $cat['category_parent'] ); |
|
410 $category_description = isset( $cat['category_description'] ) ? $cat['category_description'] : ''; |
|
411 $catarr = array( |
|
412 'category_nicename' => $cat['category_nicename'], |
|
413 'category_parent' => $category_parent, |
|
414 'cat_name' => $cat['cat_name'], |
|
415 'category_description' => $category_description |
|
416 ); |
|
417 |
|
418 $id = wp_insert_category( $catarr ); |
|
419 if ( ! is_wp_error( $id ) ) { |
|
420 if ( isset($cat['term_id']) ) |
|
421 $this->processed_terms[intval($cat['term_id'])] = $id; |
|
422 } else { |
|
423 printf( __( 'Failed to import category %s', 'wordpress-importer' ), esc_html($cat['category_nicename']) ); |
|
424 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
425 echo ': ' . $id->get_error_message(); |
|
426 echo '<br />'; |
|
427 continue; |
|
428 } |
|
429 } |
|
430 |
|
431 unset( $this->categories ); |
|
432 } |
|
433 |
|
434 /** |
|
435 * Create new post tags based on import information |
|
436 * |
|
437 * Doesn't create a tag if its slug already exists |
|
438 */ |
|
439 function process_tags() { |
|
440 if ( empty( $this->tags ) ) |
|
441 return; |
|
442 |
|
443 foreach ( $this->tags as $tag ) { |
|
444 // if the tag already exists leave it alone |
|
445 $term_id = term_exists( $tag['tag_slug'], 'post_tag' ); |
|
446 if ( $term_id ) { |
|
447 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
448 if ( isset($tag['term_id']) ) |
|
449 $this->processed_terms[intval($tag['term_id'])] = (int) $term_id; |
|
450 continue; |
|
451 } |
|
452 |
|
453 $tag_desc = isset( $tag['tag_description'] ) ? $tag['tag_description'] : ''; |
|
454 $tagarr = array( 'slug' => $tag['tag_slug'], 'description' => $tag_desc ); |
|
455 |
|
456 $id = wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr ); |
|
457 if ( ! is_wp_error( $id ) ) { |
|
458 if ( isset($tag['term_id']) ) |
|
459 $this->processed_terms[intval($tag['term_id'])] = $id['term_id']; |
|
460 } else { |
|
461 printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), esc_html($tag['tag_name']) ); |
|
462 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
463 echo ': ' . $id->get_error_message(); |
|
464 echo '<br />'; |
|
465 continue; |
|
466 } |
|
467 } |
|
468 |
|
469 unset( $this->tags ); |
|
470 } |
|
471 |
|
472 /** |
|
473 * Create new terms based on import information |
|
474 * |
|
475 * Doesn't create a term its slug already exists |
|
476 */ |
|
477 function process_terms() { |
|
478 if ( empty( $this->terms ) ) |
|
479 return; |
|
480 |
|
481 foreach ( $this->terms as $term ) { |
|
482 // if the term already exists in the correct taxonomy leave it alone |
|
483 $term_id = term_exists( $term['slug'], $term['term_taxonomy'] ); |
|
484 if ( $term_id ) { |
|
485 if ( is_array($term_id) ) $term_id = $term_id['term_id']; |
|
486 if ( isset($term['term_id']) ) |
|
487 $this->processed_terms[intval($term['term_id'])] = (int) $term_id; |
|
488 continue; |
|
489 } |
|
490 |
|
491 if ( empty( $term['term_parent'] ) ) { |
|
492 $parent = 0; |
|
493 } else { |
|
494 $parent = term_exists( $term['term_parent'], $term['term_taxonomy'] ); |
|
495 if ( is_array( $parent ) ) $parent = $parent['term_id']; |
|
496 } |
|
497 $description = isset( $term['term_description'] ) ? $term['term_description'] : ''; |
|
498 $termarr = array( 'slug' => $term['slug'], 'description' => $description, 'parent' => intval($parent) ); |
|
499 |
|
500 $id = wp_insert_term( $term['term_name'], $term['term_taxonomy'], $termarr ); |
|
501 if ( ! is_wp_error( $id ) ) { |
|
502 if ( isset($term['term_id']) ) |
|
503 $this->processed_terms[intval($term['term_id'])] = $id['term_id']; |
|
504 } else { |
|
505 printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($term['term_taxonomy']), esc_html($term['term_name']) ); |
|
506 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
507 echo ': ' . $id->get_error_message(); |
|
508 echo '<br />'; |
|
509 continue; |
|
510 } |
|
511 } |
|
512 |
|
513 unset( $this->terms ); |
|
514 } |
|
515 |
|
516 /** |
|
517 * Create new posts based on import information |
|
518 * |
|
519 * Posts marked as having a parent which doesn't exist will become top level items. |
|
520 * Doesn't create a new post if: the post type doesn't exist, the given post ID |
|
521 * is already noted as imported or a post with the same title and date already exists. |
|
522 * Note that new/updated terms, comments and meta are imported for the last of the above. |
|
523 */ |
|
524 function process_posts() { |
|
525 foreach ( $this->posts as $post ) { |
|
526 if ( ! post_type_exists( $post['post_type'] ) ) { |
|
527 printf( __( 'Failed to import “%s”: Invalid post type %s', 'wordpress-importer' ), |
|
528 esc_html($post['post_title']), esc_html($post['post_type']) ); |
|
529 echo '<br />'; |
|
530 continue; |
|
531 } |
|
532 |
|
533 if ( isset( $this->processed_posts[$post['post_id']] ) && ! empty( $post['post_id'] ) ) |
|
534 continue; |
|
535 |
|
536 if ( $post['status'] == 'auto-draft' ) |
|
537 continue; |
|
538 |
|
539 if ( 'nav_menu_item' == $post['post_type'] ) { |
|
540 $this->process_menu_item( $post ); |
|
541 continue; |
|
542 } |
|
543 |
|
544 $post_type_object = get_post_type_object( $post['post_type'] ); |
|
545 |
|
546 $post_exists = post_exists( $post['post_title'], '', $post['post_date'] ); |
|
547 if ( $post_exists && get_post_type( $post_exists ) == $post['post_type'] ) { |
|
548 printf( __('%s “%s” already exists.', 'wordpress-importer'), $post_type_object->labels->singular_name, esc_html($post['post_title']) ); |
|
549 echo '<br />'; |
|
550 $comment_post_ID = $post_id = $post_exists; |
|
551 } else { |
|
552 $post_parent = (int) $post['post_parent']; |
|
553 if ( $post_parent ) { |
|
554 // if we already know the parent, map it to the new local ID |
|
555 if ( isset( $this->processed_posts[$post_parent] ) ) { |
|
556 $post_parent = $this->processed_posts[$post_parent]; |
|
557 // otherwise record the parent for later |
|
558 } else { |
|
559 $this->post_orphans[intval($post['post_id'])] = $post_parent; |
|
560 $post_parent = 0; |
|
561 } |
|
562 } |
|
563 |
|
564 // map the post author |
|
565 $author = sanitize_user( $post['post_author'], true ); |
|
566 if ( isset( $this->author_mapping[$author] ) ) |
|
567 $author = $this->author_mapping[$author]; |
|
568 else |
|
569 $author = (int) get_current_user_id(); |
|
570 |
|
571 $postdata = array( |
|
572 'import_id' => $post['post_id'], 'post_author' => $author, 'post_date' => $post['post_date'], |
|
573 'post_date_gmt' => $post['post_date_gmt'], 'post_content' => $post['post_content'], |
|
574 'post_excerpt' => $post['post_excerpt'], 'post_title' => $post['post_title'], |
|
575 'post_status' => $post['status'], 'post_name' => $post['post_name'], |
|
576 'comment_status' => $post['comment_status'], 'ping_status' => $post['ping_status'], |
|
577 'guid' => $post['guid'], 'post_parent' => $post_parent, 'menu_order' => $post['menu_order'], |
|
578 'post_type' => $post['post_type'], 'post_password' => $post['post_password'] |
|
579 ); |
|
580 |
|
581 if ( 'attachment' == $postdata['post_type'] ) { |
|
582 $remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid']; |
|
583 |
|
584 // try to use _wp_attached file for upload folder placement to ensure the same location as the export site |
|
585 // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload() |
|
586 $postdata['upload_date'] = $post['post_date']; |
|
587 if ( isset( $post['postmeta'] ) ) { |
|
588 foreach( $post['postmeta'] as $meta ) { |
|
589 if ( $meta['key'] == '_wp_attached_file' ) { |
|
590 if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) ) |
|
591 $postdata['upload_date'] = $matches[0]; |
|
592 break; |
|
593 } |
|
594 } |
|
595 } |
|
596 |
|
597 $comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url ); |
|
598 } else { |
|
599 $comment_post_ID = $post_id = wp_insert_post( $postdata, true ); |
|
600 } |
|
601 |
|
602 if ( is_wp_error( $post_id ) ) { |
|
603 printf( __( 'Failed to import %s “%s”', 'wordpress-importer' ), |
|
604 $post_type_object->labels->singular_name, esc_html($post['post_title']) ); |
|
605 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
606 echo ': ' . $post_id->get_error_message(); |
|
607 echo '<br />'; |
|
608 continue; |
|
609 } |
|
610 |
|
611 if ( $post['is_sticky'] == 1 ) |
|
612 stick_post( $post_id ); |
|
613 } |
|
614 |
|
615 // map pre-import ID to local ID |
|
616 $this->processed_posts[intval($post['post_id'])] = (int) $post_id; |
|
617 |
|
618 // add categories, tags and other terms |
|
619 if ( ! empty( $post['terms'] ) ) { |
|
620 $terms_to_set = array(); |
|
621 foreach ( $post['terms'] as $term ) { |
|
622 // back compat with WXR 1.0 map 'tag' to 'post_tag' |
|
623 $taxonomy = ( 'tag' == $term['domain'] ) ? 'post_tag' : $term['domain']; |
|
624 $term_exists = term_exists( $term['slug'], $taxonomy ); |
|
625 $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists; |
|
626 if ( ! $term_id ) { |
|
627 $t = wp_insert_term( $term['name'], $taxonomy, array( 'slug' => $term['slug'] ) ); |
|
628 if ( ! is_wp_error( $t ) ) { |
|
629 $term_id = $t['term_id']; |
|
630 } else { |
|
631 printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($taxonomy), esc_html($term['name']) ); |
|
632 if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG ) |
|
633 echo ': ' . $t->get_error_message(); |
|
634 echo '<br />'; |
|
635 continue; |
|
636 } |
|
637 } |
|
638 $terms_to_set[$taxonomy][] = intval( $term_id ); |
|
639 } |
|
640 |
|
641 foreach ( $terms_to_set as $tax => $ids ) { |
|
642 $tt_ids = wp_set_post_terms( $post_id, $ids, $tax ); |
|
643 } |
|
644 unset( $post['terms'], $terms_to_set ); |
|
645 } |
|
646 |
|
647 // add/update comments |
|
648 if ( ! empty( $post['comments'] ) ) { |
|
649 $num_comments = 0; |
|
650 $inserted_comments = array(); |
|
651 foreach ( $post['comments'] as $comment ) { |
|
652 $comment_id = $comment['comment_id']; |
|
653 $newcomments[$comment_id]['comment_post_ID'] = $comment_post_ID; |
|
654 $newcomments[$comment_id]['comment_author'] = $comment['comment_author']; |
|
655 $newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email']; |
|
656 $newcomments[$comment_id]['comment_author_IP'] = $comment['comment_author_IP']; |
|
657 $newcomments[$comment_id]['comment_author_url'] = $comment['comment_author_url']; |
|
658 $newcomments[$comment_id]['comment_date'] = $comment['comment_date']; |
|
659 $newcomments[$comment_id]['comment_date_gmt'] = $comment['comment_date_gmt']; |
|
660 $newcomments[$comment_id]['comment_content'] = $comment['comment_content']; |
|
661 $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved']; |
|
662 $newcomments[$comment_id]['comment_type'] = $comment['comment_type']; |
|
663 $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent']; |
|
664 $newcomments[$comment_id]['commentmeta'] = isset( $comment['commentmeta'] ) ? $comment['commentmeta'] : array(); |
|
665 if ( isset( $this->processed_authors[$comment['comment_user_id']] ) ) |
|
666 $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']]; |
|
667 } |
|
668 ksort( $newcomments ); |
|
669 |
|
670 foreach ( $newcomments as $key => $comment ) { |
|
671 // if this is a new post we can skip the comment_exists() check |
|
672 if ( ! $post_exists || ! comment_exists( $comment['comment_author'], $comment['comment_date'] ) ) { |
|
673 if ( isset( $inserted_comments[$comment['comment_parent']] ) ) |
|
674 $comment['comment_parent'] = $inserted_comments[$comment['comment_parent']]; |
|
675 $comment = wp_filter_comment( $comment ); |
|
676 $inserted_comments[$key] = wp_insert_comment( $comment ); |
|
677 |
|
678 foreach( $comment['commentmeta'] as $meta ) { |
|
679 $value = maybe_unserialize( $meta['value'] ); |
|
680 add_comment_meta( $inserted_comments[$key], $meta['key'], $value ); |
|
681 } |
|
682 |
|
683 $num_comments++; |
|
684 } |
|
685 } |
|
686 unset( $newcomments, $inserted_comments, $post['comments'] ); |
|
687 } |
|
688 |
|
689 // add/update post meta |
|
690 if ( isset( $post['postmeta'] ) ) { |
|
691 foreach ( $post['postmeta'] as $meta ) { |
|
692 $key = apply_filters( 'import_post_meta_key', $meta['key'] ); |
|
693 $value = false; |
|
694 |
|
695 if ( '_edit_last' == $key ) { |
|
696 if ( isset( $this->processed_authors[intval($meta['value'])] ) ) |
|
697 $value = $this->processed_authors[intval($meta['value'])]; |
|
698 else |
|
699 $key = false; |
|
700 } |
|
701 |
|
702 if ( $key ) { |
|
703 // export gets meta straight from the DB so could have a serialized string |
|
704 if ( ! $value ) |
|
705 $value = maybe_unserialize( $meta['value'] ); |
|
706 |
|
707 add_post_meta( $post_id, $key, $value ); |
|
708 do_action( 'import_post_meta', $post_id, $key, $value ); |
|
709 |
|
710 // if the post has a featured image, take note of this in case of remap |
|
711 if ( '_thumbnail_id' == $key ) |
|
712 $this->featured_images[$post_id] = (int) $value; |
|
713 } |
|
714 } |
|
715 } |
|
716 } |
|
717 |
|
718 unset( $this->posts ); |
|
719 } |
|
720 |
|
721 /** |
|
722 * Attempt to create a new menu item from import data |
|
723 * |
|
724 * Fails for draft, orphaned menu items and those without an associated nav_menu |
|
725 * or an invalid nav_menu term. If the post type or term object which the menu item |
|
726 * represents doesn't exist then the menu item will not be imported (waits until the |
|
727 * end of the import to retry again before discarding). |
|
728 * |
|
729 * @param array $item Menu item details from WXR file |
|
730 */ |
|
731 function process_menu_item( $item ) { |
|
732 // skip draft, orphaned menu items |
|
733 if ( 'draft' == $item['status'] ) |
|
734 return; |
|
735 |
|
736 $menu_slug = false; |
|
737 if ( isset($item['terms']) ) { |
|
738 // loop through terms, assume first nav_menu term is correct menu |
|
739 foreach ( $item['terms'] as $term ) { |
|
740 if ( 'nav_menu' == $term['domain'] ) { |
|
741 $menu_slug = $term['slug']; |
|
742 break; |
|
743 } |
|
744 } |
|
745 } |
|
746 |
|
747 // no nav_menu term associated with this menu item |
|
748 if ( ! $menu_slug ) { |
|
749 _e( 'Menu item skipped due to missing menu slug', 'wordpress-importer' ); |
|
750 echo '<br />'; |
|
751 return; |
|
752 } |
|
753 |
|
754 $menu_id = term_exists( $menu_slug, 'nav_menu' ); |
|
755 if ( ! $menu_id ) { |
|
756 printf( __( 'Menu item skipped due to invalid menu slug: %s', 'wordpress-importer' ), esc_html( $menu_slug ) ); |
|
757 echo '<br />'; |
|
758 return; |
|
759 } else { |
|
760 $menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id; |
|
761 } |
|
762 |
|
763 foreach ( $item['postmeta'] as $meta ) |
|
764 $$meta['key'] = $meta['value']; |
|
765 |
|
766 if ( 'taxonomy' == $_menu_item_type && isset( $this->processed_terms[intval($_menu_item_object_id)] ) ) { |
|
767 $_menu_item_object_id = $this->processed_terms[intval($_menu_item_object_id)]; |
|
768 } else if ( 'post_type' == $_menu_item_type && isset( $this->processed_posts[intval($_menu_item_object_id)] ) ) { |
|
769 $_menu_item_object_id = $this->processed_posts[intval($_menu_item_object_id)]; |
|
770 } else if ( 'custom' != $_menu_item_type ) { |
|
771 // associated object is missing or not imported yet, we'll retry later |
|
772 $this->missing_menu_items[] = $item; |
|
773 return; |
|
774 } |
|
775 |
|
776 if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_parent)] ) ) { |
|
777 $_menu_item_menu_item_parent = $this->processed_menu_items[intval($_menu_item_menu_item_parent)]; |
|
778 } else if ( $_menu_item_menu_item_parent ) { |
|
779 $this->menu_item_orphans[intval($item['post_id'])] = (int) $_menu_item_menu_item_parent; |
|
780 $_menu_item_menu_item_parent = 0; |
|
781 } |
|
782 |
|
783 // wp_update_nav_menu_item expects CSS classes as a space separated string |
|
784 $_menu_item_classes = maybe_unserialize( $_menu_item_classes ); |
|
785 if ( is_array( $_menu_item_classes ) ) |
|
786 $_menu_item_classes = implode( ' ', $_menu_item_classes ); |
|
787 |
|
788 $args = array( |
|
789 'menu-item-object-id' => $_menu_item_object_id, |
|
790 'menu-item-object' => $_menu_item_object, |
|
791 'menu-item-parent-id' => $_menu_item_menu_item_parent, |
|
792 'menu-item-position' => intval( $item['menu_order'] ), |
|
793 'menu-item-type' => $_menu_item_type, |
|
794 'menu-item-title' => $item['post_title'], |
|
795 'menu-item-url' => $_menu_item_url, |
|
796 'menu-item-description' => $item['post_content'], |
|
797 'menu-item-attr-title' => $item['post_excerpt'], |
|
798 'menu-item-target' => $_menu_item_target, |
|
799 'menu-item-classes' => $_menu_item_classes, |
|
800 'menu-item-xfn' => $_menu_item_xfn, |
|
801 'menu-item-status' => $item['status'] |
|
802 ); |
|
803 |
|
804 $id = wp_update_nav_menu_item( $menu_id, 0, $args ); |
|
805 if ( $id && ! is_wp_error( $id ) ) |
|
806 $this->processed_menu_items[intval($item['post_id'])] = (int) $id; |
|
807 } |
|
808 |
|
809 /** |
|
810 * If fetching attachments is enabled then attempt to create a new attachment |
|
811 * |
|
812 * @param array $post Attachment post details from WXR |
|
813 * @param string $url URL to fetch attachment from |
|
814 * @return int|WP_Error Post ID on success, WP_Error otherwise |
|
815 */ |
|
816 function process_attachment( $post, $url ) { |
|
817 if ( ! $this->fetch_attachments ) |
|
818 return new WP_Error( 'attachment_processing_error', |
|
819 __( 'Fetching attachments is not enabled', 'wordpress-importer' ) ); |
|
820 |
|
821 // if the URL is absolute, but does not contain address, then upload it assuming base_site_url |
|
822 if ( preg_match( '|^/[\w\W]+$|', $url ) ) |
|
823 $url = rtrim( $this->base_url, '/' ) . $url; |
|
824 |
|
825 $upload = $this->fetch_remote_file( $url, $post ); |
|
826 if ( is_wp_error( $upload ) ) |
|
827 return $upload; |
|
828 |
|
829 if ( $info = wp_check_filetype( $upload['file'] ) ) |
|
830 $post['post_mime_type'] = $info['type']; |
|
831 else |
|
832 return new WP_Error( 'attachment_processing_error', __('Invalid file type', 'wordpress-importer') ); |
|
833 |
|
834 $post['guid'] = $upload['url']; |
|
835 |
|
836 // as per wp-admin/includes/upload.php |
|
837 $post_id = wp_insert_attachment( $post, $upload['file'] ); |
|
838 wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) ); |
|
839 |
|
840 // remap resized image URLs, works by stripping the extension and remapping the URL stub. |
|
841 if ( preg_match( '!^image/!', $info['type'] ) ) { |
|
842 $parts = pathinfo( $url ); |
|
843 $name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2 |
|
844 |
|
845 $parts_new = pathinfo( $upload['url'] ); |
|
846 $name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" ); |
|
847 |
|
848 $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new; |
|
849 } |
|
850 |
|
851 return $post_id; |
|
852 } |
|
853 |
|
854 /** |
|
855 * Attempt to download a remote file attachment |
|
856 * |
|
857 * @param string $url URL of item to fetch |
|
858 * @param array $post Attachment details |
|
859 * @return array|WP_Error Local file location details on success, WP_Error otherwise |
|
860 */ |
|
861 function fetch_remote_file( $url, $post ) { |
|
862 // extract the file name and extension from the url |
|
863 $file_name = basename( $url ); |
|
864 |
|
865 // get placeholder file in the upload dir with a unique, sanitized filename |
|
866 $upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] ); |
|
867 if ( $upload['error'] ) |
|
868 return new WP_Error( 'upload_dir_error', $upload['error'] ); |
|
869 |
|
870 // fetch the remote url and write it to the placeholder file |
|
871 $headers = wp_get_http( $url, $upload['file'] ); |
|
872 |
|
873 // request failed |
|
874 if ( ! $headers ) { |
|
875 @unlink( $upload['file'] ); |
|
876 return new WP_Error( 'import_file_error', __('Remote server did not respond', 'wordpress-importer') ); |
|
877 } |
|
878 |
|
879 // make sure the fetch was successful |
|
880 if ( $headers['response'] != '200' ) { |
|
881 @unlink( $upload['file'] ); |
|
882 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']) ) ); |
|
883 } |
|
884 |
|
885 $filesize = filesize( $upload['file'] ); |
|
886 |
|
887 if ( isset( $headers['content-length'] ) && $filesize != $headers['content-length'] ) { |
|
888 @unlink( $upload['file'] ); |
|
889 return new WP_Error( 'import_file_error', __('Remote file is incorrect size', 'wordpress-importer') ); |
|
890 } |
|
891 |
|
892 if ( 0 == $filesize ) { |
|
893 @unlink( $upload['file'] ); |
|
894 return new WP_Error( 'import_file_error', __('Zero size file downloaded', 'wordpress-importer') ); |
|
895 } |
|
896 |
|
897 $max_size = (int) $this->max_attachment_size(); |
|
898 if ( ! empty( $max_size ) && $filesize > $max_size ) { |
|
899 @unlink( $upload['file'] ); |
|
900 return new WP_Error( 'import_file_error', sprintf(__('Remote file is too large, limit is %s', 'wordpress-importer'), size_format($max_size) ) ); |
|
901 } |
|
902 |
|
903 // keep track of the old and new urls so we can substitute them later |
|
904 $this->url_remap[$url] = $upload['url']; |
|
905 $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed? |
|
906 // keep track of the destination if the remote url is redirected somewhere else |
|
907 if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url ) |
|
908 $this->url_remap[$headers['x-final-location']] = $upload['url']; |
|
909 |
|
910 return $upload; |
|
911 } |
|
912 |
|
913 /** |
|
914 * Attempt to associate posts and menu items with previously missing parents |
|
915 * |
|
916 * An imported post's parent may not have been imported when it was first created |
|
917 * so try again. Similarly for child menu items and menu items which were missing |
|
918 * the object (e.g. post) they represent in the menu |
|
919 */ |
|
920 function backfill_parents() { |
|
921 global $wpdb; |
|
922 |
|
923 // find parents for post orphans |
|
924 foreach ( $this->post_orphans as $child_id => $parent_id ) { |
|
925 $local_child_id = $local_parent_id = false; |
|
926 if ( isset( $this->processed_posts[$child_id] ) ) |
|
927 $local_child_id = $this->processed_posts[$child_id]; |
|
928 if ( isset( $this->processed_posts[$parent_id] ) ) |
|
929 $local_parent_id = $this->processed_posts[$parent_id]; |
|
930 |
|
931 if ( $local_child_id && $local_parent_id ) |
|
932 $wpdb->update( $wpdb->posts, array( 'post_parent' => $local_parent_id ), array( 'ID' => $local_child_id ), '%d', '%d' ); |
|
933 } |
|
934 |
|
935 // all other posts/terms are imported, retry menu items with missing associated object |
|
936 $missing_menu_items = $this->missing_menu_items; |
|
937 foreach ( $missing_menu_items as $item ) |
|
938 $this->process_menu_item( $item ); |
|
939 |
|
940 // find parents for menu item orphans |
|
941 foreach ( $this->menu_item_orphans as $child_id => $parent_id ) { |
|
942 $local_child_id = $local_parent_id = 0; |
|
943 if ( isset( $this->processed_menu_items[$child_id] ) ) |
|
944 $local_child_id = $this->processed_menu_items[$child_id]; |
|
945 if ( isset( $this->processed_menu_items[$parent_id] ) ) |
|
946 $local_parent_id = $this->processed_menu_items[$parent_id]; |
|
947 |
|
948 if ( $local_child_id && $local_parent_id ) |
|
949 update_post_meta( $local_child_id, '_menu_item_menu_item_parent', (int) $local_parent_id ); |
|
950 } |
|
951 } |
|
952 |
|
953 /** |
|
954 * Use stored mapping information to update old attachment URLs |
|
955 */ |
|
956 function backfill_attachment_urls() { |
|
957 global $wpdb; |
|
958 // make sure we do the longest urls first, in case one is a substring of another |
|
959 uksort( $this->url_remap, array(&$this, 'cmpr_strlen') ); |
|
960 |
|
961 foreach ( $this->url_remap as $from_url => $to_url ) { |
|
962 // remap urls in post_content |
|
963 $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url) ); |
|
964 // remap enclosure urls |
|
965 $result = $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url) ); |
|
966 } |
|
967 } |
|
968 |
|
969 /** |
|
970 * Update _thumbnail_id meta to new, imported attachment IDs |
|
971 */ |
|
972 function remap_featured_images() { |
|
973 // cycle through posts that have a featured image |
|
974 foreach ( $this->featured_images as $post_id => $value ) { |
|
975 if ( isset( $this->processed_posts[$value] ) ) { |
|
976 $new_id = $this->processed_posts[$value]; |
|
977 // only update if there's a difference |
|
978 if ( $new_id != $value ) |
|
979 update_post_meta( $post_id, '_thumbnail_id', $new_id ); |
|
980 } |
|
981 } |
|
982 } |
|
983 |
|
984 /** |
|
985 * Parse a WXR file |
|
986 * |
|
987 * @param string $file Path to WXR file for parsing |
|
988 * @return array Information gathered from the WXR file |
|
989 */ |
|
990 function parse( $file ) { |
|
991 $parser = new WXR_Parser(); |
|
992 return $parser->parse( $file ); |
|
993 } |
|
994 |
|
995 // Display import page title |
|
996 function header() { |
|
997 echo '<div class="wrap">'; |
|
998 screen_icon(); |
|
999 echo '<h2>' . __( 'Import WordPress', 'wordpress-importer' ) . '</h2>'; |
|
1000 |
|
1001 $updates = get_plugin_updates(); |
|
1002 $basename = plugin_basename(__FILE__); |
|
1003 if ( isset( $updates[$basename] ) ) { |
|
1004 $update = $updates[$basename]; |
|
1005 echo '<div class="error"><p><strong>'; |
|
1006 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 ); |
|
1007 echo '</strong></p></div>'; |
|
1008 } |
|
1009 } |
|
1010 |
|
1011 // Close div.wrap |
|
1012 function footer() { |
|
1013 echo '</div>'; |
|
1014 } |
|
1015 |
|
1016 /** |
|
1017 * Display introductory text and file upload form |
|
1018 */ |
|
1019 function greet() { |
|
1020 echo '<div class="narrow">'; |
|
1021 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>'; |
|
1022 echo '<p>'.__( 'Choose a WXR (.xml) file to upload, then click Upload file and import.', 'wordpress-importer' ).'</p>'; |
|
1023 wp_import_upload_form( 'admin.php?import=wordpress&step=1' ); |
|
1024 echo '</div>'; |
|
1025 } |
|
1026 |
|
1027 /** |
|
1028 * Decide if the given meta key maps to information we will want to import |
|
1029 * |
|
1030 * @param string $key The meta key to check |
|
1031 * @return string|bool The key if we do want to import, false if not |
|
1032 */ |
|
1033 function is_valid_meta_key( $key ) { |
|
1034 // skip attachment metadata since we'll regenerate it from scratch |
|
1035 // skip _edit_lock as not relevant for import |
|
1036 if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) ) |
|
1037 return false; |
|
1038 return $key; |
|
1039 } |
|
1040 |
|
1041 /** |
|
1042 * Decide whether or not the importer is allowed to create users. |
|
1043 * Default is true, can be filtered via import_allow_create_users |
|
1044 * |
|
1045 * @return bool True if creating users is allowed |
|
1046 */ |
|
1047 function allow_create_users() { |
|
1048 return apply_filters( 'import_allow_create_users', true ); |
|
1049 } |
|
1050 |
|
1051 /** |
|
1052 * Decide whether or not the importer should attempt to download attachment files. |
|
1053 * Default is true, can be filtered via import_allow_fetch_attachments. The choice |
|
1054 * made at the import options screen must also be true, false here hides that checkbox. |
|
1055 * |
|
1056 * @return bool True if downloading attachments is allowed |
|
1057 */ |
|
1058 function allow_fetch_attachments() { |
|
1059 return apply_filters( 'import_allow_fetch_attachments', true ); |
|
1060 } |
|
1061 |
|
1062 /** |
|
1063 * Decide what the maximum file size for downloaded attachments is. |
|
1064 * Default is 0 (unlimited), can be filtered via import_attachment_size_limit |
|
1065 * |
|
1066 * @return int Maximum attachment file size to import |
|
1067 */ |
|
1068 function max_attachment_size() { |
|
1069 return apply_filters( 'import_attachment_size_limit', 0 ); |
|
1070 } |
|
1071 |
|
1072 /** |
|
1073 * Added to http_request_timeout filter to force timeout at 60 seconds during import |
|
1074 * @return int 60 |
|
1075 */ |
|
1076 function bump_request_timeout() { |
|
1077 return 60; |
|
1078 } |
|
1079 |
|
1080 // return the difference in length between two strings |
|
1081 function cmpr_strlen( $a, $b ) { |
|
1082 return strlen($b) - strlen($a); |
|
1083 } |
|
1084 } |
|
1085 |
|
1086 } // class_exists( 'WP_Importer' ) |
|
1087 |
|
1088 function wordpress_importer_init() { |
|
1089 load_plugin_textdomain( 'wordpress-importer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); |
|
1090 |
|
1091 /** |
|
1092 * WordPress Importer object for registering the import callback |
|
1093 * @global WP_Import $wp_import |
|
1094 */ |
|
1095 $GLOBALS['wp_import'] = new WP_Import(); |
|
1096 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' ) ); |
|
1097 } |
|
1098 add_action( 'admin_init', 'wordpress_importer_init' ); |