# WXRImporter plugin for Movable Type
# Author: Six Apart (http://www.sixapart.com)
# Released under the Artistic License
#
# $Id$

package WXRImporter::Import;
use strict;

use base qw(MT::ErrorHandler);

sub import_contents {
    my $class = shift;
    my %param = @_;
    my $iter  = $param{Iter};
    my $blog  = $param{Blog}
        or return $class->error( MT->translate("No Blog") );
    my $cb = $param{Callback} || sub { };
    my $encoding = $param{Encoding};

    my ( $root_path, $root_url, $relative_path );
    if ( my $p = delete $param{'mt_site_path'} ) {
        $root_path = $root_url = '%r';
    }
    else {
        $root_path = $root_url = '%a';
    }

    if ( $root_path && $root_url ) {
        $relative_path = delete $param{'mt_extra_path'};
        my $path = $root_path;
        if ($relative_path) {
            if ( $relative_path =~ m!\.\.|\0|\|! ) {
                return $class->error(
                    MT->translate(
                        "Invalid extra path '[_1]'",
                        $relative_path
                    )
                );
            }
            $path = File::Spec->catdir( $path, $relative_path );
        }

        ## $path should be local path to file now (we don't create/upload files nor mkpath)

        my $url = $path;
        $url =~ s!\\!/!g;

        $param{'mt_path'} = $path;
        $param{'mt_url'}  = $url;
    }

    if ( exists $param{ImportAs} ) {
    }
    elsif ( exists $param{ParentAuthor} ) {
        require MT::Auth;
        return $class->error(
            MT->translate(
                      "You need to provide a password if you are going to "
                    . "create new users for each user listed in your blog."
            )
            )
            if MT::Auth->password_exists
                && !( exists $param{NewAuthorPassword} );
    }
    else {
        return $class->error(
            MT->translate("Need either ImportAs or ParentAuthor") );
    }
    $cb->("\n");
    my $import_result = eval {
        while ( my $stream = $iter->() )
        {
            my $result = eval { $class->start_import( $stream, %param ); };
            $cb->($@) unless $result;
        }
        $class->errstr ? undef : 1;
    };
    $import_result;
}

sub start_import {
    my $self = shift;
    my ( $stream, %param ) = @_;

    #if (ref($stream) eq 'Fh') {
    #    $stream = WXRImporter::Stream->new($stream);
    #}

    my $xml = do { local $/ = undef; <$stream> }
        || '';
    $xml
        =~ s{<wp:comment_content>(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?</wp:comment_content>} 
             {<wp:comment_content><![CDATA[$1]]></wp:comment_content>}sg;
    use HTML::Entities::Numbered;
    $xml = HTML::Entities::Numbered::name2hex_xml($xml);

    require WXRImporter::WXRHandler;
    my $handler = WXRImporter::WXRHandler->new(
        callback       => $param{Callback},
        blog           => $param{Blog},
        def_cat_id     => $param{DefaultCategoryID},
        convert_breaks => $param{ConvertBreaks},
        ( exists $param{ImportAs} )
        ? ( author => $param{ImportAs} )
        : ( parent => $param{ParentAuthor} ),
        pass        => $param{NewAuthorPassword},
        wp_path     => $param{wp_path},
        mt_path     => $param{mt_path},
        mt_url      => $param{mt_url},
        wp_download => $param{wp_download},
    );

    require MT::Util;
    my $parser = MT::Util::sax_parser();
    $param{Callback}->( ref($parser) . "\n" )
        if MT::ConfigMgr->instance->DebugMode;
    $handler->{is_pp} = ref($parser) eq 'XML::SAX::PurePerl' ? 1 : 0;
    $parser->{Handler} = $handler;
    my $e;
    eval { $parser->parse_string($xml); };

    #eval { $parser->parse_file($stream); };
    $e = $@ if $@;
    if ($e) {
        $param{Callback}->($e);
        return $self->error($e);
    }
    1;
}

sub get_param {
    my $class = shift;
    my ($blog_id) = @_;

    my $blog = MT::Blog->load($blog_id)
        or return $class->error( MT->translate('No Blog') );

    my $param = { blog_id => $blog_id };
    my $label_path;
    if ( $blog->column('archive_path') ) {
        $param->{enable_archive_paths} = 1;
        $label_path = MT->translate('Archive Root');
    }
    else {
        $label_path = MT->translate('Site Root');
    }
    $param->{missing_paths}
        = (    ( defined $blog->site_path || defined $blog->archive_path )
            && ( -d $blog->site_path || -d $blog->archive_path ) ) ? 0 : 1;
    $param;
}

## This package will be removed once WordPress fixes issues
## which it generates non-well formed XML (therefore it's
## not even XML at all).  See:
## http://trac.wordpress.org/ticket/4242
## http://trac.wordpress.org/ticket/4452
#package WXRImporter::Stream;
#
#use Symbol;
#
#use vars qw( $fh );
#sub new {
#    my $class = shift;
#    my $this = bless Symbol::gensym(), $class;
#    tie *$this, $this;
#    $fh = $_[0];
#    return $this;
#}
#
#sub read {
#    my $this = shift;
#    my $res = read($fh, $_[0], $_[1], $_[2] || 0);
#    my $string = $_[0];
#    $string = _encode_wp_comment($string);
#    $_[0] = $string;
#    $res;
#}
#
#sub binmode {
#    my $this = shift;
#    binmode $fh;
#}
#
#sub eof {
#    my $this = shift;
#    eof $fh;
#}
#
#sub close {
#    my $this = shift;
#    close $fh;
#}
#
#*READ   = \&read;
#*BINMODE = \&binmode;
#*EOF    = \&eof;
#*CLOSE  = \&close;
#
#sub TIEHANDLE {
#    return $_[0] if ref($_[0]);
#    my $class = shift;
#    my $this = bless Symbol::gensym(), $class;
#    $fh = $_[0];
#    return $this;
#}
#
#sub _encode_wp_comment {
#    my ($str) = @_;
#
#    use HTML::Entities::Numbered;
#    $str = name2hex_xml($str);
#    return $str;
#}

1;

__END__
