Current location

narf Source control manager Git

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshtrom <shtrom@1991c358-8f32-0410-a49a-990740bdf4c2>2014-04-21 12:13:09 +0000
committershtrom <shtrom@1991c358-8f32-0410-a49a-990740bdf4c2>2014-04-21 12:13:09 +0000
commit020712087b273f244e234ff2cf0d2ddf07c2bf2a (patch)
treefe11a3df7a73f0ab3afaefe0917e9d954fe7322f /WordPressImport.pl
parent143ef40445b76d88550be866a26ec56131cc450f (diff)
Import SimplePHPBlog->WordPress import script from http://www.innerhippy.com/wordpress/releases/WordPressImport.pl
git-svn-id: svn+ssh://scm.narf.ssji.net/svn/shtrom/scripts@1801 1991c358-8f32-0410-a49a-990740bdf4c2
Diffstat (limited to 'WordPressImport.pl')
-rw-r--r--WordPressImport.pl833
1 files changed, 833 insertions, 0 deletions
diff --git a/WordPressImport.pl b/WordPressImport.pl
new file mode 100644
index 0000000..81a188d
--- /dev/null
+++ b/WordPressImport.pl
@@ -0,0 +1,833 @@
+#!/usr/bin/perl -w
+#-*-perl-*-
+# $UpstreamSource: /opt/cvs/root/scripts/blog/WordPressImport.pl,v $
+# $UpstreamRevision: 1.7 $
+# $UpstreamDate: 2009/02/03 20:45:13 $
+# $UpstreamAuthor: will $
+# $Source: /opt/cvs/root/scripts/blog/WordPressImport.pl,v $
+# $Revision: 1.7 $
+# $Date: 2009/02/03 20:45:13 $
+# $Author: will $
+
+=pod
+
+=head1 SYNOPSIS
+
+B<WordPressImport.pl> <options> [command]
+
+=head1 DESCRIPTION
+
+B<WordPressImport.pl> is a migration utility to convert a SimplePHPBlog
+directory to a WordPress MySQL database.
+
+SimplePHPBlog stores the entire blog in a single directory. This utilty
+will extract posts, comments, links, blocks and categories and write them
+into the WordPress MySQL database.
+
+It can be used on a fresh WordPress installation or an existing one, though
+the former is recommended for simplicity.
+
+Running this import utility multiple times will not duplicate entries in your database, all entries are first check to see if they already exist.
+
+B<Ratings Plugin>
+
+You need to have the 'postratings' plugin installed in order for the ratings to be
+imported - this can be overriden using the -noratings switch.
+
+To install this plugin, goto this page http://wordpress.org/extend/plugins/wp-postratings
+and follow the installation instructions.
+
+Don't forget to activate the plugin after you've installed it!
+
+B<Operation>
+
+This utility will import the folling into the database:
+
+ SimplePHPBlog Wordpress
+ ------------- ---------
+ Posts Posts
+ Comments Comments
+ Categories Categories
+ Links Blogroll
+ Static Pages
+ Blocks Pages
+
+B<Simple Instructions>
+
+Starting from a fresh installation for WordPress, here are the steps:
+ 1. Create wordpress database, or run B<WordPressImport.pl -create> command (See below)
+ 2. Extract postratings plugin to wp-content/plugins directory (optional)
+ 3. Edit wp-content/themes/<your theme>/index.php and after:
+ <?php while (have_posts()) : the_post(); ?>
+ insert:
+ <?php if(function_exists('the_ratings')) { the_ratings(); } ?>
+ 4. Open browser to your WordPress site
+ 5. Enter Blog Title and email fields
+ 6. Click "Install Wordpress"
+ 7. Login with supplied password
+ 8. Click "My Profile" in top right hand corner
+ 9. Change admin email password
+ 10. Click on "Plugins"
+ 11. Activate "WP-PostRatings" and "WP-PostRatings Widget" plugins (if installed)
+ 12. Run B<WordPressImport.pl -import> command (See Below)
+ 13. Check any errors or problems and continue using WordPress
+
+=cut
+
+use strict;
+use DBI();
+use Date::Format;
+use Getopt::Long;
+
+my $version=0.7;
+
+my %OPTS = ( host => 'localhost',
+ user => 'root',
+ database => 'wordpress',
+ wp_username => 'wordpress',
+ verbose => 0);
+
+my @OPTIONS= (
+ "user=s",
+ "host=s",
+ "database=s",
+ "password:s",
+ "wp_password=s",
+ "wp_username=s",
+ "import=s",
+ "noratings",
+ "create",
+ "drop",
+ "help",
+ "verbose+",
+);
+
+sub usage {
+ print "
+Usage: $0 [options] command
+options:
+ -host - database hostname (def: $OPTS{host})
+ -user - database username (def: $OPTS{user})
+ -password - database password (prompted if empty)
+ -database - database name (def: $OPTS{database})
+ -wp_username - wordpress username (def: $OPTS{wp_username})
+ -wp_password - wordpress database password (see wp-config.php)
+ -noratings - do not import ratings
+ -help - this help
+ -verbose - verbose output - specify multiple times for increased verbosity
+commands:
+ -import [dir] - import blog from directory dir
+ -drop - drop $OPTS{database} database
+ -create - create $OPTS{database} and set permissions
+
+ current version is $version
+";
+ exit 0;
+}
+
+=pod
+
+=head1 OPTIONS
+
+ -host - database hostname (default: localhost)
+ -user - database username (default: root)
+ -password - database password. If no password is supplied then you'll
+ be prompted for on from the console.
+ -database - database name (default: 'wordpress')
+ -wp_password - wordpress database password (must match password in wp-config.php)
+ -wp_username - wordpress username (def: 'wordpress')
+ -noratings - do not import ratings (in case postratings plugin not installed)
+ -help - this helpful help
+ -verbose - verbose output - specify multiple times for increased verbosity
+
+
+=head1 COMMANDS
+
+ -import [dir] - import blog from directory dir
+ -drop - drop wordpress database (caution: 'drop' is database speak for 'trash')
+ -create - create wordpress database and set permissions
+
+=head1 EXAMPLES
+
+B<Conditions>
+
+SimplePHPBlog blog in a directory called 'sphpblog'.
+
+username/password for the MySQL database is "root/trickypassword". The assumption is that
+you have correctly installed and configured MySQL. If your database is across a network then
+ensure that you have granted correct permissions to this username in order that they in turn
+can grant correct permissions to the 'wordpress' user.
+
+The password in wp-config.php file is "bananas". This is reqired for WordPress to
+read and write to/from the database
+
+The database is on the current machine, localhost
+
+1. First, we start from scratch and completely delete the wordpress database:
+
+B<./WordPressImport.pl -host localhost -user root -password trickypassword -drop>
+
+2. Now we recreate it. We need the -wp_password option for the database to authenticate WordPress
+
+B<./WordPressImport.pl -host localhost -user root -password trickypassword -wp_password bananas -create>
+
+3. Import the SimplePHPBlog blog directory "sphpblog/"
+
+B<./WordPressImport.pl -host localhost -user root -password trickypassword -wp_password bananas -import sphpblog/>
+
+If you do not supply a value to the -password option, then you'll be prompted for it on the command line. If the -password option is not supplied at all, then it assumes that you have no password in your database (and you should hang your head in shame).
+
+You'll see a summary of the data imported. To increase verbosity, supply the -v (-verbose) option. Repeated switches will increase the verbosity (-v -v -v is very verbose).
+
+=head1 BUGS
+
+The category hierarchy is not preservered at present - not convinced it was particulalry useful anyway in SimplePHPBlog
+
+This utility was tested with SimplePHPBlog version 0.4.5 and 0.5.11
+
+=head1 REVISION HISTORY
+
+ Revision 0.6 2008/12/09
+
+ 0.1 Initial revision
+ 0.2 fixed ratings
+ 0.3 Now handles posts with multiple categories. Parses html code from blocks.
+ 0.4 Debug bug...
+ 0.5 Support pre-0.4.6.1 versions
+ 0.6 fixed import bug on wp_term_relationships table
+ 0.7 ratings needs to be written as floating point
+
+=head1 AUTHOR
+
+This implementation written by Will Hall
+I<dev@innerhippy.com>
+
+=head1 COPYRIGHT and LICENSE
+
+Copyright 2008 Innerhippy Software Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+Redistributions of source code must retain the above copyright notice,this
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY WILLIAM HALL`AS IS' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL WILLIAM HALL BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are
+those of the author and should not be interpreted as representing official
+policies, either expressed or implied, anywhere.
+
+=head1 SEE ALSO
+
+=head1 NEXT TOPIC
+
+=cut
+
+my $DBH;
+
+usage() if !GetOptions(\%OPTS,@OPTIONS) or $OPTS{help};
+
+if ($OPTS{drop}) {
+ print "This will delete the whole database - sure? [y/N] ";
+ chomp (my $ans = <>);
+ $ans eq 'y' || exit;
+ dbConnect($OPTS{database});
+ dropDatabase();
+}
+
+if ($OPTS{create}) {
+ dbConnect('mysql');
+ createDatabase();
+}
+
+if ($OPTS{import}) {
+ dbConnect($OPTS{database});
+
+ my $wp = WordPressImport->new($OPTS{import});
+ my $categories = $wp->get_categories();
+ addCategories ($categories);
+ addLinks ($wp->get_links);
+ addPosts ($wp->get_posts, $categories);
+ addStatic ($wp->get_static);
+ addBlocks ($wp->get_blocks);
+ updateCatCount();
+}
+
+loggit ("ok");
+$DBH && $DBH->disconnect;
+
+sub loggit {
+ my ($str, $level) = @_;
+ $level||=0;
+ return if $level > $OPTS{verbose};
+ print STDOUT "$str\n";
+}
+
+sub error_exit {
+ loggit "Error: @_\n";
+ $DBH && $DBH->disconnect;
+ exit 1;
+}
+
+sub slug {
+ my $str = shift;
+ $str =~ s/[ ]/-/g;
+ return lc $str;
+}
+sub updateCatCount {
+ # Multiple rows returned so can't use runSelSQL
+ my $sth = $DBH->prepare("SELECT term_taxonomy_id
+ FROM wp_term_relationships group by term_taxonomy_id") or die $DBH->errstr;
+ $sth->execute(@_);
+ my @cats;
+ while ( my $row = $sth->fetchrow_arrayref) {
+ push @cats, $row->[0];
+ }
+ $sth->finish;
+ foreach my $taxonomy_id (@cats) {
+ runSQL ("UPDATE wp_term_taxonomy tt
+ SET tt.count = ( select count(*)
+ FROM wp_term_relationships tr
+ WHERE tr.term_taxonomy_id = tt.term_taxonomy_id )
+ WHERE tt.term_taxonomy_id = ?", $taxonomy_id);
+ }
+}
+
+sub addEntry {
+ my ($cats, $subject, $date, $content, $type) = @_;
+
+ if ( (runSelSQL ("SELECT * FROM wp_posts
+ WHERE post_title=?
+ AND post_type=?", $subject, $type))[0]) {
+ loggit ("Post exists: '$subject'", 1);
+ return;
+ }
+ runSQL ("INSERT INTO wp_posts (
+ post_author, post_date, post_date_gmt, post_content, post_title,
+ post_category, post_excerpt, post_password, post_name, to_ping,
+ pinged, post_modified, post_modified_gmt, post_content_filtered,
+ guid, post_mime_type, post_type)
+ VALUES (1,?,?,?,?,?,'','',?,'','',?,?,'',0,'',?)",
+ $date, $date, $content, $subject, 0,
+ slug($subject), $date, $date, $type);
+
+ my $siteurl = (runSelSQL ("SELECT option_value FROM wp_options WHERE option_name='siteurl'"))[0]
+ || error_exit "Cannot get siteurl from options table";
+ my $insert_id = $DBH->last_insert_id(undef, undef, 'wp_posts', 'ID');
+ runSQL ("UPDATE wp_posts SET guid=? WHERE post_title=?", "$siteurl/?p=$insert_id", $subject);
+
+ foreach my $category (@$cats) {
+ my $category_id=(runSelSQL (qq{SELECT term_taxonomy_id
+ FROM wp_term_taxonomy,wp_terms
+ WHERE wp_term_taxonomy.term_id = wp_terms.term_id
+ AND wp_terms.name = ?}, $category))[0]
+ || die "lost category '$category'";
+
+
+ runSQL ("INSERT INTO wp_term_relationships (object_id, term_taxonomy_id)
+ VALUES (?,?)", $insert_id, $category_id);
+ }
+ return $insert_id;
+}
+
+sub addStatic {
+ my ($static) = @_;
+ my ($added, $skipped)=(0,0);
+
+ foreach my $s (@$static) {
+ my $id = addEntry (['Uncategorized'], $s->{subject},$s->{date},$s->{content},'page');
+ if ($id) {
+ $added++;
+ loggit ("Added pages '$s->{subject}'", 1);
+ } else {
+ $skipped++;
+ }
+ }
+ loggit ("Added $added, skipped $skipped static as pages");
+}
+
+sub addBlocks {
+ my ($blocks) = @_;
+ my ($added, $skipped)=(0,0);
+
+ foreach my $b (@$blocks) {
+ my $id = addEntry (['Uncategorized'], $b->{subject},"0000-00-00 00:00:00" ,$b->{content},'page');
+ if ($id) {
+ $added++;
+ loggit ("Added blocks '$b->{subject}'", 1);
+ } else {
+ $skipped++;
+ }
+ }
+ loggit ("Added $added, skipped $skipped blocks as pages");
+}
+
+sub addPosts {
+ my ($posts, $categories) = @_;
+ unless ($OPTS{noratings}) {
+ (runSelSQL("SELECT table_name
+ FROM information_schema.tables
+ WHERE table_schema = '$OPTS{database}'
+ AND table_name = 'wp_ratings'"))[0]
+ || error_exit "postratings plugin not installed or activated";
+ }
+
+ my ($added, $skipped)=(0,0);
+ foreach my $p (@$posts) {
+ my @cat_names;
+ foreach (@{$p->{categories}}) {
+ push @cat_names, $categories->{$_} || "Uncategorized"; # This should exist
+ }
+ my $id = addEntry (\@cat_names, $p->{subject},$p->{date},$p->{content},'post');
+ if ($id) {
+ $added++;
+ my $n = addComments ($p->get_comments, $id);
+ loggit ("Added post '$p->{subject}' with $n comments", 1);
+ addRating ($p->{points}, $p->{votes}, $id, $p->{subject});
+ } else {
+ $skipped++;
+ }
+ }
+ loggit ("Added $added, skipped $skipped posts");
+}
+
+sub addRating {
+ my ($points, $votes, $id, $subject) = @_;
+ $OPTS{noratings} && return;
+ my $max = (runSelSQL ("SELECT option_value FROM wp_options WHERE option_name='postratings_max'"))[0];
+
+ $points = sprintf ("%.0f", ($points||0)*$max/5);
+ my $avg = sprintf ("%.2f", ($points||0)/($votes||1)); # average rating score for max rating = 5
+
+ runSQL ("INSERT INTO wp_postmeta (post_id, meta_key, meta_value)
+ VALUES (?,'ratings_users',?), (?, 'ratings_score', ?), (?, 'ratings_average', ?)",
+ $id, $votes, $id, $points, $id, $avg);
+}
+
+sub addComments {
+ my ($comments, $id) = @_;
+ my $i=0;
+ foreach my $c (@$comments) {
+ $i++;
+ runSQL ("INSERT INTO wp_comments (comment_post_ID, comment_author,
+ comment_author_email, comment_author_url, comment_author_IP,
+ comment_date, comment_date_gmt, comment_content, comment_agent,
+ comment_type)
+ VALUES (?, ?, ?, ?, '', ?, ?, ?, '', '')",
+ $id, $c->{name}, $c->{email}, $c->{url}, $c->{date}, $c->{date}, $c->{content});
+ }
+ # Update comment count
+ runSQL ("UPDATE wp_posts set comment_count=? where ID=?", $i, $id);
+ return $i;
+}
+sub addCategories {
+ my $cat = shift;
+ my ($added, $skipped) = (0,0);
+
+ # Make sure there's one called 'Uncategorized'
+ unless ( (runSelSQL ("SELECT term_id FROM wp_terms
+ WHERE name='Uncategorized'"))[0]) {
+ # find next category number free
+ my $max;
+ $max = $_ foreach (sort keys %$cat);
+ $cat->{$max +1} = 'Uncategorized';
+ }
+
+
+ foreach (keys %$cat) {
+ if ((runSelSQL("SELECT term_id,name from wp_terms WHERE name=?", $cat->{$_}))[0]) {
+ loggit ("category exists: $cat->{$_}", 1);
+ $skipped++;
+ next;
+ }
+ my $slug = slug ($cat->{$_});
+ runSQL("INSERT INTO wp_terms (name,slug,term_group) VALUES (?, ?, 0)", $cat->{$_}, $slug);
+ my $insert_id = $DBH->last_insert_id(undef, undef, 'wp_terms', 'term_id');
+ runSQL("INSERT INTO wp_term_taxonomy (term_id, taxonomy, description, parent, count)
+ VALUES (?, 'category','',0,1)", $insert_id);
+ $added++;
+ }
+ loggit ("Added $added, skipped $skipped categories");
+}
+
+sub addLinks {
+ my $links = shift;
+ my ($added, $skipped) = (0,0);
+ my ($taxonomy_id, $count) = runSelSQL (
+ "SELECT tt.term_taxonomy_id, tt.count
+ FROM wp_term_taxonomy AS tt, wp_terms AS t
+ WHERE t.name='Blogroll'
+ AND tt.term_id = t.term_id
+ AND tt.taxonomy='link_category'");
+ $taxonomy_id || die "no link_category";
+
+ foreach my $name (keys %$links) {
+ if ( (runSelSQL ("SELECT COUNT(*) FROM wp_links WHERE
+ link_url=? AND link_name=?", $links->{$name}, $name))[0]) {
+ loggit ("Link exists: $name", 1);
+ $skipped++;
+ next;
+ }
+ runSQL ("INSERT INTO wp_links (link_url, link_name, link_image, link_target,
+ link_description, link_rel, link_notes, link_rss)
+ VALUES (?, ?, '', '', '', '', '', '')", $links->{$name}, $name);
+ my $insert_id = $DBH->last_insert_id(undef, undef, 'wp_links', 'link_id');
+ runSQL ("INSERT INTO wp_term_relationships (object_id, term_taxonomy_id) VALUES (?,?)", $insert_id, $taxonomy_id);
+ $count++;
+ $added++;
+ }
+ $added && runSQL ("UPDATE wp_term_taxonomy SET count=? WHERE term_taxonomy_id=?", $count, $taxonomy_id);
+ loggit ("Added $added, skipped $skipped links");
+}
+
+sub runSelSQL {
+ my $sql = shift;
+ loggit (qq{SQL:"$sql"}, 2);
+ @_ && loggit (qq{ARGS:"@_"}, 3);
+ my $sth = $DBH->prepare($sql) or die $DBH->errstr;
+ $sth->execute(@_);
+ my @arr = $sth->fetchrow_array;
+ $sth->finish;
+ return @arr;
+}
+
+sub runSQL {
+ my $sql = shift;
+ loggit (qq{SQL:"$sql"}, 2);
+ @_ && loggit (qq{ARGS:"@_"}, 3);
+ my $sth = $DBH->prepare($sql) or die $DBH->errstr;
+ $sth->execute(@_);
+}
+
+sub dropDatabase {
+ runSQL ("DROP DATABASE $OPTS{database}");
+}
+
+sub createDatabase {
+ defined $OPTS{wp_password} or error_exit "need -wp_password to specify password";
+
+ runSQL("CREATE DATABASE $OPTS{database}");
+ runSQL("GRANT ALL PRIVILEGES ON $OPTS{database}.* to '$OPTS{wp_username}'\@'localhost'
+ IDENTIFIED BY ?", $OPTS{wp_password});
+ runSQL("FLUSH PRIVILEGES");
+}
+
+sub dbConnect {
+ my $database = shift;
+ my $password = $OPTS{password};
+
+ # Connect to the database.
+ if (!defined $password) {
+ $password = '';
+ }
+ elsif ($password eq '') {
+ # empty password supplied - prompt for value
+ print "password: ";
+ system 'stty', '-echo';
+ chomp ($password = <>);
+ system 'stty', 'echo';
+ print "\n";
+ }
+ $DBH = DBI->connect("DBI:mysql:database=$database:host=$OPTS{host}",
+ "$OPTS{user}", "$password",
+ {'RaiseError' =>1});
+}
+
+package WordPressImport;
+
+use strict;
+use warnings;
+
+sub new {
+ my ($class, $dir) = @_;
+ my $self = {
+ categories => {},
+ links => {},
+ static => [],
+ blocks => [],
+ posts => [],
+ };
+
+ bless $self, $class;
+ $self->import_dir($dir);
+ return $self;
+}
+
+sub parse_fields {
+ my ($h, $file, $str) = @_;
+ open IN, $file or die "Cannot open $file:$!";
+ local $/;
+ $_=<IN>;
+ close IN;
+ while ( s/^([a-zA-Z]+)\|(.*?)(\||$)//s) {
+ my ($p, $v) = ($1, $2);
+ $p =~ /$str/ and $h->{lc $p} = qq{$v};
+ }
+}
+
+sub parse_legacy_fields {
+ # Old format (pre-0.4.6.1) entries have no key words (bit of a hack)
+ my ($h, $file,$f1, $f2) = @_;
+ open IN, $file or die "Cannot open $file:$!";
+ local $/;
+ $_=<IN>;
+ close IN;
+ ($h->{$f1}, $h->{$f2}) = /^(.*)\|\d+\|(.*)$/s;
+}
+
+
+sub num_posts {
+ my $self = shift;
+ return scalar @{$self->{posts}};
+}
+
+sub get_posts {
+ my $self = shift;
+ return $self->{posts}
+}
+
+sub get_static {
+ my $self = shift;
+ return $self->{static}
+}
+
+
+sub get_categories {
+ my $self = shift;
+ return $self->{categories};
+}
+
+sub get_links {
+ my $self = shift;
+ return $self->{links};
+}
+
+sub get_blocks {
+ my $self = shift;
+ return $self->{blocks};
+}
+
+sub get_category {
+ my ($self, $index) = @_;
+ $self->{categories}{$index} || die "bad category";
+ return $self->{categories}{$index};
+}
+
+sub import_dir {
+ my ($self, $dir) = @_;
+ local(*DIR);
+ opendir (DIR, $dir) or die "Cannot open dir $dir: $!";
+ foreach (sort grep !/^\.+$/, readdir(DIR)) {
+ -d "$dir/$_" && $self->import_dir ("$dir/$_");
+ /^(entry[\d-]+)\.txt$/ && $self->add_post("$dir/$1");
+ /^categories\.txt$/ && $self->add_category("$dir/$_");
+ /^static[\d-]+(\.txt)?$/ && $self->add_static("$dir/$_");
+ /^blocks\.txt$/ && $self->add_blocks("$dir/$_");
+ /^links\.txt$/ && $self->add_links("$dir/$_");
+ }
+}
+
+sub format_date {
+ my ($s) = @_;
+ my ($year, $month, $day, $hour, $min, $sec) = ($s =~ /\/.*(\d\d)(\d\d)(\d\d)-(\d\d)(\d\d)(\d\d)/);
+ return "20$year-$month-$day $hour:$min:$sec"; # Y2K compliant ish...
+}
+
+sub sanitize {
+ my ($s) = shift;
+ no warnings;
+ $$s =~ s/\[(\/)?b\]/<$1strong>/g;
+ $$s =~ s/\[(\/)?i\]/<$1em>/g;
+ $$s =~ s/\[url=(.*) new=.*\](.*)\[\/url\]/<a href="$1">$2<\/a>/g;
+ $$s =~ s/\[img=(.*)\]/<img src=$1\/>/g;
+ if ( $$s =~ s/\[[\/]?html\]//g) {
+ $$s =~ s/&lt;/</g;
+ $$s =~ s/&gt;/>/g;
+ $$s =~ s/&quot;/"/g;
+ }
+}
+
+sub add_static {
+ my ($self, $file) = @_;
+ push @{$self->{static}}, WordPressImport::Static->new ($file);
+}
+
+sub add_post {
+ my ($self, $dir) = @_;
+
+ # Get post
+ my $post = WordPressImport::Post->new("${dir}.txt");
+
+ # Get ratings and comments
+ $post->add_data($dir);
+
+ # Store post
+ push @{$self->{posts}}, $post;
+}
+
+sub add_links {
+ my ($self, $file) = @_;
+ open IN, $file or die "Cannot open $file:$!";
+ my @arr=split(/\|/s, <IN>);
+ for (my $i=0; $i<= $#arr; $i += 2) {
+ $self->{links}{$arr[$i]} = $arr[$i +1];
+ }
+ close IN;
+}
+
+sub add_blocks {
+ my ($self, $file) = @_;
+ open IN, $file or die "Cannot open $file:$!";
+ local $/;
+ $_=<IN>;
+ close IN;
+ my @arr=split(/\|/s);
+ for (my $i=0; $i<= $#arr; $i += 2) {
+ push @{$self->{blocks}}, WordPressImport::Block->new ($arr[$i], $arr[$i +1]);
+ }
+}
+
+
+sub add_category {
+ my ($self, $file) = @_;
+ open IN, $file or die "Cannot open $file:$!";
+ local $/;
+ $_=<IN>;
+ close IN;
+ $self->{categories}{$1}=$2 while (s/^(\d+)\|([\w ]+)\|\d+\|?//);
+}
+
+sub print_categories {
+ my ($self) = shift;
+ foreach (keys %{$self->{categories}}) {
+ print "$_ : $self->{categories}{$_}\n";
+ }
+}
+
+package WordPressImport::Post;
+
+sub new {
+ my ($class, $file) = @_;
+ my $self = {
+ date => undef,
+ subject => undef,
+ categories => undef,
+ content => undef,
+ comments => [],
+ points => undef,
+ votes => undef,
+ };
+ bless $self, $class;
+ $self->{date} = WordPressImport::format_date ($file);
+ WordPressImport::parse_fields ($self, $file, "SUBJECT|CONTENT|CATEGORIES");
+ $self->{content} || WordPressImport::parse_legacy_fields ($self, $file, "subject", "content");
+ $self->{categories} ||=0; # Account for no category in post (seen once)
+ # A nasty kludge - but accommodate for posts with multiple categories
+ # by redefining categories as an array. Yuk.
+ $self->{categories} = [ split ",", $self->{categories} ];
+ WordPressImport::sanitize (\$self->{content});
+ return $self;
+}
+
+sub num_comments {
+ my ($self) = shift;
+ return scalar @{$self->{comments}};
+}
+
+sub get_comments {
+ my ($self) = shift;
+ return $self->{comments};
+}
+
+sub add_comments {
+ my ($self, $dir) = @_;
+ -d $dir || return;
+ local(*DIR);
+ opendir (DIR, $dir) or die "Cannot open dir $dir: $!";
+ foreach (grep /\.txt$/, readdir(DIR)) {
+ push @{$self->{comments}}, WordPressImport::Comment->new ("$dir/$_");
+ }
+}
+
+sub add_rating {
+ my ($self, $file) = @_;
+ WordPressImport::parse_fields ($self, $file, "points|votes");
+ $self->{points} || die "no points";
+ $self->{votes} || die "no votes";
+}
+
+sub add_data {
+ my ($self, $dir) = @_;
+ -d $dir || return;
+ local(*DIR);
+ my $cm;
+ opendir (DIR, $dir) or die "Cannot open dir $dir: $!";
+ foreach (grep !/^\.+$/, readdir(DIR)) {
+ /^comments$/ && $self->add_comments("$dir/$_");
+ /^rating.txt$/ && $self->add_rating("$dir/$_");
+ }
+}
+
+package WordPressImport::Comment;
+
+sub new {
+ my ($class, $file) = @_;
+ my $self = {
+ date => undef,
+ name => undef,
+ content => undef,
+ email => "",
+ url => "",
+ };
+ bless $self, $class;
+ $self->{date} = WordPressImport::format_date($file);
+ my $newdate = WordPressImport::format_date($file);
+ WordPressImport::parse_fields ($self, $file, "NAME|CONTENT|EMAIL|URL");
+ $self->{content} || WordPressImport::parse_legacy_fields ($self, $file, "name", "content");
+ WordPressImport::sanitize (\$self->{content});
+ return $self;
+}
+
+package WordPressImport::Static;
+sub new {
+ my ($class, $file) = @_;
+ my $self = {
+ date => undef,
+ subject => undef,
+ content => undef,
+ };
+ bless $self, $class;
+ $self->{date} = WordPressImport::format_date($file);
+ WordPressImport::parse_fields ($self, $file, "SUBJECT|CONTENT");
+ $self->{content} || WordPressImport::parse_legacy_fields ($self, $file, "subject", "content");
+ WordPressImport::sanitize (\$self->{content});
+ return $self;
+}
+
+package WordPressImport::Block;
+sub new {
+ my ($class, $subject, $content) = @_;
+ my $self = {
+ subject => undef,
+ content => undef,
+ };
+ bless $self, $class;
+ $self->{subject} = $subject;
+ $self->{content} = $content;
+ WordPressImport::sanitize (\$self->{content});
+ return $self;
+}
+
+1