WordPress.org

Make WordPress Core

Ticket #7543: atompub-importer.diff

File atompub-importer.diff, 49.9 KB (added by cavemonkey50, 10 years ago)

Current AtomPub importer work as of 8/18/08.

  • wp-admin/import/typepad.php

     
     1<?php
     2
     3class Typepad_Import {
     4       
     5        // General
     6        var $username;
     7        var $password;
     8       
     9        // XML parsing
     10        var $parser;
     11        var $inside_tag = '';
     12        var $active_tag = '';
     13        var $entry_tag = '';
     14        var $last = '';
     15        var $start_byte = '';
     16        var $first_child = 0;
     17        var $inside_entry = 0;
     18        var $channel = array();
     19        var $items = array();
     20        var $item = array();
     21       
     22        // The data
     23        var $posts = array();
     24        var $site_url;
     25        var $next_url;
     26        var $xmlrpc_url;
     27        var $post_count = 0;
     28        var $current_post = 0;
     29        var $first_run = true;
     30       
     31        function header() {
     32                echo '<div class="wrap">';
     33                echo '<h2>'.__('Import TypePad').'</h2>';
     34        }
     35
     36        function footer() {
     37                echo '</div>';
     38        }
     39
     40        function greet() {
     41                $this->header();
     42?>
     43<div class="narrow">
     44<p><?php _e('Howdy! We&#8217;re about to begin importing all of your TypePad entries into WordPress. To begin, enter the URL of your blog followed by the username and password of an administrator account. When you&#8217;re finished, click "Start Importing".'); ?></p>
     45
     46<form method="post" action="<?php echo add_query_arg('step', 1); ?>" class="import-upload-form">
     47
     48<?php wp_nonce_field('import-typepad'); ?>
     49<table class="form-table">
     50<tr>
     51<td><label for="mturl"><?php _e('Blog URL:') ?></label></td>
     52<td><input type="text" style="width:300px" name="mturl" id="mturl" value="http://" /></td>
     53</tr>
     54<tr>
     55<td><label for="mtuser"><?php _e('Username:') ?></label></td>
     56<td><input type="text" style="width:300px" name="mtuser" id="mtuser" value="" /></td>
     57</tr>
     58<tr>
     59<td><label for="mtpass"><?php _e("Password:") ?></label></td>
     60<td><input type="password" style="width:300px" name="mtpass" id="mtpass" value="" /></td>
     61</tr>
     62</table>
     63<p class="submit">
     64<input type="submit" value="<?php echo attribute_escape(__('Start Importing')); ?>" id="atom-submit" onclick="jQuery('#atom-loading').show();jQuery('#atom-submit').val('<?php echo attribute_escape(__('Importing...')); ?>');" /> <span style="display: none;" id="atom-loading"><img src="<?php echo get_option('home'); ?>/wp-admin/images/loading.gif" alt="Loading" style="margin-bottom: -3px;" /> <?php echo attribute_escape(__('Retrieving entries from server. Do not navigate away from this page.')); ?></span>
     65</p>
     66</form>
     67<p><?php _e('The importer is smart enough not to import duplicates, so you can run this multiple times without worry if&#8212;for whatever reason&#8212;it doesn\'t finish.'); ?> </p>
     68</div>
     69<?php
     70                $this->footer();
     71        }
     72               
     73        function detect_atom_uri($url) {
     74                // Grab the homepage
     75                $ch = curl_init();
     76                curl_setopt($ch, CURLOPT_URL, $url);
     77                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     78                curl_setopt($ch, CURLOPT_TIMEOUT, 5);
     79                $output = @curl_exec($ch);
     80               
     81                // Parse out the RSD URL
     82                preg_match('#<link rel="EditURI" type="application\/rsd\+xml" title="RSD" href="(.*)" \/>#i', $output, $matches);
     83               
     84                // Grab the RSD page
     85                $ch2 = curl_init();
     86                curl_setopt($ch2, CURLOPT_URL, $matches[1]);
     87                curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
     88                curl_setopt($ch2, CURLOPT_TIMEOUT, 5);
     89                $output = @curl_exec($ch2);
     90               
     91                // Parse out the xmlrpc URI
     92                preg_match('#<api name="MovableType" preferred="false" apiLink="([^"]*)" blogid="([^"]*)" \/>#i', $output, $xmlrpc);
     93                $this->xmlrpc_url = $xmlrpc[1];
     94               
     95                // Parse out the Atom URI
     96                preg_match('#<api name="Atom" preferred="false" apiLink="(.*)" \/>#i', $output, $matches);
     97               
     98                return $matches[1];
     99        }
     100       
     101        function fetch_atom($url, $username, $password) {
     102                include_once(ABSPATH . '/wp-admin/includes/class-atom-api.php');
     103               
     104                $atom_api = new AtomAPI($url, $username, $password, 'WSSE'); // Authenticate to the AtomPub feed using WSSE
     105                // If the login failed, throw an error message
     106                if ( ( $atom_api->err_no != '' ) && ( count($this->posts) == 0 ) ) {
     107                        $this->error();
     108                        return 'error';
     109                }
     110               
     111                 // Grab the raw feed data and pass it to the parser
     112                $this->parse_atom( $atom_api->get_feeds( $xml = false ) );
     113        }
     114       
     115        function parse_atom($xml) {
     116                // Reset the data before parsing a new feed
     117                unset($this->parser);
     118                unset($this->inside_tag);
     119                unset($this->active_tag);
     120                unset($this->channel);
     121                unset($this->items);
     122                unset($this->item);
     123                $this->inside_tag = '';
     124                $this->active_tag = '';
     125                $this->entry_tag = '';
     126                $this->last = '';
     127                $this->start_byte = '';
     128                $this->first_child = 0;
     129                $this->inside_entry = 0;
     130                $this->channel = array();
     131                $this->items = array();
     132                $this->item = array();
     133               
     134                // Create an XML parser
     135                $this->parser = xml_parser_create();
     136               
     137                // Used to make the XML parser work in a class
     138                xml_set_object($this->parser, $this);
     139               
     140                // Set the start and ending element functions           
     141                xml_set_element_handler($this->parser, "start_element", "end_element");
     142               
     143                // Set the character data functions
     144                xml_set_character_data_handler($this->parser, "character_data");
     145               
     146                // Begin parsing the XML
     147                xml_parse($this->parser, $xml)
     148                        or die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)));
     149               
     150                // Clean up after the parse
     151                xml_parser_free($this->parser);
     152        }
     153       
     154        function start_element($parser, $element, $attrs) {
     155                switch ($element) {
     156                        case 'FEED':
     157                        case 'ENTRY':
     158                                $this->inside_tag = $element;
     159                                break;
     160
     161                        case 'CONTENT':
     162                        case 'SUMMARY':
     163                                if ( $this->inside_tag == 'ENTRY' ) {
     164                                        $this->inside_entry = 1;
     165                                        $this->entry_tag = strtolower($element);
     166                                }
     167                                break;
     168
     169                        case 'LINK' :
     170                                if ( $this->inside_tag == 'FEED' ) {
     171                                        if ( $attrs['REL'] == 'alternate' || !$attrs['REL'] ) {
     172                                                $this->_add('channel', 'link', $attrs['HREF']);
     173                                        } elseif ( $attrs['REL'] == 'next' ) {
     174                                                $this->_add('channel', 'next', $attrs['HREF']);
     175                                        }
     176                                } elseif ( $this->inside_tag == 'ENTRY' ) {
     177                                        if ( $attrs['REL'] == 'alternate' || !$attrs['REL'] ) {
     178                                                if ( $attrs['TYPE'] == 'text/html' )
     179                                                        $this->_add('item', 'link', $attrs['HREF']);
     180                                        } elseif ( $attrs['REL'] == 'service.edit' ) {
     181                                                $this->_add('item', 'link:service.edit', $attrs['HREF']);
     182                                        } elseif ( $attrs['REL'] == 'replies' ) {
     183                                                $this->_add('item', 'link:entry.comments', $attrs['HREF']);
     184                                        }
     185                                } elseif ( $this->inside_tag != 'FEED' && $this->inside_tag != 'ENTRY' ) {
     186                                        if ( $attrs['REL'] == 'next' ) {
     187                                                $this->_add('channel', 'next', $attrs['HREF']);
     188                                        }
     189                                }
     190                                break;
     191                       
     192                        case 'CATEGORY':
     193                                if ( $this->inside_tag == 'ENTRY' ) {
     194                                        $cats = array ( 'type' => $attrs['SCHEME'], 'term' => $attrs["TERM"] );
     195                                        $this->_add('item', 'categories', $cats, 1);
     196                                }
     197                                break;
     198                       
     199                        case 'AUTHOR':
     200                                if ( $this->inside_tag == 'ENTRY' ) {
     201                                        $this->inside_tag = 'ENTRY|AUTHOR';
     202                                }
     203                                break;
     204                       
     205                        case 'ALLOW':
     206                                if ( $this->inside_tag == 'ENTRY' ) {
     207                                        $this->_add('item', 'privacy', $attrs['NAME']);
     208                                }
     209                                break;
     210
     211                        default :
     212                                $this->active_tag = $element;
     213                }
     214               
     215                // Deal with tags inside of content and summary
     216                if ( $this->inside_entry && $element != 'CONTENT' && $element != 'SUMMARY' ) {
     217                        // If tags are inlined, then flatten
     218                        $attrs = array_change_key_case($attrs, CASE_LOWER);
     219                        $attrs_str = implode(' ',
     220                                array_map(array($this, 'map_attrs'),
     221                                array_keys($attrs),
     222                                array_values($attrs) ) );
     223                               
     224                        // Add a space if there are attrs
     225                        if ( $attrs_str != '' )
     226                                $attrs_str = ' ' . $attrs_str;
     227                       
     228                        // Make the element lowercase
     229                        $el = strtolower($element);
     230                       
     231                        // Close an opening tag if it had no data
     232                        if ( $this->first_child )
     233                                $this->_add('item', $this->entry_tag, ">");
     234                       
     235                        // Add the start tag
     236                        $this->_add('item', $this->entry_tag, "<$el" . "$attrs_str");
     237                       
     238                        // Handle self-closing tags
     239                        $this->first_child = 1;
     240                        $this->start_byte = xml_get_current_byte_index($parser);
     241                }
     242        }
     243       
     244        function character_data($parser, $cdata) {
     245                switch ($this->inside_tag) {
     246                        // Grab general channel information
     247                        case 'FEED':
     248                                switch ($this->active_tag) {
     249                                        case 'TITLE':
     250                                                $this->_add('channel', strtolower($this->active_tag), $cdata);
     251                                                break;
     252                                        case 'OPENSEARCH:TOTALRESULTS':
     253                                                $this->_add('channel', strtolower('fullcount'), $cdata);
     254                                                break;
     255                                }
     256                                break;
     257
     258                        // Grab item information
     259                        case 'ENTRY':
     260                                switch ($this->active_tag) {
     261                                        case 'TITLE':
     262                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     263                                                break;
     264
     265                                        case 'CONTENT':
     266                                        case 'SUMMARY':
     267                                                $this->_add('item', $this->inside_tag, $cdata);
     268                                                break;
     269                                       
     270                                        case 'ISSUED':
     271                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     272                                                break;
     273                                       
     274                                        case 'ID':
     275                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     276                                                break;
     277                                }
     278                                break;
     279                       
     280                        // For author tags
     281                        case 'ENTRY|AUTHOR':
     282                                switch ($this->active_tag) {
     283                                        case 'NAME':
     284                                                $this->_add('item', 'author', $cdata);
     285                                                break;
     286                                        case 'URI':
     287                                                $this->_add('item', 'author_uri', $cdata);
     288                                                break;
     289                                }
     290                                break;
     291
     292                        }   
     293
     294                        // Deal with data inside content tags
     295                        if ( $this->inside_entry ) {
     296                                // Append the start tag close if first_child
     297                                if ( $this->first_child ) {
     298                                        $this->_add('item', $this->entry_tag, '>');
     299                                        $this->first_child = 0;
     300                                }
     301                               
     302                                $this->_add('item', $this->entry_tag, $cdata);
     303                        }
     304        }
     305       
     306        function end_element($parser, $element) {
     307                // Deal with tags inside of content and summary
     308                if ( $this->inside_entry && $element != 'CONTENT' && $element != 'SUMMARY' ) {
     309                        $el = strtolower($element);                     
     310                       
     311                        // Add the appropriate end tag depending if the element is a self-closing element
     312                        if ( xml_get_current_byte_index($parser) - $this->start_byte > 2 ) {
     313                                if ( $this->first_child )
     314                                        $this->_add('item', $this->entry_tag, ">");
     315                                $this->_add('item', $this->entry_tag, "</$el>");
     316                        } else {
     317                                $this->_add('item', $this->entry_tag, " />");
     318                        }
     319                        $this->first_child = 0;
     320                }
     321               
     322                // Reset inside tag back to entry for author tags
     323                if ( $element == 'AUTHOR' && $this->inside_tag == 'ENTRY|AUTHOR' ) {
     324                        $this->inside_tag = 'ENTRY';
     325                }
     326               
     327                if ( $element == $this->inside_tag ) {
     328                        $this->inside_tag = '';
     329                        $this->struct[] = array_merge(array('type' => strtolower($element)), $this->last);
     330                }
     331
     332                if ( $element == 'ENTRY' ) {
     333                        $this->items[] = $this->item;
     334                        $this->item = '';
     335                }
     336
     337                if ( $element == 'CONTENT' || $element == 'SUMMARY' ) {                 
     338                        $this->inside_entry = 0;
     339                }
     340
     341                $this->active_tag = '';
     342        }
     343       
     344        function _add($type, $field, $value, $array = 0) {
     345                if ( $array ) {
     346                        $this->{$type}[$field][] = $value;
     347                } else {               
     348                        if ( empty($this->{$type}) || empty($this->{$type}[$field]) ) {
     349                                $this->{$type}[$field] = $value;
     350                        } else {
     351                                $this->{$type}[$field] .= $value;
     352                        }
     353                }
     354
     355                $this->last = $this->{$type};
     356        }
     357       
     358        function map_attrs($k, $v) {
     359                return "$k=\"$v\"";
     360        }
     361       
     362        function get_entries() {
     363                // Set the URL
     364                if ( $this->next_url != '' )
     365                        $url = $this->next_url;
     366                else
     367                        $url = $this->detect_atom_uri(trim($_POST['mturl']));
     368       
     369                // Get the entries from the atom feed
     370                $result = $this->fetch_atom($url, $this->username, $this->password);
     371                if ( $result == 'error' ) return $result;
     372       
     373                // Set the site URL and next URLs
     374                $this->site_url = $this->channel['link'];
     375                $this->next_url = $this->channel['next'];
     376                $this->post_count = $this->channel['fullcount'];
     377               
     378                // Convert the parsed atom feed to the posts / pages array
     379                foreach ( $this->items AS $item ) {                     
     380                        $this->posts[] = $item;
     381                }
     382        }
     383       
     384        function get_comments($comment_feed) {
     385                $comments = array();
     386               
     387                // While there are more comments
     388                do {
     389               
     390                        // Select the right comments feed URL
     391                        if ( $comments_next != '' )
     392                                $comment_feed = $comments_next;                 
     393               
     394                        // Get the comments from the atom feed
     395                        if ( !empty($comment_feed) )
     396                                $this->fetch_atom($comment_feed, $this->username, $this->password);
     397                       
     398                        // The next URL
     399                        $comments_next = $this->channel['next'];
     400                       
     401                        // Convert the parsed atom feed to the comments array
     402                        foreach ( $this->items AS $item ) {                     
     403                                $comments[] = $item;
     404                        }
     405               
     406                } while ( $comments_next != '' );
     407               
     408                return $comments;
     409        }
     410       
     411        function get_trackbacks($post_id) {
     412                include_once(ABSPATH . WPINC . '/class-IXR.php');
     413               
     414                $rpc = new IXR_Client($this->xmlrpc_url);
     415                if ( !$rpc->query('mt.getTrackbackPings', $post_id) ) {
     416                //      print("Error (" . $rpc->getErrorCode() . "): ");
     417                //      print($rpc->getErrorMessage() . "\n\n");
     418                }
     419               
     420                return $rpc->getResponse();
     421        }
     422       
     423        function get_additional_data($post_id) {
     424                include_once(ABSPATH . WPINC . '/class-IXR.php');
     425               
     426                $rpc = new IXR_Client($this->xmlrpc_url);
     427                if ( !$rpc->query('metaWeblog.getPost', $post_id, $this->username, $this->password) ) {
     428                //      print("Error (" . $rpc->getErrorCode() . "): ");
     429                //      print($rpc->getErrorMessage() . "\n\n");
     430                }
     431               
     432                return $rpc->getResponse();
     433        }
     434       
     435        function process_posts() {
     436                // Start the output list if this is the first run
     437                if ( $this->first_run == true ) {
     438                        echo '<div class="wrap"><ol>';
     439                        $this->first_run = false;
     440                }
     441               
     442                // Use output buffering to show the current import progress
     443                if (ob_get_level() == 0) {
     444                    ob_start();
     445                }
     446                // Pad the page with some data so output buffering works across browsers
     447                echo str_pad('',4096);
     448               
     449                foreach ( $this->posts AS $entry ) {
     450                       
     451                        // Construct the post class from the AtomPub feed
     452                        $post = new StdClass();
     453
     454                        // The entry type (over 1 and we have a post)
     455                        if ( count(explode('/', substr($entry['link'], strlen($this->site_url)))) > 1 )
     456                                $post->post_type = 'post';
     457                        else
     458                                $post->post_type = 'page';
     459                        // The entry title
     460                        if ( isset($entry['title']) )
     461                                $post->post_title = trim($entry['title']);
     462                        else
     463                                $post->post_title = '';
     464                        // The post content
     465                        if ( isset($entry['content']) )
     466                                $post->post_content = trim($entry['content']);
     467                        // The post excerpt
     468                        if ( isset($entry['summary']) )
     469                                $post->post_excerpt = trim($entry['summary']);
     470                        // The post date
     471                        $date = strtotime(trim($entry['issued']));
     472                        $date = date('Y-m-d H:i:s', $date);
     473                        $date_gmt = get_gmt_from_date($date);
     474                        $post->post_modified = $date;
     475                        $post->post_modified_gmt = $date_gmt;
     476                        $post->post_date = $date;
     477                        $post->post_date_gmt = $date_gmt;
     478                        // The post slug
     479                        $slug = array_reverse(explode('/', trim($entry['link'])));
     480                        $slug = substr($slug[0], 0 , -5);
     481                        $post->post_name = $slug;
     482                        // The categories and tags
     483                        if ( isset($entry['categories']) ) {
     484                                foreach ( $entry['categories'] AS $cat ) {
     485                                        $post->categories[] = trim($cat['term']);
     486                                }
     487                        } else {
     488                                $post->categories = array();
     489                        }
     490                        // The post author
     491                        if ( isset($entry['author']) )
     492                                $post->post_author = trim($entry['author']);
     493                        // The post id
     494                        $post_id = trim($entry['id']);
     495                        $post_id = substr(strrchr($post_id, '-'), 1);
     496                        // The additional data
     497                        $additional_data = $this->get_additional_data($post_id);
     498                        // The comment status
     499                        if ( $additional_data['mt_allow_comments'] == 1 )
     500                                $post->comment_status = 'open';
     501                        else
     502                                $post->comment_status = 'closed';
     503                        if ( $additional_data['mt_allow_pings'] == 1 )
     504                                $post->ping_status = 'open';
     505                        else
     506                                $post->ping_status = 'closed';
     507                        // The tags
     508                        $post->post_keywords = $additional_data['mt_keywords'];
     509                        // The draft status
     510                        if ( isset($entry['privacy']) ) {
     511                                if ( $entry['privacy'] == 'Self' )
     512                                        $post->post_status = 'draft';
     513                                else
     514                                        $post->post_status = 'publish';
     515                        }
     516                       
     517                        unset($comments);
     518                        $comments = array();
     519                       
     520                        // Fetch the comments if the post has comments
     521                        $coms = $this->get_comments(trim($entry['link:entry.comments']));
     522                        if ( count($coms) > 0 ) {
     523                                foreach ( $coms AS $com ) {
     524                                        // Construct the comment class from the AtomPub feed
     525                                        $comment = new StdClass();
     526                               
     527                                        // The comment date
     528                                        $date = strtotime(trim($com['issued']));
     529                                        $date = date('Y-m-d H:i:s', $date);
     530                                        $comment->comment_date = $date;
     531                                        // The comment content
     532                                        $comment->comment_content = trim($com['content']);
     533                                        // The comment author
     534                                        $comment->comment_author = trim($com['author']);
     535                                        // The comment author uri
     536                                        $comment->comment_author_url = trim($com['author_uri']);
     537                                        // Set the unknown variables
     538                                        $comment->comment_author_email = '';
     539                                        $comment->comment_author_IP = '';
     540                               
     541                                        // Add the comment to the comments array
     542                                        $comments[] = $comment;
     543                                }
     544                        }
     545                       
     546                        unset($trackbacks);
     547                        $pings = array();
     548                       
     549                        // Fetch the trackbacks
     550                        $trackbacks = $this->get_trackbacks($post_id);
     551                        if ( count($trackbacks) > 0 ) {
     552                                foreach ( $trackbacks AS $trackback ) {
     553                                        $ping = new StdClass();
     554                                        // The ping date (the date of the post since we don't know the real one)
     555                                        $ping->comment_date = $post->post_date;
     556                                        // The ping IP address
     557                                        $ping->comment_author_IP = $trackback['pingIP'];
     558                                        // The ping URL
     559                                        $ping->comment_author_url = $trackback['pingURL'];
     560                                        // The ping author
     561                                        $ping->comment_author = $trackback['pingTitle'];
     562                                        // Set the unknow variables
     563                                        $ping->comment_author_email = '';
     564                                        $ping->comment_content = '';
     565                                        $ping->comment_type = 'pingback';
     566                               
     567                                        // Add the ping to the pings array
     568                                        $pings[] = $ping;
     569                                }
     570                        }
     571                       
     572                        $result = $this->save_post($post, $comments, $pings);
     573                        if ( is_wp_error( $result ) )
     574                                return $result;
     575                       
     576                        // Increase the post count
     577                        $this->current_post++;
     578                       
     579                        // Update the progress bar
     580                        $progress_bar = round(( $this->current_post / $this->post_count ) * 500);
     581                        $progress_percent = round(( $this->current_post / $this->post_count ) * 100, 1);
     582?>
     583<script type="text/javascript">
     584        jQuery('.progress_bar .progress_display').animate({
     585                width: "<?php echo $progress_bar; ?>px"
     586        }, 200);
     587        jQuery('.progress_percent span.percent').html('<?php echo $progress_percent; ?>');
     588        <?php if ( $progress_percent == 100 ) { ?>
     589                jQuery('.progress_percent img').hide();
     590        <?php } ?>
     591</script>
     592<?php
     593                       
     594                        // Flush the output buffer to show current state
     595                        ob_flush();
     596                        flush();
     597                        usleep(50000);
     598                }
     599               
     600                // Clean up after using the output buffer
     601                ob_end_flush();
     602               
     603                // If there are no more posts end the list tags
     604                if ( $this->next_url == '' ) {
     605                        echo '</ol>';           
     606                        do_action('import_done', 'typepad');           
     607                        echo '<h3>'.sprintf(__('All done. <a href="%s">Have fun!</a>'), get_option('home')).'</h3></div>';
     608                }
     609        }
     610       
     611        function save_post(&$post, &$comments, &$pings) {
     612                $post = get_object_vars($post);
     613                $post = add_magic_quotes($post);
     614                $post = (object) $post;
     615               
     616                if ( $post_id = post_exists($post->post_title, '', $post->post_date) ) {
     617                        echo '<li>';
     618                        printf(__('Post <em>%s</em> already exists.'), stripslashes($post->post_title));
     619                } else {
     620                        echo '<li>';
     621                        printf(__('Importing post <em>%s</em>...'), stripslashes($post->post_title));
     622                       
     623                        $post->post_author = $this->check_author($post->post_author); //just so that if a post already exists, new users are not created by checkauthor
     624                        $post_id = wp_insert_post($post);
     625                        if ( is_wp_error( $post_id ) )
     626                                return $post_id;
     627               
     628                        // Add categories.
     629                        if ( 0 != count($post->categories) ) {
     630                                wp_create_categories($post->categories, $post_id);
     631                        }
     632                       
     633                        // Add tags or keywords
     634                        if ( 1 < strlen($post->post_keywords) ) {
     635                                // Keywords exist.
     636                                printf(__('<br />Adding tags <i>%s</i>...'), stripslashes($post->post_keywords));
     637                                wp_add_post_tags($post_id, $post->post_keywords);
     638                        }
     639                       
     640                        $num_comments = 0;
     641                        foreach ( $comments as $comment ) {
     642                                $comment = get_object_vars($comment);
     643                                $comment = add_magic_quotes($comment);
     644
     645                                if ( !comment_exists($comment['comment_author'], $comment['comment_date'])) {
     646                                        $comment['comment_post_ID'] = $post_id;
     647                                        $comment = wp_filter_comment($comment);
     648                                        wp_insert_comment($comment);
     649                                        $num_comments++;
     650                                }
     651                        }
     652
     653                        if ( $num_comments )
     654                                printf(' '.__ngettext('(%s comment)', '(%s comments)', $num_comments), $num_comments);
     655                       
     656                        $num_pings = 0;
     657                        foreach ( $pings as $ping ) {
     658                                $ping = get_object_vars($ping);
     659                                $ping = add_magic_quotes($ping);
     660
     661                                if ( !comment_exists($ping['comment_author'], $ping['comment_date'])) {
     662                                        $ping['comment_content'] = "<strong>{$ping['comment_author']}</strong>";
     663                                        $ping['comment_post_ID'] = $post_id;
     664                                        $ping = wp_filter_comment($ping);
     665                                        wp_insert_comment($ping);
     666                                        $num_pings++;
     667                                }
     668                        }
     669
     670                        if ( $num_pings )
     671                                printf(' '.__ngettext('(%s ping)', '(%s pings)', $num_pings), $num_pings);
     672                }
     673               
     674                echo '</li>';
     675        }
     676       
     677        function check_author($author) {
     678                global $wpdb;
     679               
     680                $user_id = username_exists($author);
     681               
     682                // If the username does not exist
     683                if ( !$user_id ) {
     684                        $pass = wp_generate_password();
     685                        $user_id = wp_create_user($author, $pass);
     686                }
     687               
     688                return $user_id;
     689        }
     690       
     691        function error() {
     692?>
     693                <div class="narrow">
     694                        <h3><?php _e('Import Failed'); ?></h3>
     695                        <p><?php _e('There was an error starting the import process. Please go back and verify that the URL, username, and password were entered correctly.'); ?></p>
     696                        <p><a href="<?php echo add_query_arg('step', 0); ?>"><?php _e('Restart the Import Process &raquo;')?></a></p>
     697                </div>
     698<?php
     699        }
     700       
     701        function import() {
     702                $this->header();
     703               
     704                // Add the username and password as a global
     705                $this->username = $_POST['mtuser'];
     706                $this->password = $_POST['mtpass'];
     707               
     708                // Use output buffering so the progress bar appears immediately
     709                if (ob_get_level() == 0) {
     710                    ob_start();
     711                }
     712               
     713                // Pad the page with some data so output buffering works across browsers
     714                echo str_pad('',4096);
     715               
     716?>
     717<h3><?php _e('Import in Progress, Results Will Appear Momentarily'); ?></h3>
     718
     719<p><?php _e('While the importer is running do not navigate away from this page.'); ?></p>
     720
     721<div class="progress_bar" style="float:left; width: 500px; height; 20px; padding: 1px; border: 1px solid #dadada;">
     722        <div class="progress_display" style="width: 0px; background: #ccc">&nbsp;</div>
     723</div>
     724<div class="progress_percent" style="padding: 2px;">&nbsp;<img src="<?php echo get_option('home'); ?>/wp-admin/images/loading.gif" alt="Loading" style="margin-bottom: -3px;" />&nbsp;<span class="percent">0</span>%</div>
     725<?php
     726               
     727                // Clear the output buffer
     728                ob_flush();
     729                flush();
     730                ob_end_flush();
     731               
     732                // While we have more posts
     733                do {
     734               
     735                        $result = $this->get_entries();
     736               
     737                        if ( $result != 'error' )               
     738                                $result = $this->process_posts();
     739               
     740                        if ( is_wp_error( $result ) )
     741                                echo $result->get_error_message();
     742                       
     743                        // Free memory for next round of post
     744                        unset($this->posts);
     745                        $this->posts = array();
     746                               
     747                } while ( $this->next_url != '' );
     748               
     749                $this->footer();
     750        }
     751       
     752        function dispatch() {
     753                if (empty ($_GET['step']))
     754                        $step = 0;
     755                else
     756                        $step = (int) $_GET['step'];
     757
     758                switch ($step) {
     759                        case 0 :
     760                                $this->greet();
     761                                break;
     762                        case 1 :
     763                                check_admin_referer('import-typepad');
     764                                $this->import();
     765                                break;
     766                }
     767        }
     768
     769        function Typepad_Import() {
     770                // Nothing.
     771        }
     772}
     773
     774$typepad_import = new Typepad_Import();
     775
     776register_importer('typepad', __('TypePad'), __('Import posts, comments, and categories from a TypePad blog.'), array ($typepad_import, 'dispatch'));
     777?>
     778 No newline at end of file
  • wp-admin/import/mt-atom.php

     
     1<?php
     2
     3class MT_Atom_Import {
     4       
     5        // General
     6        var $username;
     7        var $password;
     8       
     9        // XML parsing
     10        var $parser;
     11        var $inside_tag = '';
     12        var $active_tag = '';
     13        var $entry_tag = '';
     14        var $last = '';
     15        var $start_byte = '';
     16        var $first_child = 0;
     17        var $inside_entry = 0;
     18        var $channel = array();
     19        var $items = array();
     20        var $item = array();
     21       
     22        // The data
     23        var $posts = array();
     24        var $site_url;
     25        var $xmlrpc_url;
     26        var $next_url;
     27        var $post_count = 0;
     28        var $current_post = 0;
     29        var $more_posts = true;
     30        var $first_run = true;
     31       
     32        function header() {
     33                echo '<div class="wrap">';
     34                echo '<h2>'.__('Import Movable Type').'</h2>';
     35        }
     36
     37        function footer() {
     38                echo '</div>';
     39        }
     40
     41        function greet() {
     42                $this->header();
     43?>
     44<div class="narrow">
     45<p><?php _e('Howdy! We&#8217;re about to begin importing all of your Movable Type entries into WordPress. To begin, enter the URL of your blog followed by the username and password of an administrator account. When you&#8217;re finished, click "Start Importing".'); ?></p>
     46<p><?php _e('<strong>Note:</strong> Use your web services password instead of your regular account password. To obtain this password, log in to your MT blog and follow these steps:'); ?></p>
     47<ol>
     48<li><?php _e('In the upper right, click Hi [username].'); ?></li>
     49<li><?php _e('Scroll down to the Preferences section.'); ?></li>
     50<li><?php _e('Under Web Services Password, click reveal.'); ?></li>
     51<li><?php _e('Enter the password displayed in the password box below.'); ?></li>
     52</ol>
     53
     54<form method="post" action="<?php echo add_query_arg('step', 1); ?>" class="import-upload-form">
     55
     56<?php wp_nonce_field('import-mt-atom'); ?>
     57<table class="form-table">
     58<tr>
     59<td><label for="mturl"><?php _e('Blog URL:') ?></label></td>
     60<td><input type="text" style="width:300px" name="mturl" id="mturl" value="http://" /></td>
     61</tr>
     62<tr>
     63<td><label for="mtuser"><?php _e('Username:') ?></label></td>
     64<td><input type="text" style="width:300px" name="mtuser" id="mtuser" value="" /></td>
     65</tr>
     66<tr>
     67<td><label for="mtpass"><?php _e("Password:") ?></label></td>
     68<td><input type="password" style="width:300px" name="mtpass" id="mtpass" value="" /></td>
     69</tr>
     70</table>
     71<p class="submit">
     72<input type="submit" value="<?php echo attribute_escape(__('Start Importing')); ?>" id="atom-submit" onclick="jQuery('#atom-loading').show();jQuery('#atom-submit').val('<?php echo attribute_escape(__('Importing...')); ?>');" /> <span style="display: none;" id="atom-loading"><img src="<?php echo get_option('home'); ?>/wp-admin/images/loading.gif" alt="Loading" style="margin-bottom: -3px;" /> <?php echo attribute_escape(__('Retrieving entries from server. Do not navigate away from this page.')); ?></span>
     73</p>
     74</form>
     75<p><?php _e('The importer is smart enough not to import duplicates, so you can run this multiple times without worry if&#8212;for whatever reason&#8212;it doesn\'t finish.'); ?> </p>
     76</div>
     77<?php
     78                $this->footer();
     79        }
     80               
     81        function detect_atom_uri($url) {
     82                // Set the RSD URL
     83                $rsd_url = $url . '/rsd.xml';
     84               
     85                // Grab the RSD page
     86                $ch2 = curl_init();
     87                curl_setopt($ch2, CURLOPT_URL, $rsd_url);
     88                curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
     89                curl_setopt($ch2, CURLOPT_TIMEOUT, 5);
     90                $output = @curl_exec($ch2);
     91               
     92                // Parse out the xmlrpc URI
     93                preg_match('#<api name="MovableType" preferred="false" apiLink="([^"]*)" blogid="([^"]*)" \/>#i', $output, $xmlrpc);
     94                $this->xmlrpc_url = $xmlrpc[1];
     95               
     96                // Parse out the Atom URI
     97                preg_match('#<api name="Atom" preferred="false" apiLink="([^"]*)" blogid="([^"]*)" \/>#i', $output, $matches);
     98               
     99                return $matches[1] . '/blog_id=' . $matches[2];
     100        }
     101       
     102        function fetch_atom($url, $username, $password) {
     103                include_once(ABSPATH . '/wp-admin/includes/class-atom-api.php');
     104               
     105                $atom_api = new AtomAPI($url, $username, $password, 'WSSE'); // Authenticate to the AtomPub feed using WSSE
     106                // If the login failed, throw an error message
     107                if ( ( $atom_api->err_no != '' ) && ( count($this->posts) == 0 ) ) {
     108                        $this->error();
     109                        return 'error';
     110                }
     111               
     112                 // Grab the raw feed data and pass it to the parser
     113                $this->parse_atom( $atom_api->get_feeds( $xml = false ) );
     114        }
     115       
     116        function parse_atom($xml) {
     117                // Reset the data before parsing a new feed
     118                unset($this->parser);
     119                unset($this->inside_tag);
     120                unset($this->active_tag);
     121                unset($this->channel);
     122                unset($this->items);
     123                unset($this->item);
     124                $this->inside_tag = '';
     125                $this->active_tag = '';
     126                $this->entry_tag = '';
     127                $this->last = '';
     128                $this->start_byte = '';
     129                $this->first_child = 0;
     130                $this->inside_entry = 0;
     131                $this->channel = array();
     132                $this->items = array();
     133                $this->item = array();
     134               
     135                // Create an XML parser
     136                $this->parser = xml_parser_create();
     137               
     138                // Used to make the XML parser work in a class
     139                xml_set_object($this->parser, $this);
     140               
     141                // Set the start and ending element functions           
     142                xml_set_element_handler($this->parser, "start_element", "end_element");
     143               
     144                // Set the character data functions
     145                xml_set_character_data_handler($this->parser, "character_data");
     146               
     147                // Begin parsing the XML
     148                xml_parse($this->parser, $xml)
     149                        or die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)));
     150               
     151                // Clean up after the parse
     152                xml_parser_free($this->parser);
     153        }
     154       
     155        function start_element($parser, $element, $attrs) {
     156                switch ($element) {
     157                        case 'FEED':
     158                        case 'ENTRY':
     159                                $this->inside_tag = $element;
     160                                break;
     161
     162                        case 'CONTENT':
     163                        case 'SUMMARY':
     164                                if ( $this->inside_tag == 'ENTRY' ) {
     165                                        $this->inside_entry = 1;
     166                                        $this->entry_tag = strtolower($element);
     167                                }
     168                                break;
     169
     170                        case 'LINK' :
     171                                if ( $this->inside_tag == 'FEED' ) {
     172                                        if ( $attrs['REL'] == 'alternate' || !$attrs['REL'] ) {
     173                                                $this->_add('channel', 'link', $attrs['HREF']);
     174                                        } elseif ( $attrs['REL'] == 'next' ) {
     175                                                $this->_add('channel', 'next', $attrs['HREF']);
     176                                        }
     177                                } elseif ( $this->inside_tag == 'ENTRY' ) {
     178                                        if ( $attrs['REL'] == 'alternate' || !$attrs['REL'] ) {
     179                                                $this->_add('item', 'link', $attrs['HREF']);
     180                                        } elseif ( $attrs['REL'] == 'service.edit' ) {
     181                                                $this->_add('item', 'link:service.edit', $attrs['HREF']);
     182                                        } elseif ( $attrs['REL'] == 'replies' ) {
     183                                                $this->_add('item', 'link:replies', $attrs['HREF']);
     184                                        }
     185                                } elseif ( $this->inside_tag != 'FEED' && $this->inside_tag != 'ENTRY' ) {
     186                                        if ( $attrs['REL'] == 'next' ) {
     187                                                $this->_add('channel', 'next', $attrs['HREF']);
     188                                        }
     189                                }
     190                                break;
     191                       
     192                        case 'CATEGORY':
     193                                if ( $this->inside_tag == 'ENTRY' ) {
     194                                        $cats = array ( 'type' => $attrs['SCHEME'], 'term' => $attrs["TERM"] );
     195                                        $this->_add('item', 'categories', $cats, 1);
     196                                }
     197                                break;
     198                       
     199                        case 'AUTHOR':
     200                                if ( $this->inside_tag == 'ENTRY' ) {
     201                                        $this->inside_tag = 'ENTRY|AUTHOR';
     202                                }
     203                                break;
     204
     205                        default :
     206                                $this->active_tag = $element;
     207                }
     208               
     209                // Deal with tags inside of content and summary
     210                if ( $this->inside_entry && $element != 'CONTENT' && $element != 'SUMMARY' ) {
     211                        // If tags are inlined, then flatten
     212                        $attrs = array_change_key_case($attrs, CASE_LOWER);
     213                        $attrs_str = implode(' ',
     214                                array_map(array($this, 'map_attrs'),
     215                                array_keys($attrs),
     216                                array_values($attrs) ) );
     217                               
     218                        // Add a space if there are attrs
     219                        if ( $attrs_str != '' )
     220                                $attrs_str = ' ' . $attrs_str;
     221                       
     222                        // Make the element lowercase
     223                        $el = strtolower($element);
     224                       
     225                        // Close an opening tag if it had no data
     226                        if ( $this->first_child )
     227                                $this->_add('item', $this->entry_tag, ">");
     228                       
     229                        // Add the start tag
     230                        $this->_add('item', $this->entry_tag, "<$el" . "$attrs_str");
     231                       
     232                        // Handle self-closing tags
     233                        $this->first_child = 1;
     234                        $this->start_byte = xml_get_current_byte_index($parser);
     235                }
     236        }
     237       
     238        function character_data($parser, $cdata) {
     239                switch ($this->inside_tag) {
     240
     241                        // Grab general channel information
     242                        case 'FEED':
     243                                switch ($this->active_tag) {
     244                                        case 'TITLE':
     245                                                $this->_add('channel', strtolower($this->active_tag), $cdata);
     246                                                break;
     247                                        case 'FULLCOUNT':
     248                                                $this->_add('channel', strtolower($this->active_tag), $cdata);
     249                                                break;
     250                                }
     251                                break;
     252
     253                        // Grab item information
     254                        case 'ENTRY':
     255                                switch ($this->active_tag) {
     256                                        case 'TITLE':
     257                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     258                                                break;
     259
     260                                        case 'CONTENT':
     261                                        case 'SUMMARY':
     262                                                $this->_add('item', $this->inside_tag, $cdata);
     263                                                break;
     264                                       
     265                                        case 'ISSUED':
     266                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     267                                                break;
     268                                       
     269                                        case 'PUBLISHED':
     270                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     271                                                break;
     272                                       
     273                                        case 'ID':
     274                                                $this->_add('item', strtolower($this->active_tag), $cdata);
     275                                                break;
     276                                }
     277                                break;
     278                       
     279                        // For author tags
     280                        case 'ENTRY|AUTHOR':
     281                                switch ($this->active_tag) {
     282                                        case 'NAME':
     283                                                $this->_add('item', 'author', $cdata);
     284                                                break;
     285                                        case 'URI':
     286                                                $this->_add('item', 'author_uri', $cdata);
     287                                                break;
     288                                        case 'EMAIL':
     289                                                $this->_add('item', 'author_email', $cdata);
     290                                                break;
     291                                }
     292                                break;
     293
     294                        }   
     295
     296                        // Deal with data inside content tags
     297                        if ( $this->inside_entry ) {
     298                                // Append the start tag close if first_child
     299                                if ( $this->first_child ) {
     300                                        $this->_add('item', $this->entry_tag, '>');
     301                                        $this->first_child = 0;
     302                                }
     303                               
     304                                $this->_add('item', $this->entry_tag, $cdata);
     305                        }
     306        }
     307       
     308        function end_element($parser, $element) {
     309                // Deal with tags inside of content and summary
     310                if ( $this->inside_entry && $element != 'CONTENT' && $element != 'SUMMARY' ) {
     311                        $el = strtolower($element);                     
     312                       
     313                        // Add the appropriate end tag depending if the element is a self-closing element
     314                        if ( xml_get_current_byte_index($parser) - $this->start_byte > 2 ) {
     315                                if ( $this->first_child )
     316                                        $this->_add('item', $this->entry_tag, ">");
     317                                $this->_add('item', $this->entry_tag, "</$el>");
     318                        } else {
     319                                $this->_add('item', $this->entry_tag, " />");
     320                        }
     321                        $this->first_child = 0;
     322                }
     323               
     324                // Reset inside tag back to entry for author tags
     325                if ( $element == 'AUTHOR' && $this->inside_tag == 'ENTRY|AUTHOR' ) {
     326                        $this->inside_tag = 'ENTRY';
     327                }
     328               
     329                if ( $element == $this->inside_tag ) {
     330                        $this->inside_tag = '';
     331                        $this->struct[] = array_merge(array('type' => strtolower($element)), $this->last);
     332                }
     333
     334                if ( $element == 'ENTRY' ) {
     335                        $this->items[] = $this->item;
     336                        $this->item = '';
     337                }
     338
     339                if ( $element == 'CONTENT' || $element == 'SUMMARY' ) {                 
     340                        $this->inside_entry = 0;
     341                }
     342
     343                $this->active_tag = '';
     344        }
     345       
     346        function _add($type, $field, $value, $array = 0) {
     347                if ( $array ) {
     348                        $this->{$type}[$field][] = $value;
     349                } else {               
     350                        if ( empty($this->{$type}) || empty($this->{$type}[$field]) ) {
     351                                $this->{$type}[$field] = $value;
     352                        } else {
     353                                $this->{$type}[$field] .= $value;
     354                        }
     355                }
     356
     357                $this->last = $this->{$type};
     358        }
     359       
     360        function map_attrs($k, $v) {
     361                return "$k=\"$v\"";
     362        }
     363       
     364        function get_entries() {
     365                // Set the URL
     366                if ( $this->next_url != '' )
     367                        $url = $this->detect_atom_uri(trim($_POST['mturl'])) . '/offset=' . $this->next_url . '/limit=20';
     368                else
     369                        $url = $this->detect_atom_uri(trim($_POST['mturl'])) . '/offset=0/limit=20';
     370       
     371                // Get the entries from the atom feed
     372                $result = $this->fetch_atom($url, $this->username, $this->password);
     373                if ( $result == 'error' ) return $result;
     374       
     375                // Set the site URL and next URLs
     376                $this->site_url = $this->channel['link'];
     377                $this->next_url = $this->next_url + 20;
     378        //      $this->post_count = $this->channel['fullcount'];
     379               
     380                // Convert the parsed atom feed to the posts / pages array
     381                foreach ( $this->items AS $item ) {                     
     382                        $this->posts[] = $item;
     383                }
     384        }
     385       
     386        function get_comments($comment_feed) {
     387                $comments = array();
     388               
     389                // While there are more comments
     390                do {
     391               
     392                        // Select the right comments feed URL
     393                        if ( $comments_next != '' )
     394                                $comment_uri = $comment_feed . '/offset=' . $comments_next . '/limit=20';       
     395                        else
     396                                $comment_uri = $comment_feed . '/offset=0/limit=20';
     397               
     398                        // Get the comments from the atom feed
     399                        if ( !empty($comment_uri) )
     400                                $this->fetch_atom($comment_uri, $this->username, $this->password);
     401                       
     402                        // Convert the parsed atom feed to the comments array
     403                        foreach ( $this->items AS $item ) {                     
     404                                $comments[] = $item;
     405                        }
     406                       
     407                        $comments_next = $comments_next + 20;
     408                        $more_comments = ( count($this->items) > 0 ) ? true : false;
     409               
     410                } while ( $more_comments );
     411               
     412                return $comments;
     413        }
     414       
     415        function get_additional_data($post_id) {
     416                include_once(ABSPATH . WPINC . '/class-IXR.php');
     417               
     418                $rpc = new IXR_Client($this->xmlrpc_url);
     419                if ( !$rpc->query('metaWeblog.getPost', $post_id, $this->username, $this->password) ) {
     420                //      print("Error (" . $rpc->getErrorCode() . "): ");
     421                //      print($rpc->getErrorMessage() . "\n\n");
     422                }
     423               
     424                return $rpc->getResponse();
     425        }
     426       
     427        function get_trackbacks($post_id) {
     428                include_once(ABSPATH . WPINC . '/class-IXR.php');
     429               
     430                $rpc = new IXR_Client($this->xmlrpc_url);
     431                if ( !$rpc->query('mt.getTrackbackPings', $post_id) ) {
     432                //      print("Error (" . $rpc->getErrorCode() . "): ");
     433                //      print($rpc->getErrorMessage() . "\n\n");
     434                }
     435               
     436                return $rpc->getResponse();
     437        }
     438       
     439        function check_draft($url) {
     440                $ch = curl_init();
     441                curl_setopt($ch, CURLOPT_URL, $url);
     442                curl_setopt($ch, CURLOPT_HEADER, 1);
     443                curl_setopt($ch, CURLOPT_NOBODY, 1);
     444                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     445                curl_setopt($ch, CURLOPT_TIMEOUT, 5);
     446                $output = @curl_exec($ch);
     447                $response = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
     448               
     449                // If 404 assume this a draft
     450                if ( $response == '404' )
     451                        return 'draft';
     452                else
     453                        return 'publish';
     454        }
     455       
     456        function process_posts() {
     457                // Start the output list if this is the first run
     458                if ( $this->first_run == true ) {
     459                        echo '<div class="wrap"><ol>';
     460                        $this->first_run = false;
     461                }
     462               
     463                // Use output buffering to show the current import progress
     464                if (ob_get_level() == 0) {
     465                    ob_start();
     466                }
     467                // Pad the page with some data so output buffering works across browsers
     468                echo str_pad('',4096);
     469               
     470                foreach ( $this->posts AS $entry ) {
     471                       
     472                        // Construct the post class from the AtomPub feed
     473                        $post = new StdClass();
     474
     475                        // The entry type (over 1 and we have a post)
     476                        if ( count(explode('/', substr($entry['link'], strlen($this->site_url)))) > 1 )
     477                                $post->post_type = 'post';
     478                        else
     479                                $post->post_type = 'page';
     480                        // The entry title
     481                        if ( isset($entry['title']) )
     482                                $post->post_title = trim($entry['title']);
     483                        else
     484                                $post->post_title = '';
     485                        // The post content
     486                        if ( isset($entry['content']) )
     487                                $post->post_content = trim($entry['content']);
     488                        // The post excerpt
     489                        if ( isset($entry['summary']) )
     490                                $post->post_excerpt = trim($entry['summary']);
     491                        // The post date
     492                        $date = strtotime(trim($entry['issued']));
     493                        $date = date('Y-m-d H:i:s', $date);
     494                        $date_gmt = get_gmt_from_date($date);
     495                        $post->post_modified = $date;
     496                        $post->post_modified_gmt = $date_gmt;
     497                        $post->post_date = $date;
     498                        $post->post_date_gmt = $date_gmt;
     499                        // The post slug
     500                        $slug = array_reverse(explode('/', trim($entry['link'])));
     501                        $slug = substr($slug[0], 0 , -5);
     502                        $post->post_name = $slug;
     503                        // The categories and tags
     504                        if ( isset($entry['categories']) ) {
     505                                foreach ( $entry['categories'] AS $cat ) {
     506                                        $post->categories[] = trim($cat['term']);
     507                                        $post_keywords = '';
     508                                }
     509                        } else {
     510                                $post->categories = array();
     511                                $post->post_keywords = '';
     512                        }
     513                        // The post author
     514                        if ( isset($entry['author']) )
     515                                $post->post_author = trim($entry['author']);                   
     516                        // The post id
     517                        $post_id = trim($entry['id']);
     518                        $post_id = substr(strrchr($post_id, '.'), 1);
     519                        // The additional data
     520                        $additional_data = $this->get_additional_data($post_id);
     521                        // The comment status
     522                        if ( $additional_data['mt_allow_comments'] == 1 )
     523                                $post->comment_status = 'open';
     524                        else
     525                                $post->comment_status = 'closed';
     526                        if ( $additional_data['mt_allow_pings'] == 1 )
     527                                $post->ping_status = 'open';
     528                        else
     529                                $post->ping_status = 'closed';
     530                        // The tags
     531                        $post->post_keywords = $additional_data['mt_tags'];
     532                        // The draft status
     533                        $post->post_status = $this->check_draft(trim($entry['link']));
     534                       
     535                        // Set the post count if we weren't able to determine it earlier. Asssume the current ID count is the number of posts
     536                        if ( $this->post_count == '' )
     537                                $this->post_count = $post_id;
     538                       
     539                        unset($comments);
     540                        $comments = array();
     541                       
     542                        // Fetch the comments if the post has comments
     543                        $coms = $this->get_comments(trim($entry['link:replies']));
     544                                               
     545                        if ( count($coms) > 0 ) {
     546                                foreach ( $coms AS $com ) {
     547                                        // Construct the comment class from the AtomPub feed
     548                                        $comment = new StdClass();
     549                       
     550                                        // The comment date
     551                                        $date = strtotime(trim($com['published']));
     552                                        $date = date('Y-m-d H:i:s', $date);
     553                                        $comment->comment_date = $date;
     554                                        // The comment content
     555                                        $comment->comment_content = trim($com['content']);
     556                                        // The comment author
     557                                        $comment->comment_author = trim($com['author']);
     558                                        // The comment author uri
     559                                        $comment->comment_author_url = trim($com['author_uri']);
     560                                        // The comment author email
     561                                        $comment->comment_author_email = trim($com['author_email']);
     562                                        // Set the unknown variables
     563                                        $comment->comment_author_IP = '';
     564                       
     565                                        // Add the comment to the comments array
     566                                        $comments[] = $comment;
     567                                }
     568                        }
     569                       
     570                        unset($trackbacks);
     571                        $pings = array();
     572                       
     573                        // Fetch the trackbacks
     574                        $trackbacks = $this->get_trackbacks($post_id);
     575                        if ( count($trackbacks) > 0 ) {
     576                                foreach ( $trackbacks AS $trackback ) {
     577                                        $ping = new StdClass();
     578                                        // The ping date (the date of the post since we don't know the real one)
     579                                        $ping->comment_date = $post->post_date;
     580                                        // The ping IP address
     581                                        $ping->comment_author_IP = $trackback['pingIP'];
     582                                        // The ping URL
     583                                        $ping->comment_author_url = $trackback['pingURL'];
     584                                        // The ping author
     585                                        $ping->comment_author = $trackback['pingTitle'];
     586                                        // Set the unknow variables
     587                                        $ping->comment_author_email = '';
     588                                        $ping->comment_content = '';
     589                                        $ping->comment_type = 'pingback';
     590                               
     591                                        // Add the ping to the pings array
     592                                        $pings[] = $ping;
     593                                }
     594                        }
     595                       
     596                        $result = $this->save_post($post, $comments, $pings);
     597                        if ( is_wp_error( $result ) )
     598                                return $result;
     599                       
     600                        // Increase the post count
     601                        $this->current_post++;
     602                       
     603                        // Update the progress bar
     604                        $progress_bar = round(( $this->current_post / $this->post_count ) * 500);
     605                        $progress_percent = round(( $this->current_post / $this->post_count ) * 100, 1);
     606?>
     607<script type="text/javascript">
     608        jQuery('.progress_bar .progress_display').animate({
     609                width: "<?php echo $progress_bar; ?>px"
     610        }, 200);
     611        jQuery('.progress_percent span.percent').html('<?php echo $progress_percent; ?>');
     612        <?php if ( $progress_percent == 100 ) { ?>
     613                jQuery('.progress_percent img').hide();
     614        <?php } ?>
     615</script>
     616<?php
     617                       
     618                        // Flush the output buffer to show current state
     619                        ob_flush();
     620                        flush();
     621                        usleep(50000);
     622                }
     623               
     624                // Clean up after using the output buffer
     625                ob_end_flush();
     626               
     627                // If there are no more posts end the list tags
     628                if ( $this->more_posts == false ) {
     629                       
     630                        // Update the progress bar
     631                        $progress_bar = 500;
     632                        $progress_percent = 100;
     633?>
     634<script type="text/javascript">
     635        jQuery('.progress_bar .progress_display').animate({
     636                width: "<?php echo $progress_bar; ?>px"
     637        }, 200);
     638        jQuery('.progress_percent span.percent').html('<?php echo $progress_percent; ?>');
     639        <?php if ( $progress_percent == 100 ) { ?>
     640                jQuery('.progress_percent img').hide();
     641        <?php } ?>
     642</script>
     643<?php
     644                       
     645                        echo '</ol>';           
     646                        do_action('import_done', 'mt-atom');           
     647                        echo '<h3>'.sprintf(__('All done. <a href="%s">Have fun!</a>'), get_option('home')).'</h3></div>';
     648                }
     649        }
     650       
     651        function save_post(&$post, &$comments, &$pings) {
     652                $post = get_object_vars($post);
     653                $post = add_magic_quotes($post);
     654                $post = (object) $post;
     655               
     656                if ( $post_id = post_exists($post->post_title, '', $post->post_date) ) {
     657                        echo '<li>';
     658                        printf(__('Post <em>%s</em> already exists.'), stripslashes($post->post_title));
     659                } else {
     660                        echo '<li>';
     661                        printf(__('Importing post <em>%s</em>...'), stripslashes($post->post_title));
     662                       
     663                        $post->post_author = $this->check_author($post->post_author); //just so that if a post already exists, new users are not created by checkauthor
     664                        $post_id = wp_insert_post($post);
     665                        if ( is_wp_error( $post_id ) )
     666                                return $post_id;
     667               
     668                        // Add categories.
     669                        if ( 0 != count($post->categories) ) {
     670                                wp_create_categories($post->categories, $post_id);
     671                        }
     672                       
     673                        // Add tags or keywords
     674                        if ( 1 < strlen($post->post_keywords) ) {
     675                                // Keywords exist.
     676                                printf(__('<br />Adding tags <i>%s</i>...'), stripslashes($post->post_keywords));
     677                                wp_add_post_tags($post_id, $post->post_keywords);
     678                        }
     679                       
     680                        $num_comments = 0;
     681                        foreach ( $comments as $comment ) {
     682                                $comment = get_object_vars($comment);
     683                                $comment = add_magic_quotes($comment);
     684
     685                                if ( !comment_exists($comment['comment_author'], $comment['comment_date'])) {
     686                                        $comment['comment_post_ID'] = $post_id;
     687                                        $comment = wp_filter_comment($comment);
     688                                        wp_insert_comment($comment);
     689                                        $num_comments++;
     690                                }
     691                        }
     692
     693                        if ( $num_comments )
     694                                printf(' '.__ngettext('(%s comment)', '(%s comments)', $num_comments), $num_comments);
     695                       
     696                        $num_pings = 0;
     697                        foreach ( $pings as $ping ) {
     698                                $ping = get_object_vars($ping);
     699                                $ping = add_magic_quotes($ping);
     700
     701                                if ( !comment_exists($ping['comment_author'], $ping['comment_date'])) {
     702                                        $ping['comment_content'] = "<strong>{$ping['comment_author']}</strong>";
     703                                        $ping['comment_post_ID'] = $post_id;
     704                                        $ping = wp_filter_comment($ping);
     705                                        wp_insert_comment($ping);
     706                                        $num_pings++;
     707                                }
     708                        }
     709
     710                        if ( $num_pings )
     711                                printf(' '.__ngettext('(%s ping)', '(%s pings)', $num_pings), $num_pings);
     712                }
     713               
     714                echo '</li>';
     715        }
     716       
     717        function check_author($author) {
     718                global $wpdb;
     719               
     720                $user_id = username_exists($author);
     721               
     722                // If the username does not exist
     723                if ( !$user_id ) {
     724                        $pass = wp_generate_password();
     725                        $user_id = wp_create_user($author, $pass);
     726                }
     727               
     728                return $user_id;
     729        }
     730       
     731        function error() {
     732?>
     733                <div class="narrow">
     734                        <h3><?php _e('Import Failed'); ?></h3>
     735                        <p><?php _e('There was an error starting the import process. Please go back and verify that the URL, username, and password were entered correctly.'); ?></p>
     736                        <p><a href="<?php echo add_query_arg('step', 0); ?>"><?php _e('Restart the Import Process &raquo;')?></a></p>
     737                </div>
     738<?php
     739        }
     740       
     741        function import() {
     742                $this->header();
     743               
     744                // Add the username and password as a global
     745                $this->username = $_POST['mtuser'];
     746                $this->password = $_POST['mtpass'];
     747               
     748                // Use output buffering so the progress bar appears immediately
     749                if (ob_get_level() == 0) {
     750                    ob_start();
     751                }
     752               
     753                // Pad the page with some data so output buffering works across browsers
     754                echo str_pad('',4096);
     755               
     756?>
     757<h3><?php _e('Import in Progress, Results Will Appear Momentarily'); ?></h3>
     758
     759<p><?php _e('While the importer is running do not navigate away from this page.'); ?></p>
     760
     761<div class="progress_bar" style="float:left; width: 500px; height; 20px; padding: 1px; border: 1px solid #dadada;">
     762        <div class="progress_display" style="width: 0px; background: #ccc">&nbsp;</div>
     763</div>
     764<div class="progress_percent" style="padding: 2px;">&nbsp;<img src="<?php echo get_option('home'); ?>/wp-admin/images/loading.gif" alt="Loading" style="margin-bottom: -3px;" />&nbsp;<span class="percent">0</span>%</div>
     765<?php
     766               
     767                // Clear the output buffer
     768                ob_flush();
     769                flush();
     770                ob_end_flush();
     771               
     772                // While we have more posts
     773                do {
     774               
     775                        $result = $this->get_entries();
     776                       
     777                        $this->more_posts = ( count($this->posts) > 0 ) ? true : false;
     778               
     779                        if ( $result != 'error' )               
     780                                $result = $this->process_posts();
     781               
     782                        if ( is_wp_error( $result ) )
     783                                echo $result->get_error_message();
     784                       
     785                        // Free memory for next round of post
     786                        unset($this->posts);
     787                        $this->posts = array();
     788                               
     789                } while ( $this->more_posts );
     790               
     791                $this->footer();
     792        }
     793       
     794        function dispatch() {
     795                if (empty ($_GET['step']))
     796                        $step = 0;
     797                else
     798                        $step = (int) $_GET['step'];
     799
     800                switch ($step) {
     801                        case 0 :
     802                                $this->greet();
     803                                break;
     804                        case 1 :
     805                                check_admin_referer('import-mt-atom');
     806                                $this->import();
     807                                break;
     808                }
     809        }
     810
     811        function MT_Atom_Import() {
     812                // Nothing.
     813        }
     814}
     815
     816$mt_atom_import = new MT_Atom_Import();
     817
     818register_importer('mt-atom', __('Movable Type'), __('Import posts and comments from a Movable Type blog version 4.2 or newer.'), array ($mt_atom_import, 'dispatch'));
     819?>
     820 No newline at end of file
  • wp-admin/import/mt.php

     
    2424
    2525        function header() {
    2626                echo '<div class="wrap">';
    27                 echo '<h2>'.__('Import Movable Type or TypePad').'</h2>';
     27                echo '<h2>'.__('Import Movable Type Old').'</h2>';
    2828        }
    2929
    3030        function footer() {
     
    3535                $this->header();
    3636?>
    3737<div class="narrow">
    38 <p><?php _e('Howdy! We&#8217;re about to begin importing all of your Movable Type or Typepad entries into WordPress. To begin, either choose a file to upload and click "Upload file and import," or use FTP to upload your MT export file as <code>mt-export.txt</code> in your <code>/wp-content/</code> directory and then click "Import mt-export.txt"'); ?></p>
     38<p><?php _e('Howdy! We&#8217;re about to begin importing all of your Movable Type entries into WordPress. To begin, either choose a file to upload and click "Upload file and import," or use FTP to upload your MT export file as <code>mt-export.txt</code> in your <code>/wp-content/</code> directory and then click "Import mt-export.txt"'); ?></p>
    3939
    4040<?php wp_import_upload_form( add_query_arg('step', 1) ); ?>
    4141<form method="post" action="<?php echo add_query_arg('step', 1); ?>" class="import-upload-form">
     
    478478
    479479$mt_import = new MT_Import();
    480480
    481 register_importer('mt', __('Movable Type and TypePad'), __('Import posts and comments from a Movable Type or Typepad blog.'), array ($mt_import, 'dispatch'));
     481register_importer('mt', __('Movable Type Old'), __('Import posts and comments from a Movable Type blog version 4.12 or older.'), array ($mt_import, 'dispatch'));
    482482?>