KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.4.62
System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
User : www ( 80)
PHP Version : 8.3.8
Disable Function : NONE
Directory :  /domains/fatshado/cgi-bin/MT/lib/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /domains/fatshado/cgi-bin/MT/lib/MT.pm
# Copyright 2001, 2002 Benjamin Trott. This code cannot be redistributed without
# permission from www.movabletype.org.
#
# $Id: MT.pm,v 1.108 2002/10/08 05:38:48 btrott Exp $

package MT;
use strict;

use vars qw( $VERSION );
$VERSION = '2.5';

use MT::ConfigMgr;
use MT::Object;
use MT::Blog;
use MT::Util qw( start_end_day start_end_week start_end_month
                 archive_file_for get_entry );
use File::Spec;
use Fcntl qw( LOCK_EX );

use MT::ErrorHandler;
@MT::ISA = qw( MT::ErrorHandler );

sub version_number {
    (my $ver = $VERSION) =~ s/[^\d\.].*$//;
    $ver;
}

sub version_slug {
    return <<SLUG;
Powered by Movable Type
Version $VERSION
http://www.movabletype.org/
SLUG
}

sub new {
    my $class = shift;
    my $mt = bless { }, $class;
    $mt->init(@_) or
        return $class->error($mt->errstr);
    $mt;
}

sub init {
    my $mt = shift;
    my %param = @_;
    ## Initialize the language to English in case any errors occur in
    ## the rest of the initialization process.
    $mt->set_language('en_us');
    my $cfg = $mt->{cfg} = MT::ConfigMgr->instance;
    my($cfg_file);
    unless ($cfg_file = $param{Config}) {
        for my $f (qw( mt.cfg )) {
            $cfg_file = $f, last if -r $f;
        }
    }
    if ($cfg_file) {
        $cfg->read_config($cfg_file) or
            return $mt->error($cfg->errstr);
    }
    if (my $dir = $param{Directory}) {
        $mt->{mt_dir} = $dir;
    } elsif ($cfg_file) {
        my($vol, $mt_dir, $fname) = File::Spec->splitpath($cfg_file);
        $mt->{mt_dir} = $mt_dir || './';
    }
    my %default_dirs = (
        TemplatePath => 'tmpl',
        ImportPath => 'import',
        PluginPath => 'plugins',
        SearchTemplatePath => 'search_templates',
    );
    for my $meth (keys %default_dirs) {
        $cfg->$meth(File::Spec->catfile($mt->{mt_dir}, $default_dirs{$meth}))
            unless defined $cfg->$meth();
    }
    if ($cfg->ObjectDriver eq 'DBI::mysql') {
        my $pass_file = File::Spec->catfile($mt->{mt_dir}, 'mt-db-pass.cgi');
        local *FH;
        if (open FH, $pass_file) {
            chomp(my $pass = <FH>);
            close FH;
            $pass =~ s!^\s*!!;
            $pass =~ s!\s*$!!;
            $cfg->DBPassword($pass);
        }
    }
    MT::Object->set_driver($cfg->ObjectDriver)
        or return $mt->error(MT::ObjectDriver->errstr);
    $mt->set_language($cfg->DefaultLanguage);
    $mt->{__rebuilt} = {};
    $mt->{__cached_maps} = {};
    $mt->{__cached_templates} = {};
    my $plugin_dir = $cfg->PluginPath;
    local *DH;
    if (opendir DH, $plugin_dir) {
        my @p = readdir DH;
        for my $plugin (@p) {
            next if $plugin !~ /\.pl$/;
            $plugin = File::Spec->catfile($plugin_dir, $plugin);
            eval { require $plugin };
            warn($@), next if $@;
        }
        closedir DH;
    }
    $mt;
}

sub rebuild {
    my $mt = shift;
    my %param = @_;
    my $blog;
    unless ($blog = $param{Blog}) {
        my $blog_id = $param{BlogID};
        $blog = MT::Blog->load($blog_id) or
            return $mt->error(
                $mt->translate("Load of blog '[_1]' failed: [_2]",
                    $blog_id, MT::Blog->errstr));
    }
    my $at = $blog->archive_type || '';
    my @at = split /,/, $at;
    if (my $set_at = $param{ArchiveType}) {
        my %at = map { $_ => 1 } @at;
        return $mt->error(
            $mt->translate("Archive type '[_1]' is not a chosen archive type",
                $set_at)) unless $at{$set_at};
        @at = ($set_at);
    }
    if (@at) {
        require MT::Entry;
        my %arg = ('sort' => 'created_on', direction => 'descend');
        if ($param{Limit}) {
            $arg{offset} = $param{Offset};
            $arg{limit} = $param{Limit};
        }
        my $iter = MT::Entry->load_iter({ blog_id => $blog->id,
                                          status => MT::Entry::RELEASE() },
            \%arg);
        my $cb = $param{EntryCallback};
        while (my $entry = $iter->()) {
            $cb->($entry) if $cb;
            for my $at (@at) {
                if ($at eq 'Category') {
                    my $cats = $entry->categories;
                    for my $cat (@$cats) {
                        $mt->_rebuild_entry_archive_type(
                            Entry => $entry, Blog => $blog,
                            Category => $cat, ArchiveType => 'Category'
                        ) or return;
                    }
                } else {
                    $mt->_rebuild_entry_archive_type( Entry => $entry,
                                                      Blog => $blog,
                                                      ArchiveType => $at )
                        or return;
                }
            }
        }
    }
    unless ($param{NoIndexes}) {
        $mt->rebuild_indexes( Blog => $blog ) or return;
    }
    1;
}

sub rebuild_entry {
    my $mt = shift;
    my %param = @_;
    my $entry = $param{Entry} or
        return $mt->error($mt->translate("Parameter '[_1]' is required",
            'Entry'));
    my $blog;
    unless ($blog = $param{Blog}) {
        my $blog_id = $entry->blog_id;
        $blog = MT::Blog->load($blog_id) or
            return $mt->error($mt->translate("Load of blog '[_1]' failed: [_2]",
                $blog_id, MT::Blog->errstr));
    }
    my $at = $blog->archive_type;
    if ($at && $at ne 'None') {
        my @at = split /,/, $at;
        for my $at (@at) {
            if ($at eq 'Category') {
                my $cats = $entry->categories;
                for my $cat (@$cats) {
                    $mt->_rebuild_entry_archive_type(
                        Entry => $entry, Blog => $blog,
                        ArchiveType => $at, Category => $cat,
                    ) or return;
                }
            } else {
                $mt->_rebuild_entry_archive_type( Entry => $entry,
                                                  Blog => $blog,
                                                  ArchiveType => $at
                ) or return;
            }
        }
    }

    ## The above will just rebuild the archive pages for this particular
    ## entry. If we want to rebuild all of the entries/archives/indexes
    ## on which this entry could be featured etc., however, we need to
    ## rebuild all of the entry's dependencies. Note that all of these
    ## are not *necessarily* dependencies, depending on the usage of tags,
    ## etc. There is not a good way to determine exact dependencies; it is
    ## easier to just rebuild, rebuild, rebuild.

    return 1 unless $param{BuildDependencies};

    ## Rebuild previous and next entry archive pages.
    if (my $prev = $entry->previous) {
        $mt->rebuild_entry( Entry => $prev ) or return;
    }
    if (my $next = $entry->next) {
        $mt->rebuild_entry( Entry => $next ) or return;
    }

    ## Rebuild all indexes, in case this entry is on an index.
    $mt->rebuild_indexes( Blog => $blog ) or return;

    ## Rebuild previous and next daily, weekly, and monthly archives;
    ## adding a new entry could cause changes to the intra-archive
    ## navigation.
    my %at = map { $_ => 1 } split /,/, $blog->archive_type;
    for my $at (qw( Daily Weekly Monthly )) {
        if ($at{$at}) {
            my @arg = ($entry->created_on, $entry->blog_id, $at);
            if (my $prev_arch = get_entry(@arg, 'previous')) {
                $mt->_rebuild_entry_archive_type(
                          Entry => $prev_arch,
                          Blog => $blog,
                          ArchiveType => $at) or return;
            }
            if (my $next_arch = get_entry(@arg, 'next')) {
                $mt->_rebuild_entry_archive_type(
                          Entry => $next_arch,
                          Blog => $blog,
                          ArchiveType => $at) or return;
            }
        }
    }

    1;
}

sub _rebuild_entry_archive_type {
    my $mt = shift;
    my %param = @_;
    my $at = $param{ArchiveType} or
        return $mt->error($mt->translate("Parameter '[_1]' is required",
            'ArchiveType'));
    return 1 if $at eq 'None';
    my $entry = $param{Entry} or
        return $mt->error($mt->translate("Parameter '[_1]' is required",
            'Entry'));
    my $blog;
    unless ($blog = $param{Blog}) {
        my $blog_id = $entry->blog_id;
        $blog = MT::Blog->load($blog_id) or
            return $mt->error($mt->translate("Load of blog '[_1]' failed: [_2]",
                $blog_id, MT::Blog->errstr));
    }

    ## Load the template-archive-type map entries for this blog and
    ## archive type. We do this before we load the list of entries, because
    ## we will run through the files and check if we even need to rebuild
    ## anything. If there is nothing to rebuild at all for this entry,
    ## we save some time by not loading the list of entries.
    require MT::TemplateMap;
    my @map;
    if (my $maps = $mt->{__cached_maps}{$at . $blog->id}) {
        @map = @$maps;
    } else {
        @map = MT::TemplateMap->load({ archive_type => $at,
                                       blog_id => $blog->id });
        $mt->{__cached_maps}{$at . $blog->id} = \@map;
    }
    return $mt->error($mt->translate(
        "You selected the archive type '[_1]', but you did not " .
        "define a template for this archive type.", $at)) unless @map;
    my @map_build;
    ## We keep a running total of the pages we have rebuilt
    ## in this session in $mt->{__rebuilt}.
    my $done = $mt->{__rebuilt};
    for my $map (@map) {
        my $file = archive_file_for($entry, $blog, $at, $param{Category}, $map);
        push @map_build, $map unless $done->{$file};
        $map->{__saved_output_file} = $file;
    }
    return 1 unless @map_build;
    @map = @map_build;

    my(%cond);
    require MT::Template::Context;
    my $ctx = MT::Template::Context->new;
    $ctx->{current_archive_type} = $at;

    if ($at eq 'Individual') {
        $ctx->stash('entry', $entry);
        $ctx->{current_timestamp} = $entry->created_on;
        $cond{EntryIfAllowComments} = $entry->allow_comments;
        $cond{EntryIfAllowPings} = $entry->allow_pings;
        $cond{EntryIfExtended} = $entry->text_more ? 1 : 0;
    } elsif ($at eq 'Daily') {
        my($start, $end) = start_end_day($entry->created_on, $blog);
        $ctx->{current_timestamp} = $start;
        $ctx->{current_timestamp_end} = $end;
        my @entries = MT::Entry->load({ created_on => [ $start, $end ],
                                        blog_id => $blog->id,
                                        status => MT::Entry::RELEASE() },
                                      { range => { created_on => 1 } });
        $ctx->stash('entries', \@entries);
    } elsif ($at eq 'Weekly') {
        my($start, $end) = start_end_week($entry->created_on, $blog);
        $ctx->{current_timestamp} = $start;
        $ctx->{current_timestamp_end} = $end;
        my @entries = MT::Entry->load({ created_on => [ $start, $end ],
                                        blog_id => $blog->id,
                                        status => MT::Entry::RELEASE() },
                                      { range => { created_on => 1 } });
        $ctx->stash('entries', \@entries);
    } elsif ($at eq 'Monthly') {
        my($start, $end) = start_end_month($entry->created_on, $blog);
        $ctx->{current_timestamp} = $start;
        $ctx->{current_timestamp_end} = $end;
        my @entries = MT::Entry->load({ created_on => [ $start, $end ],
                                        blog_id => $blog->id,
                                        status => MT::Entry::RELEASE() },
                                      { range => { created_on => 1 } });
        $ctx->stash('entries', \@entries);
    } elsif ($at eq 'Category') {
        my $cat;
        unless ($cat = $param{Category}) {
            return $mt->error($mt->translate(
                "Building category archives, but no category provided."));
        }
        require MT::Placement;
        $ctx->stash('archive_category', $cat);
        my @entries = MT::Entry->load({ blog_id => $blog->id,
                                        status => MT::Entry::RELEASE() },
                         { 'join' => [ 'MT::Placement', 'entry_id',
                                     { category_id => $cat->id } ] });
        $ctx->stash('entries', \@entries);
    }

    my $fmgr = $blog->file_mgr;
    my $arch_root = $blog->archive_path;
    return $mt->error($mt->translate("You did not set your Local Archive Path"))
        unless $arch_root;

    ## For each mapping, we need to rebuild the entries we loaded above in
    ## the particular template map, and write it to the specified archive
    ## file template.
    require MT::Template;
    for my $map (@map) {
        my $file = File::Spec->catfile($arch_root, $map->{__saved_output_file});
        my $tmpl = $mt->{__cached_templates}{$map->template_id};
        unless ($tmpl) {
            $tmpl = MT::Template->load($map->template_id);
            if ($mt->{cache_templates}) {
                $mt->{__cached_templates}{$tmpl->id} = $tmpl;
            }
        }

        my $html = $tmpl->build($ctx, \%cond) or
            return $mt->error($mt->translate(
                "Building entry '[_1]' failed: [_2]",
                $entry->title, $tmpl->errstr));

        ## Untaint. We have to assume that we can trust the user's setting of
        ## the archive_path, and nothing else is based on user input.
        ($file) = $file =~ /(.+)/s;

        ## Determine if we need to build directory structure, and build it
        ## if we do. DirUmask determines directory permissions.
        my($vol, $path, $fname) = File::Spec->splitpath($file);
        $path =~ s!/$!!;  ## OS X doesn't like / at the end in mkdir().
        unless ($fmgr->exists($path)) {
            $fmgr->mkpath($path)
                or return $mt->error($mt->translate(
                    "Error making path '[_1]': [_2]", $path, $fmgr->errstr));
        }

        ## By default we write all data to temp files, then rename the temp
        ## files to the real files (an atomic operation). Some users don't
        ## like this (requires too liberal directory permissions). So we
        ## have a config option to turn it off (NoTempFiles).
        my $use_temp_files = !$mt->{cfg}->NoTempFiles;
        my $temp_file = $use_temp_files ? "$file.new" : $file;
        defined($fmgr->put_data($html, $temp_file))
            or return $mt->error($mt->translate(
                "Writing to '[_1]' failed: [_2]", $temp_file, $fmgr->errstr));
        if ($use_temp_files) {
            $fmgr->rename($temp_file, $file)
                or return $mt->error($mt->translate(
                    "Renaming tempfile '[_1]' failed: [_2]",
                    $temp_file, $fmgr->errstr));
        }
        $done->{$map->{__saved_output_file}}++;
    }
    1;
}

sub rebuild_indexes {
    my $mt = shift;
    my %param = @_;
    require MT::Template;
    require MT::Template::Context;
    require MT::Entry;
    my $blog;
    unless ($blog = $param{Blog}) {
        my $blog_id = $param{BlogID};
        $blog = MT::Blog->load($blog_id) or
            return $mt->error($mt->translate("Load of blog '[_1]' failed: [_2]",
                $blog_id, MT::Blog->errstr));
    }
    my $iter;
    if (my $tmpl = $param{Template}) {
        my $i = 0;
        $iter = sub { $i++ < 1 ? $tmpl : undef };
    } else {
        $iter = MT::Template->load_iter({ type => 'index',
            blog_id => $blog->id });
    }
    local *FH;
    my $site_root = $blog->site_path;
    return $mt->error($mt->translate("You did not set your Local Site Path"))
        unless $site_root;
    my $fmgr = $blog->file_mgr;
    while (my $tmpl = $iter->()) {
        ## Skip index templates that the user has designated not to be
        ## rebuilt automatically. We need to do the defined-ness check
        ## because we added the flag in 2.01, and for templates saved
        ## before that time, the rebuild_me flag will be undefined. But
        ## we assume that these templates should be rebuilt, since that
        ## was the previous behavior.
        next if !$param{Force} &&
                defined $tmpl->rebuild_me && !$tmpl->rebuild_me;

        my $ctx = MT::Template::Context->new;
        my $html = $tmpl->build($ctx);
        return $mt->error( $tmpl->errstr ) unless defined $html;
        my $index = $tmpl->outfile
            or return $mt->error($mt->translate(
                "Template '[_1]' does not have an Output File.", $tmpl->name));
        unless (File::Spec->file_name_is_absolute($index)) {
            $index = File::Spec->catfile($site_root, $index);
        }
        ## Untaint. We have to assume that we can trust the user's setting of
        ## the site_path and the template outfile.
        ($index) = $index =~ /(.+)/s;
        my $use_temp_files = !$mt->{cfg}->NoTempFiles;
        my $temp_file = $use_temp_files ? "$index.new" : $index;
        defined($fmgr->put_data($html, $temp_file))
            or return $mt->error($mt->translate(
                "Writing to '[_1]' failed: [_2]", $temp_file, $fmgr->errstr));
        if ($use_temp_files) {
            $fmgr->rename($temp_file, $index)
                or return $mt->error($mt->translate(
                    "Renaming tempfile '[_1]' failed: [_2]",
                    $temp_file, $fmgr->errstr));
        }
    }
    1;
}

sub ping {
    my $mt = shift;
    my %param = @_;
    my $blog;
    unless ($blog = $param{Blog}) {
        my $blog_id = $param{BlogID};
        $blog = MT::Blog->load($blog_id) or
            return $mt->error(
                $mt->translate("Load of blog '[_1]' failed: [_2]",
                    $blog_id, MT::Blog->errstr));
    }

    my(@res);

    ## Send update pings.
    my @updates = $mt->update_ping_list($blog);
    for my $url (@updates) {
        require MT::XMLRPC;
        if (MT::XMLRPC->ping_update('weblogUpdates.ping', $blog, $url)) {
            push @res, { good => 1, url => $url, type => "update" };
        } else {
            push @res, { good => 0, url => $url, type => "update",
                         error => MT::XMLRPC->errstr };
        }
    }
    if ($blog->mt_update_key) {
        require MT::XMLRPC;
        if (MT::XMLRPC->mt_ping($blog)) {
            push @res, { good => 1, url => $mt->{cfg}->MTPingURL,
                         type => "update" };
        } else {
            push @res, { good => 0, url => $mt->{cfg}->MTPingURL,
                         type => "update", error => MT::XMLRPC->errstr };
        }
    }

    ## Send TrackBack pings.
    if (my $entry = $param{Entry}) {
        my $pings = $entry->to_ping_url_list;

        my %pinged = map { $_ => 1 } @{ $entry->pinged_url_list };
        my $cats = $entry->categories;
        for my $cat (@$cats) {
            push @$pings, grep !$pinged{$_}, @{ $cat->ping_url_list };
        }

        require LWP::UserAgent;
        my $ua = LWP::UserAgent->new;
        $ua->agent('MovableType/' . MT->VERSION);
        $ua->timeout($mt->{cfg}->PingTimeout);

        ## Build query string to be sent on each ping.
        my @qs;
        push @qs, 'title=' . MT::Util::encode_url($entry->title);
        my $url = $entry->archive_url;
        $url .= '#' . sprintf("%06d", $entry->id) 
            unless $blog->archive_type_preferred eq 'Individual';
        push @qs, 'url=' . MT::Util::encode_url($url);
        my $excerpt = $entry->excerpt ||
          MT::Util::first_n_words($entry->text, $blog->words_in_excerpt || 20);
        push @qs, 'excerpt=' . MT::Util::encode_url($excerpt);
        push @qs, 'blog_name=' . MT::Util::encode_url($blog->name);
        my $qs = join '&', @qs;

        for my $url (@$pings) {
            $url =~ s/^\s*//;
            $url =~ s/\s*$//;
            my $req;
            if ($url =~ /\?/) {
                $req = HTTP::Request->new(GET => $url . '&' . $qs);
            } else {
                $req = HTTP::Request->new(POST => $url);
                $req->content_type('application/x-www-form-urlencoded');
                $req->content($qs);
            }
            my $res = $ua->request($req);
            if (substr($res->code, 0, 1) eq '2') {
                my $c = $res->content;
                my($error, $msg) = $c =~
                    m!<error>(\d+).*<message>(.+?)</message>!s;
                if ($error) {
                    push @res, { good => 0, url => $url, type => 'trackback',
                                 error => $msg };
                } else {
                    push @res, { good => 1, url => $url, type => 'trackback' };
                }
            } else {
                push @res, { good => 0, url => $url, type => 'trackback',
                             error => "HTTP error: " . $res->status_line };
            }
        }
    }
    \@res;
}

sub needs_ping {
    my $mt = shift;
    my %param = @_;
    my $blog = $param{Blog};
    my $entry = $param{Entry};
    return unless $entry->status == MT::Entry::RELEASE();
    my $old_status = $param{OldStatus};
    my %list;
    ## If this is a new entry (!$old_status) OR the status was previously
    ## set to draft, and is now set to publish, send the update pings.
    if (!$old_status || $old_status ne MT::Entry::RELEASE()) {
        my @updates = $mt->update_ping_list($blog);
        @list{ @updates } = (1) x @updates;
        $list{$mt->{cfg}->MTPingURL} = 1 if $blog && $blog->mt_update_key;
    }
    if ($entry) {
        @list{ @{ $entry->to_ping_url_list } } = ();
        my %pinged = map { $_ => 1 } @{ $entry->pinged_url_list };
        my $cats = $entry->categories;
        for my $cat (@$cats) {
            @list{ grep !$pinged{$_}, @{ $cat->ping_url_list } } = ();
        }
    }
    my @list = keys %list;
    return unless @list;
    \@list;
}

sub update_ping_list {
    my $mt = shift;
    my($blog) = @_;
    my @updates;
    if ($blog->ping_weblogs) {
        push @updates, $mt->{cfg}->WeblogsPingURL;
    }
    if ($blog->ping_blogs) {
        push @updates, $mt->{cfg}->BlogsPingURL;
    }
    if (my $others = $blog->ping_others) {
        push @updates, split /\r?\n/, $others;
    }
    my %updates;
    for my $url (@updates) {
        for ($url) {
            s/^\s*//; s/\s*$//;
        }
        next unless $url =~ /\S/;
        $updates{$url}++;
    }
    keys %updates;
}

{
    my $LH;
    sub set_language {
        require MT::L10N;
        $LH = MT::L10N->get_handle($_[1]);
    }

    sub translate {
        my $this = shift;
        $LH->maketext(@_);
    }

    sub current_language { $LH->language_tag }
    sub language_handle { $LH }
}

sub supported_languages {
    my $mt = shift;
    require MT::L10N;
    require File::Basename;
    ## Determine full path to lib/MT/L10N directory...
    my $lib = 
        File::Spec->catdir(File::Basename::dirname($INC{'MT/L10N.pm'}), 'L10N');
    ## ... From that, determine full path to extlib/MT/L10N.
    ## To do that, we look for the last instance of the string 'lib'
    ## in $lib and replace it with 'extlib'. reverse is a nice tricky
    ## way of doing that.
    (my $extlib = reverse $lib) =~ s!bil!biltxe!;
    $extlib = reverse $extlib;
    my @dirs = ( $lib, $extlib );
    my %langs;
    for my $dir (@dirs) {
        opendir DH, $dir or next;
        for my $f (readdir DH) {
            my($tag) = $f =~ /^(\w+)\.pm$/;
            next unless $tag;
            my $lh = MT::L10N->get_handle($tag);
            $langs{$lh->language_tag} = $lh->language_name;
        }
        closedir DH;
    } 
    \%langs;
}

1;
__END__

=head1 NAME

MT - Movable Type

=head1 SYNOPSIS

    use MT;
    my $mt = MT->new;
    $mt->rebuild(BlogID => 1)
        or die $mt->errstr;

=head1 DESCRIPTION

The I<MT> class is the main high-level rebuilding/pinging interface in the
Movable Type library. It handles all rebuilding operations. It does B<not>
handle any of the application functionality--for that, look to I<MT::App> and
I<MT::App::CMS>, both of which subclass I<MT> to handle application requests.

=head1 USAGE

I<MT> has the following interface. On failure, all methods return C<undef>
and set the I<errstr> for the object or class (depending on whether the
method is an object or class method, respectively); look below at the section
L<ERROR HANDLING> for more information.

=head2 MT->new( %args )

Constructs a new I<MT> instance and returns that object. Returns C<undef>
on failure.

I<new> will also read your F<mt.cfg> file (provided that it can find it--if
you find that it can't, take a look at the I<Config> directive, below). It
will also initialize the chosen object driver; the default is the C<DBM>
object driver.

I<%args> can contain:

=over 4

=item * Config

Path to the F<mt.cfg> file.

If you do not specify a path, I<MT> will try to find your F<mt.cfg> file
in the current working directory.

=back

=head2 $mt->rebuild( %args )

Rebuilds your entire blog, indexes and archives; or some subset of your blog,
as specified in the arguments.

I<%args> can contain:

=over 4

=item * Blog

An I<MT::Blog> object corresponding to the blog that you would like to
rebuild.

Either this or C<BlogID> is required.

=item * BlogID

The ID of the blog that you would like to rebuild.

Either this or C<Blog> is required.

=item * ArchiveType

The archive type that you would like to rebuild. This should be one of the
following values: C<Individual>, C<Daily>, C<Weekly>, C<Monthly>, or
C<Category>.

This argument is optional; if not provided, all archive types will be rebuilt.

=item * EntryCallback

A callback that will be called for each entry that is rebuilt. If provided,
the value should be a subroutine reference; the subroutine will be handed
the I<MT::Entry> object for the entry that is about to be rebuilt. You could
use this to keep a running log of which entry is being rebuilt, for example:

    $mt->rebuild(
              BlogID => $blog_id,
              EntryCallback => sub { print $_[0]->title, "\n" },
          );

Or to provide a status indicator:

    use MT::Entry;
    my $total = MT::Entry->count({ blog_id => $blog_id });
    my $i = 0;
    local $| = 1;
    $mt->rebuild(
              BlogID => $blog_id,
              EntryCallback => sub { printf "%d/%d\r", ++$i, $total },
          );
    print "\n";

This argument is optional; by default no callbacks are executed.

=item * NoIndexes

By default I<rebuild> will rebuild the index templates after rebuilding all
of the entries; if you do not want to rebuild the index templates, set the
value for this argument to a true value.

This argument is optional.

=item * Limit

Limit the number of entries to be rebuilt to the last C<N> entries in the
blog. For example, if you set this to C<20> and do not provide an offset (see
L<Offset>, below), the 20 most recent entries in the blog will be rebuilt.

This is only useful if you are rebuilding C<Individual> archives.

This argument is optional; by default all entries will be rebuilt.

=item * Offset

When used with C<Limit>, specifies the entry at which to start rebuilding
your individual entry archives. For example, if you set this to C<10>, and
set a C<Limit> of C<5> (see L<Limit>, above), entries 10-14 (inclusive) will
be rebuilt. The offset starts at C<0>, and the ordering is reverse
chronological.

This is only useful if you are rebuilding C<Individual> archives, and if you
are using C<Limit>.

This argument is optional; by default all entries will be rebuilt, starting
at the first entry.

=back

=head2 $mt->rebuild_entry( %args )

Rebuilds a particular entry in your blog (and its dependencies, if specified).

I<%args> can contain:

=over 4

=item * Entry

An I<MT::Entry> object corresponding to the object you would like to rebuild.

This argument is required.

=item * Blog

An I<MT::Blog> object corresponding to the blog to which the I<Entry> belongs.

This argument is optional; if not provided, the I<MT::Blog> object will be
loaded in I<rebuild_entry> from the I<$entry-E<gt>blog_id> column of the
I<MT::Entry> object passed in. If you already have the I<MT::Blog> object
loaded, however, it makes sense to pass it in yourself, as it will skip one
small step in I<rebuild_entry> (loading the object).

=item * BuildDependencies

Saving an entry can have effects on other entries; so after saving, it is
often necessary to rebuild other entries, to reflect the changes onto all
of the affected archive pages, indexes, etc.

If you supply this parameter with a true value, I<rebuild_indexes> will
rebuild: the archives for the next and previous entries, chronologically;
all of the index templates; the archives for the next and previous daily,
weekly, and monthly archives.

=back

=head2 $mt->rebuild_indexes( %args )

Rebuilds all of the index templates in your blog, or just one, if you use
the I<Template> argument (below). Only rebuilds templates that are set to
be rebuilt automatically, unless you use the I<Force> (below).

I<%args> can contain:

=over 4

=item * Blog

An I<MT::Blog> object corresponding to the blog whose indexes you would like
to rebuild.

Either this or C<BlogID> is required.

=item * BlogID

The ID of the blog whose indexes you would like to rebuild.

Either this or C<Blog> is required.

=item * Template

An I<MT::Template> object specifying the index template to rebuild; if you use
this argument, I<only> this index template will be rebuilt.

Note that if the template that you specify here is set to not rebuild
automatically, you I<must> specify the I<Force> argument in order to force it
to be rebuilt.

=item * Force

A boolean flag specifying whether or not to rebuild index templates who have
been marked not to be rebuilt automatically.

The default is C<0> (do not rebuild such templates).

=back

=head2 $mt->ping( %args )

Sends all configured XML-RPC pings as a way of notifying other community
sites that your blog has been updated.

I<%args> can contain:

=over 4

=item * Blog

An I<MT::Blog> object corresponding to the blog for which you would like to
send the pings.

Either this or C<BlogID> is required.

=item * BlogID

The ID of the blog for which you would like to send the pings.

Either this or C<Blog> is required.

=back

=head2 $mt->set_language($tag)

Loads the localization plugin for the language specified by I<$tag>, which
should be a valid and supported language tag--see I<supported_languages> to
obtain a list of supported languages.

The language is set on a global level, and affects error messages and all
text in the administration system.

This method can be called as either a class method or an object method; in
other words,

    MT->set_language($tag)

will also work. However, the setting will still be global--it will not be
specified to the I<$mt> object.

The default setting--set when I<MT::new> is called--is U.S. English. If a
I<DefaultLanguage> is set in F<mt.cfg>, the default is then set to that
language.

=head2 $mt->translate($str)

Translates I<$str> into the currently-set language (set by I<set_language>),
and returns the translated string.

=head2 $mt->current_language

Returns the language tag for the currently-set language.

=head2 MT->supported_languages

Returns a reference to an associative array mapping language tags to their
proper names. For example:

    use MT;
    my $langs = MT->supported_languages;
    print map { $_ . " => " . $langs->{$_} . "\n" } keys %$langs;

=head2 MT->VERSION

Returns the version of MT (including any beta/alpha designations).

=head2 MT->version_number

Returns the numeric version of MT (without any beta/alpha designations).
For example, if I<VERSION> returned C<2.5b1>, I<version_number> would
return C<2.5>.

=head1 ERROR HANDLING

On an error, all of the above methods return C<undef>, and the error message
can be obtained by calling the method I<errstr> on the class or the object
(depending on whether the method called was a class method or an instance
method).

For example, called on a class name:

    my $mt = MT->new or die MT->errstr;

Or, called on an object:

    $mt->rebuild(BlogID => $blog_id)
        or die $mt->errstr;

=head1 LICENSE

Please see the file F<LICENSE> in the Movable Type distribution.

=head1 AUTHOR & COPYRIGHT

Except where otherwise noted, MT is Copyright 2001, 2002 Benjamin Trott,
[email protected], and Mena Trott, [email protected]. All rights
reserved.

=cut

Anon7 - 2021