Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
392 lines (341 sloc) 14.1 KB
<?php
/**
* Movable Type Importer utilities
*
* @package WordPress
* @subpackage Importer
*/
/**
* Movable Type Utils Class
*
* Utilities to finalize your migration from Movable Type to Wordpress.
*
* @since unknown
*/
class MT_Utils
{
function MT_Utils()
{
}
function dispatch()
{
$step = isset($_GET['step']) ? (int) $_GET['step'] : 0;
$this->_header();
switch($step) {
case 0:
$this->greet();
break;
case 10:
$this->greetTags();
break;
case 11;
check_admin_referer('import-upload');
$response = $this->doImportTags();
break;
case 20:
$response = $this->greetHtaccess();
break;
case 21;
check_admin_referer('import-upload');
$response = $this->doConfigureHtaccess();
break;
case 22;
check_admin_referer('mt-configure-htaccess');
$response = $this->doGenerateHtaccess();
break;
}
if (is_wp_error($response)) {
echo '<p><strong>** Error ** ' . htmlspecialchars($response->get_error_message()) . '</strong></p>';
}
$this->_footer();
}
function _header()
{
echo $this->_getAdditionalStyles();
echo '<div class="wrap">';
screen_icon();
echo '<h2>'.__('Movable Type Importer Utilities').'</h2>';
}
function _footer()
{
echo '</div>';
}
function greet()
{ ?>
<div class="narrow">
<p><?php _e('Howdy! This importer provides you some handy utilities to finalize your migration from Movable Type to WordPress.') ?></p>
<p><?php _e('From here you can import your Movable Type tags or create your .htaccess file for redirecting old Movable Type permalinks to the new WordPress structure.') ?></p>
<h2><?php _e('Before Starting') ?></h2>
<p><strong><?php _e('Don&#8217;t be stupid - backup your database before proceeding!') ?></strong></p>
<p><?php _e('This importer assumes you already imported your data from Movable Type with the <a href="?import=mt">Movable Type and TypePad</a> importer. If you haven&#8217;t imported them yet, please go back and run the Movable Type importer first.') ?></p>
<p><?php _e('Depending on selected action, you&#8217;ll be asked to create some special index template in your Movable Type installation to export data. Be sure you still have access to your Movable Type blog and you have permission to create index templates.') ?></p>
<p>
<a class="button-secondary" href="<?php echo add_query_arg('step', 10) ?>"><?php _e('Import Tags'); ?></a>
<a class="button-secondary" href="<?php echo add_query_arg('step', 20) ?>"><?php _e('Generate .htaccess'); ?></a>
</p>
</div>
<?php }
function greetTags()
{ ?>
<h2><?php _e('Template') ?></h2>
<p><?php _e('The default export file generated by Movable Type does&#8217;t include tags. To import your tags you first need to export them from Movable Type using the custom index template below.') ?></p>
<pre class="template"><?php echo htmlentities($this->_getTagsTemplate()) ?></pre>
<?php echo $this->_getTemplateInstructions(); ?>
<h2><?php _e('Go, import my tags!') ?></h2>
<?php wp_import_upload_form(add_query_arg('step', 11)); ?>
<?php }
function doImportTags()
{
global $wpdb;
$upload = $this->_handleUpload();
if (is_wp_error($upload)) {
return $upload;
}
$posts = $this->_parseEntries();
if (is_wp_error($posts)) {
return $posts;
}
echo '<ol>';
foreach($posts as $post) {
// FIXME: post->date doesn't work
if (empty($post->tags)) {
$result = sprintf(__('Skipping empty tags for %s.'), $post->title);
} else if ($postId = post_exists($post->title, $post->content, '')) {
$result = sprintf(__('Setting tags %s for %s.'), $post->tags, $post->title);
wp_set_post_tags($postId, $post->tags);
} else {
$result = sprintf(__('<strong>** Warning **</strong> Post %s not found.'), $post->title);
}
echo '<li>' . $result . '</li>';
}
echo '</ol>';
wp_import_cleanup($this->_uploadId);
do_action('import_done', 'mt-utils');
}
function greetHtaccess()
{ ?>
<h2><?php _e('Template') ?></h2>
<p><?php _e('Altought the default export file generated by Movable Type includes the entry basename, WordPress ignores it and automatically generate a custom permalink loosing the ability to get a reference to the original Movable Type entry.') ?></p>
<p><?php _e('The following custom template is a light version of the original Movable Type export file containing the old basename and a couple of details required to the importer to detect the corresponding post in WordPress. If you already imported tags before, you can use the same template.') ?></p>
<pre class="template"><?php echo htmlentities($this->_getHtaccessTemplate()) ?></pre>
<?php echo $this->_getTemplateInstructions(); ?>
<h2><?php _e('Go, configure my htaccess!') ?></h2>
<?php wp_import_upload_form(add_query_arg('step', 21)); ?>
<?php }
function doConfigureHtaccess()
{
global $wpdb;
$upload = $this->_handleUpload();
if (is_wp_error($upload)) {
return $upload;
}
$posts = $this->_parseEntries();
if (is_wp_error($posts)) {
return $posts;
}
?>
<h2><?php _e('Configure .htaccess') ?></h2>
<form action="<?php echo add_query_arg(array('step' => 22, '_uploadId' => $this->_uploadId)) ?>" method="post">
<?php wp_nonce_field('mt-configure-htaccess') ?>
<h3><label for="template_entry"><?php _e('Template Entry') ?></label></h3>
<p><?php _e('This is the line template for an entry item.') ?><br />
<?php _e('Available placeholders:') ?></p>
<ol>
<li><code>%{wp-id}</code>: <? _e('The WordPress post ID.') ?></li>
<li><code>%{wp-postname}</code>: <? _e('The WordPress post name.') ?></li>
<li><code>%{wp-postdate}</code>: <? _e('The WordPress post date (ex. 2008-10-12).') ?></li>
<li><code>%{wp-postdate-yyyy}</code>: <? _e('The WordPress post year (ex. 2008).') ?></li>
<li><code>%{wp-postdate-mm}</code>: <? _e('The WordPress post month, including leading 0 (ex 10).') ?></li>
<li><code>%{wp-postdate-dd}</code>: <? _e('The WordPress post day, including leading 0 (ex 12).') ?></li>
<li><code>%{mt-basename}</code>: <? _e('The Movable Type original basename.') ?></li>
</ol>
<textarea id="template_entry" name="template_entry" class="template">Redirect 301 /blog/%{wp-postdate-yyyy}/%{wp-postdate-mm}/%{mt-basename} <?php echo get_option('siteurl') ?>/%{wp-postdate-yyyy}/%{wp-postdate-mm}/%{wp-postname}</textarea>
<h3><label for="template_htaccess"><?php _e('Template Htaccess') ?></label></h3>
<p><?php _e('This is the global template for the htaccess.') ?><br />
<?php _e('Available placeholders:') ?></p>
<ol>
<li><code>%{rules}</code>: <? _e('All generated redirection rules.') ?></li>
</ol>
<textarea id="template_htaccess" name="template_htaccess" class="template">%{rules}</textarea>
<p class="submit"><input type="submit" class="button" value="<?php echo __('Submit') ?>"></p>
</form>
<?php }
function doGenerateHtaccess()
{
$upload = $this->_handleUploadedId();
if (is_wp_error($upload)) {
return $upload;
}
$posts = $this->_parseEntries();
if (is_wp_error($posts)) {
return $posts;
}
$templateHtaccess = $_POST['template_htaccess'];
$templateEntry = $_POST['template_entry'];
$generatedHtaccess = '';
$generatedEntries = array();
foreach($posts as $post) {
if ($postId = post_exists($post->title, $post->content, '')) {
$postInstance = get_post($postId, OBJECT);
$postDate = strtotime($postInstance->post_date);
$result = $this->_replacePlaceholdersInHtaccess($templateEntry, array(
'wp-id' => $postInstance->ID, 'wp-postname' => $postInstance->post_name,
'wp-postdate' => date('Y-m-d', $postDate), 'wp-postdate-yyyy' => date('Y', $postDate), 'wp-postdate-mm' => date('m', $postDate), 'wp-postdate-dd' => date('d', $postDate),
'mt-basename' => $post->basename));
} else {
$result = sprintf(__('# ** Warning ** Post %s not found.'), $post->title);
}
$generatedEntries[] = $result;
}
$generatedHtaccess = $this->_replacePlaceholdersInHtaccess($templateHtaccess, array('rules' => implode("\n", $generatedEntries)));
echo '<h2>' . __('The magic .htaccess') . '</h2>';
echo '<textarea class="template" rows="10">' . $generatedHtaccess . '</textarea>';
}
function _getTagsTemplate()
{
return trim('
<mt:Entries lastn="9999">
TITLE: <$mt:EntryTitle$>
BASENAME: <$mt:EntryBasename$>
DATE: <$mt:EntryDate$>
TAGS: <mt:EntryTags glue=", "><$mt:TagName$></mt:EntryTags>
-----
BODY:
<$mt:EntryBody$>
-----
--------
</mt:Entries>');
}
function _getHtaccessTemplate()
{
return trim('
<mt:Entries lastn="9999">
TITLE: <$mt:EntryTitle$>
BASENAME: <$mt:EntryBasename$>
DATE: <$mt:EntryDate$>
-----
BODY:
<$mt:EntryBody$>
-----
--------
</mt:Entries>');
}
function _getAdditionalStyles()
{
return <<<EOS
<style>
.wrap li { padding-left: 15px; list-style-type: decimal; list-style-position: inside; }
pre.template { font: 12px Consolas, Monaco, Courier, monospace; background: #EAEAEA; border: 1px solid #AAAAAA; padding: 5px; }
textarea.template { font: 12px Consolas, Monaco, Courier, monospace; background: #EAEAEA; border: 1px solid #AAAAAA; padding: 5px; width: 99%; }
</style>
EOS;
}
function _getTemplateInstructions()
{
return trim('
<p>' . __('For this task you need to create a new index template in your Movable Type blog.') . '</p>
<ol>
<li>' . __('Go to you blog administration panel, choose <em>Design > Templates > Create Index Template</em> and cut/paste the template above. Be sure to copy the exact template without any additional space or line feed.') . '</li>
<li>' . __('In <code>Template Options</code> use the following settings: <code>Output File => wordpress_export.txt, Template Type => Choose Custom Index Template, Link to File => Leave the field empty, Publishing => Choose statically</code>.') . '</li>
<li>' . __('Save the template, then rebuild it.') . '</li>
<li>' . __("You're almost done. Now download the file from your server and feed this importer!") . '</li>
</ol>');
}
function _parseEntries()
{
$handle = $this->fopen($this->_uploadFile, 'r');
if ($handle == null) {
return new WP_Error('mt_utils_parse_entries', sprintf(__('Unable to parse file %s'), $this->_uploadFile));;
}
$posts = array();
$post = new StdClass;
$context = '';
while ($line = $this->fgets($handle)) {
$line = trim($line);
if ( '-----' == $line ) {
$context = '';
} else if ($line == '--------') {
$posts[] = $post;
$post = new StdClass;
} else if ($line == 'BODY:') {
$context = 'body';
} else if (preg_match('/^DATE: (.*)$/', $line, $matches)) {
list($all, $value) = $matches;
$date = strtotime($value);
$date = date('Y-m-d H:i:s', $date);
$post->date = $date;
} else if (preg_match('/^([A-Z]*): (.*)$/', $line, $matches)) {
list($all, $key, $value) = $matches;
$key = strtolower($key);
$post->$key = $value;
} else {
$line .= "\n";
if ($context == 'body') {
$post->content .= $line;
}
}
}
$this->fclose($handle);
return $posts;
}
function _replacePlaceholdersInHtaccess($htaccess, $mapping)
{
$keys = array_keys($mapping);
$values = array_values($mapping);
// I'm missing lambdas here... :(
$placeholders = array();
foreach($keys as $key) {
$placeholders[] = '%{' . $key . '}';
}
return str_replace($placeholders, $values, $htaccess);
}
function _handleUpload()
{
$file = wp_import_handle_upload();
if (isset($file['error'])) {
return new WP_Error('mt_utils_handle_upload', $file['error']);
}
$this->_uploadFile = $file['file'];
$this->_uploadId = (int) $file['id'];
return true;
}
function _handleUploadedId()
{
$this->_uploadId = (int) $_GET['_uploadId'];
$this->_uploadFile = get_attached_file($this->_uploadId);
}
// The following functions has been extracted from official wordpress files.
// I haven't changed any function name even if the functions shuld be considered protected.
function has_gzip() {
return is_callable('gzopen');
}
function fopen($filename, $mode='r') {
if ( $this->has_gzip() )
return gzopen($filename, $mode);
return fopen($filename, $mode);
}
function feof($fp) {
if ( $this->has_gzip() )
return gzeof($fp);
return feof($fp);
}
function fgets($fp, $len=8192) {
if ( $this->has_gzip() )
return gzgets($fp, $len);
return fgets($fp, $len);
}
function fclose($fp) {
if ( $this->has_gzip() )
return gzclose($fp);
return fclose($fp);
}
}
/**
* Register Importer
*
* @since unknown
* @var MT_Utils
* @name $mt_utils
*/
$mtUtils = new MT_Utils();
register_importer('mt-utils', __('Movable Type Importer Utilities'), __('Utilities to finalize your migration from Movable Type to Wordpress.'), array($mtUtils, 'dispatch'));