# Copyright 2001-2003 Six Apart. This code cannot be redistributed without # permission from www.movabletype.org. # # $Id: Viewer.pm,v 1.8 2003/02/12 00:15:05 btrott Exp $ package MT::App::Viewer; use strict; use MT::App; @MT::App::Viewer::ISA = qw( MT::App ); use MT::Entry; use MT::Template; use MT::Template::Context; use constant INDEX => 'Main Index'; sub init { my $app = shift; $app->SUPER::init(@_) or return; $app->add_methods(main => \&view); $app->{default_mode} = 'main'; $app; } sub view { my $app = shift; my $R = MT::Request->instance; $R->stash('live_view', 1); ## Process the path info. my $uri = $app->path_info; unless ($uri =~ s!^/(\d+)!!) { return $app->error("No blog_id"); } $app->{__blog_id} = my $blog_id = $1; require MT::Blog; my $blog = $app->{__blog} = MT::Blog->load($blog_id) or return $app->error("Loading blog with ID $blog_id failed"); if (!$uri || $uri eq '/') { return $app->_view_index; } elsif ($uri =~ m!^/archives/(.*)$!) { return $app->_view_date_archive($1); } elsif ($uri =~ m!^/entry/(\d+)/?$!) { return $app->_view_entry($1); } elsif ($uri =~ m!^/section/(\d+)/?$!) { return $app->_view_section($1); } else { return $app->_view_index($uri); } } my %MimeTypes = ( css => 'text/css', txt => 'text/plain', rdf => 'text/xml', rss => 'text/xml', xml => 'text/xml', ); sub _view_index { my $app = shift; my($uri) = @_; my $q = $app->{query}; my $tmpl; if ($uri) { $uri =~ s!^/!!; my $iter = MT::Template->load_iter({ blog_id => $app->{__blog_id} }); while (my $t = $iter->()) { $tmpl = $t, last if $t->type eq 'index' && $t->outfile eq $uri; } } else { $tmpl = MT::Template->load({ blog_id => $app->{__blog_id}, name => INDEX }); } ## xxx 404? return $app->error("Can't load '@{[ $uri || INDEX ]}' template.") unless $tmpl; my($limit, $offset) = map $q->param($_), qw( limit offset ); my $ctx = MT::Template::Context->new; if ($limit || $offset) { $limit ||= 20; my %arg = ( 'sort' => 'created_on', direction => 'descend', limit => $limit, ($offset ? (offset => $offset) : ()), ); my @entries = MT::Entry->load({ blog_id => $app->{__blog_id}, status => MT::Entry::RELEASE() }, \%arg); $ctx->stash('entries', \@entries); } my $out = $tmpl->build($ctx) or return $app->error("Building template failed: " . $tmpl->errstr); (my $ext = $tmpl->outfile) =~ s/.*\.//; my $mime = $MimeTypes{$ext} || 'text/html'; $app->send_http_header($mime); $app->print($out); $app->{no_print_body} = 1; 1; } sub _view_date_archive { my $app = shift; my($spec) = @_; my($start, $end, $at); my $ctx = MT::Template::Context->new; if ($spec =~ m!^(\d{4})/(\d{2})/(\d{2})!) { my($y, $m, $d) = ($1, $2, $3); ($start, $end) = ($y . $m . $d . '000000', $y . $m . $d . '235959'); $at = $ctx->{current_archive_type} = 'Daily'; } elsif ($spec =~ m!^(\d{4})/(\d{2})!) { my($y, $m) = ($1, $2); my $days = MT::Util::days_in($m, $y); ($start, $end) = ($1 . $2 . '01000000', $1 . $2 . $days . '235959'); $at = $ctx->{current_archive_type} = 'Monthly'; } elsif ($spec =~ m!^week/(\d{4})/(\d{2})/(\d{2})!) { my($y, $m, $d) = ($1, $2, $3); ($start, $end) = MT::Util::start_end_week("$1$2${3}000000", $app->{__blog}); $at = $ctx->{current_archive_type} = 'Weekly'; } else { return $app->error("Invalid date spec"); } $ctx->{current_timestamp} = $start; $ctx->{current_timestamp_end} = $end; my @entries = MT::Entry->load({ created_on => [ $start, $end ], blog_id => $app->{__blog_id}, status => MT::Entry::RELEASE() }, { range => { created_on => 1 } }); $ctx->stash('entries', \@entries); require MT::TemplateMap; my $map = MT::TemplateMap->load({ archive_type => $at, blog_id => $app->{__blog_id}, is_preferred => 1 }); my $tmpl = MT::Template->load($map->template_id) or return $app->error("Can't load template " . $map->template_id); my $out = $tmpl->build($ctx) or return $app->error("Building archive failed: " . $tmpl->errstr); $out; } sub _view_entry { my $app = shift; my($entry_id) = @_; my $entry = MT::Entry->load($entry_id) or return $app->error("Invalid entry ID '" . $entry_id . "'"); my $ctx = MT::Template::Context->new; $ctx->{current_archive_type} = 'Individual'; $ctx->{current_timestamp} = $entry->created_on; $ctx->stash('entry', $entry); my %cond = ( EntryIfAllowComments => $entry->allow_comments, EntryIfCommentsOpen => $entry->allow_comments eq '1', EntryIfAllowPings => $entry->allow_pings, EntryIfExtended => $entry->text_more ? 1 : 0, ); require MT::TemplateMap; my $map = MT::TemplateMap->load({ archive_type => 'Individual', blog_id => $app->{__blog_id}, is_preferred => 1 }); my $tmpl = MT::Template->load($map->template_id) or return $app->error("Can't load template " . $map->template_id); my $out = $tmpl->build($ctx, \%cond) or return $app->error("Building archive failed: " . $tmpl->errstr); $out; } sub _view_section { my $app = shift; my($cat_id) = @_; require MT::Category; my $cat = MT::Category->load($cat_id) or return $app->error("Invalid category ID '$cat_id'"); my($start, $end, $at); my $ctx = MT::Template::Context->new; $ctx->stash('archive_category', $cat); $ctx->{current_archive_type} = 'Category'; require MT::Placement; my @entries = MT::Entry->load({ blog_id => $app->{__blog_id}, status => MT::Entry::RELEASE() }, { 'join' => [ 'MT::Placement', 'entry_id', { category_id => $cat_id } ] }); $ctx->stash('entries', \@entries); require MT::TemplateMap; my $map = MT::TemplateMap->load({ archive_type => 'Category', blog_id => $app->{__blog_id}, is_preferred => 1 }); my $tmpl = MT::Template->load($map->template_id) or return $app->error("Can't load template " . $map->template_id); my $out = $tmpl->build($ctx) or return $app->error("Building archive failed: " . $tmpl->errstr); $out; } 1;