WordPress.org

Make WordPress Core

Ticket #8999: db-based-lj-importer.diff

File db-based-lj-importer.diff, 39.4 KB (added by beaulebens, 7 years ago)

DB-based version, with some optimizations from azaozz.

  • livejournal.php

     
    11<?php 
     2 
    23/** 
    34 * LiveJournal API Importer 
    45 * 
     
    910// XML-RPC library for communicating with LiveJournal API 
    1011require_once( ABSPATH . WPINC . '/class-IXR.php' ); 
    1112 
    12 // Snoopy for getting comments (with cookies) 
    13 require_once( ABSPATH . WPINC . '/class-snoopy.php' ); 
    14  
    1513/** 
    1614 * LiveJournal API Importer class 
    1715 * 
     
    2624        var $ixr; 
    2725        var $username; 
    2826        var $password; 
    29         var $snoop; 
    3027        var $comment_meta; 
    3128        var $comments; 
    3229        var $usermap; 
    3330        var $postmap; 
     31        var $commentmap; 
    3432        var $pointers = array(); 
    3533         
    3634        // This list taken from LJ, they don't appear to have an API for it 
     
    188186                        <p class="submit"> 
    189187                                <input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Continue previous import' ) ) ?>" /> 
    190188                        </p> 
    191                         <p><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&amp;step=-1&amp;_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&amp;_wp_http_referer=' . attribute_escape( $_SERVER['REQUEST_URI'] ) ?>"><?php _e( 'Cancel &amp; start a new import' ) ?></a></p> 
     189                        <p class="submitbox"><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&amp;step=-1&amp;_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&amp;_wp_http_referer=' . attribute_escape( $_SERVER['REQUEST_URI'] ) ?>" class="deletion submitdelete"><?php _e( 'Cancel &amp; start a new import' ) ?></a></p> 
    192190                        <p> 
    193191                <?php else : ?> 
    194192                        <input type="hidden" name="step" value="1" /> 
     
    228226                        </p> 
    229227                 
    230228                        <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> 
    231233                <?php endif; ?> 
    232234                </form> 
    233235                </div> 
     
    248250                do { 
    249251                        $lastsync = date( 'Y-m-d H:i:s', strtotime( get_option( 'ljapi_lastsync' ) ) ); 
    250252                        $synclist = $this->lj_ixr( 'syncitems', array( 'ver' => 1, 'lastsync' => $lastsync ) ); 
    251                         $this->log( $synclist, 'ljimport-items-' . $total . '.txt' ); 
    252253                         
    253254                        // Keep track of if we've downloaded everything 
    254255                        $total = $synclist['total']; 
     
    261262                                                $lastsync = $event['time']; 
    262263                                } 
    263264                        } 
    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 ); 
    269265                } while ( $total > $count ); 
    270266                // endwhile - all post meta is cached locally 
    271                 $this->log( $sync_item_times, 'ljimport-post-mod-times.txt' ); 
    272267                 
     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>'; 
     274                 
    273275                echo '<ol>'; 
    274276                 
    275277                $imported_count = (int) get_option( 'ljapi_imported_count' ); 
     
    285287                                                                                                                        'selecttype' => 'syncitems', 
    286288                                                                                                                        'lineendings' => 'pc', 
    287289                                                                                                                        'lastsync' => $lastsync ) ); 
    288                         $this->log( $itemlist, 'ljimport-posts-' . $imported_count . '.txt' ); 
    289290                        if ( is_wp_error( $itemlist ) ) 
    290291                                return $itemlist; 
     292                                 
    291293                        if ( $num = count( $itemlist['events'] ) ) { 
    292294                                foreach ( $itemlist['events'] as $event ) { 
    293295                                        $imported_count++; 
     
    312314                        return; 
    313315                 
    314316                $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 
    318321 
    319322                // For some reason, LJ sometimes sends a date as "2004-04-1408:38:00" (no space btwn date/time) 
    320323                $post_date = $post['eventtime']; 
     
    322325                        $post_date = substr( $post_date, 0, 10 ) . ' ' . substr( $post_date, 10 ); 
    323326                 
    324327                // Cleaning up and linking the title 
    325                 $post_title = trim( $post['subject'] ); 
     328                $post_title = isset( $post['subject'] ) ? trim( $post['subject'] ) : ''; 
    326329                $post_title = $this->translate_lj_user( $post_title ); // Translate it, but then we'll strip the link 
    327330                $post_title = strip_tags( $post_title ); // Can't have tags in the title in WP 
    328331                $post_title = $wpdb->escape( $post_title ); 
     
    365368                        } 
    366369                        $postdata['post_ID']   = $post_id; 
    367370                        $postdata['lj_itemid'] = $post['itemid']; 
    368                         $this->log( $postdata, 'ljimport-post-' . $post_id . '.txt' ); 
    369371                         
    370372                        // Handle all the metadata for this post 
    371373                        $this->insert_postmeta( $post_id, $post ); 
     
    404406                } 
    405407        } 
    406408         
    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() { 
    410411                // Get a session via XMLRPC 
    411412                $cookie = $this->lj_ixr( 'sessiongenerate', array( 'ver' => 1, 'expiration' => 'short' ) ); 
     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(); 
    412419                 
    413                 // Comment Meta 
    414                  
    415420                // Load previous state (if any) 
    416421                $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; 
    423424                 
    424425                // We need to loop over the metadata request until we have it all 
    425426                while ( $maxid > $highest_id ) { 
    426427                        // 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.' ) ); 
    432432                         
     433                        $results = wp_remote_retrieve_body( $results ); 
     434                         
    433435                        // Get the maxid so we know if we have them all yet 
    434436                        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                        } 
    435444                        $maxid = !empty( $matches[1] ) ? $matches[1] : $maxid; 
    436445                         
    437446                        // Parse comments and get highest id available 
     
    446455                        foreach ( $matches[1] as $count => $userid ) 
    447456                                $this->usermap[$userid] = $matches[2][$count]; // need this in memory for translating ids => names 
    448457                                 
    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(); 
    452459                } 
    453460                // endwhile - should have seen all comment meta at this point 
     461 
     462                update_option( 'ljapi_usermap',    $this->usermap ); 
     463                update_option( 'ljapi_maxid',      $maxid ); 
     464                update_option( 'ljapi_highest_id', $highest_id ); 
    454465                 
     466                echo '<p>' . __( ' Comment metadata downloaded successfully, proceeding with posts...' ) . '</p>'; 
    455467                 
    456                 // Download Comment XML 
    457                  
    458                 // 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 ) { 
    470                         // 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 ) ); 
    497                 } 
    498                 // endwhile - all comments downloaded and ready for bulk processing 
    499                  
    500                 echo '</ol>'; 
    501                  
    502468                return true; 
    503469        } 
    504470         
    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(); 
     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(); 
    515476                 
    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]; 
     477                // Load previous state (if any) 
     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++; 
    521484                         
    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 ); 
     485                        // Get a batch of comments, using the highest_id we've already got as a starting point 
     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.' ) ); 
    524490                         
    525                         // Parse this comment into an array 
    526                         $comment = $this->parse_comment( $comment ); 
    527                         if ( empty( $comment['comment_post_ID'] ) ) 
    528                                 continue; 
     491                        $results = wp_remote_retrieve_body( $results ); 
    529492                         
    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; 
     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 ); 
    539513                        } 
     514                         
     515                        // Clear cache to preseve memory 
     516                        wp_cache_flush(); 
    540517                } 
     518                // endwhile - all comments downloaded and ready for bulk processing 
    541519                 
    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(); 
     520                // Counter just used to show progress to user 
     521                update_option( 'ljapi_comment_batch', ( (int) get_option( 'ljapi_comment_batch' ) + 1 ) ); 
    548522                 
    549                 // Don't need this XML file anymore 
    550                 unlink( $xml_file ); 
    551                  
    552523                return true; 
    553524        } 
    554525         
     526        // Takes a block of XML and parses out all the elements of the comment 
    555527        function parse_comment( $comment ) { 
    556528                global $wpdb; 
    557529                 
     
    562534                preg_match( '| jitemid=\'(\d+)\'|i', $attribs[1], $matches ); 
    563535                $lj_comment_post_ID = $matches[1]; 
    564536                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'; 
    570542                 
    571543                // Clean up "subject" - this will become the first line of the comment in WP 
    572544                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                } 
    576550                 
    577551                // Get the body and HTMLize it 
    578552                preg_match( '|<body>(.*)</body>|is', $comment, $matches ); 
     
    590564                $comment_date = trim( str_replace( array( 'T', 'Z' ), ' ', $matches[1] ) ); 
    591565                 
    592566                // 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] : ''; 
    595569                 
    596570                // 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]; 
    598572                if ( get_option( 'ljapi_username' ) == $author ) { 
    599573                        $user    = wp_get_current_user(); 
    600574                        $user_id = $user->ID; 
     
    613587                                                'comment_post_ID' => $this->get_wp_post_ID( $lj_comment_post_ID ), 
    614588                                                'comment_author' => $author, 
    615589                                                'comment_author_url' => $url, 
     590                                                'comment_author_email' => '', 
    616591                                                'comment_content' => $comment_content, 
    617592                                                'comment_date' => $comment_date, 
    618593                                                'comment_author_IP' => ( !empty( $comment_author_IP ) ? $comment_author_IP : '' ), 
    619594                                                '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                                        ); 
    623600        } 
    624601         
    625602         
     
    627604        function get_wp_post_ID( $post ) { 
    628605                global $wpdb; 
    629606                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 ) ); 
    631608                return $this->postmap[$post]; 
    632609        } 
    633610         
    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; 
     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]; 
    676617        } 
    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(); 
    704618                         
    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>'; 
    748         } 
    749                          
    750619        function lj_ixr() { 
    751620                if ( $challenge = $this->ixr->query( 'LJ.XMLRPC.getchallenge' ) ) { 
    752621                        $challenge = $this->ixr->getResponse(); 
     
    767636                if ( $this->ixr->query( 'LJ.XMLRPC.' . $method, $params ) ) { 
    768637                        return $this->ixr->getResponse(); 
    769638                } else { 
    770                         $this->log( $this->ixr->message, 'ljimport-error-' . $method . '.txt' ); 
    771639                        return new WP_Error( 'IXR', __( 'XML-RPC Request Failed - ' ) . $this->ixr->getErrorCode() . ': ' . $this->ixr->getErrorMessage() ); 
    772640                } 
    773641        } 
     
    788656                                $this->greet(); 
    789657                                break; 
    790658                        case 1 : 
    791                         case 2 : 
    792659                                $this->ixr = new IXR_Client( $this->ixr_url ); 
    793660                                // Intentional no break 
     661                        case 2 : 
    794662                        case 3 : 
    795                         case 4 : 
    796                         case 5 : 
    797663                                check_admin_referer( 'lj-api-import' ); 
    798664                                $result = $this->{ 'step' . $step }(); 
    799665                                if ( is_wp_error( $result ) ) 
     
    837703                $login = $this->lj_ixr( 'login' ); 
    838704                if ( is_wp_error( $login ) ) { 
    839705                        if ( 100 == $this->ixr->getErrorCode() || 101 == $this->ixr->getErrorCode() ) { 
     706                                delete_option( 'ljapi_username' ); 
     707                                delete_option( 'ljapi_password' ); 
    840708                                ?> 
    841709                                <p><?php _e( 'Logging in to LiveJournal failed. Check your username and password and try again.' ) ?></p> 
    842710                                <p><a href="<?php echo $_SERVER['PHP_SELF'] . '?import=livejournal&amp;step=-1&amp;_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&amp;_wp_http_referer=' . attribute_escape( str_replace( '&step=1', '', $_SERVER['REQUEST_URI'] ) ) ?>"><?php _e( 'Start again' ) ?></a></p> 
     
    848716                } 
    849717                 
    850718                // 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 ); 
    856722                 
    857723                echo '<h3>' . __( 'Importing Posts' ) . '</h3>'; 
    858724                echo '<p>' . __( "We're downloading and importing all your LiveJournal posts..." ) . '</p>'; 
     
    873739                        } 
    874740                } 
    875741                 
    876                 echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to process &amp; import your comments." ) . '</p>'; 
     742                echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to download &amp; import your comments." ) . '</p>'; 
    877743                echo $this->next_step( 2, __( 'Download my comments &raquo;' ) ); 
    878744                $this->auto_submit(); 
    879745        } 
     
    884750                update_option( 'ljapi_step', 2 ); 
    885751                $this->username = get_option( 'ljapi_username' ); 
    886752                $this->password = get_option( 'ljapi_password' ); 
     753                $this->ixr = new IXR_Client( $this->ixr_url ); 
    887754                 
     755                echo '<div id="ljapi-status">'; 
    888756                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>'; 
    890758                ob_flush(); flush(); 
    891759                 
    892                 $result = $this->download_comments(); 
    893                 if ( is_wp_error( $result ) ) 
    894                         return $result; 
    895  
    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 &raquo;' ) ); 
    898                 $this->auto_submit(); 
    899         } 
    900  
    901         // Parse XML into comment cache files    
    902         function step3() { 
    903  
    904                 set_time_limit( 0 ); 
    905                 update_option( 'ljapi_step', 3 ); 
    906                  
    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 ); 
     760                if ( !get_option( 'ljapi_usermap' ) ) { 
     761                        // We haven't downloaded meta yet, so do that first 
     762                        $result = $this->download_comment_meta(); 
    919763                        if ( is_wp_error( $result ) ) 
    920764                                return $result; 
    921  
    922                         update_option( 'ljapi_comment_xml_files', $files ); 
    923765                } 
    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 &raquo;' ) ) ?>" /> <span id="auto-message"></span></p> 
    932                                 </form> 
    933                                 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 
    934                         <?php 
     766 
     767                // Download a batch of actual comments 
     768                $result = $this->download_comment_bodies(); 
     769                if ( is_wp_error( $result ) ) 
     770                        return $result; 
     771 
     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 &raquo;' ) ) ?>" /> <span id="auto-message"></span></p> 
     781                        </form> 
     782                        <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 
     783                <?php 
    935784                } 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 &raquo;' ) ); 
     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 &raquo;' ) ); 
    938787                        $this->auto_submit(); 
    939788                } 
    940789                echo '</div>'; 
    941790        } 
    942  
    943         // Thread comments within their cache files      
    944         function step4() { 
     791         
     792        // Re-thread comments already in the DB 
     793        function step3() { 
     794                global $wpdb; 
    945795                set_time_limit( 0 ); 
    946                 update_option( 'ljapi_step', 4 ); 
     796                update_option( 'ljapi_step', 3 ); 
    947797                 
    948798                echo '<div id="ljapi-status">'; 
    949799                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>'; 
    951801                ob_flush(); flush(); 
    952802                 
    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 ); 
     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' ); 
    962812                } 
    963813                 
    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 &raquo;' ) ) ?>" /> <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 &raquo;' ) ); 
    978                         $this->auto_submit(); 
     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(); 
    979823                } 
    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 ); 
    987824                 
    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 ); 
     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}" ); 
    1005831                } 
    1006832                 
    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 &raquo;' ) ) ?>" /> <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                 } 
     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>'; 
    1024841                echo '</div>'; 
    1025842        } 
    1026843         
     
    1035852                 
    1036853                return $str; 
    1037854        } 
    1038  
    1039         // Automatically submit the form with #id to continue the process 
    1040         // Hide any submit buttons to avoid people clicking them 
    1041         // 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 ) { 
     855         
     856        // Automatically submit the specified form after $seconds 
     857        // Include a friendly countdown in the element with id=$msg 
     858        function auto_submit( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 10 ) { 
    1043859                ?><script type="text/javascript"> 
    1044860                        next_counter = <?php echo $seconds ?>; 
    1045861                        jQuery(document).ready(function(){ 
     
    1052868                                if ( next_counter <= 0 ) { 
    1053869                                        if ( jQuery( '#<?php echo $id ?>' ).length ) { 
    1054870                                                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" />'; 
     871                                                str = '<?php _e( "Continuing" ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; 
    1057872                                                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'] ?>'}); 
     873                                                jQuery( '#<?php echo $id ?>' ).submit(); 
    1062874                                                return; 
    1063875                                        } 
    1064876                                } 
     
    1068880                </script><?php 
    1069881        } 
    1070882         
    1071         // Automatically submit the specified form after $seconds 
    1072         // Include a friendly countdown in the element with id=$msg 
    1073         function auto_submit( $id = 'ljapi-next-form', $msg = 'auto-message', $seconds = 10 ) { 
     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 ) { 
    1074887                ?><script type="text/javascript"> 
    1075888                        next_counter = <?php echo $seconds ?>; 
    1076889                        jQuery(document).ready(function(){ 
     
    1083896                                if ( next_counter <= 0 ) { 
    1084897                                        if ( jQuery( '#<?php echo $id ?>' ).length ) { 
    1085898                                                jQuery( "#<?php echo $id ?> input[type='submit']" ).hide(); 
    1086                                                 str = '<?php _e( "Continuing" ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; 
     899                                                jQuery.ajaxSetup({'timeout':3600000}); 
     900                                                str = '<?php _e( "Processing next batch." ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />'; 
    1087901                                                jQuery( '#<?php echo $msg ?>' ).html( str ); 
    1088                                                 jQuery( '#<?php echo $id ?>' ).submit(); 
     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'] ?>'}); 
    1089906                                                return; 
    1090907                                        } 
    1091908                                } 
     
    1095912                </script><?php 
    1096913        } 
    1097914 
    1098         // Remove all options used during import process 
     915        // Remove all options used during import process and 
     916        // set wp_comments entries back to "normal" values 
    1099917        function cleanup() { 
     918                global $wpdb; 
     919                 
    1100920                delete_option( 'ljapi_username' ); 
    1101921                delete_option( 'ljapi_password' ); 
    1102922                delete_option( 'ljapi_protected_password' ); 
     
    1111931                delete_option( 'ljapi_usermap' ); 
    1112932                delete_option( 'ljapi_highest_id' ); 
    1113933                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' ); 
    1120935                delete_option( 'ljapi_step' ); 
     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' ) ); 
    1121943        } 
    1122944         
    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  
    1162945        function LJ_API_Import() { 
    1163946                $this->__construct(); 
    1164947        }