Changeset 10538
- Timestamp:
- 02/10/2009 07:34:52 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-admin/import/livejournal.php
r10501 r10538 1 1 <?php 2 2 3 /** 3 4 * LiveJournal API Importer … … 9 10 // XML-RPC library for communicating with LiveJournal API 10 11 require_once( ABSPATH . WPINC . '/class-IXR.php' ); 11 12 // Snoopy for getting comments (with cookies)13 require_once( ABSPATH . WPINC . '/class-snoopy.php' );14 12 15 13 /** … … 27 25 var $username; 28 26 var $password; 29 var $snoop;30 27 var $comment_meta; 31 28 var $comments; 32 29 var $usermap; 33 30 var $postmap; 31 var $commentmap; 34 32 var $pointers = array(); 35 33 … … 189 187 <input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Continue previous import' ) ) ?>" /> 190 188 </p> 191 <p ><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( $_SERVER['REQUEST_URI'] ) ?>"><?php _e( 'Cancel & start a new import' ) ?></a></p>189 <p class="submitbox"><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( $_SERVER['REQUEST_URI'] ) ?>" class="deletion submitdelete"><?php _e( 'Cancel & start a new import' ) ?></a></p> 192 190 <p> 193 191 <?php else : ?> … … 229 227 230 228 <p><?php _e( '<strong>NOTE:</strong> If the import process is interrupted for <em>any</em> reason, come back to this page and it will continue from where it stopped automatically.' ) ?></p> 229 230 <noscript> 231 <p><?php _e( '<strong>NOTE:</strong> You appear to have JavaScript disabled, so you will need to manually click through each step of this importer. If you enable JavaScript, it will step through automatically.' ) ?></p> 232 </noscript> 231 233 <?php endif; ?> 232 234 </form> … … 249 251 $lastsync = date( 'Y-m-d H:i:s', strtotime( get_option( 'ljapi_lastsync' ) ) ); 250 252 $synclist = $this->lj_ixr( 'syncitems', array( 'ver' => 1, 'lastsync' => $lastsync ) ); 251 $this->log( $synclist, 'ljimport-items-' . $total . '.txt' );252 253 253 254 // Keep track of if we've downloaded everything … … 262 263 } 263 264 } 264 265 update_option( 'ljapi_sync_item_times', $sync_item_times );266 update_option( 'ljapi_total', $total );267 update_option( 'ljapi_count', $count );268 update_option( 'ljapi_lastsync', $lastsync );269 265 } while ( $total > $count ); 270 266 // endwhile - all post meta is cached locally 271 $this->log( $sync_item_times, 'ljimport-post-mod-times.txt' ); 267 268 update_option( 'ljapi_sync_item_times', $sync_item_times ); 269 update_option( 'ljapi_total', $total ); 270 update_option( 'ljapi_count', $count ); 271 update_option( 'ljapi_lastsync', $lastsync ); 272 273 echo '<p>' . __( 'Post metadata has been downloaded, proceeding with posts...' ) . '</p>'; 272 274 273 275 echo '<ol>'; … … 286 288 'lineendings' => 'pc', 287 289 'lastsync' => $lastsync ) ); 288 $this->log( $itemlist, 'ljimport-posts-' . $imported_count . '.txt' );289 290 if ( is_wp_error( $itemlist ) ) 290 291 return $itemlist; 292 291 293 if ( $num = count( $itemlist['events'] ) ) { 292 294 foreach ( $itemlist['events'] as $event ) { … … 313 315 314 316 $user = wp_get_current_user(); 315 $post_author = $user->ID; 316 $post_status = ( 'private' == trim( $post['security'] ) ) ? 'private' : 'publish'; // Only me 317 $post_password = ( 'usemask' == trim( $post['security'] ) ) ? $this->protected_password : ''; // "Friends" via password 317 $post_author = $user->ID; 318 $post['security'] = !empty( $post['security'] ) ? $post['security'] : ''; 319 $post_status = ( 'private' == trim( $post['security'] ) ) ? 'private' : 'publish'; // Only me 320 $post_password = ( 'usemask' == trim( $post['security'] ) ) ? $this->protected_password : ''; // "Friends" via password 318 321 319 322 // For some reason, LJ sometimes sends a date as "2004-04-1408:38:00" (no space btwn date/time) … … 323 326 324 327 // Cleaning up and linking the title 325 $post_title = trim( $post['subject'] );328 $post_title = isset( $post['subject'] ) ? trim( $post['subject'] ) : ''; 326 329 $post_title = $this->translate_lj_user( $post_title ); // Translate it, but then we'll strip the link 327 330 $post_title = strip_tags( $post_title ); // Can't have tags in the title in WP … … 366 369 $postdata['post_ID'] = $post_id; 367 370 $postdata['lj_itemid'] = $post['itemid']; 368 $this->log( $postdata, 'ljimport-post-' . $post_id . '.txt' );369 371 370 372 // Handle all the metadata for this post … … 405 407 } 406 408 407 // Loops through and gets comment meta and content from LJ in batches 408 // Writes raw XML files to disk for later processing 409 function download_comments() { 409 // Set up a session (authenticate) with LJ 410 function getsession() { 410 411 // Get a session via XMLRPC 411 412 $cookie = $this->lj_ixr( 'sessiongenerate', array( 'ver' => 1, 'expiration' => 'short' ) ); 412 413 // Comment Meta 413 return new WP_Http_Cookie( array( 'name' => 'ljsession', 'value' => $cookie['ljsession'] ) ); 414 } 415 416 // Loops through and gets comment meta from LJ in batches 417 function download_comment_meta() { 418 $cookie = $this->getsession(); 414 419 415 420 // Load previous state (if any) 416 421 $this->usermap = (array) get_option( 'ljapi_usermap' ); 417 $maxid = (int) get_option( 'ljapi_maxid' ) || 1; 418 $highest_id = (int) get_option( 'ljapi_highest_id' ); 419 420 // Snoopy is required to handle the cookie 421 $this->snoop = new Snoopy(); 422 $this->snoop->cookies = $cookie; 422 $maxid = get_option( 'ljapi_maxid' ) ? get_option( 'ljapi_maxid' ) : 1; 423 $highest_id = get_option( 'ljapi_highest_id' ) ? get_option( 'ljapi_highest_id' ) : 0; 423 424 424 425 // We need to loop over the metadata request until we have it all 425 426 while ( $maxid > $highest_id ) { 426 427 // Now get the meta listing 427 if ( !$this->snoop->fetch( $this->comments_url . '?get=comment_meta&startid=' . ( $highest_id + 1 ) ) ) 428 return new WP_Error( 'Snoopy', __( 'Failed to retrieve comment meta information from LiveJournal. Please try again soon.' ) ); 429 430 // Snoopy doesn't provide an accessor for results... 431 $results = $this->snoop->results; 428 $results = wp_remote_get( $this->comments_url . '?get=comment_meta&startid=' . ( $highest_id + 1 ), 429 array( 'cookies' => array( $cookie ), 'timeout' => 20 ) ); 430 if ( is_wp_error( $results ) ) 431 return new WP_Error( 'comment_meta', __( 'Failed to retrieve comment meta information from LiveJournal. Please try again soon.' ) ); 432 433 $results = wp_remote_retrieve_body( $results ); 432 434 433 435 // Get the maxid so we know if we have them all yet 434 436 preg_match( '|<maxid>(\d+)</maxid>|', $results, $matches ); 437 if ( 0 == $matches[1] ) { 438 // No comment meta = no comments for this journal 439 echo '<p>' . __( 'You have no comments to import!' ) . '</p>'; 440 update_option( 'ljapi_highest_id', 1 ); 441 update_option( 'ljapi_highest_comment_id', 1 ); 442 return false; // Bail out of comment importing entirely 443 } 435 444 $maxid = !empty( $matches[1] ) ? $matches[1] : $maxid; 436 445 … … 447 456 $this->usermap[$userid] = $matches[2][$count]; // need this in memory for translating ids => names 448 457 449 update_option( 'ljapi_usermap', $this->usermap ); 450 update_option( 'ljapi_maxid', $maxid ); 451 update_option( 'ljapi_highest_id', $highest_id ); 458 wp_cache_flush(); 452 459 } 453 460 // endwhile - should have seen all comment meta at this point 454 455 456 // Download Comment XML 461 462 update_option( 'ljapi_usermap', $this->usermap ); 463 update_option( 'ljapi_maxid', $maxid ); 464 update_option( 'ljapi_highest_id', $highest_id ); 465 466 echo '<p>' . __( ' Comment metadata downloaded successfully, proceeding with posts...' ) . '</p>'; 467 468 return true; 469 } 470 471 // Downloads actual comment bodies from LJ 472 // Inserts them all directly to the DB, with additional info stored in "spare" fields 473 function download_comment_bodies() { 474 global $wpdb; 475 $cookie = $this->getsession(); 457 476 458 477 // Load previous state (if any) 459 $highest_id = (int) get_option( 'ljapi_highest_comment_id' ); 460 $comment_xml_files = get_option( 'ljapi_comment_xml_files' ); 461 if ( !is_array( $comment_xml_files ) ) { 462 update_option( 'ljapi_comment_xml_files', array() ); 463 $comment_xml_files = array(); 464 } 465 466 echo '<ol>'; 467 468 // And now request the actual comments, and keep going until we have them all 469 while ( $maxid > $highest_id ) { 478 $this->usermap = (array) get_option( 'ljapi_usermap' ); 479 $maxid = get_option( 'ljapi_maxid' ) ? (int) get_option( 'ljapi_maxid' ) : 1; 480 $highest_id = (int) get_option( 'ljapi_highest_comment_id' ); 481 $loop = 0; 482 while ( $maxid > $highest_id && $loop < 5 ) { // We do 5 loops per call to avoid memory limits 483 $loop++; 484 470 485 // Get a batch of comments, using the highest_id we've already got as a starting point 471 if ( !$this->snoop->fetch( $this->comments_url . '?get=comment_body&startid=' . ( $highest_id + 1 ) ) ) 472 return new WP_Error( 'Snoopy', __( 'Failed to retrieve comment bodies from LiveJournal. Please try again soon.' ) ); 473 474 // Get the highest post ID in this batch (required for loop control) 475 $results = $this->snoop->results; 476 preg_match_all( '|<comment id=\'(\d+)\'|i', $results, $comments ); 477 for ( $r = 0; $r < count( $comments[1] ); $r++ ) { 478 if ( $comments[1][$r] > $highest_id ) 479 $highest_id = $comments[1][$r]; 480 } 481 482 // $this->snoop-results is where the actual response is stored 483 $this->log( $this->snoop->results, 'ljimport-comment-bodies-' . $highest_id . '.txt' ); 484 485 // Store in uploads dir. Can't use *.xml because it's not allowed 486 $results = wp_upload_bits( 'raw-comments-' . $highest_id . '.txt', null, $results ); 487 if ( !empty( $results['error'] ) ) 488 return new WP_Error( 'xml', $results['error'] ); 489 $comment_xml_files[] = $results['file']; 490 491 echo '<li>' . sprintf( __( 'Downloaded <strong>%s</strong>' ), basename( $results['file'] ) ) . '</li>'; 492 ob_flush(); flush(); 493 494 $comment_xml_files = array_unique( $comment_xml_files ); 495 update_option( 'ljapi_comment_xml_files', $comment_xml_files ); 496 update_option( 'ljapi_comment_xml_files_count', count( $comment_xml_files ) ); 486 $results = wp_remote_get( $this->comments_url . '?get=comment_body&startid=' . ( $highest_id + 1 ), 487 array( 'cookies' => array( $cookie ), 'timeout' => 20 ) ); 488 if ( is_wp_error( $results ) ) 489 return new WP_Error( 'comment_bodies', __( 'Failed to retrieve comment bodies from LiveJournal. Please try again soon.' ) ); 490 491 $results = wp_remote_retrieve_body( $results ); 492 493 // Parse out each comment and insert directly 494 preg_match_all( '|<comment id=\'(\d+)\'.*</comment>|iUs', $results, $matches ); 495 for ( $c = 0; $c < count( $matches[0] ); $c++ ) { 496 // Keep track of highest id seen 497 if ( $matches[1][$c] > $highest_id ) { 498 $highest_id = $matches[1][$c]; 499 update_option( 'ljapi_highest_comment_id', $highest_id ); 500 } 501 502 $comment = $matches[0][$c]; 503 504 // Filter out any captured, deleted comments (nothing useful to import) 505 $comment = preg_replace( '|<comment id=\'\d+\' jitemid=\'\d+\' posterid=\'\d+\' state=\'D\'[^/]*/>|is', '', $comment ); 506 507 // Parse this comment into an array and insert 508 $comment = $this->parse_comment( $comment ); 509 $id = wp_insert_comment( $comment ); 510 511 // Clear cache 512 clean_comment_cache( $id ); 513 } 514 515 // Clear cache to preseve memory 516 wp_cache_flush(); 497 517 } 498 518 // endwhile - all comments downloaded and ready for bulk processing 499 519 500 echo '</ol>'; 520 // Counter just used to show progress to user 521 update_option( 'ljapi_comment_batch', ( (int) get_option( 'ljapi_comment_batch' ) + 1 ) ); 501 522 502 523 return true; 503 524 } 504 525 505 function parse_comment_xml( $xml_file ) { 506 if ( !is_file( $xml_file ) || !is_readable( $xml_file ) ) 507 return new WP_Error( 'file', sprintf( __( 'Could not access comment XML file: %s'), $filename ) ); 508 509 // Get content from file 510 $xml = @file_get_contents( $xml_file ); 511 512 $cache_files = get_option( 'ljapi_comment_cache_files' ); 513 if ( !is_array( $cache_files ) ) 514 $cache_files = array(); 515 516 // Parse XML into comments 517 preg_match_all( '|<comment id.*</comment>|iUs', $xml, $matches ); 518 unset( $xml ); 519 for ( $c = 0; $c < count( $matches[0] ); $c++ ) { 520 $comment = $matches[0][$c]; 521 522 // Filter out any captured, deleted comments (nothing useful to import) 523 $comment = preg_replace( '|<comment id=\'\d+\' jitemid=\'\d+\' posterid=\'\d+\' state=\'D\'[^/]*/>|is', '', $comment ); 524 525 // Parse this comment into an array 526 $comment = $this->parse_comment( $comment ); 527 if ( empty( $comment['comment_post_ID'] ) ) 528 continue; 529 530 // Add this comment to the appropriate cache file 531 $filename = $this->full_path( 'ljimport-comments-' . $comment['comment_post_ID'] . '.php' ); 532 if ( $this->write_file( '<?php $comments[] = ' . var_export( $comment, true ) . '; ?>' . "\n", 533 $filename, 534 $comment['comment_post_ID'], 535 'a' ) ) 536 { 537 // Keep track of files used 538 $cache_files[] = $filename; 539 } 540 } 541 542 // Update list of files in the DB 543 sort( $cache_files ); 544 $cache_files = array_unique( $cache_files ); 545 update_option( 'ljapi_comment_cache_files', $cache_files ); 546 update_option( 'ljapi_comment_cache_files_count', count( $cache_files ) ); 547 $this->close_file_pointers(); 548 549 // Don't need this XML file anymore 550 unlink( $xml_file ); 551 552 return true; 553 } 554 526 // Takes a block of XML and parses out all the elements of the comment 555 527 function parse_comment( $comment ) { 556 528 global $wpdb; … … 563 535 $lj_comment_post_ID = $matches[1]; 564 536 preg_match( '| posterid=\'(\d+)\'|i', $attribs[1], $matches ); 565 $comment_author_ID = $matches[1];566 preg_match( '| parentid=\'(\d+)\'|i', $attribs[1], $matches ); 567 $lj_comment_parent = $matches[1];568 preg_match( '| state=\'([SDFA])\'|i', $attribs[1], $matches ); 569 $lj_comment_state = !empty( $matches[1] ) ? $matches[1] : 'A';537 $comment_author_ID = isset( $matches[1] ) ? $matches[1] : 0; 538 preg_match( '| parentid=\'(\d+)\'|i', $attribs[1], $matches ); // optional 539 $lj_comment_parent = isset( $matches[1] ) ? $matches[1] : 0; 540 preg_match( '| state=\'([SDFA])\'|i', $attribs[1], $matches ); // optional 541 $lj_comment_state = isset( $matches[1] ) ? $matches[1] : 'A'; 570 542 571 543 // Clean up "subject" - this will become the first line of the comment in WP 572 544 preg_match( '|<subject>(.*)</subject>|is', $comment, $matches ); 573 $comment_subject = $wpdb->escape( trim( $matches[1] ) ); 574 if ( 'Re:' == $comment_subject ) 575 $comment_subject = ''; 545 if ( isset( $matches[1] ) ) { 546 $comment_subject = $wpdb->escape( trim( $matches[1] ) ); 547 if ( 'Re:' == $comment_subject ) 548 $comment_subject = ''; 549 } 576 550 577 551 // Get the body and HTMLize it … … 591 565 592 566 // Grab IP if available 593 preg_match( '|<property name=\'poster_ip\'>(.*)</property>|i', $comment, $matches ); 594 $comment_author_IP = $matches[1];567 preg_match( '|<property name=\'poster_ip\'>(.*)</property>|i', $comment, $matches ); // optional 568 $comment_author_IP = isset( $matches[1] ) ? $matches[1] : ''; 595 569 596 570 // Try to get something useful for the comment author, especially if it was "my" comment 597 $author = ( substr( $this->usermap[$comment_author_ID], 0, 4 ) == 'ext_' || empty( $comment_author_ID )) ? __( 'Anonymous' ) : $this->usermap[$comment_author_ID];571 $author = ( empty( $comment_author_ID ) || empty( $this->usermap[$comment_author_ID] ) || substr( $this->usermap[$comment_author_ID], 0, 4 ) == 'ext_' ) ? __( 'Anonymous' ) : $this->usermap[$comment_author_ID]; 598 572 if ( get_option( 'ljapi_username' ) == $author ) { 599 573 $user = wp_get_current_user(); … … 614 588 'comment_author' => $author, 615 589 'comment_author_url' => $url, 590 'comment_author_email' => '', 616 591 'comment_content' => $comment_content, 617 592 'comment_date' => $comment_date, 618 593 'comment_author_IP' => ( !empty( $comment_author_IP ) ? $comment_author_IP : '' ), 619 594 'comment_approved' => ( in_array( $lj_comment_state, array( 'A', 'F' ) ) ? 1 : 0 ), 620 'comment_agent' => 'WP LJ Importer', 621 'user_id' => $user_id 622 ); 595 'comment_karma' => $lj_comment_ID, // Need this and next value until rethreading is done 596 'comment_agent' => $lj_comment_parent, 597 'comment_type' => 'livejournal', // Custom type, so we can find it later for processing 598 'user_ID' => $user_id 599 ); 623 600 } 624 601 … … 628 605 global $wpdb; 629 606 if ( empty( $this->postmap[$post] ) ) 630 $this->postmap[$post] = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'lj_itemid' AND meta_value = %d", $post ) );607 $this->postmap[$post] = (int) $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'lj_itemid' AND meta_value = %d", $post ) ); 631 608 return $this->postmap[$post]; 632 609 } 633 610 634 // Re-build the threading within a single cache file 635 function thread_comments( $filename ) { 636 if ( !is_file( $filename ) || !is_readable( $filename ) ) 637 return new WP_Error( 'File', __( sprintf( 'Cannot access file %s', $filename ) ) ); 638 639 $comments = array(); 640 @include( $filename ); 641 $this->comments = $comments; 642 unset( $comments ); 643 if ( !is_array( $this->comments ) ) 644 $this->comments = array(); 645 646 $count = count( $this->comments ); 647 for ( $c = 0; $c < $count; $c++ ) { 648 // Skip anything that's not "top-level" for now 649 if ( 0 != $this->comments[$c]['lj_comment_parent'] ) 650 continue; 651 $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] ); 652 } 653 654 // Remove anything that's not supposed to be at top level 655 $top_comments = array(); 656 for ( $c = 0; $c < $count; $c++ ) { 657 if ( 0 == $this->comments[$c]['lj_comment_parent'] ) { 658 $top_comments[] = $this->comments[$c]; 659 } 660 } 661 662 // Write back to file 663 @unlink( $filename ); 664 $this->write_file( '<?php $comments = ' . var_export( $top_comments, true ) . '; ?>', $filename, $count, 'w' ); 665 unset( $top_comments ); 666 $this->close_file_pointers(); 667 668 // Reference this file as being threaded 669 $files = get_option( 'ljapi_comment_threaded_files' ); 670 $files[] = $filename; 671 array_unique( $files ); 672 update_option( 'ljapi_comment_threaded_files', $files ); 673 update_option( 'ljapi_comment_threaded_files_count', count( $files ) ); 674 675 return true; 676 } 677 678 function get_child_comments( $id ) { 679 $children = array(); 680 $count = count( $this->comments ); 681 for ( $c = 0; $c < $count; $c++ ) { 682 // This comment is a child of the $id 683 if ( $id == $this->comments[$c]['lj_comment_parent'] ) { 684 $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] ); 685 $children[] = $this->comments[$c]; 686 } 687 } 688 return $children; 689 } 690 691 // Inserts the contents of each cache file (should be threaded already) 692 function insert_comments( $filename ) { 693 echo '<ol>'; 694 695 if ( !is_file( $filename ) || !is_readable( $filename ) ) 696 return new WP_Error( 'File', __( sprintf( 'Cannot access file %s', $filename ) ) ); 697 698 $comments = array(); 699 @include( $filename ); 700 $this->comments = $comments; 701 unset( $comments ); 702 if ( !is_array( $this->comments ) ) 703 $this->comments = array(); 704 705 $count = count( $this->comments ); 706 for ( $c = 0; $c < $count; $c++ ) { 707 $comment =& $this->comments[$c]; 708 echo '<li>'; 709 printf( __( 'Imported comment from <strong>%s</strong> on %s' ), $comment['comment_author'], $comment['comment_date'] ); 710 711 $id = wp_insert_comment( $comment ); 712 $comment['comment_ID'] = $id; 713 if ( count( $comment['children'] ) ) { 714 _e( ' and replies:' ); 715 $this->insert_child_comments( $comment['children'], $id ); 716 } 717 718 echo '</li>'; 719 } 720 721 // Remove the file now that we're done with it 722 @unlink( $filename ); 723 724 echo '</ol>'; 725 726 return true; 727 } 728 729 function insert_child_comments( &$comments, $parent ) { 730 echo '<ol>'; 731 $count = count( $comments ); 732 for ( $c = 0; $c < $count; $c++ ) { 733 $comment =& $comments[$c]; 734 $comment['comment_parent'] = $parent; 735 echo '<li>'; 736 printf( __( 'Imported reply from <strong>%s</strong> on %s' ), $comment['comment_author'], $comment['comment_date'] ); 737 738 $id = wp_insert_comment( $comment ); 739 $comment['comment_ID'] = $id; 740 if ( count( $comment['children'] ) ) { 741 _e( ' and replies:' ); 742 $this->insert_child_comments( $comment['children'], $id ); 743 } 744 745 echo '</li>'; 746 } 747 echo '</ol>'; 611 // Gets the comment_ID that a LJ comment has been saved as within WP 612 function get_wp_comment_ID( $comment ) { 613 global $wpdb; 614 if ( empty( $this->commentmap[$comment] ) ) 615 $this->commentmap[$comment] = $wpdb->get_var( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_karma = %d", $comment ) ); 616 return $this->commentmap[$comment]; 748 617 } 749 618 … … 768 637 return $this->ixr->getResponse(); 769 638 } else { 770 $this->log( $this->ixr->message, 'ljimport-error-' . $method . '.txt' );771 639 return new WP_Error( 'IXR', __( 'XML-RPC Request Failed - ' ) . $this->ixr->getErrorCode() . ': ' . $this->ixr->getErrorMessage() ); 772 640 } … … 789 657 break; 790 658 case 1 : 791 case 2 :792 659 $this->ixr = new IXR_Client( $this->ixr_url ); 793 660 // Intentional no break 661 case 2 : 794 662 case 3 : 795 case 4 :796 case 5 :797 663 check_admin_referer( 'lj-api-import' ); 798 664 $result = $this->{ 'step' . $step }(); … … 838 704 if ( is_wp_error( $login ) ) { 839 705 if ( 100 == $this->ixr->getErrorCode() || 101 == $this->ixr->getErrorCode() ) { 706 delete_option( 'ljapi_username' ); 707 delete_option( 'ljapi_password' ); 840 708 ?> 841 709 <p><?php _e( 'Logging in to LiveJournal failed. Check your username and password and try again.' ) ?></p> … … 849 717 850 718 // Set up some options to avoid them autoloading (these ones get big) 851 add_option( 'ljapi_sync_item_times', '', '', 'no' ); 852 add_option( 'ljapi_usermap', '', '', 'no' ); 853 add_option( 'ljapi_comment_xml_files', '', '', 'no' ); 854 add_option( 'ljapi_comment_cache_files', '', '', 'no' ); 855 add_option( 'ljapi_comment_threaded_files', '', '', 'no' ); 719 add_option( 'ljapi_sync_item_times', '', '', 'no' ); 720 add_option( 'ljapi_usermap', '', '', 'no' ); 721 update_option( 'ljapi_comment_batch', 0 ); 856 722 857 723 echo '<h3>' . __( 'Importing Posts' ) . '</h3>'; … … 874 740 } 875 741 876 echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to process& import your comments." ) . '</p>';742 echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to download & import your comments." ) . '</p>'; 877 743 echo $this->next_step( 2, __( 'Download my comments »' ) ); 878 744 $this->auto_submit(); … … 885 751 $this->username = get_option( 'ljapi_username' ); 886 752 $this->password = get_option( 'ljapi_password' ); 887 753 $this->ixr = new IXR_Client( $this->ixr_url ); 754 755 echo '<div id="ljapi-status">'; 888 756 echo '<h3>' . __( 'Downloading Comments' ) . '</h3>'; 889 echo '<p>' . __( 'Now we will download your comments so we can process and import them...' ) . '</p>';757 echo '<p>' . __( 'Now we will download your comments so we can import them (this could take a <strong>long</strong> time if you have lots of comments)...' ) . '</p>'; 890 758 ob_flush(); flush(); 891 759 892 $result = $this->download_comments(); 760 if ( !get_option( 'ljapi_usermap' ) ) { 761 // We haven't downloaded meta yet, so do that first 762 $result = $this->download_comment_meta(); 763 if ( is_wp_error( $result ) ) 764 return $result; 765 } 766 767 // Download a batch of actual comments 768 $result = $this->download_comment_bodies(); 893 769 if ( is_wp_error( $result ) ) 894 770 return $result; 895 771 896 echo '<p>' . __( 'Your comments have all been downloaded to this server now, so we can process them and get them ready for importing.' ) . '</p>'; 897 echo $this->next_step( 3, __( 'Process my comment files »' ) ); 898 $this->auto_submit(); 899 } 900 901 // Parse XML into comment cache files 772 $maxid = get_option( 'ljapi_maxid' ) ? (int) get_option( 'ljapi_maxid' ) : 1; 773 $highest_id = (int) get_option( 'ljapi_highest_comment_id' ); 774 if ( $maxid > $highest_id ) { 775 ?> 776 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> 777 <p><strong><?php printf( __( 'Imported comment batch %d of <strong>approximately</strong> %d' ), get_option( 'ljapi_comment_batch' ), ( $maxid / 5000 ) ) ?></strong></p> 778 <?php wp_nonce_field( 'lj-api-import' ) ?> 779 <input type="hidden" name="step" id="step" value="2" /> 780 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Import the next batch »' ) ) ?>" /> <span id="auto-message"></span></p> 781 </form> 782 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 783 <?php 784 } else { 785 echo '<p>' . __( 'Your comments have all been imported now, but we still need to rebuild your conversation threads.' ) . '</p>'; 786 echo $this->next_step( 3, __( 'Rebuild my comment threads »' ) ); 787 $this->auto_submit(); 788 } 789 echo '</div>'; 790 } 791 792 // Re-thread comments already in the DB 902 793 function step3() { 903 794 global $wpdb; 904 795 set_time_limit( 0 ); 905 796 update_option( 'ljapi_step', 3 ); 906 797 907 $this->usermap = get_option( 'ljapi_usermap' );908 909 echo '<div id="ljapi-status">';910 echo '<h3>' . __( 'Parsing Comments' ) . '</h3>';911 echo '<p>' . __( 'Time to clean up your comments and get them into a format WordPress understands...' ) . '</p>';912 ob_flush(); flush();913 914 $files = get_option( 'ljapi_comment_xml_files' );915 if ( count( $files ) ) {916 $file = array_pop( $files );917 918 $result = $this->parse_comment_xml( $file );919 if ( is_wp_error( $result ) )920 return $result;921 922 update_option( 'ljapi_comment_xml_files', $files );923 }924 925 if ( count( $files ) ) {926 ?>927 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost">928 <p><strong><?php printf( __( 'Processed comment file %d of %d' ), ( get_option( 'ljapi_comment_xml_files_count' ) - count( $files ) ), get_option( 'ljapi_comment_xml_files_count' ) ) ?></strong></p>929 <?php wp_nonce_field( 'lj-api-import' ) ?>930 <input type="hidden" name="step" id="step" value="3" />931 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Process the next comment file »' ) ) ?>" /> <span id="auto-message"></span></p>932 </form>933 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?>934 <?php935 } else {936 echo '<p>' . __( 'Yay, we finished processing all of your comment files! Now we need to re-build your conversation threads.' ) . '</p>';937 echo $this->next_step( 4, __( 'Thread my comments »' ) );938 $this->auto_submit();939 }940 echo '</div>';941 }942 943 // Thread comments within their cache files944 function step4() {945 set_time_limit( 0 );946 update_option( 'ljapi_step', 4 );947 948 798 echo '<div id="ljapi-status">'; 949 799 echo '<h3>' . __( 'Threading Comments' ) . '</h3>'; 950 echo '<p>' . __( ' Re-building your conversation threads ready for import...' ) . '</p>';800 echo '<p>' . __( 'We are now re-building the threading of your comments (this can also take a while if you have lots of comments)...' ) . '</p>'; 951 801 ob_flush(); flush(); 952 802 953 $files = get_option( 'ljapi_comment_cache_files' ); 954 if ( count( $files ) ) { 955 $file = array_pop( $files ); 956 957 $result = $this->thread_comments( $file ); 958 if ( is_wp_error( $result ) ) 959 return $result; 960 961 update_option( 'ljapi_comment_cache_files', $files ); 962 } 963 964 if ( count( $files ) ) { 965 ?> 966 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> 967 <p><strong><?php printf( __( 'Threaded cache file %d of %d' ), ( get_option( 'ljapi_comment_cache_files_count' ) - count( $files ) ), get_option( 'ljapi_comment_cache_files_count' ) ) ?></strong></p> 968 <?php wp_nonce_field( 'lj-api-import' ) ?> 969 <input type="hidden" name="step" id="step" value="4" /> 970 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Thread the next cache file »' ) ) ?>" /> <span id="auto-message"></span></p> 971 </form> 972 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 973 <?php 974 } else { 975 echo '<p>' . __( "Alrighty, your comments are all threaded. There's just one last step -- time to actually import them all now!" ) . '</p>'; 976 echo '<p>' . __( 'This last part in particular can take a really long time if you have a lot of comments. You might want to go and do something else while you wait.' ) . '</p>'; 977 echo $this->next_step( 5, __( 'Import my threaded comments into WordPress »' ) ); 978 $this->auto_submit(); 979 } 980 echo '</div>'; 981 } 982 983 // Import comments from cache files into WP 984 function step5() { 985 set_time_limit( 0 ); 986 update_option( 'ljapi_step', 5 ); 987 988 989 echo '<div id="ljapi-status">'; 990 echo '<h3>' . __( 'Importing Comments' ) . '</h3>'; 991 echo '<p>' . __( 'This is the big one -- we are now inserting your comment threads into WordPress...' ) . '</p>'; 992 993 $files = get_option( 'ljapi_comment_threaded_files' ); 994 echo '<p><strong>' . sprintf( __( 'Importing cache file %d of %d' ), ( get_option( 'ljapi_comment_threaded_files_count' ) - count( $files ) + 1 ), get_option( 'ljapi_comment_threaded_files_count' ) ) . '</strong></p>'; 995 ob_flush(); flush(); 996 997 if ( count( $files ) ) { 998 $file = array_pop( $files ); 999 1000 $result = $this->insert_comments( $file ); 1001 if ( is_wp_error( $result ) ) 1002 return $result; 1003 1004 update_option( 'ljapi_comment_threaded_files', $files ); 1005 } 1006 1007 if ( count( $files ) ) { 1008 ?> 1009 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> 1010 <?php wp_nonce_field( 'lj-api-import' ) ?> 1011 <input type="hidden" name="step" id="step" value="5" /> 1012 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Import the next cache file »' ) ) ?>" /> <span id="auto-message"></span></p> 1013 </form> 1014 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 1015 <?php 1016 } else { 1017 // Clean up database and we're out 1018 $this->cleanup(); 1019 do_action( 'import_done', 'livejournal' ); 1020 echo '<h3>'; 1021 printf( __( 'All done. <a href="%s">Have fun!</a>' ), get_option( 'home' ) ); 1022 echo '</h3>'; 1023 } 803 // Only bother adding indexes if they have over 5000 comments (arbitrary number) 804 $imported_comments = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_type = 'livejournal'" ); 805 $added_indices = false; 806 if ( 5000 < $imported_comments ) { 807 include_once(ABSPATH . 'wp-admin/includes/upgrade.php'); 808 $added_indices = true; 809 add_clean_index( $wpdb->comments, 'comment_type' ); 810 add_clean_index( $wpdb->comments, 'comment_karma' ); 811 add_clean_index( $wpdb->comments, 'comment_agent' ); 812 } 813 814 // Get LJ comments, which haven't been threaded yet, 5000 at a time and thread them 815 while ( $comments = $wpdb->get_results( "SELECT comment_ID, comment_agent FROM {$wpdb->comments} WHERE comment_type = 'livejournal' AND comment_agent != '0' LIMIT 5000", OBJECT ) ) { 816 foreach ( $comments as $comment ) { 817 $wpdb->update( $wpdb->comments, 818 array( 'comment_parent' => $this->get_wp_comment_ID( $comment->comment_agent ), 'comment_type' => 'livejournal-done' ), 819 array( 'comment_ID' => $comment->comment_ID ) ); 820 } 821 wp_cache_flush(); 822 $wpdb->flush(); 823 } 824 825 // Revert the comments table back to normal and optimize it to reclaim space 826 if ( $added_indices ) { 827 drop_index( $wpdb->comments, 'comment_type' ); 828 drop_index( $wpdb->comments, 'comment_karma' ); 829 drop_index( $wpdb->comments, 'comment_agent' ); 830 $wpdb->query( "OPTIMIZE TABLE {$wpdb->comments}" ); 831 } 832 833 // Clean up database and we're out 834 $this->cleanup(); 835 do_action( 'import_done', 'livejournal' ); 836 if ( $imported_comments > 1 ) 837 echo '<p>' . sprintf( __( "Successfully re-threaded %d comments." ), number_format( $imported_comments ) ) . '</p>'; 838 echo '<h3>'; 839 printf( __( 'All done. <a href="%s">Have fun!</a>' ), get_option( 'home' ) ); 840 echo '</h3>'; 1024 841 echo '</div>'; 1025 842 } … … 1035 852 1036 853 return $str; 1037 }1038 1039 // Automatically submit the form with #id to continue the process1040 // Hide any submit buttons to avoid people clicking them1041 // Display a countdown in the element indicated by $msg for "Continuing in x"1042 function auto_ajax( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 5 ) {1043 ?><script type="text/javascript">1044 next_counter = <?php echo $seconds ?>;1045 jQuery(document).ready(function(){1046 ljapi_msg();1047 });1048 1049 function ljapi_msg() {1050 str = '<?php _e( "Continuing in %d" ) ?>';1051 jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) );1052 if ( next_counter <= 0 ) {1053 if ( jQuery( '#<?php echo $id ?>' ).length ) {1054 jQuery( "#<?php echo $id ?> input[type='submit']" ).hide();1055 jQuery.ajaxSetup({'timeout':3600000});1056 str = '<?php _e( "Processing next file." ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />';1057 jQuery( '#<?php echo $msg ?>' ).html( str );1058 jQuery('#ljapi-status').load(ajaxurl, {'action':'lj-importer',1059 'step':jQuery('#step').val(),1060 '_wpnonce':'<?php echo wp_create_nonce( 'lj-api-import' ) ?>',1061 '_wp_http_referer':'<?php echo $_SERVER['REQUEST_URI'] ?>'});1062 return;1063 }1064 }1065 next_counter = next_counter - 1;1066 setTimeout('ljapi_msg()', 1000);1067 }1068 </script><?php1069 854 } 1070 855 … … 1095 880 </script><?php 1096 881 } 1097 1098 // Remove all options used during import process 882 883 // Automatically submit the form with #id to continue the process 884 // Hide any submit buttons to avoid people clicking them 885 // Display a countdown in the element indicated by $msg for "Continuing in x" 886 function auto_ajax( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 5 ) { 887 ?><script type="text/javascript"> 888 next_counter = <?php echo $seconds ?>; 889 jQuery(document).ready(function(){ 890 ljapi_msg(); 891 }); 892 893 function ljapi_msg() { 894 str = '<?php _e( "Continuing in %d" ) ?>'; 895 jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) ); 896 if ( next_counter <= 0 ) { 897 if ( jQuery( '#<?php echo $id ?>' ).length ) { 898 jQuery( "#<?php echo $id ?> input[type='submit']" ).hide(); 899 jQuery.ajaxSetup({'timeout':3600000}); 900 str = '<?php _e( "Processing next batch." ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; 901 jQuery( '#<?php echo $msg ?>' ).html( str ); 902 jQuery('#ljapi-status').load(ajaxurl, {'action':'lj-importer', 903 'step':jQuery('#step').val(), 904 '_wpnonce':'<?php echo wp_create_nonce( 'lj-api-import' ) ?>', 905 '_wp_http_referer':'<?php echo $_SERVER['REQUEST_URI'] ?>'}); 906 return; 907 } 908 } 909 next_counter = next_counter - 1; 910 setTimeout('ljapi_msg()', 1000); 911 } 912 </script><?php 913 } 914 915 // Remove all options used during import process and 916 // set wp_comments entries back to "normal" values 1099 917 function cleanup() { 918 global $wpdb; 919 1100 920 delete_option( 'ljapi_username' ); 1101 921 delete_option( 'ljapi_password' ); … … 1112 932 delete_option( 'ljapi_highest_id' ); 1113 933 delete_option( 'ljapi_highest_comment_id' ); 1114 delete_option( 'ljapi_comment_xml_files' ); 1115 delete_option( 'ljapi_comment_xml_files_count' ); 1116 delete_option( 'ljapi_comment_cache_files' ); 1117 delete_option( 'ljapi_comment_cache_files_count' ); 1118 delete_option( 'ljapi_comment_threaded_files' ); 1119 delete_option( 'ljapi_comment_threaded_files_count' ); 934 delete_option( 'ljapi_comment_batch' ); 1120 935 delete_option( 'ljapi_step' ); 1121 } 1122 1123 // Dump a string to a log file (appends to existing file) 1124 function log( $string, $name ) { 1125 return; // remove this to enable "debugging" output to files in /wp-content/ljimport 1126 $path = wp_upload_dir(); 1127 $path = $path['path']; 1128 if ( get_option( 'uploads_use_yearmonth_folders' ) ) 1129 $path = substr( $path, 0, -8 ); 1130 1131 if ( !is_dir( $path . '/ljimport' ) ) 1132 mkdir( $path . '/ljimport' ); 1133 1134 $fh = @fopen( $path . '/ljimport/' . $name, 'a' ); 1135 if ( $fh ) { 1136 if ( is_array( $string ) || is_object( $string ) ) 1137 fwrite( $fh, var_export( $string, true ) . "\n\n" ); 1138 else 1139 fwrite( $fh, $string . "\n\n" ); 1140 fclose( $fh ); 1141 } 1142 } 1143 1144 function write_file( $data, $name, $id, $mode = 'a' ) { 1145 if ( empty( $this->pointers[$id] ) ) 1146 $this->pointers[$id] = @fopen( $name, $mode ); 1147 if ( $this->pointers[$id] ) 1148 return fwrite( $this->pointers[$id], $data ); 1149 return false; 1150 } 1151 1152 function full_path( $basename ) { 1153 $uploads = wp_upload_dir(); 1154 return $uploads['path'] . '/' . $basename; 1155 } 1156 1157 function close_file_pointers() { 1158 foreach ( $this->pointers as $p ) 1159 @fclose( $p ); 1160 } 1161 936 937 $wpdb->update( $wpdb->comments, 938 array( 'comment_karma' => 0, 'comment_agent' => 'WP LJ Importer', 'comment_type' => '' ), 939 array( 'comment_type' => 'livejournal-done' ) ); 940 $wpdb->update( $wpdb->comments, 941 array( 'comment_karma' => 0, 'comment_agent' => 'WP LJ Importer', 'comment_type' => '' ), 942 array( 'comment_type' => 'livejournal' ) ); 943 } 944 1162 945 function LJ_API_Import() { 1163 946 $this->__construct();
Note: See TracChangeset
for help on using the changeset viewer.