--- loncom/interface/lonsearchcat.pm 2003/09/28 00:14:25 1.187 +++ loncom/interface/lonsearchcat.pm 2003/12/27 23:04:28 1.198 @@ -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.198 2003/12/27 23:04:28 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(); @@ -84,101 +72,46 @@ use Apache::loncommon(); use Apache::lonmysql(); 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 - +## +## Global variables +## ###################################################################### ###################################################################### - -# -- 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 %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 +## %Views: +## Hash which associates an output view description with the function +## that produces it. +# View Description/Name 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 ###################################################################### ###################################################################### 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; @@ -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,14 +484,15 @@ sub print_basic_search_form{ $bodytag ENDDOCUMENT if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { + my $CatalogSearch=&mt('Catalog Search'); + my $Statement=&mt('Enter terms or phrases separated by AND, OR, or NOT then press SEARCH below'); $scrout.=(<Catalog Search -
+

$CatalogSearch

+ $hidden_fields

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

@@ -556,17 +500,19 @@ then press SEARCH below. ENDDOCUMENT $scrout.=' '.&simpletextfield('basicexp',$ENV{'form.basicexp'},40). ' '; - my $relatedcheckbox = &simplecheckbox('related',$ENV{'form.related'}); + my $relatedcheckbox = &simplecheckbox('related','related',$ENV{'form.related'}); my $domain = $r->dir_config('lonDefDomain'); my $domaincheckbox = &simplecheckbox('domains',$domain); my $srch=&mt('Search'); my $header=&mt('Advanced Search'); + my $userelatedwords=&mt('use related words'); + my $onlysearchdomain=&mt('only search domain'); $scrout.=< - - + +
$header
$relatedcheckbox use related words$domaincheckbox only search domain $domain
$relatedcheckbox $userelatedwords$domaincheckbox $onlysearchdomain $domain

@@ -577,7 +523,7 @@ END $ENV{'form.viewselect'}, undef,undef,undef, sort(keys(%Views))); - $scrout.=&selectbox('Per page','show', + $scrout.=&selectbox('Per Page','show', $ENV{'form.show'}, undef,undef,undef, (10,20,50,100)); @@ -595,7 +541,7 @@ ENDDOCUMENT $scrout.=(<

$lt{'header'}

- + $hidden_fields

@@ -642,7 +588,7 @@ Returns a scalar which holds html for th ###################################################################### sub print_advanced_search_form{ - my ($r,$closebutton) = @_; + my ($r,$closebutton,$hidden_fields) = @_; my $advanced_buttons = <<"END";

@@ -702,6 +648,7 @@ ENDHEADER $ENV{'form.notes'}); $scrout.=&searchphrasefield_with_related('abstract','abstract', $ENV{'form.abstract'}); + $scrout.=&searchphrasefield('Standards','standards',$ENV{'form.standards'}); # Hack - an empty table row. $scrout.="   \n"; $scrout.=&searchphrasefield('file
extension','extension', @@ -1029,7 +976,7 @@ sub simpletextfield { =item &simplecheckbox() -Inputs: $name,$value +Inputs: $name,$value,$checked Returns a simple check box with the given $name. If $value eq 'on' the box is checked. @@ -1041,7 +988,7 @@ If $value eq 'on' the box is checked. sub simplecheckbox{ my ($name,$value,$checked)=@_; - $checked="checked" if ($value eq 'on'); + $checked="checked" if ($value eq $checked || $value eq 'on'); return ''; } @@ -1294,7 +1241,7 @@ Parse advanced search form and return th ###################################################################### ###################################################################### sub parse_advanced_search { - my ($r,$closebutton)=@_; + my ($r,$closebutton,$hidden_fields)=@_; my $fillflag=0; my $pretty_search_string = "
\n"; # Clean up fields for safety @@ -1328,7 +1275,7 @@ sub parse_advanced_search { } } unless ($fillflag) { - &output_blank_field_error($r,$closebutton,'phase=disp_adv'); + &output_blank_field_error($r,$closebutton,'phase=disp_adv',$hidden_fields); return ; } # Turn the form input into a SQL-based query @@ -1411,7 +1358,7 @@ sub parse_advanced_search { ); # Test to see if date windows are legitimate if ($datequery=~/^Incorrect/) { - &output_date_error($r,$datequery,$closebutton); + &output_date_error($r,$datequery,$closebutton,$hidden_fields); return ; } elsif ($datequery) { # Here is where you would set up pretty_search_string to output @@ -1846,6 +1793,7 @@ sub ensure_db_and_table { ###################################################################### sub print_sort_form { my ($r,$pretty_query_string) = @_; + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); ## my %SortableFields=&Apache::lonlocal::texthash( id => 'Default', @@ -1954,10 +1902,36 @@ my @Datatypes = { name => 'notes', type=>'TEXT'}, { name => 'abstract', type=>'TEXT'}, { name => 'mime', type=>'TEXT'}, - { name => 'lang', type=>'TEXT'}, + { name => 'language', type=>'TEXT'}, { name => 'owner', type=>'TEXT'}, { name => 'copyright', type=>'TEXT'}, - { name => 'hostname', type=>'TEXT'}, + { name => 'dependencies', type=>'TEXT'}, + { name => 'modifyinguser', type=>'TEXT'}, + { name => 'authorspace', type=>'TEXT'}, + { name => 'lowestgradelevel', type=>'INT'}, + { name => 'highestgradelevel', type=>'INT'}, + { name => 'standards', type=>'TEXT'}, + { name => 'count', type=>'INT'}, + { name => 'course', type=>'INT'}, + { name => 'course_list', type=>'TEXT'}, + { name => 'goto', type=>'INT'}, + { name => 'goto_list', type=>'TEXT'}, + { name => 'comefrom', type=>'INT'}, + { name => 'comefrom_list', type=>'TEXT'}, + { name => 'sequsage', type=>'INT'}, + { name => 'sequsage_list', type=>'TEXT'}, + { name => 'stdno', type=>'INT'}, + { name => 'stdno_list', type=>'TEXT'}, + { name => 'avetries', type=>'FLOAT'}, + { name => 'avetries_list', type=>'TEXT'}, + { name => 'difficulty', type=>'FLOAT'}, + { name => 'difficulty_list', type=>'TEXT'}, + { name => 'clear', type=>'FLOAT'}, + { name => 'technical', type=>'FLOAT'}, + { name => 'correct', type=>'FLOAT'}, + { name => 'helpful', type=>'FLOAT'}, + { name => 'depth', type=>'FLOAT'}, + { name => 'hostname', type=> 'TEXT'}, #-------------------------------------------------- { name => 'creationdate', type=>'DATETIME'}, { name => 'lastrevisiondate', type=>'DATETIME'}, @@ -2038,7 +2012,6 @@ sub update_count_status { sub update_status { my ($r,$text) = @_; $text =~ s/\'/\\\'/g; - $text=&mt($text); $r->print ("\n"); $r->rflush(); @@ -2092,6 +2065,7 @@ sub revise_button { ###################################################################### sub run_search { my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_; + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); my $connection = $r->connection; # # Timing variables @@ -2181,7 +2155,7 @@ END if (@Servers_to_contact) { # Contact one server my $server = shift(@Servers_to_contact); - &update_status($r,'contacting '.$server); + &update_status($r,&mt('contacting').' '.$server); my $reply=&Apache::lonnet::metadata_query($query,$customquery, $customshow,[$server]); ($server) = keys(%$reply); @@ -2193,7 +2167,7 @@ END # left to contact. if (scalar (keys(%Server_status))) { &update_status($r, - 'waiting on '.(join(' ',keys(%Server_status)))); + &mt('waiting on').' '.(join(' ',keys(%Server_status)))); } sleep(1); } @@ -2210,12 +2184,12 @@ END $status=~/^([\.\w]+)$/; my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1; if (-e $datafile && ! -e "$datafile.end") { - &update_status($r,'Receiving results from '.$server); + &update_status($r,&mt('Receiving results from').' '.$server); next; } last if ($connection->aborted()); if (-e "$datafile.end") { - &update_status($r,'Reading results from '.$server); + &update_status($r,&mt('Reading results from').' '.$server); if (-z "$datafile") { delete($Server_status{$server}); next; @@ -2270,7 +2244,7 @@ END &update_seconds($r,$time_remaining); } } - &update_status($r,'Search Complete'.$server); + &update_status($r,&mt('Search Complete').$server); &update_seconds($r,0); &Apache::lonmysql::disconnect_from_db(); # We have run out of time or run out of servers to talk to and @@ -2342,7 +2316,7 @@ sub prev_next_buttons { ###################################################################### ###################################################################### sub display_results { - my ($r,$importbutton,$closebutton) = @_; + my ($r,$importbutton,$closebutton,$diropendb) = @_; my $connection = $r->connection; $r->print(&search_results_header($importbutton,$closebutton)); ## @@ -2522,7 +2496,7 @@ sub parse_row { $Fields{$Datatypes[$i]->{'name'}}=&Apache::lonnet::unescape($Row[$i]); } $Fields{'language'} = - &Apache::loncommon::languagedescription($Fields{'lang'}); + &Apache::loncommon::languagedescription($Fields{'language'}); $Fields{'copyrighttag'} = &Apache::loncommon::copyrightdescription($Fields{'copyright'}); $Fields{'mimetag'} = @@ -2538,13 +2512,10 @@ sub parse_row { =item &parse_raw_result() Takes a line from the file of results and parse it. Returns a hash -with keys for the following fields: -'title', 'author', 'subject', 'url', 'keywords', 'version', 'notes', -'abstract', 'mime', 'lang', 'owner', 'copyright', 'creationdate', -'lastrevisiondate'. +with keys according to column labels In addition, the following tags are set by calling the appropriate -lonnet function: 'language', 'cprtag', 'mimetag'. +lonnet function: 'language', 'copyrighttag', 'mimetag'. The 'title' field is set to "Untitled" if the title field is blank. @@ -2565,27 +2536,15 @@ sub parse_raw_result { my @fields=map { &Apache::lonnet::unescape($_); } (split(/\,/,$result)); - my ($title,$author,$subject,$url,$keywords,$version, - $notes,$abstract,$mime,$lang, - $creationdate,$lastrevisiondate,$owner,$copyright)=@fields; - my %Fields = - ( title => &Apache::lonnet::unescape($title), - author => &Apache::lonnet::unescape($author), - subject => &Apache::lonnet::unescape($subject), - url => &Apache::lonnet::unescape($url), - keywords => &Apache::lonnet::unescape($keywords), - version => &Apache::lonnet::unescape($version), - notes => &Apache::lonnet::unescape($notes), - abstract => &Apache::lonnet::unescape($abstract), - mime => &Apache::lonnet::unescape($mime), - lang => &Apache::lonnet::unescape($lang), - owner => &Apache::lonnet::unescape($owner), - copyright => &Apache::lonnet::unescape($copyright), - creationdate => &Apache::lonnet::unescape($creationdate), - lastrevisiondate => &Apache::lonnet::unescape($lastrevisiondate) - ); +# conclude from self to others regarding fields + my @columns=&Apache::lonmysql::col_order('metadata'); + my %Fields=(); + for (my $i=0; $i<=$#columns; $i++) { + $Fields{$columns[$i]}=$fields[$i]; + } +# prettier display $Fields{'language'} = - &Apache::loncommon::languagedescription($Fields{'lang'}); + &Apache::loncommon::languagedescription($Fields{'language'}); $Fields{'copyrighttag'} = &Apache::loncommon::copyrightdescription($Fields{'copyright'}); $Fields{'mimetag'} = @@ -2599,7 +2558,7 @@ sub parse_raw_result { $Fields{'title'}='Untitled'; } unless ($ENV{'user.adv'}) { - # What is this anyway? + # do not show descriptive information to non-advanced users $Fields{'keywords'} = '- not displayed -'; $Fields{'notes'} = '- not displayed -'; $Fields{'abstract'} = '- not displayed -'; @@ -2689,8 +2648,16 @@ Checked for existance & 'edit' mode. =item 'form.form' +Contains the name of the form that has the input fields to set + =item 'form.element' +the name of the input field to put the URL into + +=item 'form.titleelement' + +the name of the input field to put the title into + =back =cut @@ -2699,6 +2666,7 @@ Checked for existance & 'edit' mode. ###################################################################### sub search_results_header { my ($importbutton,$closebutton) = @_; + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); my $result = ''; # output beginning of search page # conditional output of script functions dependent on the mode in @@ -2727,14 +2695,31 @@ SCRIPT } elsif ($ENV{'form.mode'} eq 'edit') { my $form = $ENV{'form.form'}; my $element = $ENV{'form.element'}; + my $titleelement = $ENV{'form.titleelement'}; + my $changetitle; + if (!$titleelement) { + $changetitle='function changeTitle(val) {}'; + } else { + $changetitle=< function select_data(title,url) { changeURL(url); + changeTitle(title); parent.close(); } -function changeTitle(val) { -} +$changetitle function changeURL(val) { if (parent.targetwin.document) { parent.targetwin.document.forms["$form"].elements["$element"].value=val; @@ -2785,6 +2770,7 @@ END ###################################################################### ###################################################################### sub search_status_header { + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); return <Search Status $bodytag @@ -2852,8 +2838,9 @@ extra custom metadata to show. ###################################################################### sub detailed_citation_view { my ($prefix,%values) = @_; + my $icon=&Apache::loncommon::icon($values{'url'}); my $result=<$prefix$prefix$values{'title'}

$values{'author'}, $values{'owner'}
@@ -2863,7 +2850,7 @@ sub detailed_citation_view { Notes: $values{'notes'}
MIME Type: $values{'mimetag'}
Language: $values{'language'}
-Copyright/Distribution: $values{'cprtag'}
+Copyright/Distribution: $values{'copyrighttag'}

$values{'extrashow'}

@@ -2886,8 +2873,9 @@ END ###################################################################### sub summary_view { my ($prefix,%values) = @_; + my $icon=&Apache::loncommon::icon($values{'url'}); my $result=<$values{'author'}
$values{'title'}
$values{'owner'} -- $values{'lastrevisiondate'}
@@ -2912,8 +2900,9 @@ END ###################################################################### sub compact_view { my ($prefix,%values) = @_; + my $icon=&Apache::loncommon::icon($values{'url'}); my $result=< +$prefix $values{'title'} $values{'author'}
END @@ -2934,8 +2923,9 @@ END ###################################################################### sub fielded_format_view { my ($prefix,%values) = @_; + my $icon=&Apache::loncommon::icon($values{'url'}); my $result=< URL: $values{'url'}
@@ -2989,8 +2979,8 @@ $prefix <mimetag>$values{'mimetag'}</mimetag> </mimeInfo> <languageInfo> -<language>$values{'lang'}</language> -<languagetag>$values{'language'}</languagetag> +<language>$values{'language'}</language> +<languagetag>$values{'languagetag'}</languagetag> </languageInfo> <creationdate>$values{'creationdate'}</creationdate> <lastrevisiondate>$values{'lastrevisiondate'}</lastrevisiondate> @@ -3051,7 +3041,8 @@ $parms is extra information to include i ###################################################################### ###################################################################### sub output_blank_field_error { - my ($r,$closebutton,$parms)=@_; + my ($r,$closebutton,$parms,$hidden_fields)=@_; + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); # make query information persistent to allow for subsequent revision $r->print(< @@ -3100,8 +3091,9 @@ Inputs: ###################################################################### ###################################################################### sub output_date_error { - my ($r,$message,$closebutton)=@_; + my ($r,$message,$closebutton,$hidden_fields)=@_; # make query information persistent to allow for subsequent revision + my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); $r->print(< @@ -3155,7 +3147,6 @@ sub start_fresh_session { sub cleanup { if (tied(%groupsearch_db)) { - &Apache::lonnet::logthis('Cleanup searchcat: groupsearch_db'); unless (untie(%groupsearch_db)) { &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db'); }