Make WordPress Core


Ignore:
Timestamp:
02/04/2009 05:47:50 PM (16 years ago)
Author:
ryan
Message:

Revert new LJ importer. see #8999

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/import/livejournal.php

    r10492 r10499  
    11<?php
    22/**
    3  * LiveJournal API Importer
     3 * LiveJournal Importer
    44 *
    55 * @package WordPress
     
    77 */
    88
    9 // XML-RPC library for communicating with LiveJournal API
    10 require_once( ABSPATH . WPINC . '/class-IXR.php' );
     9/**
     10 * LiveJournal Importer class
     11 *
     12 * Imports your LiveJournal XML exported file into WordPress.
     13 *
     14 * @since unknown
     15 */
     16class LJ_Import {
    1117
    12 // Snoopy for getting comments (with cookies)
    13 require_once( ABSPATH . WPINC . '/class-snoopy.php' );
    14 
    15 /**
    16  * LiveJournal API Importer class
    17  *
    18  * Imports your LiveJournal contents into WordPress using the LJ API
    19  *
    20  * @since 2.7.1
    21  */
    22 class LJ_API_Import {
    23 
    24     var $comments_url = 'http://www.livejournal.com/export_comments.bml';
    25     var $ixr_url      = 'http://www.livejournal.com/interface/xmlrpc';
    26     var $ixr;
    27     var $username;
    28     var $password;
    29     var $snoop;
    30     var $comment_meta;
    31     var $comments;
    32     var $usermap;
    33     var $postmap;
    34     var $pointers = array();
    35    
    36     // This list taken from LJ, they don't appear to have an API for it
    37     var $moods = array( '1' => 'aggravated',
    38                         '10' => 'discontent',
    39                         '100' => 'rushed',
    40                         '101' => 'contemplative',
    41                         '102' => 'nerdy',
    42                         '103' => 'geeky',
    43                         '104' => 'cynical',
    44                         '105' => 'quixotic',
    45                         '106' => 'crazy',
    46                         '107' => 'creative',
    47                         '108' => 'artistic',
    48                         '109' => 'pleased',
    49                         '11' => 'energetic',
    50                         '110' => 'bitchy',
    51                         '111' => 'guilty',
    52                         '112' => 'irritated',
    53                         '113' => 'blank',
    54                         '114' => 'apathetic',
    55                         '115' => 'dorky',
    56                         '116' => 'impressed',
    57                         '117' => 'naughty',
    58                         '118' => 'predatory',
    59                         '119' => 'dirty',
    60                         '12' => 'enraged',
    61                         '120' => 'giddy',
    62                         '121' => 'surprised',
    63                         '122' => 'shocked',
    64                         '123' => 'rejected',
    65                         '124' => 'numb',
    66                         '125' => 'cheerful',
    67                         '126' => 'good',
    68                         '127' => 'distressed',
    69                         '128' => 'intimidated',
    70                         '129' => 'crushed',
    71                         '13' => 'enthralled',
    72                         '130' => 'devious',
    73                         '131' => 'thankful',
    74                         '132' => 'grateful',
    75                         '133' => 'jealous',
    76                         '134' => 'nervous',
    77                         '14' => 'exhausted',
    78                         '15' => 'happy',
    79                         '16' => 'high',
    80                         '17' => 'horny',
    81                         '18' => 'hungry',
    82                         '19' => 'infuriated',
    83                         '2' => 'angry',
    84                         '20' => 'irate',
    85                         '21' => 'jubilant',
    86                         '22' => 'lonely',
    87                         '23' => 'moody',
    88                         '24' => 'pissed off',
    89                         '25' => 'sad',
    90                         '26' => 'satisfied',
    91                         '27' => 'sore',
    92                         '28' => 'stressed',
    93                         '29' => 'thirsty',
    94                         '3' => 'annoyed',
    95                         '30' => 'thoughtful',
    96                         '31' => 'tired',
    97                         '32' => 'touched',
    98                         '33' => 'lazy',
    99                         '34' => 'drunk',
    100                         '35' => 'ditzy',
    101                         '36' => 'mischievous',
    102                         '37' => 'morose',
    103                         '38' => 'gloomy',
    104                         '39' => 'melancholy',
    105                         '4' => 'anxious',
    106                         '40' => 'drained',
    107                         '41' => 'excited',
    108                         '42' => 'relieved',
    109                         '43' => 'hopeful',
    110                         '44' => 'amused',
    111                         '45' => 'determined',
    112                         '46' => 'scared',
    113                         '47' => 'frustrated',
    114                         '48' => 'indescribable',
    115                         '49' => 'sleepy',
    116                         '5' => 'bored',
    117                         '51' => 'groggy',
    118                         '52' => 'hyper',
    119                         '53' => 'relaxed',
    120                         '54' => 'restless',
    121                         '55' => 'disappointed',
    122                         '56' => 'curious',
    123                         '57' => 'mellow',
    124                         '58' => 'peaceful',
    125                         '59' => 'bouncy',
    126                         '6' => 'confused',
    127                         '60' => 'nostalgic',
    128                         '61' => 'okay',
    129                         '62' => 'rejuvenated',
    130                         '63' => 'complacent',
    131                         '64' => 'content',
    132                         '65' => 'indifferent',
    133                         '66' => 'silly',
    134                         '67' => 'flirty',
    135                         '68' => 'calm',
    136                         '69' => 'refreshed',
    137                         '7' => 'crappy',
    138                         '70' => 'optimistic',
    139                         '71' => 'pessimistic',
    140                         '72' => 'giggly',
    141                         '73' => 'pensive',
    142                         '74' => 'uncomfortable',
    143                         '75' => 'lethargic',
    144                         '76' => 'listless',
    145                         '77' => 'recumbent',
    146                         '78' => 'exanimate',
    147                         '79' => 'embarrassed',
    148                         '8' => 'cranky',
    149                         '80' => 'envious',
    150                         '81' => 'sympathetic',
    151                         '82' => 'sick',
    152                         '83' => 'hot',
    153                         '84' => 'cold',
    154                         '85' => 'worried',
    155                         '86' => 'loved',
    156                         '87' => 'awake',
    157                         '88' => 'working',
    158                         '89' => 'productive',
    159                         '9' => 'depressed',
    160                         '90' => 'accomplished',
    161                         '91' => 'busy',
    162                         '92' => 'blah',
    163                         '93' => 'full',
    164                         '95' => 'grumpy',
    165                         '96' => 'weird',
    166                         '97' => 'nauseated',
    167                         '98' => 'ecstatic',
    168                         '99' => 'chipper' );
     18    var $file;
    16919
    17020    function header() {
    17121        echo '<div class="wrap">';
    17222        screen_icon();
    173         echo '<h2>' . __( 'Import LiveJournal' ) . '</h2>';
     23        echo '<h2>'.__('Import LiveJournal').'</h2>';
    17424    }
    17525
     
    17828    }
    17929
     30    function unhtmlentities($string) { // From php.net for < 4.3 compat
     31        $trans_tbl = get_html_translation_table(HTML_ENTITIES);
     32        $trans_tbl = array_flip($trans_tbl);
     33        return strtr($string, $trans_tbl);
     34    }
     35
    18036    function greet() {
    181         ?>
    182         <div class="narrow">
    183         <form action="admin.php?import=livejournal" method="post">
    184         <?php wp_nonce_field( 'lj-api-import' ) ?>
    185         <?php if ( get_option( 'ljapi_username' ) && get_option( 'ljapi_password' ) ) : ?>
    186             <input type="hidden" name="step" value="<?php echo get_option( 'ljapi_step' ) ?>" />
    187             <p><?php _e( 'It looks like you attempted to import your LiveJournal posts previously and got interrupted.' ) ?></p>
    188             <p class="submit">
    189                 <input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Continue previous import' ) ) ?>" />
    190             </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>
    192             <p>
    193         <?php else : ?>
    194             <input type="hidden" name="step" value="1" />
    195             <p><?php _e( 'Howdy! This importer allows you to connect directly to LiveJournal and download all your entries and comments' ) ?></p>
    196             <p><?php _e( 'Enter your LiveJournal username and password below so we can connect to your account:' ) ?></p>
    197        
    198             <table class="form-table">
     37        echo '<div class="narrow">';
     38        echo '<p>'.__('Howdy! Upload your LiveJournal XML export file and we&#8217;ll import the posts into this blog.').'</p>';
     39        echo '<p>'.__('Choose a LiveJournal XML file to upload, then click Upload file and import.').'</p>';
     40        wp_import_upload_form("admin.php?import=livejournal&amp;step=1");
     41        echo '</div>';
     42    }
    19943
    200             <tr>
    201             <th scope="row"><label for="lj_username"><?php _e( 'LiveJournal Username' ) ?></label></th>
    202             <td><input type="text" name="lj_username" id="lj_username" class="regular-text" /></td>
    203             </tr>
     44    function import_posts() {
     45        global $wpdb, $current_user;
    20446
    205             <tr>
    206             <th scope="row"><label for="lj_password"><?php _e( 'LiveJournal Password' ) ?></label></th>
    207             <td><input type="password" name="lj_password" id="lj_password" class="regular-text" /></td>
    208             </tr>
    209      
    210             </table>
    211      
    212             <p><?php _e( 'If you have any entries on LiveJournal which are marked as private, they will be password-protected when they are imported so that only people who know the password can see them.' ) ?></p>
    213             <p><?php _e( "If you don't enter a password, ALL ENTRIES from your LiveJournal will be imported as public posts in WordPress." ) ?></p>
    214             <p><?php _e( 'Enter the password you would like to use for all protected entries here:' ) ?></p>
    215             <table class="form-table">
     47        set_magic_quotes_runtime(0);
     48        $importdata = file($this->file); // Read the file into an array
     49        $importdata = implode('', $importdata); // squish it
     50        $importdata = str_replace(array ("\r\n", "\r"), "\n", $importdata);
    21651
    217             <tr>
    218             <th scope="row"><label for="protected_password"><?php _e( 'Protected Post Password' ) ?></label></th>
    219             <td><input type="text" name="protected_password" id="protected_password" class="regular-text" /></td>
    220             </tr>
     52        preg_match_all('|<entry>(.*?)</entry>|is', $importdata, $posts);
     53        $posts = $posts[1];
     54        unset($importdata);
     55        echo '<ol>';
     56        foreach ($posts as $post) {
     57            preg_match('|<subject>(.*?)</subject>|is', $post, $post_title);
     58            $post_title = $wpdb->escape(trim($post_title[1]));
     59            if ( empty($post_title) ) {
     60                preg_match('|<itemid>(.*?)</itemid>|is', $post, $post_title);
     61                $post_title = $wpdb->escape(trim($post_title[1]));
     62            $post_content = preg_replace('|<lj\s+user\s*=\s*["\']([\w-]+)["\']>|', '<a href="http://$1.livejournal.com/">$1</a>', $post_content);
     63            }
    22164
    222             </table>
     65            preg_match('|<eventtime>(.*?)</eventtime>|is', $post, $post_date);
     66            $post_date = strtotime($post_date[1]);
     67            $post_date = date('Y-m-d H:i:s', $post_date);
    22368
    224             <p><?php _e( "<strong>WARNING:</strong> This can take a really long time if you have a lot of entries in your LiveJournal, or a lot of comments. Ideally, you should only start this process if you can leave your computer alone while it finishes the import." ) ?></p>
    225        
    226             <p class="submit">
    227                 <input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Connect to LiveJournal and Import' ) ) ?>" />
    228             </p>
    229        
    230             <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>
    231         <?php endif; ?>
    232         </form>
    233         </div>
    234         <?php
    235     }
    236    
    237     function import_posts() {
    238         $total           = (int) get_option( 'ljapi_total' );
    239         $count           = (int) get_option( 'ljapi_count' );
    240         $lastsync        = get_option( 'ljapi_lastsync' );
    241         if ( !$lastsync ) {
    242             update_option( 'ljapi_lastsync', '1900-01-01 00:00:00' );
    243         }
    244         $sync_item_times = get_option( 'ljapi_sync_item_times' );
    245         if ( !is_array( $sync_item_times ) )
    246             $sync_item_times = array();
    247        
    248         do {
    249             $lastsync = date( 'Y-m-d H:i:s', strtotime( get_option( 'ljapi_lastsync' ) ) );
    250             $synclist = $this->lj_ixr( 'syncitems', array( 'ver' => 1, 'lastsync' => $lastsync ) );
    251             $this->log( $synclist, 'ljimport-items-' . $total . '.txt' );
    252            
    253             // Keep track of if we've downloaded everything
    254             $total = $synclist['total'];
    255             $count = $synclist['count'];
    256        
    257             foreach ( $synclist['syncitems'] as $event ) {
    258                 if ( substr( $event['item'], 0, 2 ) == 'L-' ) {
    259                     $sync_item_times[ str_replace( 'L-', '', $event['item'] ) ] = $event['time'];
    260                     if ( $event['time'] > $lastsync )
    261                         $lastsync = $event['time'];
     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);
     72
     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;
    26295                }
    26396            }
    26497
    265             update_option( 'ljapi_sync_item_times', $sync_item_times );
    266             update_option( 'ljapi_total', $total );
    267             update_option( 'ljapi_count', $count );
    268             update_option( 'ljapi_lastsync', $lastsync );
    269         } while ( $total > $count );
    270         // endwhile - all post meta is cached locally
    271         $this->log( $sync_item_times, 'ljimport-post-mod-times.txt' );
    272        
    273         echo '<ol>';
    274        
    275         $imported_count = (int) get_option( 'ljapi_imported_count' );
    276         $lastsync = get_option( 'ljapi_lastsync_posts' );
    277         if ( !$lastsync )
    278             update_option( 'ljapi_lastsync_posts', date( 'Y-m-d H:i:s', 0 ) );
    279        
    280         do {
    281             $lastsync = date( 'Y-m-d H:i:s', strtotime( get_option( 'ljapi_lastsync_posts' ) ) );
    282            
    283             // Get the batch of items that match up with the syncitems list
    284             $itemlist = $this->lj_ixr( 'getevents', array( 'ver' => 1,
    285                                                             'selecttype' => 'syncitems',
    286                                                             'lineendings' => 'pc',
    287                                                             'lastsync' => $lastsync ) );
    288             $this->log( $itemlist, 'ljimport-posts-' . $imported_count . '.txt' );
    289             if ( is_wp_error( $itemlist ) )
    290                 return $itemlist;
    291             if ( $num = count( $itemlist['events'] ) ) {
    292                 foreach ( $itemlist['events'] as $event ) {
    293                     $imported_count++;
    294                     $this->import_post( $event );
    295                     if ( $sync_item_times[ $event['itemid'] ] > $lastsync )
    296                         $lastsync = $sync_item_times[ $event['itemid'] ];
     98            preg_match_all('|<comment>(.*?)</comment>|is', $post, $comments);
     99            $comments = $comments[1];
     100
     101            if ( $comments ) {
     102                $comment_post_ID = (int) $post_id;
     103                $num_comments = 0;
     104                foreach ($comments as $comment) {
     105                    preg_match('|<event>(.*?)</event>|is', $comment, $comment_content);
     106                    $comment_content = str_replace(array ('<![CDATA[', ']]>'), '', trim($comment_content[1]));
     107                    $comment_content = $this->unhtmlentities($comment_content);
     108
     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);
     114
     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));
     118
     119                    preg_match('|<name>(.*?)</name>|is', $comment, $comment_author);
     120                    $comment_author = $wpdb->escape(trim($comment_author[1]));
     121
     122                    preg_match('|<email>(.*?)</email>|is', $comment, $comment_author_email);
     123                    $comment_author_email = $wpdb->escape(trim($comment_author_email[1]));
     124
     125                    $comment_approved = 1;
     126                    // Check if it's already there
     127                    if (!comment_exists($comment_author, $comment_date)) {
     128                        $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_date', 'comment_content', 'comment_approved');
     129                        $commentdata = wp_filter_comment($commentdata);
     130                        wp_insert_comment($commentdata);
     131                        $num_comments++;
     132                    }
    297133                }
    298                 update_option( 'ljapi_lastsync_posts',  $lastsync );
    299                 update_option( 'ljapi_imported_count',  $imported_count );
    300                 update_option( 'ljapi_last_sync_count', $num );
    301134            }
    302         } while ( $num > 0 );
    303 
    304         echo '</ol>';
    305     }
    306    
    307     function import_post( $post ) {
    308         global $wpdb;
    309        
    310         // Make sure we haven't already imported this one
    311         if ( $this->get_wp_post_ID( $post['itemid'] ) )
    312             return;
    313        
    314         $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
    318 
    319         // For some reason, LJ sometimes sends a date as "2004-04-1408:38:00" (no space btwn date/time)
    320         $post_date = $post['eventtime'];
    321         if ( 18 == strlen( $post_date ) )
    322             $post_date = substr( $post_date, 0, 10 ) . ' ' . substr( $post_date, 10 );
    323        
    324         // Cleaning up and linking the title
    325         $post_title = trim( $post['subject'] );
    326         $post_title = $this->translate_lj_user( $post_title ); // Translate it, but then we'll strip the link
    327         $post_title = strip_tags( $post_title ); // Can't have tags in the title in WP
    328         $post_title = $wpdb->escape( $post_title );
    329        
    330         // Clean up content
    331         $post_content = $post['event'];
    332         $post_content = preg_replace_callback( '|<(/?[A-Z]+)|', create_function( '$match', 'return "<" . strtolower( $match[1] );' ), $post_content );
    333         // XHTMLize some tags
    334         $post_content = str_replace( '<br>', '<br />', $post_content );
    335         $post_content = str_replace( '<hr>', '<hr />', $post_content );
    336         // lj-cut ==>  <!--more-->
    337         $post_content = preg_replace( '|<lj-cut text="([^"]*)">|is', '<!--more $1-->', $post_content );
    338         $post_content = str_replace( array( '<lj-cut>', '</lj-cut>' ), array( '<!--more-->', '' ), $post_content );
    339         $first = strpos( $post_content, '<!--more' );
    340         $post_content = substr( $post_content, 0, $first + 1 ) . preg_replace( '|<!--more(.*)?-->|sUi', '', substr( $post_content, $first + 1 ) );
    341         // lj-user ==>  a href
    342         $post_content = $this->translate_lj_user( $post_content );
    343         $post_content = force_balance_tags( $post_content );
    344         $post_content = $wpdb->escape( $post_content );
    345        
    346         // Handle any tags associated with the post
    347         $tags_input = !empty( $post['props']['taglist'] ) ? $post['props']['taglist'] : '';
    348        
    349         // Check if comments are closed on this post
    350         $comment_status = !empty( $post['props']['opt_nocomments'] ) ? 'closed' : 'open';
    351 
    352         echo '<li>';
    353         if ( $post_id = post_exists( $post_title, $post_content, $post_date ) ) {
    354             printf( __( 'Post <strong>%s</strong> already exists.' ), stripslashes( $post_title ) );
    355         } else {
    356             printf( __( 'Importing post <strong>%s</strong>...' ), stripslashes( $post_title ) );
    357             $postdata = compact( 'post_author', 'post_date', 'post_content', 'post_title', 'post_status', 'post_password', 'tags_input', 'comment_status' );
    358             $post_id = wp_insert_post( $postdata );
    359             if ( is_wp_error( $post_id ) )
    360                 return $post_id;
    361             if ( !$post_id ) {
    362                 _e( "Couldn't get post ID" );
    363                 echo '</li>';
    364                 break;
     135            if ( $num_comments ) {
     136                echo ' ';
     137                printf(__ngettext('(%s comment)', '(%s comments)', $num_comments), $num_comments);
    365138            }
    366             $postdata['post_ID']   = $post_id;
    367             $postdata['lj_itemid'] = $post['itemid'];
    368             $this->log( $postdata, 'ljimport-post-' . $post_id . '.txt' );
    369            
    370             // Handle all the metadata for this post
    371             $this->insert_postmeta( $post_id, $post );
    372         }
    373         echo '</li>';
    374     }
    375    
    376     // Convert lj-user tags to links to that user
    377     function translate_lj_user( $str ) {
    378         return preg_replace( '|<lj\s+user\s*=\s*["\']([\w-]+)["\']>|', '<a href="http://$1.livejournal.com/" class="lj-user">$1</a>', $str );
    379     }
    380    
    381     function insert_postmeta( $post_id, $post ) {
    382         // Need the original LJ id for comments
    383         add_post_meta( $post_id, 'lj_itemid', $post['itemid'] );
    384        
    385         // And save the permalink on LJ in case we want to link back or something
    386         add_post_meta( $post_id, 'lj_permalink', $post['url'] );
    387        
    388         // Supports the following "props" from LJ, saved as lj_<prop_name> in wp_postmeta
    389         //      Adult Content - adult_content
    390         //      Location - current_coords + current_location
    391         //      Mood - current_mood (translated from current_moodid)
    392         //      Music - current_music
    393         //      Userpic - picture_keyword
    394         foreach ( array( 'adult_content', 'current_coords', 'current_location', 'current_moodid', 'current_music', 'picture_keyword' ) as $prop ) {
    395             if ( !empty( $post['props'][$prop] ) ) {
    396                 if ( 'current_moodid' == $prop ) {
    397                     $prop = 'current_mood';
    398                     $val = $this->moods[ $post['props']['current_moodid'] ];
    399                 } else {
    400                     $val = $post['props'][$prop];
    401                 }
    402                 add_post_meta( $post_id, 'lj_' . $prop, $val );
    403             }
    404         }
    405     }
    406    
    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() {
    410         // Get a session via XMLRPC
    411         $cookie = $this->lj_ixr( 'sessiongenerate', array( 'ver' => 1, 'expiration' => 'short' ) );
    412        
    413         // Comment Meta
    414        
    415         // Load previous state (if any)
    416         $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;
    423        
    424         // We need to loop over the metadata request until we have it all
    425         while ( $maxid > $highest_id ) {
    426             // 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;
    432            
    433             // Get the maxid so we know if we have them all yet
    434             preg_match( '|<maxid>(\d+)</maxid>|', $results, $matches );
    435             $maxid = !empty( $matches[1] ) ? $matches[1] : $maxid;
    436            
    437             // Parse comments and get highest id available
    438             preg_match_all( '|<comment id=\'(\d+)\'|is', $results, $matches );
    439             foreach ( $matches[1] as $id ) {
    440                 if ( $id > $highest_id )
    441                     $highest_id = $id;
    442             }
    443 
    444             // Parse out the list of user mappings, and add it to the known list
    445             preg_match_all( '|<usermap id=\'(\d+)\' user=\'([^\']+)\' />|', $results, $matches );
    446             foreach ( $matches[1] as $count => $userid )
    447                 $this->usermap[$userid] = $matches[2][$count]; // need this in memory for translating ids => names
    448                
    449             update_option( 'ljapi_usermap',    $this->usermap );
    450             update_option( 'ljapi_maxid',      $maxid );
    451             update_option( 'ljapi_highest_id', $highest_id );
    452         }
    453         // endwhile - should have seen all comment meta at this point
    454        
    455        
    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        
    502         return true;
    503     }
    504    
    505     function parse_comment_xml( $xml_file ) {
    506         if ( !is_file( $xml_file ) || !is_readable( $xml_file ) )
    507             return new WP_Error( 'file', sprintf( __( 'Could not access comment XML file: %s'), $filename ) );
    508            
    509         // Get content from file
    510         $xml = @file_get_contents( $xml_file );
    511 
    512         $cache_files = get_option( 'ljapi_comment_cache_files' );
    513         if ( !is_array( $cache_files ) )
    514             $cache_files = array();
    515        
    516         // Parse XML into comments
    517         preg_match_all( '|<comment id.*</comment>|iUs', $xml, $matches );
    518         unset( $xml );
    519         for ( $c = 0; $c < count( $matches[0] ); $c++ ) {
    520             $comment = $matches[0][$c];
    521            
    522             // Filter out any captured, deleted comments (nothing useful to import)
    523             $comment = preg_replace( '|<comment id=\'\d+\' jitemid=\'\d+\' posterid=\'\d+\' state=\'D\'[^/]*/>|is', '', $comment );
    524            
    525             // Parse this comment into an array
    526             $comment = $this->parse_comment( $comment );
    527             if ( empty( $comment['comment_post_ID'] ) )
    528                 continue;
    529            
    530             // Add this comment to the appropriate cache file
    531             $filename = $this->full_path( 'ljimport-comments-' . $comment['comment_post_ID'] . '.php' );
    532             if ( $this->write_file( '<?php $comments[] = ' . var_export( $comment, true ) . '; ?>' . "\n",
    533                                 $filename,
    534                                 $comment['comment_post_ID'],
    535                                 'a' ) )
    536             {
    537                 // Keep track of files used
    538                 $cache_files[] = $filename;
    539             }
    540         }
    541        
    542         // Update list of files in the DB
    543         sort( $cache_files );
    544         $cache_files = array_unique( $cache_files );
    545         update_option( 'ljapi_comment_cache_files', $cache_files );
    546         update_option( 'ljapi_comment_cache_files_count', count( $cache_files ) );
    547         $this->close_file_pointers();
    548        
    549         // Don't need this XML file anymore
    550         unlink( $xml_file );
    551        
    552         return true;
    553     }
    554    
    555     function parse_comment( $comment ) {
    556         global $wpdb;
    557        
    558         // Get the top-level attributes
    559         preg_match( '|<comment([^>]+)>|i', $comment, $attribs );
    560         preg_match( '| id=\'(\d+)\'|i', $attribs[1], $matches );
    561         $lj_comment_ID = $matches[1];
    562         preg_match( '| jitemid=\'(\d+)\'|i', $attribs[1], $matches );
    563         $lj_comment_post_ID = $matches[1];
    564         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';
    570        
    571         // Clean up "subject" - this will become the first line of the comment in WP
    572         preg_match( '|<subject>(.*)</subject>|is', $comment, $matches );
    573         $comment_subject = $wpdb->escape( trim( $matches[1] ) );
    574         if ( 'Re:' == $comment_subject )
    575             $comment_subject = '';
    576        
    577         // Get the body and HTMLize it
    578         preg_match( '|<body>(.*)</body>|is', $comment, $matches );
    579         $comment_content = !empty( $comment_subject ) ? $comment_subject . "\n\n" . $matches[1] : $matches[1];
    580         $comment_content = html_entity_decode( $comment_content );
    581         $comment_content = str_replace( '&apos;', "'", $comment_content );
    582         $comment_content = wpautop( $comment_content );
    583         $comment_content = str_replace( '<br>', '<br />', $comment_content );
    584         $comment_content = str_replace( '<hr>', '<hr />', $comment_content );
    585         $comment_content = preg_replace_callback( '|<(/?[A-Z]+)|', create_function( '$match', 'return "<" . strtolower( $match[1] );' ), $comment_content );
    586         $comment_content = $wpdb->escape( trim( $comment_content ) );
    587        
    588         // Get and convert the date
    589         preg_match( '|<date>(.*)</date>|i', $comment, $matches );
    590         $comment_date = trim( str_replace( array( 'T', 'Z' ), ' ', $matches[1] ) );
    591        
    592         // Grab IP if available
    593         preg_match( '|<property name=\'poster_ip\'>(.*)</property>|i', $comment, $matches );
    594         $comment_author_IP = $matches[1];
    595        
    596         // 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];
    598         if ( get_option( 'ljapi_username' ) == $author ) {
    599             $user    = wp_get_current_user();
    600             $user_id = $user->ID;
    601             $author  = $user->display_name;
    602             $url     = trailingslashit( get_option( 'home' ) );
    603         } else {
    604             $user_id = 0;
    605             $url     = ( __( 'Anonymous' ) == $author ) ? '' : 'http://' . $author . '.livejournal.com/';           
    606         }
    607        
    608         // Send back the array of details
    609         return array( 'lj_comment_ID' => $lj_comment_ID,
    610                         'lj_comment_post_ID' => $lj_comment_post_ID,
    611                         'lj_comment_parent' => ( !empty( $lj_comment_parent ) ? $lj_comment_parent : 0 ),
    612                         'lj_comment_state' => $lj_comment_state,
    613                         'comment_post_ID' => $this->get_wp_post_ID( $lj_comment_post_ID ),
    614                         'comment_author' => $author,
    615                         'comment_author_url' => $url,
    616                         'comment_content' => $comment_content,
    617                         'comment_date' => $comment_date,
    618                         'comment_author_IP' => ( !empty( $comment_author_IP ) ? $comment_author_IP : '' ),
    619                         'comment_approved' => ( in_array( $lj_comment_state, array( 'A', 'F' ) ) ? 1 : 0 ),
    620                         'comment_agent' => 'WP LJ Importer',
    621                         'user_id' => $user_id
    622                         );
    623     }
    624    
    625    
    626     // Gets the post_ID that a LJ post has been saved as within WP
    627     function get_wp_post_ID( $post ) {
    628         global $wpdb;
    629         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 ) );
    631         return $this->postmap[$post];
    632     }
    633    
    634     // Re-build the threading within a single cache file
    635     function thread_comments( $filename ) {
    636         if ( !is_file( $filename ) || !is_readable( $filename ) )
    637             return new WP_Error( 'File', __( sprintf( 'Cannot access file %s', $filename ) ) );
    638        
    639         $comments = array();
    640         @include( $filename );
    641         $this->comments = $comments;
    642         unset( $comments );
    643         if ( !is_array( $this->comments ) )
    644             $this->comments = array();
    645            
    646         $count = count( $this->comments );
    647         for ( $c = 0; $c < $count; $c++ ) {
    648             // Skip anything that's not "top-level" for now
    649             if ( 0 != $this->comments[$c]['lj_comment_parent'] )
    650                 continue;
    651             $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] );
    652         }
    653        
    654         // Remove anything that's not supposed to be at top level
    655         $top_comments = array();
    656         for ( $c = 0; $c < $count; $c++ ) {
    657             if ( 0 == $this->comments[$c]['lj_comment_parent'] ) {
    658                 $top_comments[] = $this->comments[$c];
    659             }
    660         }
    661        
    662         // Write back to file
    663         @unlink( $filename );
    664         $this->write_file( '<?php $comments = ' . var_export( $top_comments, true ) . '; ?>', $filename, $count, 'w' );
    665         unset( $top_comments );
    666         $this->close_file_pointers();
    667        
    668         // Reference this file as being threaded
    669         $files = get_option( 'ljapi_comment_threaded_files' );
    670         $files[] = $filename;
    671         array_unique( $files );
    672         update_option( 'ljapi_comment_threaded_files', $files );
    673         update_option( 'ljapi_comment_threaded_files_count', count( $files ) );
    674        
    675         return true;
    676     }
    677    
    678     function get_child_comments( $id ) {
    679         $children = array();
    680         $count = count( $this->comments );
    681         for ( $c = 0; $c < $count; $c++ ) {
    682             // This comment is a child of the $id
    683             if ( $id == $this->comments[$c]['lj_comment_parent'] ) {
    684                 $this->comments[$c]['children'] = $this->get_child_comments( $this->comments[$c]['lj_comment_ID'] );
    685                 $children[] = $this->comments[$c];
    686             }
    687         }
    688         return $children;
    689     }
    690    
    691     // Inserts the contents of each cache file (should be threaded already)
    692     function insert_comments( $filename ) {
    693         echo '<ol>';
    694 
    695         if ( !is_file( $filename ) || !is_readable( $filename ) )
    696             return new WP_Error( 'File', __( sprintf( 'Cannot access file %s', $filename ) ) );
    697        
    698         $comments = array();
    699         @include( $filename );
    700         $this->comments = $comments;
    701         unset( $comments );
    702         if ( !is_array( $this->comments ) )
    703             $this->comments = array();
    704            
    705         $count = count( $this->comments );
    706         for ( $c = 0; $c < $count; $c++ ) {
    707             $comment =& $this->comments[$c];
    708             echo '<li>';
    709             printf( __( 'Imported comment from <strong>%s</strong> on %s' ), $comment['comment_author'], $comment['comment_date'] );
    710 
    711             $id = wp_insert_comment( $comment );
    712             $comment['comment_ID'] = $id;
    713             if ( count( $comment['children'] ) ) {
    714                 _e( ' and replies:' );
    715                 $this->insert_child_comments( $comment['children'], $id );
    716             }
    717            
    718             echo '</li>';
    719         }
    720        
    721         // Remove the file now that we're done with it
    722         @unlink( $filename );
    723 
    724         echo '</ol>';
    725        
    726         return true;
    727     }
    728    
    729     function insert_child_comments( &$comments, $parent ) {
    730         echo '<ol>';
    731         $count = count( $comments );
    732         for ( $c = 0; $c < $count; $c++ ) {
    733             $comment =& $comments[$c];
    734             $comment['comment_parent'] = $parent;
    735             echo '<li>';
    736             printf( __( 'Imported reply from <strong>%s</strong> on %s' ), $comment['comment_author'], $comment['comment_date'] );
    737 
    738             $id = wp_insert_comment( $comment );
    739             $comment['comment_ID'] = $id;
    740             if ( count( $comment['children'] ) ) {
    741                 _e( ' and replies:' );
    742                 $this->insert_child_comments( $comment['children'], $id );
    743             }
    744            
    745139            echo '</li>';
    746140        }
    747141        echo '</ol>';
    748142    }
    749            
    750     function lj_ixr() {
    751         if ( $challenge = $this->ixr->query( 'LJ.XMLRPC.getchallenge' ) ) {
    752             $challenge = $this->ixr->getResponse();
     143
     144    function import() {
     145        $file = wp_import_handle_upload();
     146        if ( isset($file['error']) ) {
     147            echo $file['error'];
     148            return;
    753149        }
    754         if ( isset( $challenge['challenge'] ) ) {
    755             $params = array( 'username' => $this->username,
    756                             'auth_method' => 'challenge',
    757                             'auth_challenge' => $challenge['challenge'],
    758                             'auth_response' => md5( $challenge['challenge'] . md5( $this->password ) ) );
    759         } else {
    760             return new WP_Error( 'IXR', __( 'LiveJournal does not appear to be responding right now. Please try again later.' ) );
    761         }
    762        
    763         $args = func_get_args();
    764         $method = array_shift( $args );
    765         if ( isset( $args[0] ) )
    766             $params = array_merge( $params, $args[0] );
    767         if ( $this->ixr->query( 'LJ.XMLRPC.' . $method, $params ) ) {
    768             return $this->ixr->getResponse();
    769         } else {
    770             $this->log( $this->ixr->message, 'ljimport-error-' . $method . '.txt' );
    771             return new WP_Error( 'IXR', __( 'XML-RPC Request Failed - ' ) . $this->ixr->getErrorCode() . ': ' . $this->ixr->getErrorMessage() );
    772         }
     150
     151        $this->file = $file['file'];
     152        $result = $this->import_posts();
     153        if ( is_wp_error( $result ) )
     154            return $result;
     155        wp_import_cleanup($file['id']);
     156        do_action('import_done', 'livejournal');
     157
     158        echo '<h3>';
     159        printf(__('All done. <a href="%s">Have fun!</a>'), get_option('home'));
     160        echo '</h3>';
    773161    }
    774    
     162
    775163    function dispatch() {
    776         if ( empty( $_REQUEST['step'] ) )
     164        if (empty ($_GET['step']))
    777165            $step = 0;
    778166        else
    779             $step = (int) $_REQUEST['step'];
     167            $step = (int) $_GET['step'];
    780168
    781169        $this->header();
    782        
    783         switch ( $step ) {
    784             case -1 :
    785                 $this->cleanup();
    786                 // Intentional no break
     170
     171        switch ($step) {
    787172            case 0 :
    788173                $this->greet();
    789174                break;
    790175            case 1 :
    791             case 2 :
    792                 $this->ixr = new IXR_Client( $this->ixr_url );
    793                 // Intentional no break
    794             case 3 :
    795             case 4 :
    796             case 5 :
    797                 check_admin_referer( 'lj-api-import' );
    798                 $result = $this->{ 'step' . $step }();
     176                check_admin_referer('import-upload');
     177                $result = $this->import();
    799178                if ( is_wp_error( $result ) )
    800179                    echo $result->get_error_message();
     
    805184    }
    806185
    807     // Check form inputs and start importing posts
    808     function step1() {
    809         // Get details from form or from DB
    810         if ( !empty( $_POST['lj_username'] ) && !empty( $_POST['lj_password'] ) ) {
    811             // Store details for later
    812             $this->username = $_POST['lj_username'];
    813             $this->password = $_POST['lj_password'];
    814             update_option( 'ljapi_username', $this->username );
    815             update_option( 'ljapi_password', $this->password );
    816         } else {
    817             $this->username = get_option( 'ljapi_username' );
    818             $this->password = get_option( 'ljapi_password' );
    819         }
    820    
    821         // This is the password to set on protected posts
    822         if ( !empty( $_POST['protected_password'] ) ) {
    823             $this->protected_password = $_POST['protected_password'];
    824             update_option( 'ljapi_protected_password', $this->protected_password );
    825         } else {
    826             $this->protected_password = get_option( 'ljapi_protected_password' );
    827         }
    828        
    829         // Login to confirm the details are correct
    830         if ( empty( $this->username ) || empty( $this->password ) ) {
    831             ?>
    832             <p><?php _e( 'Please enter your LiveJournal username <em>and</em> password so we can download your posts and comments.' ) ?></p>
    833             <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>
    834             <?php
    835             return;
    836         }
    837         $login = $this->lj_ixr( 'login' );
    838         if ( is_wp_error( $login ) ) {
    839             if ( 100 == $this->ixr->getErrorCode() || 101 == $this->ixr->getErrorCode() ) {
    840                 ?>
    841                 <p><?php _e( 'Logging in to LiveJournal failed. Check your username and password and try again.' ) ?></p>
    842                 <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>
    843                 <?php
    844                 return;
    845             } else {
    846                 return $login;
    847             }
    848         }
    849        
    850         // 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' );
    856        
    857         echo '<h3>' . __( 'Importing Posts' ) . '</h3>';
    858         echo '<p>' . __( "We're downloading and importing all your LiveJournal posts..." ) . '</p>';
    859         ob_flush(); flush();
    860        
    861         // Now do the grunt work
    862         set_time_limit( 0 );
    863         $result = $this->import_posts();
    864         if ( is_wp_error( $result ) ) {
    865             if ( 406 == $this->ixr->getErrorCode() ) {
    866                 ?>
    867                 <p><strong><?php _e( 'Uh oh &ndash; LiveJournal has disconnected us because we made too many requests to their servers too quickly.' ) ?></strong></p>
    868                 <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>
    869                 <?php
    870                 return;
    871             } else {
    872                 return $result;
    873             }
    874         }
    875        
    876         echo '<p>' . __( "Your posts have all been imported, but wait - there's more! Now we need to process &amp; import your comments." ) . '</p>';
    877         echo $this->next_step( 2, __( 'Download my comments &raquo;' ) );
    878         $this->auto_submit();
    879     }
    880    
    881     // Download comments to local XML
    882     function step2() {
    883         set_time_limit( 0 );
    884         update_option( 'ljapi_step', 2 );
    885         $this->username = get_option( 'ljapi_username' );
    886         $this->password = get_option( 'ljapi_password' );
    887        
    888         echo '<h3>' . __( 'Downloading Comments' ) . '</h3>';
    889         echo '<p>' . __( 'Now we will download your comments so we can process and import them...' ) . '</p>';
    890         ob_flush(); flush();
    891        
    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 );
    919             if ( is_wp_error( $result ) )
    920                 return $result;
    921 
    922             update_option( 'ljapi_comment_xml_files', $files );
    923         }
    924        
    925         if ( count( $files ) ) {
    926             ?>
    927                 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost">
    928                 <p><strong><?php printf( __( 'Processed comment file %d of %d' ), ( get_option( 'ljapi_comment_xml_files_count' ) - count( $files ) ), get_option( 'ljapi_comment_xml_files_count' ) ) ?></strong></p>
    929                 <?php wp_nonce_field( 'lj-api-import' ) ?>
    930                 <input type="hidden" name="step" id="step" value="3" />
    931                 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Process the next comment file &raquo;' ) ) ?>" /> <span id="auto-message"></span></p>
    932                 </form>
    933                 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?>
    934             <?php
    935         } 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;' ) );
    938             $this->auto_submit();
    939         }
    940         echo '</div>';
    941     }
    942 
    943     // Thread comments within their cache files
    944     function step4() {
    945         set_time_limit( 0 );
    946         update_option( 'ljapi_step', 4 );
    947        
    948         echo '<div id="ljapi-status">';
    949         echo '<h3>' . __( 'Threading Comments' ) . '</h3>';
    950         echo '<p>' . __( 'Re-building your conversation threads ready for import...' ) . '</p>';
    951         ob_flush(); flush();
    952        
    953         $files = get_option( 'ljapi_comment_cache_files' );
    954         if ( count( $files ) ) {
    955             $file = array_pop( $files );
    956        
    957             $result = $this->thread_comments( $file );
    958             if ( is_wp_error( $result ) )
    959                 return $result;
    960            
    961             update_option( 'ljapi_comment_cache_files', $files );
    962         }
    963        
    964         if ( count( $files ) ) {
    965             ?>
    966                 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost">
    967                 <p><strong><?php printf( __( 'Threaded cache file %d of %d' ), ( get_option( 'ljapi_comment_cache_files_count' ) - count( $files ) ), get_option( 'ljapi_comment_cache_files_count' ) ) ?></strong></p>
    968                 <?php wp_nonce_field( 'lj-api-import' ) ?>
    969                 <input type="hidden" name="step" id="step" value="4" />
    970                 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Thread the next cache file &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();
    979         }
    980         echo '</div>';
    981     }
    982 
    983     // Import comments from cache files into WP
    984     function step5() {
    985         set_time_limit( 0 );
    986         update_option( 'ljapi_step', 5 );
    987        
    988        
    989         echo '<div id="ljapi-status">';
    990         echo '<h3>' . __( 'Importing Comments' ) . '</h3>';
    991         echo '<p>' . __( 'This is the big one -- we are now inserting your comment threads into WordPress...' ) . '</p>';
    992        
    993         $files = get_option( 'ljapi_comment_threaded_files' );
    994         echo '<p><strong>' . sprintf( __( 'Importing cache file %d of %d' ), ( get_option( 'ljapi_comment_threaded_files_count' ) - count( $files ) + 1 ), get_option( 'ljapi_comment_threaded_files_count' ) ) . '</strong></p>';
    995         ob_flush(); flush();
    996        
    997         if ( count( $files ) ) {
    998             $file = array_pop( $files );
    999        
    1000             $result = $this->insert_comments( $file );
    1001             if ( is_wp_error( $result ) )
    1002                 return $result;
    1003            
    1004             update_option( 'ljapi_comment_threaded_files', $files );
    1005         }
    1006        
    1007         if ( count( $files ) ) {
    1008             ?>
    1009                 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost">
    1010                 <?php wp_nonce_field( 'lj-api-import' ) ?>
    1011                 <input type="hidden" name="step" id="step" value="5" />
    1012                 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Import the next cache file &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         }
    1024         echo '</div>';
    1025     }
    1026    
    1027     // Returns the HTML for a link to the next page
    1028     function next_step( $next_step, $label, $id = 'ljapi-next-form' ) {
    1029         $str  = '<form action="admin.php?import=livejournal" method="post" id="' . $id . '">';
    1030         $str .= wp_nonce_field( 'lj-api-import', '_wpnonce', true, false );
    1031         $str .= wp_referer_field( false );
    1032         $str .= '<input type="hidden" name="step" id="step" value="' . $next_step . '" />';
    1033         $str .= '<p><input type="submit" class="button-primary" value="' . attribute_escape( $label ) . '" /> <span id="auto-message"></span></p>';
    1034         $str .= '</form>';
    1035        
    1036         return $str;
    1037     }
    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 ) {
    1043         ?><script type="text/javascript">
    1044             next_counter = <?php echo $seconds ?>;
    1045             jQuery(document).ready(function(){
    1046                 ljapi_msg();
    1047             });
    1048            
    1049             function ljapi_msg() {
    1050                 str = '<?php _e( "Continuing in %d" ) ?>';
    1051                 jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) );
    1052                 if ( next_counter <= 0 ) {
    1053                     if ( jQuery( '#<?php echo $id ?>' ).length ) {
    1054                         jQuery( "#<?php echo $id ?> input[type='submit']" ).hide();
    1055                         jQuery.ajaxSetup({'timeout':3600000});
    1056                         str = '<?php _e( "Processing next file." ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />';
    1057                         jQuery( '#<?php echo $msg ?>' ).html( str );
    1058                         jQuery('#ljapi-status').load(ajaxurl, {'action':'lj-importer',
    1059                                                                 'step':jQuery('#step').val(),
    1060                                                                 '_wpnonce':'<?php echo wp_create_nonce( 'lj-api-import' ) ?>',
    1061                                                                 '_wp_http_referer':'<?php echo $_SERVER['REQUEST_URI'] ?>'});
    1062                         return;
    1063                     }
    1064                 }
    1065                 next_counter = next_counter - 1;
    1066                 setTimeout('ljapi_msg()', 1000);
    1067             }
    1068         </script><?php
    1069     }
    1070    
    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 ) {
    1074         ?><script type="text/javascript">
    1075             next_counter = <?php echo $seconds ?>;
    1076             jQuery(document).ready(function(){
    1077                 ljapi_msg();
    1078             });
    1079            
    1080             function ljapi_msg() {
    1081                 str = '<?php _e( "Continuing in %d" ) ?>';
    1082                 jQuery( '#<?php echo $msg ?>' ).text( str.replace( /%d/, next_counter ) );
    1083                 if ( next_counter <= 0 ) {
    1084                     if ( jQuery( '#<?php echo $id ?>' ).length ) {
    1085                         jQuery( "#<?php echo $id ?> input[type='submit']" ).hide();
    1086                         str = '<?php _e( "Continuing" ) ?> <img src="images/loading-publish.gif" alt="" id="processing" align="top" />';
    1087                         jQuery( '#<?php echo $msg ?>' ).html( str );
    1088                         jQuery( '#<?php echo $id ?>' ).submit();
    1089                         return;
    1090                     }
    1091                 }
    1092                 next_counter = next_counter - 1;
    1093                 setTimeout('ljapi_msg()', 1000);
    1094             }
    1095         </script><?php
    1096     }
    1097 
    1098     // Remove all options used during import process
    1099     function cleanup() {
    1100         delete_option( 'ljapi_username' );
    1101         delete_option( 'ljapi_password' );
    1102         delete_option( 'ljapi_protected_password' );
    1103         delete_option( 'ljapi_total' );
    1104         delete_option( 'ljapi_count' );
    1105         delete_option( 'ljapi_lastsync' );
    1106         delete_option( 'ljapi_last_sync_count' );
    1107         delete_option( 'ljapi_sync_item_times' );
    1108         delete_option( 'ljapi_lastsync_posts' );
    1109         delete_option( 'ljapi_imported_count' );
    1110         delete_option( 'ljapi_maxid' );
    1111         delete_option( 'ljapi_usermap' );
    1112         delete_option( 'ljapi_highest_id' );
    1113         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' );
    1120         delete_option( 'ljapi_step' );
    1121     }
    1122    
    1123     // Dump a string to a log file (appends to existing file)
    1124     function log( $string, $name ) {
    1125         return; // remove this to enable "debugging" output to files in /wp-content/ljimport
    1126         $path = wp_upload_dir();
    1127         $path = $path['path'];
    1128         if ( get_option( 'uploads_use_yearmonth_folders' ) )
    1129             $path = substr( $path, 0, -8 );
    1130 
    1131         if ( !is_dir( $path . '/ljimport' ) )
    1132             mkdir( $path . '/ljimport' );
    1133            
    1134         $fh = @fopen( $path . '/ljimport/' . $name, 'a' );
    1135         if ( $fh ) {
    1136             if ( is_array( $string ) || is_object( $string ) )
    1137                 fwrite( $fh, var_export( $string, true ) . "\n\n" );
    1138             else
    1139                 fwrite( $fh, $string . "\n\n" );
    1140             fclose( $fh );
    1141         }
    1142     }
    1143    
    1144     function write_file( $data, $name, $id, $mode = 'a' ) {
    1145         if ( empty( $this->pointers[$id] ) )
    1146             $this->pointers[$id] = @fopen( $name, $mode );
    1147         if ( $this->pointers[$id] )
    1148             return fwrite( $this->pointers[$id], $data );
    1149         return false;
    1150     }
    1151    
    1152     function full_path( $basename ) {
    1153         $uploads = wp_upload_dir();
    1154         return $uploads['path'] . '/' . $basename;
    1155     }
    1156    
    1157     function close_file_pointers() {
    1158         foreach ( $this->pointers as $p )
    1159             @fclose( $p );
    1160     }
    1161 
    1162     function LJ_API_Import() {
    1163         $this->__construct();
    1164     }
    1165    
    1166     function __construct() {
    1167         // Nothing
     186    function LJ_Import() {
     187        // Nothing.
    1168188    }
    1169189}
    1170190
    1171 $lj_api_import = new LJ_API_Import();
     191$livejournal_import = new LJ_Import();
    1172192
    1173 register_importer( 'livejournal', __( 'LiveJournal' ), __( 'Import posts from LiveJournal using their API.' ), array( $lj_api_import, 'dispatch' ) );
     193register_importer('livejournal', __('LiveJournal'), __('Import posts from a LiveJournal XML export file.'), array ($livejournal_import, 'dispatch'));
    1174194?>
Note: See TracChangeset for help on using the changeset viewer.