--- loncom/interface/lonsearchcat.pm 2002/06/24 16:45:22 1.128
+++ loncom/interface/lonsearchcat.pm 2002/07/28 20:02:14 1.145
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Search Catalog
#
-# $Id: lonsearchcat.pm,v 1.128 2002/06/24 16:45:22 harris41 Exp $
+# $Id: lonsearchcat.pm,v 1.145 2002/07/28 20:02:14 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -40,7 +40,7 @@
=head1 NAME
-lonsearchcat
+lonsearchcat - LONCAPA Search Interface
=head1 SYNOPSIS
@@ -87,8 +87,10 @@ use Apache::lonnet();
use Apache::File();
use CGI qw(:standard);
use Text::Query;
+use DBI;
use GDBM_File;
use Apache::loncommon();
+use Apache::lonmysql();
# ---------------------------------------- variables used throughout the module
@@ -101,23 +103,26 @@ use Apache::loncommon();
=over 4
-=item $closebutton
-
-button that closes the search window
-
=item $importbutton
-button to take the selecte results and go to group sorting
+button to take the select results and go to group sorting
-=item %hash
+=item %groupsearch_db
-The ubiquitous database hash
+Database hash used to save values for the groupsearch RAT interface.
=item $diropendb
The full path to the (temporary) search database file. This is set and
used in &handler() and is also used in &output_results().
+=item %Views
+
+Hash which associates an output view description with the function
+that produces it. Adding a new view type should be as easy as
+adding a line to the definition of this hash and making sure the function
+takes the proper parameters.
+
=back
=cut
@@ -126,13 +131,19 @@ used in &handler() and is also used in &
######################################################################
# -- dynamically rendered interface components
-my $closebutton; # button that closes the search window
my $importbutton; # button to take the selected results and go to group sorting
# -- miscellaneous variables
-my %hash; # database hash
+my %groupsearch_db; # database hash
my $diropendb = ""; # db file
-
+# View Description Function Pointer
+my %Views = ("Detailed Citation View" => \&detailed_citation_view,
+ "Summary View" => \&summary_view,
+ "Fielded Format" => \&fielded_format_view,
+ "XML/SGML" => \&xml_sgml_view );
+my $persistent_db_file;
+my %persistent_db;
+my $hidden_fields;
######################################################################
######################################################################
@@ -160,26 +171,57 @@ string that holds portions of the screen
######################################################################
sub handler {
my $r = shift;
- untie %hash;
-
+ #
+ untie %groupsearch_db if (tied(%groupsearch_db));
+ #
+ my $closebutton; # button that closes the search window
+ # This button is different for the RAT compared to
+ # normal invocation.
+ #
$r->content_type('text/html');
$r->send_http_header;
return OK if $r->header_only;
-
+ ##
+ ## Pick up form fields passed in the links.
+ ##
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['catalogmode','launch','acts','mode','form','element',
+ 'reqinterface','persistent_db_id','table']);
+ ##
+ ## Initialize global variables
+ ##
my $domain = $r->dir_config('lonDefDomain');
$diropendb= "/home/httpd/perl/tmp/".&Apache::lonnet::escape($domain).
"\_".&Apache::lonnet::escape($ENV{'user.name'})."_searchcat.db";
-
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['catalogmode','launch','acts','mode','form','element',
- 'reqinterface']);
+ #
+ # set the name of the persistent database
+ # $ENV{'form.persistent_db_id'} can only have digits in it.
+ if (! exists($ENV{'form.persistent_db_id'}) ||
+ $ENV{'form.persistent_db_id'} =~ /\D/ ) {
+ $ENV{'form.persistent_db_id'} = time;
+ }
+ $persistent_db_file = "/home/httpd/perl/tmp/".
+ &Apache::lonnet::escape($domain).
+ '_'.&Apache::lonnet::escape($ENV{'user.name'}).
+ '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';
+ #
+ # Read in the database. It should (hopefully) not be catastrophic to
+ # fail in this exercise.
+ if (-e $persistent_db_file) {
+ # Read in the previous values, if we can.
+ if (tie(%persistent_db,'GDBM_File',$persistent_db_file,
+ &GDBM_READER,0640)) {
+ &reconstruct_persistent_form_data($r);
+ untie (%persistent_db);
+ }
+ }
##
- ## Clear out old values from database
+ ## Clear out old values from groupsearch database
##
if ($ENV{'form.launch'} eq '1') {
- if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
+ if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
&start_fresh_session();
- untie %hash;
+ untie %groupsearch_db;
} else {
$r->print('
Unable to tie hash to db '.
'file');
@@ -187,23 +229,14 @@ sub handler {
}
}
##
- ## Produce some output, so people know it is working
- ##
- $r->print("\n");
- $r->rflush;
- ##
## Configure dynamic components of interface
##
- my $hidden; # Holds 'hidden' html forms
+ $hidden_fields = '';
if ($ENV{'form.catalogmode'} eq 'interactive') {
- $hidden="".
- "\n";
$closebutton=""."\n";
} elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {
- $hidden=<
-END
$closebutton=<
END
@@ -212,29 +245,68 @@ END
onClick='javascript:select_group()'>
END
}
- $hidden .= <
-
-
-
-END
##
- ## What are we doing?
+ ## Do a search, if needed.
##
- if ($ENV{'form.basicsubmit'} eq 'SEARCH') {
- # Perform basic search and give results
- return &basicsearch($r,\%ENV,$hidden);
- } elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
- # Perform advanced search and give results
- return &advancedsearch($r,\%ENV,$hidden);
- } elsif ($ENV{'form.reqinterface'} eq 'advanced') {
- # Output the advanced interface
- $r->print(&advanced_search_form($closebutton,$hidden));
- return OK;
- } else {
- # Output normal search interface
- $r->print(&basic_search_form($closebutton,$hidden));
+ my $searchtype;
+ $searchtype = 'Basic' if ($ENV{'form.basicsubmit'} eq 'SEARCH');
+ $searchtype = 'Advanced' if ($ENV{'form.advancedsubmit'} eq 'SEARCH');
+ if ($searchtype) {
+ ##
+ ## make query information persistent to allow for subsequent revision
+ ##
+ tie(%persistent_db,'GDBM_File',$persistent_db_file,&GDBM_WRCREAT,0640);
+ &make_persistent(\%ENV);
+ untie(%persistent_db);
+ #
+ # We are running a search
+ my ($query,$customquery,$customshow,$libraries) =
+ (undef,undef,undef,undef);
+ my $pretty_string;
+ if ($searchtype eq 'Basic') {
+ ($query,$pretty_string) = &parse_basic_search($r,$closebutton);
+ } elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
+ ($query,$customquery,$customshow,$libraries,$pretty_string)
+ = &parse_advanced_search($r,$closebutton);
+ return OK if (! defined($query));
+ }
+ # Output some information to the user.
+ $r->print(&search_results_header($searchtype,$pretty_string));
+ $r->print("Sending search request to LON-CAPA servers. \n");
+ $r->rflush();
+ &run_search($r,$query,$customquery,$customshow,$libraries);
+ ##
+ ## Display the results
+ ##
+ &display_results($r,$searchtype,$importbutton,$closebutton);
+ $r->rflush();
+ } else {
+ #
+ # Set the default view if it is not already set.
+ if (!defined($ENV{'form.viewselect'})) {
+ $ENV{'form.viewselect'} ="Detailed Citation View";
+ }
+ #
+ # remove the requested interface from the environment.
+ my $interface;
+ if ($ENV{'form.reqinterface'}) {
+ $interface = lc($ENV{'form.reqinterface'});
+ } else {
+ $interface = 'basic';
+ }
+ ##
+ ## Determine course of action
+ ##
+ if ($interface eq 'display') {
+ # &display_results($closebutton));
+ } elsif ($interface eq 'advanced') {
+ $r->print(&advanced_search_form($closebutton));
+ } elsif ($interface eq 'basic') {
+ # Output normal search interface
+ $r->print(&basic_search_form($closebutton));
+ }
}
+ untie (%persistent_db);
return OK;
}
@@ -253,7 +325,7 @@ Returns a scalar which holds html for th
######################################################################
sub basic_search_form{
- my ($closebutton,$hidden) = @_;
+ my ($closebutton) = @_;
my $scrout=<<"ENDDOCUMENT";
@@ -270,10 +342,11 @@ sub basic_search_form{
Search Catalog
@@ -321,7 +394,18 @@ Returns a scalar which holds html for th
######################################################################
sub advanced_search_form{
- my ($closebutton,$hidden) = @_;
+ my ($closebutton) = @_;
+ my $advanced_buttons = <<"END";
+
+
+
+$closebutton
+
+
+END
+ if (!defined($ENV{'form.viewselect'})) {
+ $ENV{'form.viewselect'} ="Detailed Citation View";
+ }
my $scrout=<<"ENDHEADER";
@@ -336,35 +420,76 @@ sub advanced_search_form{
-
Search Catalog
-
@@ -467,35 +576,72 @@ ENDDOCUMENT
=pod
-=item &make_persistent()
+=item &reconstruct_persistent_form_data
-Returns a scalar which holds the current ENV{'form.*'} values in
-a 'hidden' html input tag. This allows search interface information
-to be somewhat persistent.
+This function is the reverse of &make_persistent();
+Retrieve persistent data from %persistent_db. Retrieved items will have their
+values unescaped. If the item contains commas (before unescaping), the
+returned value will be an array pointer. Items will be returned in the
+environment in $ENV{"form.$name"}.
=cut
######################################################################
######################################################################
-
-sub make_persistent {
- my $persistent='';
- foreach (keys %ENV) {
- if (/^form\./ && !/submit/) {
- my $name=$_;
- my $key=$name;
- $ENV{$key}=~s/\'//g; # do not mess with html field syntax
- $name=~s/^form\.//;
- $persistent.=<
-END
+sub reconstruct_persistent_form_data {
+ foreach my $name (keys %persistent_db) {
+ # &Apache::lonnet::logthis("Reconstructing $name = $persistent_db{$name}");
+ my @Values = split(',',$persistent_db{$name});
+ my @value = map { &Apache::lonnet::unescape($_) } @Values;
+ $name = 'form.'.$name;
+ if (exists($ENV{$name})) {
+ if (ref($ENV{$name})) {
+ # Assume it is an array reference
+ $ENV{$name} = [@{$ENV{$name}},@value];
+ } else {
+ $ENV{$name} = [$ENV{$name},@value];
+ }
+ } else {
+ if (@value > 1) {
+ $ENV{$name} = [@value];
+ } else {
+ $ENV{$name} = $value[0];
+ }
}
}
- return $persistent;
+ return;
}
+######################################################################
+######################################################################
+
+=pod
+
+=item &make_persistent()
+
+Store (environment) variables away to the %persistent_db.
+Values will be escaped. Values that are array pointers will have their
+elements escaped and concatenated in a comma seperated string.
+
+=cut
+
+######################################################################
+######################################################################
+sub make_persistent {
+ my %save = %{shift()};
+ foreach my $name (keys %save) {
+ next if ($name !~ /^form\./ || $name =~ /submit/);
+ my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));
+ # We handle array references, but not recursively.
+ my $store = join(',', map { &Apache::lonnet::escape($_); } @values );
+ $name=~s/^form\.//;
+ $persistent_db{$name} = $store;
+ }
+ return '';
+}
######################################################################
+# HTML form building functions #
######################################################################
=pod
@@ -504,6 +650,13 @@ END
=over 4
+=cut
+
+###############################################
+###############################################
+
+=pod
+
=item &simpletextfield()
Inputs: $name,$value,$size
@@ -511,6 +664,23 @@ Inputs: $name,$value,$size
Returns a text input field with the given name, value, and size.
If size is not specified, a value of 20 is used.
+=cut
+
+###############################################
+###############################################
+
+sub simpletextfield {
+ my ($name,$value,$size)=@_;
+ $size = 20 if (! defined($size));
+ return '';
+}
+
+###############################################
+###############################################
+
+=pod
+
=item &simplecheckbox()
Inputs: $name,$value
@@ -518,56 +688,107 @@ Inputs: $name,$value
Returns a simple check box with the given $name.
If $value eq 'on' the box is checked.
-=item &searchphrasefield()
+=cut
-Inputs: $title,$name,$value
+###############################################
+###############################################
-Returns html for a title line and an input field for entering search terms.
-the instructions "Enter terms or phrases separated by search operators such
-as AND, OR, or NOT." are given following the title. The entry field (which
-is where the $name and $value are used) is an 80 column simpletextfield.
+sub simplecheckbox {
+ my ($name,$value)=@_;
+ my $checked='';
+ $checked="checked" if $value eq 'on';
+ return '';
+}
-=item &dateboxes()
+###############################################
+###############################################
-Returns html selection form elements for the specification of
-the day, month, and year.
+=pod
-=item &selectbox()
+=item &fieldtitle()
-Returns html selection form.
+Input: $title
-=back
+Returns a scalar with html which will display $title as a search
+field heading.
=cut
-######################################################################
-######################################################################
+###############################################
+###############################################
-sub simpletextfield {
- my ($name,$value,$size)=@_;
- $size = 20 if (! defined($size));
- return '';
+sub fieldtitle {
+ my $title = uc(shift());
+ return ''.$title.
+ ': ';
}
-sub simplecheckbox {
- my ($name,$value)=@_;
- my $checked='';
- $checked="CHECKED" if $value eq 'on';
- return '';
-}
+###############################################
+###############################################
+=pod
+
+=item &searchphrasefield()
+
+Inputs: $title,$name,$value
+
+Returns html for a title line and an input field for entering search terms.
+The entry field (which is where the $name and $value are used) is a 50 column
+simpletextfield. The html returned is for a row in a three column table.
+
+=cut
+
+###############################################
+###############################################
+
sub searchphrasefield {
my ($title,$name,$value)=@_;
- my $instruction=<'.$uctitle.':'.
- " $instruction ".&simpletextfield($name,$value,80);
+ return '
'.&fieldtitle($title).'
'.
+ &simpletextfield($name,$value,50)."
\n";
+}
+
+###############################################
+###############################################
+
+=pod
+
+=item &searchphrasefield_with_related()
+
+Inputs: $title,$name,$value
+
+Returns html for a title line and an input field for entering search terms
+and a check box for 'related words'. The entry field (which is where the
+$name and $value are used) is a 50 column simpletextfield. The name of
+the related words checkbox is "$name_related".
+
+=cut
+
+###############################################
+###############################################
+
+sub searchphrasefield_with_related {
+ my ($title,$name,$value)=@_;
+ return '
');
+ if (! tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
+ $r->print('Unable to tie hash to db file');
+ $r->rflush();
+ return;
+ }
+ ##
+ ## Prepare the table for querying
+ ##
+ my $table = $ENV{'form.table'};
+ my $connection_result = &Apache::lonmysql::connect_to_db();
+ if (!defined($connection_result)) {
+ &write_status($r,&Apache::lonmysql::get_error());
+ }
+ my $table_check = &Apache::lonmysql::check_table($table);
+ if (! defined($table_check)) {
+ $r->print("A MySQL error has occurred.