« Tagwire Plugin | Main | mt-db-convert.cgi: MT Database Converter »

Dynamic Tag Archiving with Tagwire and MT-XSearch

Instead of static tag/category archives supported by Tags Plugin, Tagwire provides Dynamic Tag Archiving by using Tim Appnel's MT-XSearch. Dynamic Tag Archiving is slower than static one but preferable to support more flexible archiving. For example, Tagwire supports listing entries having two or more tags.

In this article, I will explain how Tagwire plugin cooperates with Tim Appnel's MT-XSearch and realize Dynamic Tag Archiving.

How to setup

Now assume that you've already installed Tagwire plugin.

  1. Install MT-XSearch:
    First, download mt-plus-1.01.zip from Download mt-plus | Appnel Internet Solutions. And unpack it and copy/upload the following files into your Movable Type directory.
    • mt-xsearch.cgi (this file should be executable)
    • plugins/mt-xsearch.pl
    • extlib/MT/XSearch.pm
  2. Modify mt-xsearch.cgi and plugins/mt-xsearch.pl a little. These are for multilingual support and bug fix, and they may be included in the future releases of MT-Plus/MT-XSearch.
    --- mt-xsearch.cgi.bak	Fri Aug 27 12:06:24 2004
    +++ mt-xsearch.cgi	Sat Jun 11 02:58:33 2005
    @@ -41,7 +41,8 @@
         $ctx->stash('CGI',$q);
         my $out = $tmpl->build($ctx)
             or die "Building search template failed: ".$tmpl->errstr;
    -    print $q->header.$out;
    +    my $charset = $mt->{cfg}->PublishCharset;
    +    print $q->header(-charset=>$charset).$out;
     };
     if ($@) {
         print "Content-Type: text/html\n\n";
    
    --- plugins/mt-xsearch.pl.bak	Sat May 14 06:01:19 2005
    +++ plugins/mt-xsearch.pl	Sat Jun 11 00:31:39 2005
    @@ -63,7 +63,7 @@
         my $pages = $limit ? ($count-($count % $limit)) / $limit : 1;
         $pages += ($limit && $count % $limit) ? 1 : 0;
         my $offset = $xsearch->args->{offset} || 0;
    -    my $current = $offset / $limit + 1;
    +    my $current = $limit ? ($offset / $limit + 1) : 1;
         $ctx->stash('MT::XSearch::current_page',$current);
         $ctx->stash('MT::XSearch::pages',$pages);
         my $builder = $ctx->stash('builder');
    
  3. Create a template module named "XSearch Tagwire" (other name is not permitted):
    <html>
    <body>
    <form method="get" action="<$MTCGIPath$>mt-xsearch.cgi">
    <input type="hidden" name="blog_id" value="<$MTBlogID$>" />
    <input type="hidden" name="search_key" value="Tagwire" />
    <label for="search" accesskey="4">Search this site:</label>
    <input id="search" name="search" size="20" value="<$MTSearchString decode_url="1" encode_html="1"$>" />
    <input type="submit" value="Search" />
    </form>
     
    <MTSearchResults>
    <MTSearchHeader>
    Results found: <$MTSearchResultCount$> 
    <ol>
    </MTSearchHeader>
    <li><a href="<$MTEntryLink$>"><$MTEntryTitle$></a></li>
    <MTSearchFooter>
    </ol>
    <p>Searched on: <em><$MTSearchString decode_url="1"$></em></p>
    </MTSearchFooter>
    </MTSearchResults>
    <MTNoSearch><p>No search performed.</p></MTNoSearch>
    <MTNoSearchResults><p>Nothing found.</p></MTNoSearchResults>
     
    </body>
    </html>
    
    This template can be customized as you like.

Usage

Tag Search Form:

To create tag search form, simply add the following code to your index/archive templates:

<form method="get" action="<$MTCGIPath$>mt-xsearch.cgi">
<input type="hidden" name="blog_id" value="<$MTBlogID$>" />
<input type="hidden" name="search_key" value="Tagwire" />
<label for="search" accesskey="4">Search this site:</label>
<input id="search" name="search" size="20" value="<$MTSearchString decode_url="1" encode_html="1"$>" />
<input type="submit" value="Search" />
</form>

Tag Archive Links:

To generate directly tag archive links instead of forms, you can write as like follows:

<MTEntryTags glue=", ">
<a href="<$MTCGIPath$>mt-xsearch.cgi?blog_id=<$MTBlogID$>&search_key=Tagwire&search=<$MTTag encode_url="1"$>"><$MTTag$></a>
</MTEntryTags>

Smarter Tag Archive Links:

To realize smarter representation of the tag archive URL such as "http://my.host.tld/tag/Tag", add the following to your .htaccess:

RewriteEngine on
RewriteRule ^tag/(.*) /mt/mt-xsearch.cgi?blog_id=1&search_key=Tagwire&search=$1 [QSA,L]

Once the above setting complete, you need only to write as follows:

<MTEntryTags glue=", ">
<a href="<$MTBlogURL$>tag/<$MTTag encode_url="1"$>"><$MTTag$></a>
</MTEntryTags>

Options

The following options can be added as hidden input fields of the Tag Search Form or as query strings of the Tag Archive Links:

blog_id (REQUIRED)
A blog ID.
search_key (REQUIRED)
Must be set to "Tagwire" for tag search.
search (REQUIRED)
An URL-encoded search string. You can specify one or more tags separated by the delimiter character. When you specify two or more tags, MT-XSearch generates the list of entries with all these tags. And the default delimiter is a whitespace, which should be represented as "%20" or "+" in a URL-encoded string. So if you specify "movable+type" as the search string and omit the delimiter option, MT-XSearch generates the list of entries having both of "movable" and "type" tags.
delimiter
Sets the delimiter character for the search string. For example, if you set "movable,type" as the search string and "," as the delimiter, MT-XSearch generates the list of entries having both of "movable" and "type" tags.
case_sensitive [0 | 1]
Chooses whether the plugin treats tags as the case-sensitive manner or not. The default is case_sensitive="1".
sort_order [ascend | descend]
Chooses the sorting order. The default sort_order is "descend".

Advanced Issue: CGI::Cache enabled MT-XSearch

The above mentioned method is not so a fast solution. Because, everytime you access tag archives, it invokes CGI process and retrieves the tag information from the DB engine and then generates the result page.

But, generally saying, the tag information is not so often added or modified. In short, by caching pages and suppressing page transfers, we make it possible to reduce the overhead of dynamic tag archives effectively.

Based on this observation, I introduce a speedup method for Tagwire/MT-XSearch, with enabling CGI::Cache module. CGI::Cache enabled MT-XSearch can cache the result pages for a fixed period (e.g, 1 hour) and return the pages to the clients with the Last-Modified HTTP Header (the cached time may be preferable).

To realize CGI::Cache enabled MT-XSearch, install CGI::Cache module from CPAN, and modify mt-xsearch.cgi as follows:

--- mt-xsearch.cgi.bak	Fri Aug 27 12:06:24 2004
+++ mt-xsearch.cgi	Sat Jun 11 03:44:32 2005
@@ -17,6 +17,7 @@
 }
 
 use CGI;
+use CGI::Cache;
 use MT;
 use MT::ConfigMgr;
 use MT::Template;
@@ -27,10 +28,13 @@
     my $mt = MT->new( Config => $MT_DIR . 'mt.cfg', Directory => $MT_DIR )
         or die MT->errstr;
     my $q = new CGI;
+    CGI::Cache::setup({ cache_options => { cache_root => './cache', default_expires_in => 3600 } });
     my $blog_id = $q->param('blog_id') or
         die "Missing parameter blog_id";
     my $key = $q->param('search_key') or
         die "Missing parameter key";
+    CGI::Cache::set_key($q->Vars);
+    CGI::Cache::start() or exit;
     my $search = MT::XSearch->execute($q);
     my $tmpl = MT::Template->load( { 
                         name=>'XSearch '.$key, 
@@ -41,7 +45,14 @@
     $ctx->stash('CGI',$q);
     my $out = $tmpl->build($ctx)
         or die "Building search template failed: ".$tmpl->errstr;
-    print $q->header.$out;
+    my $charset = $mt->{cfg}->PublishCharset;
+    my @m = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+    my @w = qw(Sun Mon Tue Wed Thu Fri Sat);
+    my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime(time);
+    my $now = sprintf("%3s, %02d %3s %04d %02d:%02d:%02d GMT",
+        $w[$wday], $mday, $m[$mon], $year+1900, $hour, $min, $sec);
+    print $q->header(-charset=>$charset,-Last_Modified=>$now).$out;
+    CGI::Cache::stop();
 };
 if ($@) {
     print "Content-Type: text/html\n\n";

Reds mean the cache directory and the cache lifetime by seconds. In the above example, the directory is "./cache" and the lifetime is 3600 secs(1 hour).

TrackBack

TrackBack URL for this entry:
http://as-is.net/mt/en_US/mt-tb.cgi/11

Listed below are links to weblogs that reference Dynamic Tag Archiving with Tagwire and MT-XSearch:

» Dynamic Tag Archiving with Tagwire and MT-XSearch from einfach persoenlich Sideblog
Anstelle von statischen Kategorie-Archiven verwendet Hirotaka Ogawa mit seinem T... [Read More]

» Tutorial: Kreatives Tagging im Movable Type Weblog from einfach-persoenlich
Tags sollen neben Kategorien im Weblog mehr Ordnung, guten Zugriff und Flexibil... [Read More]

» Kreatives Tagging in MT-Blogs weitergedacht from einfach-persoenlich
Kaum war das Tutorial Kreatives Tagging im Movable Type Weblog fertig geschriebe... [Read More]

Comments

For some reason the when I try to use the search it doesn't list the entries.

Is it because I'm using MT 3.2? You can see it here:
http://dementedstudios.org/tag.php

Please add "&delimiter=," to your dynamic tag URL as like:
http://dementedstudios.org/mt/mt-xsearch.cgi?blog_id=1&search_key=Tagwire&search=Wentworth%20Miller&delimiter=,

It is required to tell mt-xsearch "*space* is not a delimiter character."
You can use "|" or "_" or something else that you won't use in your tags.

I get an error message at http://www.naturelich.com/games/tag/review:

Got an error: Can't call method "build" without a package or object reference at mt-xsearch.cgi line 42

I get an error message at http://www.naturelich.com/games/tag/review

Got an error: Can't call method "build" without a package or object reference at mt-xsearch.cgi line 42

Oh, and another question: how did you get the tag cloud running?

OK, it works now. Please be aware that the .htaccess command is somehow cut off. I had to copy it from the HTML source. Now it works excellent, thank you very much. Oh, but still: any idea how to do the tag cloud? I'd really appreciate any help...

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)