Author Archives in Movable Type

Because of the way I wanted to use MT for one of my blogs, I thought Author-based archiving could be extremely useful. Instead, initially, I had to do a little work-around using Categories. But, today I sat down and implemented Author Archives in MT.

You can see this code in action on the campaign journal blog I setup for a game I was in.

The following is the diff I generated from my new code, which I will make available for anyone who is interested in testing:

diff -c -r ./lib/MT/App/CMS.pm /usr/local/www/data/mt/lib/MT/App/CMS.pm *** ./lib/MT/App/CMS.pm Wed Oct 30 15:36:37 2002 --- /usr/local/www/data/mt/lib/MT/App/CMS.pm Wed Nov 27 14:07:57 2002 *************** *** 517,522 **** --- 517,523 ---- $obj->type eq 'custom' || $obj->type eq 'archive' || $obj->type eq 'category' || + $obj->type eq 'author' || $obj->type eq 'individual'; $param{has_outfile} = $obj->type eq 'index'; $param{has_rebuild} = $obj->type eq 'index'; *************** *** 628,633 **** --- 629,635 ---- $q->param('type') eq 'custom' || $q->param('type') eq 'archive' || $q->param('type') eq 'category' || + $q->param('type') eq 'author' || $q->param('type') eq 'individual'; $param{has_outfile} = $q->param('type') eq 'index'; $param{has_rebuild} = $q->param('type') eq 'index'; *************** *** 875,881 **** $obj->convert_paras_comments(1); $obj->ping_weblogs(0); $obj->ping_blogs(0); ! $obj->archive_type('Individual,Monthly'); $obj->archive_type_preferred('Individual'); $obj->status_default(1); } --- 877,883 ---- $obj->convert_paras_comments(1); $obj->ping_weblogs(0); $obj->ping_blogs(0); ! $obj->archive_type('Individual,Monthly,Author'); $obj->archive_type_preferred('Individual'); $obj->status_default(1); } *************** *** 917,923 **** "Populating blog with default templates failed: [_1]", $tmpl->errstr)); if ($val->{type} eq 'archive' || $val->{type} eq 'category' || ! $val->{type} eq 'individual') { push @arch_tmpl, $tmpl; } } --- 919,925 ---- "Populating blog with default templates failed: [_1]", $tmpl->errstr)); if ($val->{type} eq 'archive' || $val->{type} eq 'category' || ! $val->{type} eq 'individual' || $val->{type} eq 'author') { push @arch_tmpl, $tmpl; } } *************** *** 931,937 **** @at = qw( Category ); } elsif ($tmpl->type eq 'individual') { @at = qw( Individual ); ! } require MT::TemplateMap; for my $at (@at) { my $map = MT::TemplateMap->new; --- 933,941 ---- @at = qw( Category ); } elsif ($tmpl->type eq 'individual') { @at = qw( Individual ); ! } elsif ($tmpl->type eq 'author') { ! @at = qw( Author ); ! } require MT::TemplateMap; for my $at (@at) { my $map = MT::TemplateMap->new; *************** *** 1025,1031 **** } elsif ($obj->type eq 'custom') { push @custom_data, $row; } elsif ($obj->type eq 'archive' || $obj->type eq 'category' || ! $obj->type eq 'individual') { push @archive_data, $row; } else { $param{'template_' . $obj->type} = $obj->id; --- 1029,1035 ---- } elsif ($obj->type eq 'custom') { push @custom_data, $row; } elsif ($obj->type eq 'archive' || $obj->type eq 'category' || ! $obj->type eq 'individual' || $obj->type eq 'author') { push @archive_data, $row; } else { $param{'template_' . $obj->type} = $obj->id; *************** *** 1857,1863 **** while (my $tmpl = $iter->()) { my $type = $tmpl->type; next unless $type eq 'archive' || $type eq 'category' || ! $type eq 'individual'; $tmpl_name{$tmpl->id} = $tmpl->name; } my %map; --- 1861,1867 ---- while (my $tmpl = $iter->()) { my $type = $tmpl->type; next unless $type eq 'archive' || $type eq 'category' || ! $type eq 'individual' || $type eq 'author'; $tmpl_name{$tmpl->id} = $tmpl->name; } my %map; *************** *** 1875,1881 **** $total_rows++; } my @data; ! for my $at (qw( Individual Daily Weekly Monthly Category )) { $map{$at} = [] unless $map{$at}; my @map = sort { $a->{map_template_name} cmp $b->{map_template_name} } @{ $map{$at} }; --- 1879,1885 ---- $total_rows++; } my @data; ! for my $at (qw( Individual Daily Weekly Monthly Category Author )) { $map{$at} = [] unless $map{$at}; my @map = sort { $a->{map_template_name} cmp $b->{map_template_name} } @{ $map{$at} }; *************** *** 1961,1967 **** while (my $tmpl = $iter->()) { my $type = $tmpl->type; next unless $type eq 'archive' || $type eq 'category' || ! $type eq 'individual'; push @tmpl, { template_id => $tmpl->id, template_name => $tmpl->name }; } @tmpl = sort { $a->{template_name} cmp $b->{template_name} } @tmpl; --- 1965,1971 ---- while (my $tmpl = $iter->()) { my $type = $tmpl->type; next unless $type eq 'archive' || $type eq 'category' || ! $type eq 'individual' || $type eq 'author'; push @tmpl, { template_id => $tmpl->id, template_name => $tmpl->name }; } @tmpl = sort { $a->{template_name} cmp $b->{template_name} } @tmpl; diff -c -r ./lib/MT/Entry.pm /usr/local/www/data/mt/lib/MT/Entry.pm *** ./lib/MT/Entry.pm Mon Oct 7 23:29:29 2002 --- /usr/local/www/data/mt/lib/MT/Entry.pm Wed Nov 27 13:33:57 2002 *************** *** 211,217 **** $at = $blog->archive_type_preferred || $blog->archive_type; return '' if !$at || $at eq 'None'; my %at = map { $_ => 1 } split /,/, $at; ! for my $tat (qw( Individual Daily Weekly Monthly Category )) { $at = $tat if $at{$tat}; } } --- 211,217 ---- $at = $blog->archive_type_preferred || $blog->archive_type; return '' if !$at || $at eq 'None'; my %at = map { $_ => 1 } split /,/, $at; ! for my $tat (qw( Individual Daily Weekly Monthly Category Author )) { $at = $tat if $at{$tat}; } } diff -c -r ./lib/MT/Template/Context.pm /usr/local/www/data/mt/lib/MT/Template/Context.pm *** ./lib/MT/Template/Context.pm Tue Oct 29 19:48:10 2002 --- /usr/local/www/data/mt/lib/MT/Template/Context.pm Wed Nov 27 13:47:38 2002 *************** *** 1261,1266 **** --- 1261,1268 ---- return '' unless @entries; if ($ctx->{current_archive_type} eq 'Category') { return $ctx->stash('archive_category')->label; + } elsif ($ctx->{current_archive_type} eq 'Author') { + return $ctx->stash('archive_author')->name; } else { my $st = $TypeHandlers{$ctx->{current_archive_type}}{section_title}; my $title = $st->($ctx, $entries[0]); diff -c -r ./lib/MT/Template.pm /usr/local/www/data/mt/lib/MT/Template.pm *** ./lib/MT/Template.pm Tue Oct 29 19:55:19 2002 --- /usr/local/www/data/mt/lib/MT/Template.pm Wed Nov 27 14:01:57 2002 *************** *** 12,17 **** --- 12,18 ---- archive => 'Archive', category => 'Category Archive', individual => 'Individual', + author => 'Author Archive', comments => 'Comment Listing', pings => 'Ping Listing', comment_preview => 'Comment Preview', diff -c -r ./lib/MT/Util.pm /usr/local/www/data/mt/lib/MT/Util.pm *** ./lib/MT/Util.pm Tue Oct 29 19:51:04 2002 --- /usr/local/www/data/mt/lib/MT/Util.pm Wed Nov 27 13:33:57 2002 *************** *** 395,400 **** --- 395,412 ---- } $file = sprintf("cat_%s", $label); } + } elsif ($at eq 'Author') { + require MT::Author; + my $this_author = MT::Author->load({ id => $entry->author_id }); + if ($file_tmpl) { + $ctx->stash('archive_author', $this_author); + } else { + my $label = ''; + if ($this_author) { + $label = dirify($this_author->name); + } + $file = sprintf("author_%s", $label); + } } else { return $entry->error(MT->translate( "Invalid Archive Type setting '[_1]'", $at )); diff -c -r ./lib/MT/default-templates.pl /usr/local/www/data/mt/lib/MT/default-templates.pl *** ./lib/MT/default-templates.pl Tue Oct 29 19:54:13 2002 --- /usr/local/www/data/mt/lib/MT/default-templates.pl Wed Nov 27 13:33:57 2002 *************** *** 996,1001 **** --- 996,1081 ---- <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> + <title><$MTBlogName$>: <$MTArchiveTitle$> Archives</title> + + <link rel="stylesheet" href="<$MTBlogURL$>styles-site.css" type="text/css" /> + <link rel="alternate" type="application/rss+xml" title="RSS" href="<$MTBlogURL$>index.rdf" /> + + <script language="javascript" type="text/javascript"> + function OpenComments (c) { + window.open(c, + \'comments\', + \'width=480,height=480,scrollbars=yes,status=yes\'); + } + + function OpenTrackback (c) { + window.open(c, + \'trackback\', + \'width=480,height=480,scrollbars=yes,status=yes\'); + } + </script> + + </head> + + <body> + + <div id="banner"> + <h1><a href="<$MTBlogURL$>" accesskey="1"><$MTBlogName$></a></h1> + <span class="description"><$MTBlogDescription$></span> + </div> + + <div id="container"> + + <div class="blog"> + <MTEntries> + <$MTEntryTrackbackData$> + + <MTDateHeader> + <h2 class="date"><$MTEntryDate format="%x"$></h2> + </MTDateHeader> + + <div class="blogbody"> + + <a name="<$MTEntryID pad="1"$>"></a> + <h3 class="title"<>$MTEntryTitle$></h3> + + <$MTEntryBody$> + + <MTEntryIfExtended> + <$MTEntryMore$> + </MTEntryIfExtended> + + <div class="posted"> + Posted by <$MTEntryAuthor$> at <a href="<$MTEntryPermalink$>"><$MTEntryDate format="%X"$></a> + <MTEntryIfAllowComments> + | <a href="<$MTCGIPath$><$MTCommentScript$>?entry_id=<$MTEntryID$>" onclick="OpenComments(this.href); return false">Comments (<$MTEntryCommentCount$>)</a> + </MTEntryIfAllowComments> + <MTEntryIfAllowPings> + | <a href="<$MTCGIPath$><$MTTrackbackScript$>?__mode=view&amp;entry_id=<$MTEntryID$>" onclick="OpenTrackback(this.href); return false">TrackBack</a> + </MTEntryIfAllowPings> + </div> + + </div> + + </MTEntries> + </div> + + </div> + + </body> + </html> + ', + 'type' => 'author', + 'name' => 'Author Archive' + }, + + { + 'text' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + + <html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> + <title><$MTBlogName$>: <$MTEntryTitle$></title> <link rel="stylesheet" href="<$MTBlogURL$>styles-site.css" type="text/css" /> diff -c -r ./lib/MT.pm /usr/local/www/data/mt/lib/MT.pm *** ./lib/MT.pm Thu Oct 31 03:51:59 2002 --- /usr/local/www/data/mt/lib/MT.pm Wed Nov 27 13:33:57 2002 *************** *** 341,347 **** --- 341,356 ---- { 'join' => [ 'MT::Placement', 'entry_id', { category_id => $cat->id } ] }); $ctx->stash('entries', \@entries); + } elsif ($at eq 'Author') { + my $author; + require MT::Author; + $author = MT::Author->load({ id => $entry->author_id }); + $ctx->stash('archive_author', $author); + my @entries = MT::Entry->load({ blog_id => $blog->id, + author_id => $author->id, status => MT::Entry::RELEASE() }); + $ctx->stash('entries', \@entries); } + my $fmgr = $blog->file_mgr; my $arch_root = $blog->archive_path; diff -c -r ./mt-load.cgi /usr/local/www/data/mt/mt-load.cgi *** ./mt-load.cgi Mon Sep 16 02:33:04 2002 --- /usr/local/www/data/mt/mt-load.cgi Wed Nov 27 13:36:37 2002 *************** *** 77,83 **** print " Loading blog...\n"; my $blog = MT::Blog->new; $blog->name('First Blog'); ! $blog->archive_type('Individual,Monthly'); $blog->archive_type_preferred('Individual'); $blog->days_on_index(7); $blog->words_in_excerpt(20); --- 77,83 ---- print " Loading blog...\n"; my $blog = MT::Blog->new; $blog->name('First Blog'); ! $blog->archive_type('Individual,Monthly,Author'); $blog->archive_type_preferred('Individual'); $blog->days_on_index(7); $blog->words_in_excerpt(20); *************** *** 122,128 **** $obj->blog_id($blog->id); $obj->save or die $obj->errstr; if ($val->{type} eq 'archive' || $val->{type} eq 'individual' || ! $val->{type} eq 'category') { push @arch_tmpl, $obj; } } --- 122,128 ---- $obj->blog_id($blog->id); $obj->save or die $obj->errstr; if ($val->{type} eq 'archive' || $val->{type} eq 'individual' || ! $val->{type} eq 'category' || $val->{type} eq 'author') { push @arch_tmpl, $obj; } } *************** *** 138,143 **** --- 138,145 ---- @at = qw( Category ); } elsif ($tmpl->type eq 'individual') { @at = qw( Individual ); + } elsif ($tmpl->type eq 'author') { + @at = qw( Author ); } for my $at (@at) { print " Mapping template ID '", $tmpl->id, "' to '$at'\n";

3 TrackBacks

Author Archives from Stnard's Diary on October 17, 2003 1:23 PM

¤È¡¤Ãµ¤·¤Æ¤¿¤é¸«¤Ä¤±¤Þ¤·¤¿¡¥ ¤à¡Á·ë¹½Â礬¤«¤ê¤Ê Patch ¤À¤Ê¤¡¡¥ Movable Type ¼«ÂΤÎÊѹ¹¤¸¤ã¤Ê¤¯¤Æ¡¤Plug-in ¤«¤Ê¤ó¤«¤Ç¤«¤ï¤·¤¿¤¤¤ó¤À¤¬¡¤ÌµÍý¤Ê¤ó¤À¤í¤¦¤«¤Í¡¥... Read More

投稿者別一覧について、これまでに紹介された方法や、私のやり方について述べます。MTでは、投稿者別一覧を自動的に出すことはできませんので、MTを改造するか、自動的にというのをã... Read More

投稿者別一覧について、これまでに紹介された方法や、私のやり方について述べます。MTでは、投稿者別一覧を自動的に出すことはできませんので、MTを改造するか、自動的にというのをã... Read More

4 Comments

I use author archives on a group blog - onion colours
A plugin to do this would be excellent!
I much prefer plugins over hacks since I hate having to replace all the hacks when I upgrade MT.

oh.. we do our author archives using php.

I have a php hack but a plugin would be fantastic, yeah.

I just use is hack and generally it work well.
Thank David's great work.
However, I got an error message of :
[Can't use string ("") as a subroutine ref while "strict refs" in use at /public_html/mt/lib/MT/Template/Context.pm line 1342.]
When I tried to rebuld the index.html template using the MTArchiveLink tag for archive_type="Author"

I would be very appreciate if someone known how to solve this problem. Thanks

David, do you have this working in 2.65? :)

Leave a comment

Recent Entries

  • Must Be Doing Something Right

    It’s not because they say please and thank you so often (and appropriately). It’s not that they hug each other and say they’re sorry (eventually)...

  • Because tests and bugs are fun

    A colleague of mine just shared this particular frustration: yargh. my test passes if all of the objects are created within the same second, but...

  • Upgraded to MT 4.23

    So, yeah, it’s a month late or so, but I’ve been really busy. I finally upgraded this site to Movable Type 4.23. Maybe I’ll even...

  • I apologize about the feed updates

    I’m deploying a development version of my MediaConsumer plugin and a number of entries might appear as updated in feed readers as I start applying...

  • Plugin Writing 101

    So, I’m planning on writing up some entries about various aspects of plugin development. While I have a couple topics already in mind, I thought...

Close