Changeset 10499 for trunk/wp-admin/import/livejournal.php
- Timestamp:
- 02/04/2009 05:47:50 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-admin/import/livejournal.php
r10492 r10499 1 1 <?php 2 2 /** 3 * LiveJournal APIImporter3 * LiveJournal Importer 4 4 * 5 5 * @package WordPress … … 7 7 */ 8 8 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 */ 16 class LJ_Import { 11 17 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; 169 19 170 20 function header() { 171 21 echo '<div class="wrap">'; 172 22 screen_icon(); 173 echo '<h2>' . __( 'Import LiveJournal' ) .'</h2>';23 echo '<h2>'.__('Import LiveJournal').'</h2>'; 174 24 } 175 25 … … 178 28 } 179 29 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 180 36 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&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( $_SERVER['REQUEST_URI'] ) ?>"><?php _e( 'Cancel & start a new import' ) ?></a></p> 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’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&step=1"); 41 echo '</div>'; 42 } 199 43 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; 204 46 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); 216 51 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 } 221 64 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); 223 68 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; 262 95 } 263 96 } 264 97 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 } 297 133 } 298 update_option( 'ljapi_lastsync_posts', $lastsync );299 update_option( 'ljapi_imported_count', $imported_count );300 update_option( 'ljapi_last_sync_count', $num );301 134 } 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); 365 138 } 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 post371 $this->insert_postmeta( $post_id, $post );372 }373 echo '</li>';374 }375 376 // Convert lj-user tags to links to that user377 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 comments383 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 something386 add_post_meta( $post_id, 'lj_permalink', $post['url'] );387 388 // Supports the following "props" from LJ, saved as lj_<prop_name> in wp_postmeta389 // Adult Content - adult_content390 // Location - current_coords + current_location391 // Mood - current_mood (translated from current_moodid)392 // Music - current_music393 // Userpic - picture_keyword394 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 batches408 // Writes raw XML files to disk for later processing409 function download_comments() {410 // Get a session via XMLRPC411 $cookie = $this->lj_ixr( 'sessiongenerate', array( 'ver' => 1, 'expiration' => 'short' ) );412 413 // Comment Meta414 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 cookie421 $this->snoop = new Snoopy();422 $this->snoop->cookies = $cookie;423 424 // We need to loop over the metadata request until we have it all425 while ( $maxid > $highest_id ) {426 // Now get the meta listing427 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 yet434 preg_match( '|<maxid>(\d+)</maxid>|', $results, $matches );435 $maxid = !empty( $matches[1] ) ? $matches[1] : $maxid;436 437 // Parse comments and get highest id available438 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 list445 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 => names448 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 point454 455 456 // Download Comment XML457 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 all469 while ( $maxid > $highest_id ) {470 // Get a batch of comments, using the highest_id we've already got as a starting point471 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 stored483 $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 allowed486 $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 processing499 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 file510 $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 comments517 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 array526 $comment = $this->parse_comment( $comment );527 if ( empty( $comment['comment_post_ID'] ) )528 continue;529 530 // Add this comment to the appropriate cache file531 $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 used538 $cache_files[] = $filename;539 }540 }541 542 // Update list of files in the DB543 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 anymore550 unlink( $xml_file );551 552 return true;553 }554 555 function parse_comment( $comment ) {556 global $wpdb;557 558 // Get the top-level attributes559 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 WP572 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 it578 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( ''', "'", $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 date589 preg_match( '|<date>(.*)</date>|i', $comment, $matches );590 $comment_date = trim( str_replace( array( 'T', 'Z' ), ' ', $matches[1] ) );591 592 // Grab IP if available593 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" comment597 $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 details609 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_id622 );623 }624 625 626 // Gets the post_ID that a LJ post has been saved as within WP627 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 file635 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 now649 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 level655 $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 file663 @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 threaded669 $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 $id683 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 it722 @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 139 echo '</li>'; 746 140 } 747 141 echo '</ol>'; 748 142 } 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; 753 149 } 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>'; 773 161 } 774 162 775 163 function dispatch() { 776 if ( empty( $_REQUEST['step'] ))164 if (empty ($_GET['step'])) 777 165 $step = 0; 778 166 else 779 $step = (int) $_ REQUEST['step'];167 $step = (int) $_GET['step']; 780 168 781 169 $this->header(); 782 783 switch ( $step ) { 784 case -1 : 785 $this->cleanup(); 786 // Intentional no break 170 171 switch ($step) { 787 172 case 0 : 788 173 $this->greet(); 789 174 break; 790 175 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(); 799 178 if ( is_wp_error( $result ) ) 800 179 echo $result->get_error_message(); … … 805 184 } 806 185 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&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( str_replace( '&step=1', '', $_SERVER['REQUEST_URI'] ) ) ?>"><?php _e( 'Start again' ) ?></a></p> 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&step=-1&_wpnonce=' . wp_create_nonce( 'lj-api-import' ) . '&_wp_http_referer=' . attribute_escape( str_replace( '&step=1', '', $_SERVER['REQUEST_URI'] ) ) ?>"><?php _e( 'Start again' ) ?></a></p> 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 – 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 & import your comments." ) . '</p>'; 877 echo $this->next_step( 2, __( 'Download my comments »' ) ); 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 »' ) ); 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 »' ) ) ?>" /> <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 »' ) ); 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 »' ) ) ?>" /> <span id="auto-message"></span></p> 971 </form> 972 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 973 <?php 974 } else { 975 echo '<p>' . __( "Alrighty, your comments are all threaded. There's just one last step -- time to actually import them all now!" ) . '</p>'; 976 echo '<p>' . __( 'This last part in particular can take a really long time if you have a lot of comments. You might want to go and do something else while you wait.' ) . '</p>'; 977 echo $this->next_step( 5, __( 'Import my threaded comments into WordPress »' ) ); 978 $this->auto_submit(); 979 } 980 echo '</div>'; 981 } 982 983 // Import comments from cache files into WP 984 function step5() { 985 set_time_limit( 0 ); 986 update_option( 'ljapi_step', 5 ); 987 988 989 echo '<div id="ljapi-status">'; 990 echo '<h3>' . __( 'Importing Comments' ) . '</h3>'; 991 echo '<p>' . __( 'This is the big one -- we are now inserting your comment threads into WordPress...' ) . '</p>'; 992 993 $files = get_option( 'ljapi_comment_threaded_files' ); 994 echo '<p><strong>' . sprintf( __( 'Importing cache file %d of %d' ), ( get_option( 'ljapi_comment_threaded_files_count' ) - count( $files ) + 1 ), get_option( 'ljapi_comment_threaded_files_count' ) ) . '</strong></p>'; 995 ob_flush(); flush(); 996 997 if ( count( $files ) ) { 998 $file = array_pop( $files ); 999 1000 $result = $this->insert_comments( $file ); 1001 if ( is_wp_error( $result ) ) 1002 return $result; 1003 1004 update_option( 'ljapi_comment_threaded_files', $files ); 1005 } 1006 1007 if ( count( $files ) ) { 1008 ?> 1009 <form action="admin.php?import=livejournal" method="post" id="ljapi-auto-repost"> 1010 <?php wp_nonce_field( 'lj-api-import' ) ?> 1011 <input type="hidden" name="step" id="step" value="5" /> 1012 <p><input type="submit" class="button-primary" value="<?php echo attribute_escape( __( 'Import the next cache file »' ) ) ?>" /> <span id="auto-message"></span></p> 1013 </form> 1014 <?php $this->auto_ajax( 'ljapi-auto-repost', 'auto-message', 0 ); ?> 1015 <?php 1016 } else { 1017 // Clean up database and we're out 1018 $this->cleanup(); 1019 do_action( 'import_done', 'livejournal' ); 1020 echo '<h3>'; 1021 printf( __( 'All done. <a href="%s">Have fun!</a>' ), get_option( 'home' ) ); 1022 echo '</h3>'; 1023 } 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. 1168 188 } 1169 189 } 1170 190 1171 $l j_api_import = new LJ_API_Import();191 $livejournal_import = new LJ_Import(); 1172 192 1173 register_importer( 'livejournal', __( 'LiveJournal' ), __( 'Import posts from LiveJournal using their API.' ), array( $lj_api_import, 'dispatch' ));193 register_importer('livejournal', __('LiveJournal'), __('Import posts from a LiveJournal XML export file.'), array ($livejournal_import, 'dispatch')); 1174 194 ?>
Note: See TracChangeset
for help on using the changeset viewer.