--- loncom/interface/lonsearchcat.pm 2003/09/28 00:14:25 1.187 +++ loncom/interface/lonsearchcat.pm 2004/01/02 16:34:03 1.201 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.187 2003/09/28 00:14:25 www Exp $ +# $Id: lonsearchcat.pm,v 1.201 2004/01/02 16:34:03 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -59,20 +59,8 @@ search (on a server basis) is displayed ############################################################################### ############################################################################### -############################################################################### -## ## -## ORGANIZATION OF THIS PERL MODULE ## -## ## -## 1. Modules used by this module ## -## 2. Variables used throughout the module ## -## 3. handler subroutine called via Apache and mod_perl ## -## 4. Other subroutines ## -## ## -############################################################################### - package Apache::lonsearchcat; -# ------------------------------------------------- modules used by this module use strict; use Apache::Constants qw(:common :http); use Apache::lonnet(); @@ -82,103 +70,48 @@ use Text::Query; use GDBM_File; use Apache::loncommon(); use Apache::lonmysql(); +use Apache::lonmeta; +use Apache::lonhtmlcommon; use Apache::lonlocal; -# ---------------------------------------- variables used throughout the module - -###################################################################### -###################################################################### - -=pod - -=item Global variables - -=over 4 - -=item $importbutton - -button to take the select results and go to group sorting - -=item %groupsearch_db - -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. - -=item $bodytag - -LON-CAPA standard body tag, gotten from &Apache::lonnet::bodytag. -No title, no table, just a tag. - -=back - -=cut - ###################################################################### ###################################################################### - -# -- dynamically rendered interface components -my $importbutton; # button to take the selected results and go to group sorting - -# -- miscellaneous variables -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, - "Compact View" => \&compact_view); -my %persistent_db; -my $hidden_fields; -my $bodytag; - -# -# For course search -# -my %alreadyseen; -my $hashtied; -my %hash; -my $totalfound; - -###################################################################### -###################################################################### - -=pod - -=item &handler() - main handler invoked by httpd child - -=item Variables - -=over 4 - -=item $hidden - -holds 'hidden' html forms - -=item $scrout - -string that holds portions of the screen output - -=back - -=cut +## +## Global variables +## +###################################################################### +###################################################################### +my %groupsearch_db; # Database hash used to save values for the + # groupsearch RAT interface. +my %persistent_db; # gdbm hash which holds data which is supposed to + # persist across calls to lonsearchcat.pm + +# The different view modes and associated functions + +my %Views = ("detailed" => \&detailed_citation_view, + "summary" => \&summary_view, + "fielded" => \&fielded_format_view, + "xml" => \&xml_sgml_view, + "compact" => \&compact_view); ###################################################################### ###################################################################### sub handler { my $r = shift; +# &set_defaults(); + # + # set form defaults # + my $hidden_fields;# Hold all the hidden fields used to keep track + # of the search system state + my $importbutton; # button to take the selected results and go to group + # sorting + my $diropendb; # The full path to the (temporary) search database file. + # This is set and used in &handler() and is also used in + # &output_results(). + my $bodytag; # LON-CAPA standard body tag, gotten from + # &Apache::lonnet::bodytag. + # No title, no table, just a tag. my $loaderror=&Apache::lonnet::overloaderror($r); if ($loaderror) { return $loaderror; } @@ -200,7 +133,7 @@ sub handler { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['catalogmode','launch','acts','mode','form','element','pause', 'phase','persistent_db_id','table','start','show', - 'cleargroupsort']); + 'cleargroupsort','titleelement']); ## ## The following is a trick - we wait a few seconds if asked to so ## the daemon running the search can get ahead of the daemon @@ -282,6 +215,10 @@ END $hidden_fields .= ''."\n"; } + if (exists($ENV{'form.titleelement'})) { + $hidden_fields .= ''."\n"; + } if (exists($ENV{'form.mode'})) { $hidden_fields .= ''."\n"; @@ -330,11 +267,11 @@ END ## Switch on the phase ## if ($ENV{'form.phase'} eq 'disp_basic') { - &print_basic_search_form($r,$closebutton); + &print_basic_search_form($r,$closebutton,$hidden_fields); } elsif ($ENV{'form.phase'} eq 'disp_adv') { - &print_advanced_search_form($r,$closebutton); + &print_advanced_search_form($r,$closebutton,$hidden_fields); } elsif ($ENV{'form.phase'} eq 'results') { - &display_results($r,$importbutton,$closebutton); + &display_results($r,$importbutton,$closebutton,$diropendb); } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) { my ($query,$customquery,$customshow,$libraries,$pretty_string) = &get_persistent_data($persistent_db_file, @@ -356,11 +293,13 @@ END } # Set up table if (! defined(&create_results_table())) { + my $errorstring=&Apache::lonmysql::get_error(); $r->print(<Search Error $bodytag Unable to create table in which to store search results. The search has been aborted. +
$errorstring END @@ -384,10 +323,10 @@ END my $pretty_string; if ($ENV{'form.phase'} eq 'basic_search') { ($query,$pretty_string,$libraries) = - &parse_basic_search($r,$closebutton); + &parse_basic_search($r,$closebutton,$hidden_fields); } else { # Advanced search ($query,$customquery,$customshow,$libraries,$pretty_string) - = &parse_advanced_search($r,$closebutton); + = &parse_advanced_search($r,$closebutton,$hidden_fields); return OK if (! defined($query)); } &make_persistent({ query => $query, @@ -406,6 +345,17 @@ END ###################################################################### ###################################################################### +## +## Course Search +## +###################################################################### +###################################################################### +{ # Scope the course search to avoid global variables +# +# Variables For course search +my %alreadyseen; +my %hash; +my $totalfound; sub course_search { my $r=shift; @@ -416,9 +366,9 @@ sub course_search { if ($ENV{'form.crsrelated'}) { ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'}); if (@New_Words) { - $pretty_search_string .= " with related words: @New_Words."; + $pretty_search_string .= ' '.&mt("with related words").": @New_Words."; } else { - $pretty_search_string .= " with no related words."; + $pretty_search_string .= ' '.&mt('with no related words')."."; } } my $fulltext=$ENV{'form.crsfulltext'}; @@ -428,18 +378,20 @@ sub course_search { $bodytag.$pretty_search_string); $r->rflush(); # ======================================================= Go through the course - $hashtied=0; - undef %alreadyseen; - %alreadyseen=(); + undef %alreadyseen; + %alreadyseen=(); my $c=$r->connection; - &tiehash(); - foreach (keys %hash) { - if ($c->aborted()) { last; } - if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) { - &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext,@allwords); - } - } - &untiehash(); + if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db", + &GDBM_READER(),0640)) { + foreach (keys %hash) { + if ($c->aborted()) { last; } + if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) { + &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext, + @allwords); + } + } + untie(%hash); + } unless ($totalfound) { $r->print('

'.&mt('No resources found').'.

'); } @@ -447,23 +399,6 @@ sub course_search { $r->print(''); } -# ---------------------------------------------------------------- tie the hash - -sub tiehash { - $hashtied=0; - if ($ENV{'request.course.fn'}) { - if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db", - &GDBM_READER(),0640)) { - $hashtied=1; - } - } -} - -sub untiehash { - if ($hashtied) { untie %hash; } - $hashtied=0; -} - # =============================== This pulls up a resource and its dependencies sub checkonthis { @@ -509,6 +444,14 @@ sub checkonthis { } } +sub untiehash { + if (tied(%hash)) { + untie(%hash); + } +} + +} # End of course search scoping + ###################################################################### ###################################################################### @@ -524,7 +467,7 @@ Returns a scalar which holds html for th ###################################################################### sub print_basic_search_form{ - my ($r,$closebutton) = @_; + my ($r,$closebutton,$hidden_fields) = @_; my $bodytag=&Apache::loncommon::bodytag('Search'); my $scrout=<<"ENDDOCUMENT"; @@ -541,46 +484,46 @@ sub print_basic_search_form{ $bodytag ENDDOCUMENT if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { + my $CatalogSearch=&mt('Catalog Search'); + my $Statement=&searchhelp(); $scrout.=(<Catalog Search -
+

$CatalogSearch

+ $hidden_fields

-Enter terms or phrases separated by AND, OR, or NOT -then press SEARCH below. +$Statement.

- - + +
ENDDOCUMENT - $scrout.=' '.&simpletextfield('basicexp',$ENV{'form.basicexp'},40). + $scrout.=' '.&Apache::lonhtmlcommon::textbox('basicexp', + $ENV{'form.basicexp'},40). ' '; - my $relatedcheckbox = &simplecheckbox('related',$ENV{'form.related'}); + my $relatedcheckbox = &Apache::lonhtmlcommon::checkbox('related', + $ENV{'form.related'}); my $domain = $r->dir_config('lonDefDomain'); - my $domaincheckbox = &simplecheckbox('domains',$domain); + my $domaincheckbox = &Apache::lonhtmlcommon::checkbox('domains', + $ENV{'form.domains'}); my $srch=&mt('Search'); my $header=&mt('Advanced Search'); + my $userelatedwords=&mt('use related words'); + my $onlysearchdomain=&mt('only search domain'); + my $view=&viewoptions(); $scrout.=<$header
$relatedcheckbox use related words$domaincheckbox only search domain $domain
$relatedcheckbox $userelatedwords$domaincheckbox $onlysearchdomain $domain

+$view

   $closebutton END - $scrout.=&selectbox('View','viewselect', - $ENV{'form.viewselect'}, - undef,undef,undef, - sort(keys(%Views))); - $scrout.=&selectbox('Per page','show', - $ENV{'form.show'}, - undef,undef,undef, - (10,20,50,100)); $scrout.=< @@ -591,11 +534,13 @@ ENDDOCUMENT 'srch' => 'Search', 'header' => 'Course Search', 'note' => 'Enter terms or phrases, then press "Search" below', + 'use' => 'use related words', + 'full' =>'fulltext search (time consuming)' ); $scrout.=(<

$lt{'header'}

-
+ $hidden_fields

@@ -606,15 +551,18 @@ $lt{'note'}. ENDCOURSESEARCH $scrout.=' '. - &simpletextfield('courseexp',$ENV{'form.courseexp'},40); + &Apache::lonhtmlcommon::textbox('courseexp', + $ENV{'form.courseexp'},40); my $crscheckbox = - &simplecheckbox('crsfulltext',$ENV{'form.crsfulltext'}); + &Apache::lonhtmlcommon::checkbox('crsfulltext', + $ENV{'form.crsfulltext'}); my $relcheckbox = - &simplecheckbox('crsrelated',$ENV{'form.crsrelated'}); + &Apache::lonhtmlcommon::checkbox('crsrelated', + $ENV{'form.crsrelated'}); $scrout.=(< -$relcheckbox use related words -$crscheckbox fulltext search (time consuming) +$relcheckbox $lt{'use'} +$crscheckbox $lt{'full'}

 

@@ -642,19 +590,20 @@ Returns a scalar which holds html for th ###################################################################### sub print_advanced_search_form{ - my ($r,$closebutton) = @_; + my ($r,$closebutton,$hidden_fields) = @_; + my %lt=&Apache::lonlocal::texthash('srch' => 'Search', + 'reset' => 'Reset', + 'help' => 'Help'); my $advanced_buttons = <<"END";

- - + + $closebutton - +

END - if (!defined($ENV{'form.viewselect'})) { - $ENV{'form.viewselect'} ="Detailed Citation View"; - } my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search'); + my $searchhelp=&searchhelp(); my $scrout=<<"ENDHEADER"; @@ -668,60 +617,54 @@ END $bodytag -Enter terms or phrases separated by search operators -such as AND, OR, or NOT.
- +$searchhelp + $advanced_buttons $hidden_fields - - -\n"; - $scrout.=&searchphrasefield_with_related('title', 'title' , - $ENV{'form.title'}); - $scrout.=&searchphrasefield('author', 'author' ,$ENV{'form.author'}); - $scrout.=&searchphrasefield_with_related('subject', 'subject' , - $ENV{'form.subject'}); - $scrout.=&searchphrasefield_with_related('keywords','keywords', - $ENV{'form.keywords'}); - $scrout.=&searchphrasefield('URL', 'url' ,$ENV{'form.url'}); - $scrout.=&searchphrasefield_with_related('notes', 'notes' , - $ENV{'form.notes'}); - $scrout.=&searchphrasefield_with_related('abstract','abstract', - $ENV{'form.abstract'}); + $scrout.=&viewoptions(); + my %fields=&Apache::lonmeta::fieldnames(); + + $scrout.='
VIEW: ENDHEADER - $scrout.=&selectbox(undef,'viewselect', - $ENV{'form.viewselect'}, - undef,undef,undef, - sort(keys(%Views))); - $scrout.=' '; - $scrout.=&selectbox(undef,'show', - $ENV{'form.show'}, - undef,undef,undef, - (10,20,50,100)); - $scrout.=' '. - ''.&mt('Per Page').''; - $scrout.="".&mt('Related').'
'.&mt('Words')."
'; + $scrout.="\n"; + foreach ('title','author','keywords','notes','abstract','standards', + 'lowestgradelevel','highestgradelevel','mime') { + $scrout.=''; + } + my %dates=&Apache::lonlocal::texthash('creationdatestart' => 'Creation Date After', + 'creationdateend' => 'Creation Date Before', + 'lastrevisiondatestart' => 'Last Revision Date After', + 'lastrevisiondateend' => 'Last Revision Date Before'); + foreach (sort keys %dates) { + $scrout.=''; + } + + + # Hack - an empty table row. $scrout.="\n"; - $scrout.=&searchphrasefield('file
extension','extension', - $ENV{'form.extension'}); - $scrout.="\n"; - $scrout.=&searchphrasefield('publisher
owner','owner', - $ENV{'form.owner'}); +# $scrout.=&searchphrasefield('file
extension','extension', +# $ENV{'form.extension'}); +# $scrout.="\n"; +# $scrout.=&searchphrasefield('publisher
owner','owner', + # $ENV{'form.owner'}); $scrout.="
".&mt('Field').''.&mt('Value').'' + .&mt('Related').'
'.&mt('Words')."
'.&titlefield($fields{$_}).''. + &Apache::lonmeta::prettyinput($_,$ENV{'form.'.$_},$_,'advsearch', + 1,'',$ENV{'form.'.$_.'_related'}). + '
'.&titlefield($dates{$_}).''. + &Apache::lonhtmlcommon::date_setter('advsearch',$_,0,'',1). + ' 
   
   
   
\n"; - $ENV{'form.category'}='any' if (! defined($ENV{'form.category'})); - $scrout.=&selectbox('File Category','category', - $ENV{'form.category'}, - 'any','Any category', - undef, - (&Apache::loncommon::filecategories())); - $ENV{'form.language'}='any' unless length($ENV{'form.language'}); +# $scrout.=&Apache::lonmeta::selectbox('File Category','category', +# $ENV{'form.category'}, +# 'any','Any category', +# undef, +# (&Apache::loncommon::filecategories())); #---------------------------------------------------------------- # Allow restriction to multiple domains. # I make the crazy assumption that there will never be a domain 'any'. # - $ENV{'form.domains'} = 'any' if (! exists($ENV{'form.domains'})); my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}} : ($ENV{'form.domains'}) ); my %domain_hash = (); @@ -732,8 +675,7 @@ ENDHEADER # adjust the size of the select box my $size = 4; $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size); - $scrout.="\n".''. - 'DOMAINS TO BE SEARCHED
'. + $scrout.="\n".&titlefield(&mt('Domain to be searched')). '\n"; - #---------------------------------------------------------------- - $scrout.=&selectbox('Limit by language','language', - $ENV{'form.language'},'any','Any Language', - \&Apache::loncommon::languagedescription, - (&Apache::loncommon::languageids), - ); -# ------------------------------------------------ Compute date selection boxes - $scrout.=< -LIMIT BY CREATION DATE RANGE: - -
-between: -CREATIONDATESTART - $scrout.=&dateboxes('creationdatestart',1,1,1976, - $ENV{'form.creationdatestart_month'}, - $ENV{'form.creationdatestart_day'}, - $ENV{'form.creationdatestart_year'}, - ); - $scrout.="and:\n"; - $scrout.=&dateboxes('creationdateend',12,31,2051, - $ENV{'form.creationdateend_month'}, - $ENV{'form.creationdateend_day'}, - $ENV{'form.creationdateend_year'}, - ); - $scrout.="

"; - $scrout.=< -LIMIT BY LAST REVISION DATE RANGE: - -
between: -LASTREVISIONDATESTART - $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976, - $ENV{'form.lastrevisiondatestart_month'}, - $ENV{'form.lastrevisiondatestart_day'}, - $ENV{'form.lastrevisiondatestart_year'}, - ); - $scrout.=< @@ -825,6 +715,101 @@ ENDDOCUMENT $r->print($scrout); return; } +###################################################################### +###################################################################### + +=pod + +=item &titlefield + +Inputs: title text + +Outputs: titletext with font wrapper + +=cut + +###################################################################### +###################################################################### + +sub titlefield { + my $title=shift; + return ''.$title.''; +} +###################################################################### +###################################################################### + +=pod + +=item viewoptiontext + +Inputs: codename for view option + +Outputs: displayed text + +=cut + +###################################################################### +###################################################################### + +sub viewoptiontext { + my $code=shift; + my %desc=&Apache::lonlocal::texthash('detailed' => "Detailed Citation View", + 'xml' => 'XML/SGML', + 'compact' => 'Compact View', + 'fielded' => 'Fielded Format', + 'summary' => 'Summary View'); + return $desc{$code}; +} +###################################################################### + +=pod + +=item viewoptions + +Inputs: none + +Outputs: text for box with view options + +=cut + +###################################################################### +###################################################################### + +sub viewoptions { + my $scrout="\n\n".'
'.&mt('View Options').''. + &mt('Records per Page').'
'; + unless ($ENV{'form.viewselect'}) { $ENV{'form.viewselect'}='detailed'; } + $scrout.=&Apache::lonmeta::selectbox('viewselect', + $ENV{'form.viewselect'}, + \&viewoptiontext, + sort(keys(%Views))); + $scrout.=''; + $scrout.=&Apache::lonmeta::selectbox('show', + $ENV{'form.show'}, + undef, + (10,20,50,100,1000,10000)); + $scrout.="
\n\n"; + return $scrout; +} + +###################################################################### + +=pod + +=item searchhelp + +Inputs: none + +Outputs: return little blurb on how to enter searches + +=cut + +###################################################################### +###################################################################### + +sub searchhelp { + return &mt('Enter terms or phrases separated by AND, OR, or NOT'); +} ###################################################################### ###################################################################### @@ -987,288 +972,6 @@ sub make_form_data_persistent { } ###################################################################### -# HTML form building functions # -###################################################################### - -=pod - -=item HTML form building functions - -=over 4 - -=cut - -############################################### -############################################### - -=pod - -=item &simpletextfield() - -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 - -Returns a simple check box with the given $name. -If $value eq 'on' the box is checked. - -=cut - -############################################### -############################################### - -sub simplecheckbox{ - my ($name,$value,$checked)=@_; - $checked="checked" if ($value eq 'on'); - return ''; -} - -############################################### -############################################### - -=pod - -=item &fieldtitle() - -Input: $title - -Returns a scalar with html which will display $title as a search -field heading. - -=cut - -############################################### -############################################### - -sub fieldtitle { - my $title = uc(&mt(shift())); - return ''.$title. - ': '; -} - -############################################### -############################################### - -=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)=@_; - 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 ''.&fieldtitle($title).''. - &simpletextfield($name,$value,50).' '. - &simplecheckbox($name.'_related',$ENV{'form.'.$name.'_related'}). - " \n"; -} - -############################################### -############################################### - -=pod - -=item &dateboxes() - -Returns html selection form elements for the specification of -the day, month, and year. - -=cut - -############################################### -############################################### - -sub dateboxes { - my ($name,$defaultmonth,$defaultday,$defaultyear, - $currentmonth,$currentday,$currentyear)=@_; - ($defaultmonth,$defaultday,$defaultyear)=('','',''); - # - # Day - my $day=< - -END - for (my $i = 1; $i<=31; $i++) { - $day.="\n"; - } - $day.="\n"; - $day=~s/(\"$currentday\")/$1 SELECTED/ if length($currentday); - # - # Month - my $month=< - -END - my $i = 1; - foreach (qw/January February March April May June - July August September October November December /){ - $month .="\n"; - $i++; - } - $month.="\n"; - $month=~s/(\"$currentmonth\")/$1 SELECTED/ if length($currentmonth); - # - # Year (obviously) - my $year=< - -END - my $maxyear = 2051; - for (my $i = 1976; $i<=$maxyear; $i++) { - $year.="\n"; - } - $year.="\n"; - $year=~s/(\"$currentyear\")/$1 SELECTED/ if length($currentyear); - return "$month$day$year"; -} - -############################################### -############################################### - -=pod - -=item &selectbox() - -Returns a scalar containing an html tag. - -=item $default - -The default value of the form. Can be $anyvalue, or in @idlist. - -=item $anyvalue - -The