#!/usr/bin/perl # musings.cgi - a CGI script to search a swish index of my musings # Eric Lease Morgan # 2004/11/21 - added screen as well as print css; I don't really understand it! # 2004/11/09 - marked up subjects; added suggestions # 2004/11/07 - first investigations; based on gallery.pl # define the index file to search use constant DICTIONARY => '/usr/local/apache/htdocs/musings/etc/musings.dict'; use constant INDEX => 'etc/musings.idx'; use constant MENU => 'etc/contents.inc'; use constant NAVBAR => 'etc/navigation.inc'; use constant PREFIX => '?cmd=search&query=subject%3D'; ############################################################################################### # no configuration should be necessary below this line, unless you want to configure the output # define the necessary modules use CGI; use CGI::Carp qw(fatalsToBrowser); use Musings::Article; use Musings::Subject; use strict; use SWISH::API; use Text::Aspell; # initalize CGI I/O my $cgi = CGI->new; # initialize global variables; my ($hit_list, $number_of_hits); # initialilze the HTML output my $html = $cgi->header; my @style = ({-src => 'etc/musings.css', -media => 'screen'}, {-src => 'etc/musings-print.css', -media => 'print'}); $html .= $cgi->start_html(-title=>"Infomotions' Musings on Information and Librarianship", -style => \@style); $html .= &read_navigation; $html .= &read_menu; # get the command my $cmd = $cgi->param('cmd'); # branch according to the command if (! $cmd) { # simply get the home page $html .= '
'; $html .= $cgi->h1("Infomotions' Musings on Information and Librarianship"); $html .= $cgi->p('This is an (incomplete) collection of the things I\'ve written -- my musings.'); $html .= $cgi->p('My day job resides in an academic environment, and I believe it is my responsibility to act academically. A lot of the time, this means thinking, studying, writing, sharing, and repeating the process. The exciting thing about writing, and while it may sound corny, is that is transcends both space and time. It is entirely possible for someone to write something down and have those written words to be communicated to other people on the other side of the world days, weeks, or even years later.'); $html .= $cgi->p('I believe it is important to share one\'s ideas freely. That is why I have never completely signed away my copyrights and retained the rights to post my articles on my own website. This collection is a manifestation of that idea. I have been practicing "green" open access publishing for more than a dozen years.'); $html .= $cgi->p('To these ends I am sharing the texts in this collection with you. It contains pre-edited, formally published articles, travel logs, descriptions of software applications, and the hand-outs of workshops and presentations. Feel free to use the items in this collection as you see fit, but please don\'t call the works your own. Place the blame and/or credit where the blame and/or credit is due.'); $html .= '
'; } elsif ($cmd eq 'title') { my @articles = Musings::Article->get_articles(sort => 'name'); my $list; foreach (@articles) { $list .= $cgi->li($cgi->a({href => $_->article_path}, $_->article_title))} $html .= '
'; $html .= $cgi->h1("Infomotions' Musings on Information and Librarianship"); $html .= $cgi->h2("Title index"); $html .= $cgi->ul({class => 'detaillist'}, $list); $html .= '
'; } elsif ($cmd eq 'date') { my @articles = Musings::Article->get_articles(sort => 'date'); my $list; foreach (@articles) { $list .= $cgi->li($cgi->a({href => $_->article_path}, $_->article_title). ' (' . $_->article_date . ')')} $html .= '
'; $html .= $cgi->h1("Infomotions' Musings on Information and Librarianship"); $html .= $cgi->h2("Date index"); $html .= $cgi->ul({class => 'detaillist'}, $list); $html .= '
'; } elsif ($cmd eq 'subject') { my @subjest = Musings::Subject->get_subjects(sort => 'name'); my $list; foreach (@subjest) { $list .= $cgi->li($_->subject_term); my @article_ids = $_->article_ids; $list .= $cgi->start_ul; foreach my $a (@article_ids) { my $article = Musings::Article->new(id => $a); $list .= $cgi->li($cgi->a({href => $article->article_path}, $article->article_title)); } $list .= $cgi->end_ul; } $html .= '
'; $html .= $cgi->h1("Infomotions' Musings on Information and Librarianship"); $html .= $cgi->h2("Subject index"); $html .= $cgi->ul({class => 'detaillist'}, $list); $html .= '
'; } elsif ( $cmd eq 'help' ) { # simply disply the search help $html .= &help(); } elsif ( $cmd eq 'search' ) { # check for query if (! $cgi->param('query')) { # error $html .= '

Opps! No query was supplied.

'; # quit &gracefulExit(); } # search the index &search(); } else { # error; unknown command $html .= "Oops! Unknown value for cmd ($cmd). Call Eric."; } # quit &gracefulExit(); ############# # subroutines # display the output and exit the application sub gracefulExit { # add the footer to the output $html .= &footer; $html .= $cgi->end_html; # proces each macro $html =~ s/##NUMBEROFHITS##/$number_of_hits/g; $html =~ s/##HITLIST##/$hit_list/g; $html =~ s/##QUERY##/$cgi->param('query')/eg; # display the html, finally print $html; # quit, whew! exit; } # the heart of the matter sub search { # get the result page $html .= &results(); # open the index my $swish = SWISH::API->new(INDEX); # search the index my $results = $swish->Query($cgi->param('query')); # check for search results; need error checking $number_of_hits = $results->Hits; # initalize the hit list and a pointer $hit_list; if (! $number_of_hits) { # initalize dictionary my $dictionary = Text::Aspell->new; $dictionary->set_option('master', DICTIONARY); # parse the query my @query = split / /, $cgi->param('query'); # initialize the new query my $new_query; # process each query word foreach my $q (@query) { # get suggestion my @suggestions = $dictionary->suggest($q); # build new query $new_query .= @suggestions[0] . ' '; } $new_query = substr($new_query, 0, -1); # add a suggestion to the output $hit_list = $cgi->p("Did you mean $new_query?"); return; } # process each hit while (my $result = $results->NextResult) { # get the results my $title = $result->Property ('swishtitle'); $title =~ s/ \/.*$//; my $note = $result->Property('description'); my $date = $result->Property('date'); my $source = $result->Property('source'); my $subjects = &swishify($result->Property('subject')); my $url = $result->Property('swishdocpath'); my $details; if ($note) { $details .= $cgi->li("Description: $note") } if ($date) { $details .= $cgi->li("Date: $date") } if ($source) { $details .= $cgi->li("Source: $source") } if ($subjects) { $details .= $cgi->li("Subject(s): $subjects") } if ($url) { $details .= $cgi->li("URL: $url") } $details = $cgi->ul({-class=>'detaillist'}, $details); $hit_list .= $cgi->li("$title$details"); } # finish the hit list $hit_list = $cgi->ol($hit_list); } # edit these subroutines to change the output's display sub form { return < Query:
Help EOF } sub results { return <

Search results

Your search (##QUERY##) returned ##NUMBEROFHITS## hit(s):

##HITLIST## EOF } sub help { return <

Help text

The search engine supports any combination of Boolean logic, nested queries, phrase, and field searches. Queries are case-insensitive. Examples include:

Types Examples
simple: red
Boolean and: red and blue
Boolean and: red blue
Boolean or: red or blue
Boolean not: red not blue
nested: (red or blue) and green
phrase: "light red"
field: title = red
EOF } sub read_navigation { my $rv; open (NAV, '< ' . NAVBAR); while (