| 69 | | preg_match('|<event>(.*?)</event>|is', $post, $post_content); |
| 70 | | $post_content = str_replace(array ('<![CDATA[', ']]>'), '', trim($post_content[1])); |
| 71 | | $post_content = $this->unhtmlentities($post_content); |
| | 325 | // For some reason, LJ sometimes sends a date as "2004-04-1408:38:00" (no space btwn date/time) |
| | 326 | $post_date = $post['eventtime']; |
| | 327 | if ( 18 == strlen( $post_date ) ) |
| | 328 | $post_date = substr( $post_date, 0, 10 ) . ' ' . substr( $post_date, 10 ); |
| | 329 | |
| | 330 | // Cleaning up and linking the title |
| | 331 | $post_title = trim( $post['subject'] ); |
| | 332 | $post_title = $this->translate_lj_user( $post_title ); // Translate it, but then we'll strip the link |
| | 333 | $post_title = strip_tags( $post_title ); // Can't have tags in the title in WP |
| | 334 | $post_title = $wpdb->escape( $post_title ); |
| | 335 | |
| | 336 | // Clean up content |
| | 337 | $post_content = $post['event']; |
| | 338 | $post_content = preg_replace_callback( '|<(/?[A-Z]+)|', create_function( '$match', 'return "<" . strtolower( $match[1] );' ), $post_content ); |
| | 339 | // XHTMLize some tags |
| | 340 | $post_content = str_replace( '<br>', '<br />', $post_content ); |
| | 341 | $post_content = str_replace( '<hr>', '<hr />', $post_content ); |
| | 342 | // lj-cut ==> <!--more--> |
| | 343 | $post_content = preg_replace( '|<lj-cut text="([^"]*)">|is', '<!--more $1-->', $post_content ); |
| | 344 | $post_content = str_replace( array( '<lj-cut>', '</lj-cut>' ), array( '<!--more-->', '' ), $post_content ); |
| | 345 | $first = strpos( $post_content, '<!--more' ); |
| | 346 | $post_content = substr( $post_content, 0, $first + 1 ) . preg_replace( '|<!--more(.*)?-->|sUi', '', substr( $post_content, $first + 1 ) ); |
| | 347 | // lj-user ==> a href |
| | 348 | $post_content = $this->translate_lj_user( $post_content ); |
| | 349 | $post_content = force_balance_tags( $post_content ); |
| | 350 | $post_content = $wpdb->escape( $post_content ); |
| | 351 | |
| | 352 | // Handle any tags associated with the post |
| | 353 | $tags_input = !empty( $post['props']['taglist'] ) ? $post['props']['taglist'] : ''; |
| | 354 | |
| | 355 | // Check if comments are closed on this post |
| | 356 | $comment_status = !empty( $post['props']['opt_nocomments'] ) ? 'closed' : 'open'; |
| 73 | | // Clean up content |
| 74 | | $post_content = preg_replace_callback('|<(/?[A-Z]+)|', create_function('$match', 'return "<" . strtolower($match[1]);'), $post_content); |
| 75 | | $post_content = str_replace('<br>', '<br />', $post_content); |
| 76 | | $post_content = str_replace('<hr>', '<hr />', $post_content); |
| 77 | | $post_content = $wpdb->escape($post_content); |
| 78 | | |
| 79 | | $post_author = $current_user->ID; |
| 80 | | $post_status = 'publish'; |
| 81 | | |
| 82 | | echo '<li>'; |
| 83 | | if ($post_id = post_exists($post_title, $post_content, $post_date)) { |
| 84 | | printf(__('Post <em>%s</em> already exists.'), stripslashes($post_title)); |
| 85 | | } else { |
| 86 | | printf(__('Importing post <em>%s</em>...'), stripslashes($post_title)); |
| 87 | | $postdata = compact('post_author', 'post_date', 'post_content', 'post_title', 'post_status'); |
| 88 | | $post_id = wp_insert_post($postdata); |
| 89 | | if ( is_wp_error( $post_id ) ) |
| 90 | | return $post_id; |
| 91 | | if (!$post_id) { |
| 92 | | _e("Couldn't get post ID"); |
| 93 | | echo '</li>'; |
| 94 | | break; |
| | 358 | echo '<li>'; |
| | 359 | if ( $post_id = post_exists( $post_title, $post_content, $post_date ) ) { |
| | 360 | printf( __( 'Post <strong>%s</strong> already exists.' ), stripslashes( $post_title ) ); |
| | 361 | } else { |
| | 362 | printf( __( 'Importing post <strong>%s</strong>...' ), stripslashes( $post_title ) ); |
| | 363 | $postdata = compact( 'post_author', 'post_date', 'post_content', 'post_title', 'post_status', 'post_password', 'tags_input', 'comment_status' ); |
| | 364 | $post_id = wp_insert_post( $postdata ); |
| | 365 | if ( is_wp_error( $post_id ) ) |
| | 366 | return $post_id; |
| | 367 | if ( !$post_id ) { |
| | 368 | _e( "Couldn't get post ID" ); |
| | 369 | echo '</li>'; |
| | 370 | break; |
| | 371 | } |
| | 372 | $postdata['post_ID'] = $post_id; |
| | 373 | $postdata['lj_itemid'] = $post['itemid']; |
| | 374 | $this->log( $postdata, 'ljimport-post-' . $post_id . '.txt' ); |
| | 375 | |
| | 376 | // Handle all the metadata for this post |
| | 377 | $this->insert_postmeta( $post_id, $post ); |
| | 378 | } |
| | 379 | echo '</li>'; |
| | 380 | } |
| | 381 | |
| | 382 | // Convert lj-user tags to links to that user |
| | 383 | function translate_lj_user( $str ) { |
| | 384 | return preg_replace( '|<lj\s+user\s*=\s*["\']([\w-]+)["\']>|', '<a href="http://$1.livejournal.com/" class="lj-user">$1</a>', $str ); |
| | 385 | } |
| | 386 | |
| | 387 | function insert_postmeta( $post_id, $post ) { |
| | 388 | // Need the original LJ id for comments |
| | 389 | add_post_meta( $post_id, 'lj_itemid', $post['itemid'] ); |
| | 390 | |
| | 391 | // And save the permalink on LJ in case we want to link back or something |
| | 392 | add_post_meta( $post_id, 'lj_permalink', $post['url'] ); |
| | 393 | |
| | 394 | // Supports the following "props" from LJ, saved as lj_<prop_name> in wp_postmeta |
| | 395 | // Adult Content - adult_content |
| | 396 | // Location - current_coords + current_location |
| | 397 | // Mood - current_mood (translated from current_moodid) |
| | 398 | // Music - current_music |
| | 399 | // Userpic - picture_keyword |
| | 400 | foreach ( array( 'adult_content', 'current_coords', 'current_location', 'current_moodid', 'current_music', 'picture_keyword' ) as $prop ) { |
| | 401 | if ( !empty( $post['props'][$prop] ) ) { |
| | 402 | if ( 'current_moodid' == $prop ) { |
| | 403 | $prop = 'current_mood'; |
| | 404 | $val = $this->moods[ $post['props']['current_moodid'] ]; |
| | 405 | } else { |
| | 406 | $val = $post['props'][$prop]; |
| 109 | | // Clean up content |
| 110 | | $comment_content = preg_replace_callback('|<(/?[A-Z]+)|', create_function('$match', 'return "<" . strtolower($match[1]);'), $comment_content); |
| 111 | | $comment_content = str_replace('<br>', '<br />', $comment_content); |
| 112 | | $comment_content = str_replace('<hr>', '<hr />', $comment_content); |
| 113 | | $comment_content = $wpdb->escape($comment_content); |
| | 450 | // Parse out the list of user mappings, and add it to the known list |
| | 451 | preg_match_all( '|<usermap id=\'(\d+)\' user=\'([^\']+)\' />|', $results, $matches ); |
| | 452 | foreach ( $matches[1] as $count => $userid ) |
| | 453 | $this->usermap[$userid] = $matches[2][$count]; // need this in memory for translating ids => names |
| | 454 | |
| | 455 | update_option( 'ljapi_usermap', $this->usermap ); |
| | 456 | update_option( 'ljapi_maxid', $maxid ); |
| | 457 | update_option( 'ljapi_highest_id', $highest_id ); |
| | 458 | } |
| | 459 | // endwhile - should have seen all comment meta at this point |
| | 460 | |
| | 461 | |
| | 462 | // Download Comment XML |
| | 463 | |
| | 464 | // Load previous state (if any) |
| | 465 | $highest_id = (int) get_option( 'ljapi_highest_comment_id' ); |
| | 466 | $comment_xml_files = get_option( 'ljapi_comment_xml_files' ); |
| | 467 | if ( !is_array( $comment_xml_files ) ) { |
| | 468 | update_option( 'ljapi_comment_xml_files', array() ); |
| | 469 | $comment_xml_files = array(); |
| | 470 | } |
| | 471 | |
| | 472 | echo '<ol>'; |
| | 473 | |
| | 474 | // And now request the actual comments, and keep going until we have them all |
| | 475 | while ( $maxid > $highest_id ) { |
| | 476 | // Get a batch of comments, using the highest_id we've already got as a starting point |
| | 477 | if ( !$this->snoop->fetch( $this->comments_url . '?get=comment_body&startid=' . ( $highest_id + 1 ) ) ) |
| | 478 | return new WP_Error( 'Snoopy', __( 'Failed to retrieve comment bodies from LiveJournal. Please try again soon.' ) ); |
| | 479 | |
| | 480 | // Get the highest post ID in this batch (required for loop control) |
| | 481 | $results = $this->snoop->results; |
| | 482 | preg_match_all( '|<comment id=\'(\d+)\'|i', $results, $comments ); |
| | 483 | for ( $r = 0; $r < count( $comments[1] ); $r++ ) { |
| | 484 | if ( $comments[1][$r] > $highest_id ) |
| | 485 | $highest_id = $comments[1][$r]; |
| | 486 | } |
| | 487 | |
| | 488 | // $this->snoop-results is where the actual response is stored |
| | 489 | $this->log( $this->snoop->results, 'ljimport-comment-bodies-' . $highest_id . '.txt' ); |
| | 490 | |
| | 491 | // Store in uploads dir. Can't use *.xml because it's not allowed |
| | 492 | $results = wp_upload_bits( 'raw-comments-' . $highest_id . '.txt', null, $results ); |
| | 493 | if ( !empty( $results['error'] ) ) |
| | 494 | return new WP_Error( 'xml', $results['error'] ); |
| | 495 | $comment_xml_files[] = $results['file']; |
| | 496 | |
| | 497 | echo '<li>' . sprintf( __( 'Downloaded <strong>%s</strong>' ), basename( $results['file'] ) ) . '</li>'; |
| | 498 | ob_flush(); flush(); |
| | 499 | |
| | 500 | $comment_xml_files = array_unique( $comment_xml_files ); |
| | 501 | update_option( 'ljapi_comment_xml_files', $comment_xml_files ); |
| | 502 | update_option( 'ljapi_comment_xml_files_count', count( $comment_xml_files ) ); |
| | 503 | } |
| | 504 | // endwhile - all comments downloaded and ready for bulk processing |
| | 505 | |
| | 506 | echo '</ol>'; |
| | 507 | |
| | 508 | return true; |
| | 509 | } |
| | 510 | |
| | 511 | function parse_comment_xml( $xml_file ) { |
| | 512 | if ( !is_file( $xml_file ) || !is_readable( $xml_file ) ) |
| | 513 | return new WP_Error( 'file', sprintf( __( 'Could not access comment XML file: %s'), $filename ) ); |
| | 514 | |
| | 515 | // Get content from file |
| | 516 | $xml = @file_get_contents( $xml_file ); |
| 115 | | preg_match('|<eventtime>(.*?)</eventtime>|is', $comment, $comment_date); |
| 116 | | $comment_date = trim($comment_date[1]); |
| 117 | | $comment_date = date('Y-m-d H:i:s', strtotime($comment_date)); |
| | 518 | $cache_files = get_option( 'ljapi_comment_cache_files' ); |
| | 519 | if ( !is_array( $cache_files ) ) |
| | 520 | $cache_files = array(); |
| | 521 | |
| | 522 | // Parse XML into comments |
| | 523 | preg_match_all( '|<comment id.*</comment>|iUs', $xml, $matches ); |
| | 524 | unset( $xml ); |
| | 525 | for ( $c = 0; $c < count( $matches[0] ); $c++ ) { |
| | 526 | $comment = $matches[0][$c]; |
| | 527 | |
| | 528 | // Filter out any captured, deleted comments (nothing useful to import) |
| | 529 | $comment = preg_replace( '|<comment id=\'\d+\' jitemid=\'\d+\' posterid=\'\d+\' state=\'D\'[^/]*/>|is', '', $comment ); |
| | 530 | |
| | 531 | // Parse this comment into an array |
| | 532 | $comment = $this->parse_comment( $comment ); |
| | 533 | if ( empty( $comment['comment_post_ID'] ) ) |
| | 534 | continue; |
| | 535 | |
| | 536 | // Add this comment to the appropriate cache file |
| | 537 | $filename = $this->full_path( 'ljimport-comments-' . $comment['comment_post_ID'] . '.php' ); |
| | 538 | if ( $this->write_file( '<?php $comments[] = ' . var_export( $comment, true ) . '; ?>' . "\n", |
| | 539 | $filename, |
| | 540 | $comment['comment_post_ID'], |
| | 541 | 'a' ) ) |
| | 542 | { |
| | 543 | // Keep track of files used |
| | 544 | $cache_files[] = $filename; |
| | 545 | } |
| | 546 | } |
| | 547 | |
| | 548 | // Update list of files in the DB |
| | 549 | sort( $cache_files ); |
| | 550 | $cache_files = array_unique( $cache_files ); |
| | 551 | update_option( 'ljapi_comment_cache_files', $cache_files ); |
| | 552 | update_option( 'ljapi_comment_cache_files_count', count( $cache_files ) ); |
| | 553 | $this->close_file_pointers(); |
| | 554 | |
| | 555 | // Don't need this XML file anymore |
| | 556 | unlink( $xml_file ); |
| | 557 | |
| | 558 | return true; |
| | 559 | } |
| | 560 | |
| | 561 | function parse_comment( $comment ) { |
| | 562 | global $wpdb; |
| | 563 | |
| | 564 | // Get the top-level attributes |
| | 565 | preg_match( '|<comment([^>]+)>|i', $comment, $attribs ); |
| | 566 | preg_match( '| id=\'(\d+)\'|i', $attribs[1], $matches ); |
| | 567 | $lj_comment_ID = $matches[1]; |
| | 568 | preg_match( '| jitemid=\'(\d+)\'|i', $attribs[1], $matches ); |
| | 569 | $lj_comment_post_ID = $matches[1]; |
| | 570 | preg_match( '| posterid=\'(\d+)\'|i', $attribs[1], $matches ); |
| | 571 | $comment_author_ID = $matches[1]; |
| | 572 | preg_match( '| parentid=\'(\d+)\'|i', $attribs[1], $matches ); |
| | 573 | $lj_comment_parent = $matches[1]; |
| | 574 | preg_match( '| state=\'([SDFA])\'|i', $attribs[1], $matches ); |
| | 575 | $lj_comment_state = !empty( $matches[1] ) ? $matches[1] : 'A'; |
| | 576 | |
| | 577 | // Clean up "subject" - this will become the first line of the comment in WP |
| | 578 | preg_match( '|<subject>(.*)</subject>|is', $comment, $matches ); |
| | 579 | $comment_subject = $wpdb->escape( trim( $matches[1] ) ); |
| | 580 | if ( 'Re:' == $comment_subject ) |
| | 581 | $comment_subject = ''; |
| | 582 | |
| | 583 | // Get the body and HTMLize it |
| | 584 | preg_match( '|<body>(.*)</body>|is', $comment, $matches ); |
| | 585 | $comment_content = !empty( $comment_subject ) ? $comment_subject . "\n\n" . $matches[1] : $matches[1]; |
| | 586 | $comment_content = $this->unhtmlentities( $comment_content ); |
| | 587 | $comment_content = wpautop( $comment_content ); |
| | 588 | $comment_content = str_replace( '<br>', '<br />', $comment_content ); |
| | 589 | $comment_content = str_replace( '<hr>', '<hr />', $comment_content ); |
| | 590 | $comment_content = preg_replace_callback( '|<(/?[A-Z]+)|', create_function( '$match', 'return "<" . strtolower( $match[1] );' ), $comment_content ); |
| | 591 | $comment_content = $wpdb->escape( trim( $comment_content ) ); |
| | 592 | |
| | 593 | // Get and convert the date |
| | 594 | preg_match( '|<date>(.*)</date>|i', $comment, $matches ); |
| | 595 | $comment_date = trim( str_replace( array( 'T', 'Z' ), ' ', $matches[1] ) ); |
| | 596 | |
| | 597 | // Grab IP if available |
| | 598 | preg_match( '|<property name=\'poster_ip\'>(.*)</property>|i', $comment, $matches ); |
| | 599 | $comment_author_IP = $matches[1]; |
| | 600 | |
| | 601 | // Try to get something useful for the comment author, especially if it was "my" comment |
| | 602 | $author = ( substr( $this->usermap[$comment_author_ID], 0, 4 ) == 'ext_' || empty( $comment_author_ID ) ) ? __( 'Anonymous' ) : $this->usermap[$comment_author_ID]; |
| | 603 | if ( get_option( 'ljapi_username' ) == $author ) { |
| | 604 | $user = wp_get_current_user(); |
| | 605 | $user_id = $user->ID; |
| | 606 | $author = $user->display_name; |
| | 607 | $url = trailingslashit( get_option( 'home' ) ); |
| | 608 | } else { |
| | 609 | $user_id = 0; |
| | 610 | $url = ( __( 'Anonymous' ) == $author ) ? '' : 'http://' . $author . '.livejournal.com/'; |
| | 611 | } |
| | 612 | |
| | 613 | // Send back the array of details |
| | 614 | return array( 'lj_comment_ID' => $lj_comment_ID, |
| | 615 | 'lj_comment_post_ID' => $lj_comment_post_ID, |
| | 616 | 'lj_comment_parent' => ( !empty( $lj_comment_parent ) ? $lj_comment_parent : 0 ), |
| | 617 | 'lj_comment_state' => $lj_comment_state, |
| | 618 | 'comment_post_ID' => $this->get_wp_post_ID( $lj_comment_post_ID ), |
| | 619 | 'comment_author' => $author, |
| | 620 | 'comment_author_url' => $url, |
| | 621 | 'comment_content' => $comment_content, |
| | 622 | 'comment_date' => $comment_date, |
| | 623 | 'comment_author_IP' => ( !empty( $comment_author_IP ) ? $comment_author_IP : '' ), |
| | 624 | 'comment_approved' => ( in_array( $lj_comment_state, array( 'A', 'F' ) ) ? 1 : 0 ), |
| | 625 | 'comment_agent' => 'WP LJ Importer', |
| | 626 | 'user_id' => $user_id |
| | 627 | ); |
| | 628 | } |
| | 629 | |
| | 630 | |
| | 631 | // Gets the post_ID that a LJ post has been saved as within WP |
| | 632 | function get_wp_post_ID( $post ) { |
| | 633 | global $wpdb; |
| | 634 | if ( empty( $this->postmap[$post] ) ) |
| | 635 | $this->postmap[$post] = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'lj_itemid' AND meta_value = %d", $post ) ); |
| | 636 | return $this->postmap[$post]; |
| | 637 | } |
| | 638 | |
| | 639 | // Re-build the threading within a single cache file |
| | 640 | function thread_comments( $filename ) { |
| | 641 | if ( !is_file( $filename ) || !is_readable( $filename ) ) |
| | 642 | return new WP_Error( 'File', __( sprintf( 'Cannot access file %s', $filename ) ) ); |
| | 643 | |
| | 644 | $comments = array(); |
| | 645 | @include( $filename ); |
| | 646 | $this->comments = $comments; |
| | 647 | unset( $comments ); |
| | 648 | if ( !is_array( $this->comments ) ) |
| | 649 | $this->comments = array(); |
| | 650 | |
| | 651 | $count = count( $this->comments ); |
| | 652 | for ( $c = 0; $c < $count; $c++ ) { |
| | 653 | // Skip anything that's not "top-level" for now |
| | 654 | if ( 0 != $this->comments[$c]['lj_comment_parent'] ) |
| | 655 | continue; |
| | 656 | $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] ); |
| | 657 | } |
| | 658 | |
| | 659 | // Remove anything that's not supposed to be at top level |
| | 660 | $top_comments = array(); |
| | 661 | for ( $c = 0; $c < $count; $c++ ) { |
| | 662 | if ( 0 == $this->comments[$c]['lj_comment_parent'] ) { |
| | 663 | $top_comments[] = $this->comments[$c]; |
| | 664 | } |
| | 665 | } |
| | 666 | |
| | 667 | // Write back to file |
| | 668 | @unlink( $filename ); |
| | 669 | $this->write_file( '<?php $comments = ' . var_export( $top_comments, true ) . '; ?>', $filename, $count, 'w' ); |
| | 670 | unset( $top_comments ); |
| | 671 | $this->close_file_pointers(); |
| | 672 | |
| | 673 | // Reference this file as being threaded |
| | 674 | $files = get_option( 'ljapi_comment_threaded_files' ); |
| | 675 | $files[] = $filename; |
| | 676 | array_unique( $files ); |
| | 677 | update_option( 'ljapi_comment_threaded_files', $files ); |
| | 678 | update_option( 'ljapi_comment_threaded_files_count', count( $files ) ); |
| | 679 | |
| | 680 | return true; |
| | 681 | } |
| | 682 | |
| | 683 | function get_child_comments( $id ) { |
| | 684 | $children = array(); |
| | 685 | $count = count( $this->comments ); |
| | 686 | for ( $c = 0; $c < $count; $c++ ) { |
| | 687 | // This comment is a child of the $id |
| | 688 | if ( $id == $this->comments[$c]['lj_comment_parent'] ) { |
| | 689 | $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] ); |
| | 690 | $children[] = $this->comments[$c]; |
| | 691 | } |
| | 692 | } |
| | 693 | return $children; |
| | 694 | } |
| | 695 | |
| | 696 | // Inserts the contents of each cache file (should be threaded already) |
| | 697 | function insert_comments( $filename ) { |
| | 698 | echo '<ol>'; |
| 186 | | function LJ_Import() { |
| 187 | | // Nothing. |
| | 812 | // Check form inputs and start importing posts |
| | 813 | function step1() { |
| | 814 | // Get details from form or from DB |
| | 815 | if ( !empty( $_POST['lj_username'] ) && !empty( $_POST['lj_password'] ) ) { |
| | 816 | // Store details for later |
| | 817 | $this->username = $_POST['lj_username']; |
| | 818 | $this->password = $_POST['lj_password']; |
| | 819 | update_option( 'ljapi_username', $this->username ); |
| | 820 | update_option( 'ljapi_password', $this->password ); |
| | 821 | } else { |
| | 822 | $this->username = get_option( 'ljapi_username' ); |
| | 823 | $this->password = get_option( 'ljapi_password' ); |
| | 824 | } |
| | 825 | |
| | 826 | // This is the password to set on protected posts |
| | 827 | if ( !empty( $_POST['protected_password'] ) ) { |
| | 828 | $this->protected_password = $_POST['protected_password']; |
| | 829 | update_option( 'ljapi_protected_password', $this->protected_password ); |
| | 830 | } else { |
| | 831 | $this->protected_password = get_option( 'ljapi_protected_password' ); |
| | 832 | } |
| | 833 | |
| | 834 | // Login to confirm the details are correct |
| | 835 | if ( empty( $this->username ) || empty( $this->password ) ) { |
| | 836 | ?> |
| | 837 | <p><?php _e( 'Please enter your LiveJournal username <em>and</em> password so we can download your posts and comments.' ) ?></p> |
| | 838 | <p><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( str_replace( '&step=1', '', $_SERVER['REQUEST_URI'] ) ) ?>"><?php _e( 'Start again' ) ?></a></p> |
| | 839 | <?php |
| | 840 | return; |
| | 841 | } |
| | 842 | $login = $this->lj_ixr( 'login' ); |
| | 843 | if ( is_wp_error( $login ) ) { |
| | 844 | if ( 100 == $this->ixr->getErrorCode() || 101 == $this->ixr->getErrorCode() ) { |
| | 845 | ?> |
| | 846 | <p><?php _e( 'Logging in to LiveJournal failed. Check your username and password and try again.' ) ?></p> |
| | 847 | <p><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( str_replace( '&step=1', '', $_SERVER['REQUEST_URI'] ) ) ?>"><?php _e( 'Start again' ) ?></a></p> |
| | 848 | <?php |
| | 849 | return; |
| | 850 | } else { |
| | 851 | return $login; |
| | 852 | } |
| | 853 | } |
| | 854 | |
| | 855 | // Set up some options to avoid them autoloading (these ones get big) |
| | 856 | add_option( 'ljapi_sync_item_times', '', '', 'no' ); |
| | 857 | add_option( 'ljapi_usermap', '', '', 'no' ); |
| | 858 | add_option( 'ljapi_comment_xml_files', '', '', 'no' ); |
| | 859 | add_option( 'ljapi_comment_cache_files', '', '', 'no' ); |
| | 860 | add_option( 'ljapi_comment_threaded_files', '', '', 'no' ); |
| | 861 | |
| | 862 | echo '<h3>' . __( 'Importing Posts' ) . '</h3>'; |
| | 863 | echo '<p>' . __( "We're downloading and importing all your LiveJournal posts..." ) . '</p>'; |
| | 864 | ob_flush(); flush(); |
| | 865 | |
| | 866 | // Now do the grunt work |
| | 867 | set_time_limit( 0 ); |
| | 868 | $result = $this->import_posts(); |
| | 869 | if ( is_wp_error( $result ) ) { |
| | 870 | if ( 406 == $this->ixr->getErrorCode() ) { |
| | 871 | ?> |
| | 872 | <p><strong><?php _e( 'Uh oh – LiveJournal has disconnected us because we made too many requests to their servers too quickly.' ) ?></strong></p> |
| | 873 | <p><strong><?php _e( "We've saved where you were up to though, so if you come back to this importer in about 30 minutes, you should be able to continue from where you were." ) ?></strong></p> |
| | 874 | <?php |
| | 875 | return; |
| | 876 | } else { |
| | 877 | return $result; |
| | 878 | } |
| | 879 | } |
| | 880 | |
| | 881 | echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to process & import your comments." ) . '</p>'; |
| | 882 | echo $this->next_step( 2, __( 'Download my comments »' ) ); |
| | 883 | $this->auto_submit(); |
| | 885 | |
| | 886 | // Download comments to local XML |
| | 887 | function step2() { |
| | 888 | set_time_limit( 0 ); |
| | 889 | update_option( 'ljapi_step', 2 ); |
| | 890 | $this->username = get_option( 'ljapi_username' ); |
| | 891 | $this->password = get_option( 'ljapi_password' ); |
| | 892 | |
| | 893 | echo '<h3>' . __( 'Downloading Comments' ) . '</h3>'; |
| | 894 | echo '<p>' . __( 'Now we will download your comments so we can process and import them...' ) . '</p>'; |
| | 895 | ob_flush(); flush(); |
| | 896 | |
| | 897 | $result = $this->download_comments(); |
| | 898 | if ( is_wp_error( $result ) ) |
| | 899 | return $result; |
| | 900 | |
| | 901 | echo '<p>' . __( 'Your comments have all been downloaded to this server now, so we can process them and get them ready for importing.' ) . '</p>'; |
| | 902 | echo $this->next_step( 3, __( 'Process my comment files »' ) ); |
| | 903 | $this->auto_submit(); |
| | 904 | } |
| | 905 | |
| | 906 | // Parse XML into comment cache files |
| | 907 | function step3() { |
| | 908 | |
| | 909 | set_time_limit( 0 ); |
| | 910 | update_option( 'ljapi_step', 3 ); |
| | 911 | |
| | 912 | $this->usermap = get_option( 'ljapi_usermap' ); |
| | 913 | |
| | 914 | echo '<div id="ljapi-status">'; |
| | 915 | echo '<h3>' . __( 'Parsing Comments' ) . '</h3>'; |
| | 916 | echo '<p>' . __( 'Time to clean up your comments and get them into a format WordPress understands...' ) . '</p>'; |
| | 917 | ob_flush(); flush(); |
| | 918 | |
| | 919 | $files = get_option( 'ljapi_comment_xml_files' ); |
| | 920 | if ( count( $files ) ) { |
| | 921 | $file = array_pop( $files ); |
| | 922 | |
| | 923 | $result = $this->parse_comment_xml( $file ); |
| | 924 | if ( is_wp_error( $result ) ) |
| | 925 | return $result; |
| | 926 | |
| | 927 | update_option( 'ljapi_comment_xml_files', $files ); |
| | 928 | } |
| | 929 | |
| | 930 | if ( count( $files ) ) { |
| | 931 | ?> |
| | 932 | <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> |
| | 933 | <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> |
| | 934 | <?php wp_nonce_field( 'lj-api-import' ) ?> |
| | 935 | <input type="hidden" name="step" id="step" value="3" /> |
| | 936 | <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Process the next comment file »' ) ) ?>" /> <span id="auto-message"></span></p> |
| | 937 | </form> |
| | 938 | <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> |
| | 939 | <?php |
| | 940 | } else { |
| | 941 | echo '<p>' . __( 'Yay, we finished processing all of your comment files! Now we need to re-build your conversation threads.' ) . '</p>'; |
| | 942 | echo $this->next_step( 4, __( 'Thread my comments »' ) ); |
| | 943 | $this->auto_submit(); |
| | 944 | } |
| | 945 | echo '</div>'; |
| | 946 | } |
| | 947 | |
| | 948 | // Thread comments within their cache files |
| | 949 | function step4() { |
| | 950 | set_time_limit( 0 ); |
| | 951 | update_option( 'ljapi_step', 4 ); |
| | 952 | |
| | 953 | echo '<div id="ljapi-status">'; |
| | 954 | echo '<h3>' . __( 'Threading Comments' ) . '</h3>'; |
| | 955 | echo '<p>' . __( 'Re-building your conversation threads ready for import...' ) . '</p>'; |
| | 956 | ob_flush(); flush(); |
| | 957 | |
| | 958 | $files = get_option( 'ljapi_comment_cache_files' ); |
| | 959 | if ( count( $files ) ) { |
| | 960 | $file = array_pop( $files ); |
| | 961 | |
| | 962 | $result = $this->thread_comments( $file ); |
| | 963 | if ( is_wp_error( $result ) ) |
| | 964 | return $result; |
| | 965 | |
| | 966 | update_option( 'ljapi_comment_cache_files', $files ); |
| | 967 | } |
| | 968 | |
| | 969 | if ( count( $files ) ) { |
| | 970 | ?> |
| | 971 | <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> |
| | 972 | <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> |
| | 973 | <?php wp_nonce_field( 'lj-api-import' ) ?> |
| | 974 | <input type="hidden" name="step" id="step" value="4" /> |
| | 975 | <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Thread the next cache file »' ) ) ?>" /> <span id="auto-message"></span></p> |
| | 976 | </form> |
| | 977 | <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> |
| | 978 | <?php |
| | 979 | } else { |
| | 980 | echo '<p>' . __( "Alrighty, your comments are all threaded. There's just one last step -- time to actually import them all now!" ) . '</p>'; |
| | 981 | 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>'; |
| | 982 | echo $this->next_step( 5, __( 'Import my threaded comments into WordPress »' ) ); |
| | 983 | $this->auto_submit(); |
| | 984 | } |
| | 985 | echo '</div>'; |
| | 986 | } |
| | 987 | |
| | 988 | // Import comments from cache files into WP |
| | 989 | function step5() { |
| | 990 | set_time_limit( 0 ); |
| | 991 | update_option( 'ljapi_step', 5 ); |
| | 992 | |
| | 993 | |
| | 994 | echo '<div id="ljapi-status">'; |
| | 995 | echo '<h3>' . __( 'Importing Comments' ) . '</h3>'; |
| | 996 | echo '<p>' . __( 'This is the big one -- we are now inserting your comment threads into WordPress...' ) . '</p>'; |
| | 997 | |
| | 998 | $files = get_option( 'ljapi_comment_threaded_files' ); |
| | 999 | 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>'; |
| | 1000 | ob_flush(); flush(); |
| | 1001 | |
| | 1002 | if ( count( $files ) ) { |
| | 1003 | $file = array_pop( $files ); |
| | 1004 | |
| | 1005 | $result = $this->insert_comments( $file ); |
| | 1006 | if ( is_wp_error( $result ) ) |
| | 1007 | return $result; |
| | 1008 | |
| | 1009 | update_option( 'ljapi_comment_threaded_files', $files ); |
| | 1010 | } |
| | 1011 | |
| | 1012 | if ( count( $files ) ) { |
| | 1013 | ?> |
| | 1014 | <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> |
| | 1015 | <?php wp_nonce_field( 'lj-api-import' ) ?> |
| | 1016 | <input type="hidden" name="step" id="step" value="5" /> |
| | 1017 | <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Import the next cache file »' ) ) ?>" /> <span id="auto-message"></span></p> |
| | 1018 | </form> |
| | 1019 | <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> |
| | 1020 | <?php |
| | 1021 | } else { |
| | 1022 | // Clean up database and we're out |
| | 1023 | $this->cleanup(); |
| | 1024 | do_action( 'import_done', 'livejournal' ); |
| | 1025 | echo '<h3>'; |
| | 1026 | printf( __( 'All done. <a href="%s">Have fun!</a>' ), get_option( 'home' ) ); |
| | 1027 | echo '</h3>'; |
| | 1028 | } |
| | 1029 | echo '</div>'; |
| | 1030 | } |
| | 1031 | |
| | 1032 | // Returns the HTML for a link to the next page |
| | 1033 | function next_step( $next_step, $label, $id = 'ljapi-next-form' ) { |
| | 1034 | $str = '<form action="admin.php?import=livejournal" method="post" id="' . $id . '">'; |
| | 1035 | $str .= wp_nonce_field( 'lj-api-import', '_wpnonce', true, false ); |
| | 1036 | $str .= wp_referer_field( false ); |
| | 1037 | $str .= '<input type="hidden" name="step" id="step" value="' . $next_step . '" />'; |
| | 1038 | $str .= '<p><input type="submit" class="button-primary" value="' . attribute_escape( $label ) . '" /> <span id="auto-message"></span></p>'; |
| | 1039 | $str .= '</form>'; |
| | 1040 | |
| | 1041 | return $str; |
| | 1042 | } |
| | 1043 | |
| | 1044 | // Automatically submit the form with #id to continue the process |
| | 1045 | // Hide any submit buttons to avoid people clicking them |
| | 1046 | // Display a countdown in the element indicated by $msg for "Continuing in x" |
| | 1047 | function auto_ajax( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 5 ) { |
| | 1048 | ?><script type="text/javascript"> |
| | 1049 | next_counter = <?php echo $seconds ?>; |
| | 1050 | jQuery(document).ready(function(){ |
| | 1051 | ljapi_msg(); |
| | 1052 | }); |
| | 1053 | |
| | 1054 | function ljapi_msg() { |
| | 1055 | str = '<?php _e( "Continuing in %d" ) ?>'; |
| | 1056 | jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) ); |
| | 1057 | if ( next_counter <= 0 ) { |
| | 1058 | if ( jQuery( '#<?php echo $id ?>' ).length ) { |
| | 1059 | jQuery( "#<?php echo $id ?> input[type='submit']" ).hide(); |
| | 1060 | jQuery.ajaxSetup({'timeout':3600000}); |
| | 1061 | str = '<?php _e( "Processing next file." ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; |
| | 1062 | jQuery( '#<?php echo $msg ?>' ).html( str ); |
| | 1063 | jQuery('#ljapi-status').load(ajaxurl, {'action':'lj-importer', |
| | 1064 | 'step':jQuery('#step').val(), |
| | 1065 | '_wpnonce':'<?php echo wp_create_nonce( 'lj-api-import' ) ?>', |
| | 1066 | '_wp_http_referer':'<?php echo $_SERVER['REQUEST_URI'] ?>'}); |
| | 1067 | return; |
| | 1068 | } |
| | 1069 | } |
| | 1070 | next_counter = next_counter - 1; |
| | 1071 | setTimeout('ljapi_msg()', 1000); |
| | 1072 | } |
| | 1073 | </script><?php |
| | 1074 | } |
| | 1075 | |
| | 1076 | // Automatically submit the specified form after $seconds |
| | 1077 | // Include a friendly countdown in the element with id=$msg |
| | 1078 | function auto_submit( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 10 ) { |
| | 1079 | ?><script type="text/javascript"> |
| | 1080 | next_counter = <?php echo $seconds ?>; |
| | 1081 | jQuery(document).ready(function(){ |
| | 1082 | ljapi_msg(); |
| | 1083 | }); |
| | 1084 | |
| | 1085 | function ljapi_msg() { |
| | 1086 | str = '<?php _e( "Continuing in %d" ) ?>'; |
| | 1087 | jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) ); |
| | 1088 | if ( next_counter <= 0 ) { |
| | 1089 | if ( jQuery( '#<?php echo $id ?>' ).length ) { |
| | 1090 | jQuery( "#<?php echo $id ?> input[type='submit']" ).hide(); |
| | 1091 | str = '<?php _e( "Continuing" ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; |
| | 1092 | jQuery( '#<?php echo $msg ?>' ).html( str ); |
| | 1093 | jQuery( '#<?php echo $id ?>' ).submit(); |
| | 1094 | return; |
| | 1095 | } |
| | 1096 | } |
| | 1097 | next_counter = next_counter - 1; |
| | 1098 | setTimeout('ljapi_msg()', 1000); |
| | 1099 | } |
| | 1100 | </script><?php |
| | 1101 | } |
| | 1102 | |
| | 1103 | // Remove all options used during import process |
| | 1104 | function cleanup() { |
| | 1105 | delete_option( 'ljapi_username' ); |
| | 1106 | delete_option( 'ljapi_password' ); |
| | 1107 | delete_option( 'ljapi_protected_password' ); |
| | 1108 | delete_option( 'ljapi_total' ); |
| | 1109 | delete_option( 'ljapi_count' ); |
| | 1110 | delete_option( 'ljapi_lastsync' ); |
| | 1111 | delete_option( 'ljapi_last_sync_count' ); |
| | 1112 | delete_option( 'ljapi_sync_item_times' ); |
| | 1113 | delete_option( 'ljapi_lastsync_posts' ); |
| | 1114 | delete_option( 'ljapi_imported_count' ); |
| | 1115 | delete_option( 'ljapi_maxid' ); |
| | 1116 | delete_option( 'ljapi_usermap' ); |
| | 1117 | delete_option( 'ljapi_highest_id' ); |
| | 1118 | delete_option( 'ljapi_highest_comment_id' ); |
| | 1119 | delete_option( 'ljapi_comment_xml_files' ); |
| | 1120 | delete_option( 'ljapi_comment_xml_files_count' ); |
| | 1121 | delete_option( 'ljapi_comment_cache_files' ); |
| | 1122 | delete_option( 'ljapi_comment_cache_files_count' ); |
| | 1123 | delete_option( 'ljapi_comment_threaded_files' ); |
| | 1124 | delete_option( 'ljapi_comment_threaded_files_count' ); |
| | 1125 | delete_option( 'ljapi_step' ); |
| | 1126 | } |
| | 1127 | |
| | 1128 | // Dump a string to a log file (appends to existing file) |
| | 1129 | function log( $string, $name ) { |
| | 1130 | return; // remove this to enable "debugging" output to files in /wp-content/ljimport |
| | 1131 | $path = wp_upload_dir(); |
| | 1132 | $path = $path['path']; |
| | 1133 | if ( get_option( 'uploads_use_yearmonth_folders' ) ) |
| | 1134 | $path = substr( $path, 0, -8 ); |
| | 1135 | |
| | 1136 | if ( !is_dir( $path . '/ljimport' ) ) |
| | 1137 | mkdir( $path . '/ljimport' ); |
| | 1138 | |
| | 1139 | $fh = @fopen( $path . '/ljimport/' . $name, 'a' ); |
| | 1140 | if ( $fh ) { |
| | 1141 | if ( is_array( $string ) || is_object( $string ) ) |
| | 1142 | fwrite( $fh, var_export( $string, true ) . "\n\n" ); |
| | 1143 | else |
| | 1144 | fwrite( $fh, $string . "\n\n" ); |
| | 1145 | fclose( $fh ); |
| | 1146 | } |
| | 1147 | } |
| | 1148 | |
| | 1149 | function write_file( $data, $name, $id, $mode = 'a' ) { |
| | 1150 | if ( empty( $this->pointers[$id] ) ) |
| | 1151 | $this->pointers[$id] = @fopen( $name, $mode ); |
| | 1152 | if ( $this->pointers[$id] ) |
| | 1153 | return fwrite( $this->pointers[$id], $data ); |
| | 1154 | return false; |
| | 1155 | } |
| | 1156 | |
| | 1157 | function full_path( $basename ) { |
| | 1158 | $uploads = wp_upload_dir(); |
| | 1159 | return $uploads['path'] . '/' . $basename; |
| | 1160 | } |
| | 1161 | |
| | 1162 | function close_file_pointers() { |
| | 1163 | foreach ( $this->pointers as $p ) |
| | 1164 | @fclose( $p ); |
| | 1165 | } |
| | 1166 | |
| | 1167 | function LJ_API_Import() { |
| | 1168 | $this->__construct(); |
| | 1169 | } |
| | 1170 | |
| | 1171 | function __construct() { |
| | 1172 | // Nothing |
| | 1173 | } |