--- loncom/interface/lonsearchcat.pm 2003/09/29 15:28:40 1.188 +++ loncom/interface/lonsearchcat.pm 2008/12/19 23:24:49 1.303 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.188 2003/09/29 15:28:40 www Exp $ +# $Id: lonsearchcat.pm,v 1.303 2008/12/19 23:24:49 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -48,7 +48,7 @@ described at http://www.lon-capa.org. lonsearchcat presents the user with an interface to search the LON-CAPA digital library. lonsearchcat also initiates the execution of a search by sending the search parameters to LON-CAPA servers. The progress of -search (on a server basis) is displayed to the user in a seperate window. +search (on a server basis) is displayed to the user in a separate window. =head1 Internals @@ -59,130 +59,68 @@ 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(); +use Apache::lonnet; use Apache::File(); use CGI qw(:standard); 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 +use LONCAPA::lonmetadata(); +use HTML::Entities(); +use Parse::RecDescent; +use Apache::lonnavmaps; +use Apache::lonindexer(); +use LONCAPA; ###################################################################### ###################################################################### - -=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, + "detailedpreview" => \&detailed_citation_preview, + "summary" => \&summary_view, + "summarypreview" => \&summary_preview, + "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 $loaderror=&Apache::lonnet::overloaderror($r); if ($loaderror) { return $loaderror; } - + # my $closebutton; # button that closes the search window # This button is different for the RAT compared to # normal invocation. @@ -200,68 +138,101 @@ 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','area','inhibitmenu']); ## ## 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 ## printing the results. We only need (theoretically) to do ## this once, so the pause indicator is deleted ## - if (exists($ENV{'form.pause'})) { + if (exists($env{'form.pause'})) { sleep(1); - delete($ENV{'form.pause'}); + delete($env{'form.pause'}); } ## ## Initialize global variables ## my $domain = $r->dir_config('lonDefDomain'); - $diropendb= "/home/httpd/perl/tmp/$ENV{'user.domain'}_$ENV{'user.name'}_searchcat.db"; + $diropendb= "/home/httpd/perl/tmp/". + "$env{'user.domain'}_$env{'user.name'}_sel_res.db"; # # 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.launch'} eq '1')) { - $ENV{'form.persistent_db_id'} = time; + # $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.launch'} eq '1')) { + $env{'form.persistent_db_id'} = time; } - $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); + my $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'; - ## - if (! &get_persistent_form_data($persistent_db_file)) { - if ($ENV{'form.phase'} =~ /(run_search|results)/) { - &Apache::lonnet::logthis("lonsearchcat:Unable to recover data ". - "from $persistent_db_file"); - $r->print(< -LON-CAPA Search Error -$bodytag -We were unable to retrieve data describing your search. This is a serious -error and has been logged. Please alert your LON-CAPA administrator. - - -END - return OK; + &escape($domain). + '_'.&escape($env{'user.name'}). + '_'.$env{'form.persistent_db_id'}.'_persistent_search.db'; + ## + &Apache::lonhtmlcommon::clear_breadcrumbs(); + + my @allowed_searches = ('portfolio'); + if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) { + push(@allowed_searches,'res'); + } + if (exists($env{'request.course.id'}) && $env{'request.course.id'} ne '') { + push(@allowed_searches,'course'); + } + my $crumb_text = 'Portfolio Search'; + if (@allowed_searches == 3) { + $crumb_text = 'Course, Portfolio and Catalog Search'; + } elsif (@allowed_searches ==2) { + if (grep(/^res$/,@allowed_searches)) { + $crumb_text = 'Portfolio and Catalog Search'; + } elsif (grep(/^course$/,@allowed_searches)) { + $crumb_text = 'Portfolio and Course Search'; + } + } + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'. + &Apache::loncommon::inhibit_menu_check(). + '&catalogmode='.$env{'form.catalogmode'}. + '&launch='.$env{'form.launch'}. + '&mode='.$env{'form.mode'}, + text=>"$crumb_text", + target=>'_top', + bug=>'Searching',}); + # + if ($env{'form.phase'} !~ m/(basic|adv|course)_search/) { + if (! &get_persistent_form_data($persistent_db_file)) { + if ($env{'form.phase'} =~ /(run_search|results)/) { + &Apache::lonnet::logthis('lonsearchcat:'. + 'Unable to recover data from '. + $persistent_db_file); + my $msg = + 'We were unable to retrieve data describing your search. '. + 'This is a serious error and has been logged. '. + 'Please alert your LON-CAPA administrator.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); + return OK; + } } + } else { + &clean_up_environment(); } ## ## Clear out old values from groupsearch database ## untie %groupsearch_db if (tied(%groupsearch_db)); - if (($ENV{'form.cleargroupsort'} eq '1') || - (($ENV{'form.launch'} eq '1') && - ($ENV{'form.catalogmode'} eq 'groupsearch'))) { + if (($env{'form.cleargroupsort'} eq '1') || + (($env{'form.launch'} eq '1') && + ($env{'form.catalogmode'} eq 'import'))) { if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) { &start_fresh_session(); untie %groupsearch_db; - delete($ENV{'form.cleargroupsort'}); + delete($env{'form.cleargroupsort'}); } else { # This is a stupid error to give to the user. # It really tells them nothing. - $r->print(''.$bodytag. - 'Unable to tie hash to db file'); + my $msg = 'Unable to tie hash to db file.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); return OK; } } @@ -269,44 +240,50 @@ END ## Configure hidden fields ## $hidden_fields = ''."\n"; - if (exists($ENV{'form.catalogmode'})) { - $hidden_fields .= ''."\n"; - } - if (exists($ENV{'form.form'})) { - $hidden_fields .= ''."\n"; - } - if (exists($ENV{'form.element'})) { - $hidden_fields .= ''."\n"; - } - if (exists($ENV{'form.mode'})) { - $hidden_fields .= ''."\n"; + $env{'form.persistent_db_id'}.'" />'."\n"; + if (exists($env{'form.catalogmode'})) { + $hidden_fields .= &hidden_field('catalogmode'); + } + if (exists($env{'form.form'})) { + $hidden_fields .= &hidden_field('form'); + } + if (exists($env{'form.element'})) { + $hidden_fields .= &hidden_field('element'); + } + if (exists($env{'form.titleelement'})) { + $hidden_fields .= &hidden_field('titleelement'); + } + if (exists($env{'form.mode'})) { + $hidden_fields .= &hidden_field('mode'); + } + if (exists($env{'form.area'})) { + $hidden_fields .= &hidden_field('area'); + } + if (exists($env{'form.inhibitmenu'})) { + $hidden_fields .= &hidden_field('inhibitmenu'); } ## ## Configure dynamic components of interface ## - if ($ENV{'form.catalogmode'} eq 'interactive') { - $closebutton=" END } else { @@ -316,78 +293,82 @@ END ## ## Sanity checks on form elements ## - if (!defined($ENV{'form.viewselect'})) { - if (($ENV{'form.catalogmode'} eq 'groupsearch') || - ($ENV{'form.catalogmode'} eq 'interactive')) { - $ENV{'form.viewselect'} ="Compact View"; - } else { - $ENV{'form.viewselect'} ="Detailed Citation View"; - } + if (!defined($env{'form.viewselect'})) { + $env{'form.viewselect'} ="summary"; + } + $env{'form.phase'} = 'disp_basic' if (! exists($env{'form.phase'})); + $env{'form.show'} = 20 if (! exists($env{'form.show'})); + # + $env{'form.searchmode'} = 'basic' if (! exists($env{'form.searchmode'})); + if ($env{'form.phase'} eq 'adv_search' || + $env{'form.phase'} eq 'disp_adv') { + $env{'form.searchmode'} = 'advanced'; + } elsif ($env{'form.phase'} eq 'course_search') { + $env{'form.searchmode'} = 'course_search'; + } + # + if ($env{'form.searchmode'} eq 'advanced') { + my $srchtype = 'Catalog'; + if ($env{'form.area'} eq 'portfolio') { + $srchtype = 'Portfolio'; + } + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check(). + '&phase=disp_adv'. + '&catalogmode='.$env{'form.catalogmode'}. + '&launch='.$env{'form.launch'}. + '&mode='.$env{'form.mode'}, + text=>"Advanced $srchtype Search", + bug=>'Searching',}); + } elsif ($env{'form.searchmode'} eq 'course search') { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check(). + '&phase=disp_adv'. + 'catalogmode='.$env{'form.catalogmode'}. + '&launch='.$env{'form.launch'}. + '&mode='.$env{'form.mode'}, + text=>"Course Search", + bug=>'Searching',}); } - $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'})); - $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'})); ## ## Switch on the phase ## - if ($ENV{'form.phase'} eq 'disp_basic') { - &print_basic_search_form($r,$closebutton); - } elsif ($ENV{'form.phase'} eq 'disp_adv') { - &print_advanced_search_form($r,$closebutton); - } elsif ($ENV{'form.phase'} eq 'results') { - &display_results($r,$importbutton,$closebutton); - } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) { + if ($env{'form.phase'} eq 'disp_basic') { + &print_basic_search_form($r,$closebutton,$hidden_fields); + } elsif ($env{'form.phase'} eq 'disp_adv') { + &print_advanced_search_form($r,$closebutton,$hidden_fields); + } elsif ($env{'form.phase'} eq 'results') { + &display_results($r,$importbutton,$closebutton,$diropendb, + $env{'form.area'}); + } elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) { my ($query,$customquery,$customshow,$libraries,$pretty_string) = &get_persistent_data($persistent_db_file, ['query','customquery','customshow', 'libraries','pretty_string']); - if ($ENV{'form.phase'} eq 'sort') { + if ($env{'form.phase'} eq 'sort') { &print_sort_form($r,$pretty_string); - } elsif ($ENV{'form.phase'} eq 'run_search') { + } elsif ($env{'form.phase'} eq 'run_search') { &run_search($r,$query,$customquery,$customshow, - $libraries,$pretty_string); + $libraries,$pretty_string,$env{'form.area'}); } - } elsif ($ENV{'form.phase'} eq 'course_search') { + } elsif ($env{'form.phase'} eq 'course_search') { &course_search($r); - } elsif(($ENV{'form.phase'} eq 'basic_search') || - ($ENV{'form.phase'} eq 'adv_search')) { - $ENV{'form.searchmode'} = 'basic'; - if ($ENV{'form.phase'} eq 'adv_search') { - $ENV{'form.searchmode'} = 'advanced'; - } - # Set up table - if (! defined(&create_results_table())) { - $r->print(<Search Error -$bodytag -Unable to create table in which to store search results. -The search has been aborted. - - -END - return OK; - } - delete($ENV{'form.launch'}); - if (! &make_form_data_persistent($r,$persistent_db_file)) { - $r->print(<Search Error -$bodytag -Unable to properly store search information. The search has been aborted. - - -END - return OK; - } + } elsif(($env{'form.phase'} eq 'basic_search') || + ($env{'form.phase'} eq 'adv_search')) { # - # We are running a search + # We are running a search, try to parse it my ($query,$customquery,$customshow,$libraries) = (undef,undef,undef,undef); my $pretty_string; - if ($ENV{'form.phase'} eq 'basic_search') { + if ($env{'form.phase'} eq 'basic_search') { ($query,$pretty_string,$libraries) = - &parse_basic_search($r,$closebutton); + &parse_basic_search($r,$closebutton,$hidden_fields); + return OK if (! defined($query)); + &make_persistent({ basicexp => $env{'form.basicexp'}}, + $persistent_db_file); } 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, @@ -396,104 +377,264 @@ END libraries => $libraries, pretty_string => $pretty_string }, $persistent_db_file); + # + # Set up table + if (! defined(&create_results_table($env{'form.area'}))) { + my $errorstring=&Apache::lonmysql::get_error(); + &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '. + 'needed table. lonmysql error:'. + $errorstring); + + my $msg = + 'Unable to create table in which to save search results. '. + 'The search has been aborted.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); + return OK; + } + delete($env{'form.launch'}); + if (! &make_form_data_persistent($r,$persistent_db_file)) { + my $msg= + 'Unable to properly save search information. '. + 'The search has been aborted.'; + &Apache::loncommon::simple_error_page($r,'Search Error', + $msg); + return OK; + } ## ## Print out the frames interface ## - &print_frames_interface($r); + if (defined($query)) { + &print_frames_interface($r); + } } return OK; } +# +# The mechanism used to store values away and retrieve them does not +# handle the case of missing environment variables being significant. +# +# This routine sets non existant checkbox form elements to ''. +# +sub clean_up_environment { + if ($env{'form.phase'} eq 'basic_search') { + if (! exists($env{'form.related'})) { + $env{'form.related'} = ''; + } + if (! exists($env{'form.domains'})) { + $env{'form.domains'} = ''; + } + } elsif ($env{'form.phase'} eq 'adv_search') { + foreach my $field ('title','keywords','notes', + 'abstract','standards','mime') { + if (! exists($env{'form.'.$field.'_related'})) { + $env{'form.'.$field.'_related'} = ''; + } + } + } elsif ($env{'form.phase'} eq 'course_search') { + if (! exists($env{'form.crsrelated'})) { + $env{'form.crsrelated'} = ''; + } + } +} + +sub hidden_field { + my ($name,$value) = @_; + if (! defined($value)) { + $value = $env{'form.'.$name}; + } + return ''.$/; +} + +###################################################################### ###################################################################### +## +## Course Search +## ###################################################################### +###################################################################### +{ # Scope the course search to avoid global variables +# +# Variables For course search +my %alreadyseen; +my %hash; +my $totalfound; + +sub make_symb { + my ($id)=@_; + my ($mapid,$resid)=split(/\./,$id); + my $map=$hash{'map_id_'.$mapid}; + my $res=$hash{'src_'.$id}; + my $symb=&Apache::lonnet::encode_symb($map,$resid,$res); + return $symb; +} sub course_search { my $r=shift; - my $bodytag=&Apache::loncommon::bodytag('Course Search'); - my $pretty_search_string = ''.$ENV{'form.courseexp'}.''; - my $search_string = $ENV{'form.courseexp'}; + my $pretty_search_string = ''.$env{'form.courseexp'}.''; + my $search_string = $env{'form.courseexp'}; my @New_Words; - if ($ENV{'form.crsrelated'}) { - ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'}); + undef(%alreadyseen); + 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'}; + my $fulltext=$env{'form.crsfulltext'}; + my $discuss=$env{'form.crsdiscuss'}; my @allwords=($search_string,@New_Words); $totalfound=0; - $r->print('LON-CAPA Course Search'. - $bodytag.$pretty_search_string); + $r->print(&Apache::loncommon::start_page('Course Search'). + '
'. + $pretty_search_string.'
'. + '
'.&mt('Course content').':
'); $r->rflush(); # ======================================================= Go through the course - $hashtied=0; - 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 (sort(keys(%hash))) { + if ($c->aborted()) { last; } + if (($_=~/^src\_(.+)$/)) { + if ($hash{'randomout_'.$1} & !$env{'request.role.adv'}) { + next; + } + my $symb=&make_symb($1); + &checkonthis($r,$1,$hash{$_},0,&Apache::lonnet::gettitle($symb), + $fulltext,$symb,@allwords); + } + } + untie(%hash); + } unless ($totalfound) { - $r->print('

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

'); + $r->print('

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

'); } -# =================================================== Done going through course - $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; +# Check discussions if requested + if ($discuss) { + my $totaldiscussions = 0; + $r->print('

'.&mt('Discussion postings').':
'); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + my @allres=$navmap->retrieveResources(); + my %discussiontime = &Apache::lonnet::dump('discussiontimes', + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + foreach my $resource (@allres) { + my $result = ''; + my $applies = 0; + my $symb = $resource->symb(); + my $ressymb = $symb; + if ($symb =~ m#(___adm/$LONCAPA::domain_re/$LONCAPA::username_re)/(\d+)/bulletinboard$#) { + $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard'; + unless ($ressymb =~ m#bulletin___\d+___adm/wrapper#) { + $ressymb=~s#(bulletin___\d+___)#$1adm/wrapper/#; + } + } + if (defined($discussiontime{$ressymb})) { + my %contrib = &Apache::lonnet::restore($ressymb,$env{'request.course.id'}, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + if ($contrib{'version'}) { + for (my $id=1;$id<=$contrib{'version'};$id++) { + unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) { + if ($contrib{$id.':subject'}) { + $result .= $contrib{$id.':subject'}; + } + if ($contrib{$id.':message'}) { + $result .= $contrib{$id.':message'}; + } + if ($contrib{$id,':attachmenturl'}) { + if ($contrib{$id,':attachmenturl'} =~ m-/([^/]+)$-) { + $result .= $1; + } + } + $applies = &checkwords($result,$applies,@allwords); + } + } + } + } +# Does this discussion apply? + if ($applies) { + my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ressymb); + my $disctype = &mt('resource'); + if ($url =~ m#/bulletinboard$#) { + if ($url =~m#^adm/wrapper/adm/.*/bulletinboard$#) { + $url =~s#^adm/wrapper##; + } + $disctype = &mt('bulletin board'); + } else { + $url = '/res/'.$url; + } + if ($url =~ /\?/) { + $url .= '&symb='; + } else { + $url .= '?symb='; + } + $url .= &escape($resource->symb()); + my $title = $resource->compTitle(); + $r->print('
'. + ($title?$title:$url).'  - '. + $disctype.'
'); + $totaldiscussions++; + } else { + $r->print(' .'); + } + } + unless ($totaldiscussions) { + $r->print('

'.&mt('No matches found in postings').'.

'); + } + } else { + $r->print('
'.&mt('An error occurred retrieving information about resources in the course.').'
'.&mt('It is recommended that you [_1]re-initialize the course[_2] and then try your search again.','','').'
'); } - } -} - -sub untiehash { - if ($hashtied) { untie %hash; } - $hashtied=0; + } + +# =================================================== Done going through course + $r->print(&Apache::loncommon::end_page()); } # =============================== This pulls up a resource and its dependencies sub checkonthis { - my ($r,$url,$level,$title,$fulltext,@allwords)=@_; - $alreadyseen{$url}=1; + my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_; + $alreadyseen{$id}=1; + if (&Apache::loncommon::connection_aborted($r)) { return; } $r->rflush(); - my $result=&Apache::lonnet::metadata($url,'title').' '. - &Apache::lonnet::metadata($url,'subject').' '. - &Apache::lonnet::metadata($url,'abstract').' '. - &Apache::lonnet::metadata($url,'keywords'); - if (($url) && ($fulltext)) { - $result.=&Apache::lonnet::ssi_body($url); + + my $result=$title.' '; + if ($env{'request.role.adv'} || !$hash{'encrypted_'.$id}) { + $result.=&Apache::lonnet::metadata($url,'title').' '. + &Apache::lonnet::metadata($url,'subject').' '. + &Apache::lonnet::metadata($url,'abstract').' '. + &Apache::lonnet::metadata($url,'keywords'); + } + my ($extension)=($url=~/\.(\w+)$/); + if (&Apache::loncommon::fileembstyle($extension) eq 'ssi' && + ($url) && ($fulltext)) { + $result.=&Apache::lonnet::ssi_body($url.'?symb='.&escape($symb)); } $result=~s/\s+/ /gs; - my $applies=0; - foreach (@allwords) { - if ($_=~/\w/) { - if ($result=~/$_/si) { - $applies++; - } - } - } + my $applies = 0; + $applies = &checkwords($result,$applies,@allwords); # Does this resource apply? if ($applies) { $r->print('
'); for (my $i=0;$i<=$level*5;$i++) { $r->print(' '); } - $r->print(''. - ($title?$title:$url).'
'); + my $href=$url; + if ($hash{'encrypted_'.$id} && !$env{'request.role.adv'}) { + $href=&Apache::lonenc::encrypted($href) + .'?symb='.&Apache::lonenc::encrypted($symb); + } else { + $href.='?symb='.&escape($symb); + } + $r->print(''.($title?$title:$url). + '
'); $totalfound++; } elsif ($fulltext) { $r->print(' .'); @@ -503,12 +644,33 @@ sub checkonthis { my $dependencies= &Apache::lonnet::metadata($url,'dependencies'); foreach (split(/\,/,$dependencies)) { - if (($_=~/^\/res\//) && (!$alreadyseen{$_})) { - &checkonthis($r,$_,$level+1,'',$fulltext,@allwords); + if (($_=~/^\/res\//) && (!$alreadyseen{$id})) { + &checkonthis($r,$id,$_,$level+1,'',$fulltext,undef,@allwords); } } } +sub checkwords { + my ($result,$applies,@allwords) = @_; + foreach (@allwords) { + if ($_=~/\w/) { + if ($result=~/$_/si) { + $applies++; + } + } + } + return $applies; +} + +sub untiehash { + if (tied(%hash)) { + untie(%hash); + } +} + +} # End of course search scoping + + ###################################################################### ###################################################################### @@ -516,86 +678,39 @@ sub checkonthis { =item &print_basic_search_form() -Returns a scalar which holds html for the basic search form. +Prints the form for the basic search. Sorry the name is so cryptic. =cut ###################################################################### ###################################################################### - -sub print_basic_search_form{ - my ($r,$closebutton) = @_; - my $bodytag=&Apache::loncommon::bodytag('Search'); - my $scrout=<<"ENDDOCUMENT"; - - -The LearningOnline Network with CAPA - - -$bodytag -ENDDOCUMENT -if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { - $scrout.=(<Catalog Search -
- -$hidden_fields -

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

-

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

-

  -$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.=< - -ENDDOCUMENT - } - if ($ENV{'request.course.id'}) { - my %lt=&Apache::lonlocal::texthash( - 'srch' => 'Search', +# Search form for accessible portfolio files + $scrout.= &setup_basic_search($r,'portfolio',$hidden_fields,$closebutton); + if ($env{'request.course.id'}) { + my %lt=&Apache::lonlocal::texthash('srch' => 'Search', 'header' => 'Course Search', 'note' => 'Enter terms or phrases, then press "Search" below', + 'use' => 'use related words', + 'full' =>'fulltext search (time consuming)', + 'disc' => 'search discussion postings (resources and bulletin boards)', ); $scrout.=(< +


$lt{'header'}

-
$hidden_fields

@@ -606,27 +721,102 @@ $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'}); + my $discheckbox = + &Apache::lonhtmlcommon::checkbox('crsdiscuss', + $env{'form.crsrelated'}); $scrout.=(< -$relcheckbox use related words -$crscheckbox fulltext search (time consuming) + + +

 

+
+ ENDENDCOURSE } - $scrout.=(< - -ENDDOCUMENT + $scrout .= &Apache::loncommon::end_page(); $r->print($scrout); return; } + +sub setup_basic_search { + my ($r,$area,$hidden_fields,$closebutton) = @_; + # Define interface components + my %lt = &Apache::lonlocal::texthash ( + res => 'LON-CAPA Catalog Search', + portfolio => 'Portfolio Search', + ); + my ($userelatedwords,$onlysearchdomain,$inclext,$adv_search_link,$scrout); + $userelatedwords = ''; + $onlysearchdomain = ''; + $adv_search_link = ''.&mt('Advanced Search').''; + # + $scrout.='
'. + ''. + $hidden_fields; + if (!exists($env{'form.area'})) { + $scrout .= ''; + } + # + $scrout .= '
'.$/; +# if ($env{'request.course.id'}) { + $scrout .= '

'.$lt{$area}.'

'; +# } else { + # No need to tell them they are searching +# $scrout.= ('
'x2); +# } + $scrout.=''. + ''. + ''. + ''.$/; + # + $scrout .= ''.$/; + $scrout .= '
'. + &Apache::lonhtmlcommon::textbox('basicexp', + $env{'form.basicexp'},50). + '
'. + ''.&searchhelp().''.'
'. + ''.(' 'x3).$adv_search_link.''.'
'. + ''.(' 'x1).$userelatedwords.''.'
'. + ''.(' 'x1).$onlysearchdomain.''.'
'. + ''.(' 'x1).$inclext.''.'
'. + '
'. + ''. + ''. + (' 'x2).$closebutton.(' 'x2). &viewoptions(). + ''. + '
'.$/.'
'.'
'; + return $scrout; +} + ###################################################################### ###################################################################### @@ -634,194 +824,273 @@ ENDDOCUMENT =item &advanced_search_form() -Returns a scalar which holds html for the advanced search form. +Prints the advanced search form. =cut ###################################################################### ###################################################################### - sub print_advanced_search_form{ - my ($r,$closebutton) = @_; - my $advanced_buttons = <<"END"; -

- - + my ($r,$closebutton,$hidden_fields) = @_; + my $bread_crumb = + &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Advanced', + $env{'form.catalogmode'} ne 'import'); + 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 $scrout=<<"ENDHEADER"; - - -The LearningOnline Network with CAPA - - -$bodytag -Enter terms or phrases separated by search operators -such as AND, OR, or NOT.
-
+ my $srchtype = 'Catalog'; + my $jscript; + if ($env{'form.area'} eq 'portfolio') { + $srchtype = 'Portfolio'; + $jscript = ''; + } + my $scrout= &Apache::loncommon::start_page("Advanced $srchtype Search", + $jscript); + $scrout .= <<"ENDHEADER"; +$bread_crumb + +

$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'}); - # 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.="
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')."
   
   
\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'}); - #---------------------------------------------------------------- - # 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 = (); - foreach (@allowed_domains) { - $domain_hash{$_}++; + $scrout.=(' 'x2).&viewoptions().'

'.$hidden_fields. + ''; + my %fields=&Apache::lonmeta::fieldnames(); + # + $scrout .= '

'.&mt("Standard $srchtype Metadata").'

'; + $scrout .= "\n"; + $scrout .= '\n"; + my %related_word_search = + ('title' => 1, + 'author' => 0, + 'owner' => 0, + 'authorspace' => 0, + 'modifyinguser'=> 0, + 'keywords' => 1, + 'notes' => 1, + 'abstract' => 1, + 'standards'=> 1, + 'mime' => 1, + 'subject' => 1, + ); + # + foreach my $field ('title','author','subject','owner','authorspace', + 'modifyinguser','keywords','notes','abstract', + 'standards','mime') { + $scrout.=''.$/; } - my @domains =&Apache::loncommon::get_domains(); - # 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
'. - '\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.=< -#LIMIT BY SPECIAL METADATA FIELDS: -# -#For resource-specific metadata, enter in an expression in the form of -#key=value separated by operators such as AND, OR or NOT.
-#Example: grandmother=75 OR grandfather=85 -#
-#CUSTOMMETADATA -# $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'}); -# $scrout.=< -#SHOW SPECIAL METADATA FIELDS: -# -#Enter in a space-separated list of special metadata fields to show -#in a fielded listing for each record result. -#
-#CUSTOMSHOW -# $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'}); + foreach my $field ('lowestgradelevel','highestgradelevel') { + $scrout.='
'. + ''. + ''.$/; + } + $scrout.=''.$/; + $scrout.=''.$/; + # + # Misc metadata + if ($env{'form.area'} ne 'portfolio') { + $scrout.=''.$/; + } + $scrout.=''; + $scrout .= "
 '. + (' 'x2).&searchhelp()."
'.&titlefield($fields{$field}).''. + &Apache::lonmeta::prettyinput($field, + $env{'form.'.$field}, + $field, + 'advsearch', + $related_word_search{$field}, + '', + $env{'form.'.$field.'_related'}, + 50); + if ($related_word_search{$field}) { + $scrout .= &mt('related words'); + } else { + $scrout .= ' '; + } + $scrout .= '
'.&titlefield($fields{$field}).''. + &Apache::lonmeta::prettyinput($field, + $env{'form.'.$field}, + $field, + 'advsearch', + 0). + '
'. + &titlefield(&mt('MIME Type Category')).''. + &Apache::loncommon::filecategoryselect('category', + $env{'form.category'}). + '
'. + &titlefield(&mt('Domains')).''. + &Apache::loncommon::domain_select('domains', + $env{'form.domains'},1). + '
'. + &titlefield(&mt('Copyright/Distribution')). + ''. + &Apache::lonmeta::selectbox('copyright', + $env{'form.copyright'}, + \&Apache::loncommon::copyrightdescription, + ( undef, + &Apache::loncommon::copyrightids) + ).'
'. + &titlefield(&mt('Language')).''. + &Apache::lonmeta::selectbox('language', + $env{'form.language'}, + \&Apache::loncommon::languagedescription, + ('any',&Apache::loncommon::languageids) + ).'
\n"; + + + if ($env{'form.area'} eq 'portfolio') { + # Added fields + my $curnumadd = $env{'form.numaddedfields'}; + if ($curnumadd eq '') { + $curnumadd = 1; + } + $scrout .= '

'.&mt('Custom Metadata fields').'

'; + $scrout .= "\n"; + $scrout .= ''.''; + + for (my $j=0; $j<$curnumadd; $j++) { + my $num = $j+1; + $scrout .= ''. + ''; + } + $scrout .= '
 '. + &mt('Field Name').''. + &mt('Field Value(s)').'
'.&mt('Custom metadata [_1]: ',$num). + ''. + '
'. + '
'; + } else { + # + # Dynamic metadata + $scrout .= '

'.&mt('Problem Statistics').'

'; + $scrout .= "\n"; + $scrout .= ''.''."\n"; + foreach my $statistic + ({ name=>'count', + description=>'Network-wide number of accesses (hits)',}, + { name=>'stdno', + description=> + 'Statistics calculated for number of students',}, + { name => 'avetries', + description=>'Average number of tries till solved',}, + { name => 'difficulty', + description=>'Degree of difficulty',}, + { name => 'disc', + description=>'Degree of discrimination'}) { + $scrout .= ''.$/; + } + $scrout .= "
 '. + &mt('Minimum').''. + &mt('Maximum').'
'. + &titlefield(&mt($statistic->{'description'})). + ''. + ''. + '
\n"; + $scrout .= '

'.&mt('Evaluation Data').'

'; + $scrout .= "\n"; + $scrout .= ''.''."\n"; + foreach my $evaluation + ( { name => 'clear', + description => 'Material presented in clear way'}, + { name =>'depth', + description => 'Material covered with sufficient depth'}, + { name => 'helpful', + description => 'Material is helpful'}, + { name => 'correct', + description => 'Material appears to be correct'}, + { name => 'technical', + description => 'Resource is technically correct'}){ + $scrout .= ''.$/; + } + $scrout .= "
 '. + &mt('Minimum').''. + &mt('Maximum').'
'. + &titlefield(&mt($evaluation->{'description'})). + ''. + ''. + ''. + '
\n"; + } + # + # Creation/Modification date limits + $scrout .= '

'.&mt('Creation and Modification dates').'

'; + $scrout .= "\n\n"; + $scrout .= "\n"; + my $cafter = + &Apache::lonhtmlcommon::date_setter('advsearch', # formname + 'creationdate1', # fieldname + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + my $cbefore = + &Apache::lonhtmlcommon::date_setter('advsearch', # formname + 'creationdate2', # fieldname + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + $scrout .= '' + .'' + .'' + .''; + my $lafter = + &Apache::lonhtmlcommon::date_setter('advsearch', + 'revisiondate1', + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + my $lbefore = + &Apache::lonhtmlcommon::date_setter('advsearch', + 'revisiondate2', + 0, # current value + '', # special + 1, # includeempty + '', # state + 1, # no_hh_mm_ss + ); + $scrout .= '' + .'' + .'' + .''; + $scrout.="
 ".&mt('Month[_1]Day[_2]Year',' 'x14,' 'x6)."
'.&mt('Created between').''.$cafter.'
'.&mt('and').''.$cbefore.'
'.&mt('Last modified between').''.$lafter.'
'.&mt('and').''.$lbefore.'
\n"; $scrout.=< - - ENDDOCUMENT + $scrout .= &Apache::loncommon::end_page(); $r->print($scrout); return; } @@ -831,7 +1100,109 @@ ENDDOCUMENT =pod -=item &get_persistent_form_data +=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', + 'summarypreview' => 'Summary Preview', + 'detailedpreview' => 'Detailed Citation Preview'); + return $desc{$code}; +} + +###################################################################### +###################################################################### + +=pod + +=item viewoptions() + +Inputs: none + +Outputs: text for box with view options + +=cut + +###################################################################### +###################################################################### +sub viewoptions { + my $scrout = ''; + if (! defined($env{'form.viewselect'})) { + $env{'form.viewselect'}='detailed'; + } + $scrout.=&Apache::lonmeta::selectbox('viewselect', + $env{'form.viewselect'}, + \&viewoptiontext, + sort(keys(%Views))); + $scrout.= '  '; + my $countselect = &Apache::lonmeta::selectbox('show', + $env{'form.show'}, + undef, + (10,20,50,100,1000,10000)); + $scrout .= (' 'x2) + .&mt('[_1] Records per Page',$countselect) + .''.$/; + return $scrout; +} + +###################################################################### +###################################################################### + +=pod + +=item searchhelp() + +Inputs: none + +Outputs: return little blurb on how to enter searches + +=cut + +###################################################################### +###################################################################### +sub searchhelp { + return &mt('Enter words and quoted phrases'); +} + +###################################################################### +###################################################################### + +=pod + +=item &get_persistent_form_data() Inputs: filename of database @@ -839,7 +1210,7 @@ Outputs: returns undef on database error This function is the reverse of &make_persistent() for form data. Retrieve persistent data from %persistent_db. Retrieved items will have their -values unescaped. If a form value already exists in $ENV, it will not be +values unescaped. If a form value already exists in $env, it will not be overwritten. Form values that are array references may have values appended to them. @@ -861,20 +1232,20 @@ sub get_persistent_form_data { next if ($name !~ /^form./); # Kludgification begins! if ($name eq 'form.domains' && - $ENV{'form.searchmode'} eq 'basic' && - $ENV{'form.phase'} ne 'disp_basic') { + $env{'form.searchmode'} eq 'basic' && + $env{'form.phase'} ne 'disp_basic') { next; } # End kludge (hopefully) - next if (exists($ENV{$name})); + next if (exists($env{$name})); my @values = map { - &Apache::lonnet::unescape($_); + &unescape($_); } split(',',$persistent_db{$name}); next if (@values <1); if ($arrays_allowed{$name}) { - $ENV{$name} = [@values]; + $env{$name} = [@values]; } else { - $ENV{$name} = $values[0] if ($values[0]); + $env{$name} = $values[0] if ($values[0]); } } untie (%persistent_db); @@ -886,7 +1257,7 @@ sub get_persistent_form_data { =pod -=item &get_persistent_data +=item &get_persistent_data() Inputs: filename of database, ref to array of values to recover. @@ -914,7 +1285,7 @@ sub get_persistent_data { next; } my @values = map { - &Apache::lonnet::unescape($_); + &unescape($_); } split(',',$persistent_db{$name}); if (@values <= 1) { push @Values,$values[0]; @@ -937,7 +1308,7 @@ Inputs: Hash of values to save, filename Store 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. +elements escaped and concatenated in a comma separated string. =cut @@ -951,7 +1322,7 @@ sub make_persistent { foreach my $name (keys(%save)) { my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name})); # We handle array references, but not recursively. - my $store = join(',', map { &Apache::lonnet::escape($_); } @values ); + my $store = join(',', map { &escape($_); } @values ); $persistent_db{$name} = $store; } untie(%persistent_db); @@ -969,7 +1340,7 @@ Inputs: filename of persistent database. Store most form 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. +elements escaped and concatenated in a comma separated string. =cut @@ -979,296 +1350,14 @@ sub make_form_data_persistent { my $r = shift; my $filename = shift; my %save; - foreach (keys(%ENV)) { + foreach (keys(%env)) { next if (!/^form/ || /submit/); - $save{$_} = $ENV{$_}; + $save{$_} = $env{$_}; } return &make_persistent(\%save,$filename); } ###################################################################### -# 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 "); + $r->print("A MySQL error has occurred.". + &Apache::loncommon::end_page()); &Apache::lonnet::logthis("lonmysql was unable to determine the status". " of table ".$table); return undef; @@ -1838,7 +2193,10 @@ sub ensure_db_and_table { =pod -=item &print_sort_form +=item &print_sort_form() + +The sort feature is not implemented at this time. This form just prints +a link to change the search query. =cut @@ -1846,6 +2204,7 @@ sub ensure_db_and_table { ###################################################################### sub print_sort_form { my ($r,$pretty_query_string) = @_; + ## my %SortableFields=&Apache::lonlocal::texthash( id => 'Default', @@ -1863,62 +2222,64 @@ sub print_sort_form { lastrevisiondate => 'Revision Date' ); ## - my $table = $ENV{'form.table'}; + my $table = $env{'form.table'}; return if (! &ensure_db_and_table($r,$table)); ## ## Get the number of results ## my $total_results = &Apache::lonmysql::number_of_rows($table); if (! defined($total_results)) { - $r->print("A MySQL error has occurred."); + $r->print("A MySQL error has occurred.". + &Apache::loncommon::end_page()); &Apache::lonnet::logthis("lonmysql was unable to determine the number". " of rows in table ".$table); &Apache::lonnet::logthis(&Apache::lonmysql::get_error()); return; } - my $result; - $result.=< - - -Results - -$bodytag -
- +END + + my $start_page = &Apache::loncommon::start_page('Results',$js, + {'no_title' => 1}); + my $breadcrumbs= + &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching', + $env{'form.catalogmode'} ne 'import'); + + my $result = < + + END #

Sort Results

#Sort by: }; return $result; } @@ -2084,42 +2467,50 @@ sub revise_button { =pod -=item &run_search +=item &run_search() + +Executes a search query by sending it the the other servers and putting the +results into MySQL. =cut ###################################################################### ###################################################################### sub run_search { - my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_; + my ($r,$query,$customquery,$customshow,$serverlist, + $pretty_string,$area) = @_; + my $tabletype = 'metadata'; + if ($area eq 'portfolio') { + $tabletype = 'portfolio_search'; + } my $connection = $r->connection; # - # Timing variables - # - my $starttime = time; - my $max_time = 30; # seconds for the search to complete - # # Print run_search header # + my $start_page = &Apache::loncommon::start_page('Search Status',undef, + {'no_title' => 1}); + my $breadcrumbs = + &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching', + $env{'form.catalogmode'} ne 'import'); $r->print(< -Search Status -$bodytag - - +$start_page +$breadcrumbs END - # Check to see if $pretty_string has more than one carriage return. - # Assume \n s are following
s and truncate the value. - # (there is probably a better way)... - my @Lines = split /
/,$pretty_string; + # Remove leading and trailing
+ $pretty_string =~ s:^\s*
::i; + $pretty_string =~ s:(
)*\s*$::im; + my @Lines = split("
",$pretty_string); + # I keep getting blank items at the end of the list, hence the following: + while ($Lines[-1] =~ /^\s*$/ && @Lines) { + pop(@Lines); + } if (@Lines > 2) { - $pretty_string = join '
',(@Lines[0..2],'....
'); + $pretty_string = join '
',(@Lines[0..2],'...
'); } - $r->print(&mt("Search").": ".$pretty_string); + $r->print(&mt("Search: [_1]",$pretty_string)); $r->rflush(); # # Determine the servers we need to contact. - # my @Servers_to_contact; if (defined($serverlist)) { if (ref($serverlist) eq 'ARRAY') { @@ -2128,60 +2519,76 @@ END @Servers_to_contact = ($serverlist); } } else { - @Servers_to_contact = sort(keys(%Apache::lonnet::libserv)); + my %all_library_servers = &Apache::lonnet::all_library(); + @Servers_to_contact = sort(keys(%all_library_servers)); } my %Server_status; - my $table =$ENV{'form.table'}; + # + # Check on the mysql table we will use to store results. + my $table =$env{'form.table'}; if (! defined($table) || $table eq '' || $table =~ /\D/ ) { - $r->print("Unable to determine table id to store search results in.". - "The search has been aborted."); + $r->print("Unable to determine table id to save search results in.". + "The search has been aborted.". + &Apache::loncommon::end_page()); return; } my $table_status = &Apache::lonmysql::check_table($table); if (! defined($table_status)) { - $r->print("Unable to determine status of table."); + $r->print("Unable to determine status of table.". + &Apache::loncommon::end_page()); &Apache::lonnet::logthis("Bogus table id of $table for ". - "$ENV{'user.name'} @ $ENV{'user.domain'}"); + "$env{'user.name'} @ $env{'user.domain'}"); &Apache::lonnet::logthis("lonmysql error = ". &Apache::lonmysql::get_error()); return; } if (! $table_status) { + &Apache::lonnet::logthis("lonmysql error = ". + &Apache::lonmysql::get_error()); + &Apache::lonnet::logthis("lonmysql debug = ". + &Apache::lonmysql::get_debug()); + &Apache::lonnet::logthis('table status = "'.$table_status.'"'); $r->print("The table id,$table, we tried to use is invalid.". - "The search has been aborted."); + "The search has been aborted.". + &Apache::loncommon::end_page()); return; } ## ## Prepare for the big loop. - ## my $hitcountsum; + my %matches; my $server; my $status; my $revise = &revise_button(); - $r->print(< -StatusTotal MatchesTime Remaining - - - - -$revise - - - -END + $r->print('
'."\n". + ''."\n". + '' + .'' + .'' + .&Apache::loncommon::end_data_table_header_row() + .&Apache::loncommon::start_data_table_row() + .'' + .'' + .'' + .&Apache::loncommon::end_data_table_row() + .&Apache::loncommon::end_data_table() + .'
'."\n". + &Apache::loncommon::start_data_table()); + $r->print(&Apache::loncommon::start_data_table_header_row() + .''.&mt('Status').''.&mt('Total Matches').''.&mt('Time Remaining').' '.$revise.'
'); $r->rflush(); - my $time_remaining = $max_time - (time - $starttime) ; - my $last_time = $time_remaining; - &update_seconds($r,$time_remaining); - &update_status($r,'contacting '.$Servers_to_contact[0]); - while (($time_remaining > 0) && + &reset_timing(); + &update_seconds($r); + &update_status($r,&mt('contacting [_1]',$Servers_to_contact[0])); + while (&time_left() && ((@Servers_to_contact) || keys(%Server_status))) { - # Send out a search request if it needs to be done. + &update_seconds($r); + # + # Send out a search request if (@Servers_to_contact) { # Contact one server my $server = shift(@Servers_to_contact); - &update_status($r,'contacting '.$server); + &update_status($r,&mt('contacting [_1]',$server)); my $reply=&Apache::lonnet::metadata_query($query,$customquery, $customshow,[$server]); ($server) = keys(%$reply); @@ -2193,29 +2600,30 @@ END # left to contact. if (scalar (keys(%Server_status))) { &update_status($r, - 'waiting on '.(join(' ',keys(%Server_status)))); + &mt('waiting on [_1]',join(' ',keys(%Server_status)))); } sleep(1); } # - # # Loop through the servers we have contacted but do not # have results from yet, looking for results. - while (my ($server,$status) = each(%Server_status)) { + foreach my $server (keys(%Server_status)) { last if ($connection->aborted()); + &update_seconds($r); + my $status = $Server_status{$server}; if ($status eq 'con_lost') { delete ($Server_status{$server}); next; } - $status=~/^([\.\w]+)$/; - my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1; + $status=~s|/||g; + my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$status; if (-e $datafile && ! -e "$datafile.end") { - &update_status($r,'Receiving results from '.$server); + &update_status($r,&mt('Receiving results from [_1]',$server)); next; } last if ($connection->aborted()); if (-e "$datafile.end") { - &update_status($r,'Reading results from '.$server); + &update_status($r,&mt('Reading results from [_1]',$server)); if (-z "$datafile") { delete($Server_status{$server}); next; @@ -2230,29 +2638,37 @@ END # Read in the whole file. while (my $result = <$fh>) { last if ($connection->aborted()); - # handle custom fields? Someday we will! + # + # Records are stored one per line chomp($result); - next unless $result; + next if (! $result); + # # Parse the result. - my %Fields = &parse_raw_result($result,$server); + my %Fields = &parse_raw_result($result,$server,$tabletype); $Fields{'hostname'} = $server; + # + # Skip based on copyright next if (! ©right_check(\%Fields)); + + if ($area eq 'portfolio') { + next if (defined($matches{$Fields{'url'}})); + # Skip if inaccessible + next if (!&Apache::lonnet::portfolio_access($Fields{'url'})); + $matches{$Fields{'url'}} = 1; + } + # # Store the result in the mysql database my $result = &Apache::lonmysql::store_row($table,\%Fields); if (! defined($result)) { $r->print(&Apache::lonmysql::get_error()); } - # $r->print(&Apache::lonmysql::get_debug()); + # $hitcountsum ++; - $time_remaining = $max_time - (time - $starttime) ; - if ($last_time - $time_remaining > 0) { - &update_seconds($r,$time_remaining); - $last_time = $time_remaining; - } + &update_seconds($r); if ($hitcountsum % 50 == 0) { &update_count_status($r,$hitcountsum); } - } # End of foreach (@results) + } $fh->close(); # $server is only deleted if the results file has been # found and (successfully) opened. This may be a bad idea. @@ -2262,35 +2678,35 @@ END &update_count_status($r,$hitcountsum); } last if ($connection->aborted()); - # Finished looping through the servers - $starttime = time if (@Servers_to_contact); - $time_remaining = $max_time - (time - $starttime) ; - if ($last_time - $time_remaining > 0) { - $last_time = $time_remaining; - &update_seconds($r,$time_remaining); - } + &update_seconds($r); } - &update_status($r,'Search Complete'.$server); - &update_seconds($r,0); - &Apache::lonmysql::disconnect_from_db(); + &update_status($r,&mt('Search Complete [_1]',$server)); + &update_seconds($r); + # + &Apache::lonmysql::disconnect_from_db(); # This is unneccessary + # # We have run out of time or run out of servers to talk to and - # results to get. - $r->print(""); - if ($ENV{'form.catalogmode'} ne 'groupsearch') { + # results to get, so let the client know the top frame needs to be + # loaded from /adm/searchcat + $r->print(&Apache::loncommon::end_page()); +# if ($env{'form.catalogmode'} ne 'import') { $r->print(""); - } +# } return; } ###################################################################### ###################################################################### + =pod -=item &prev_next_buttons +=item &prev_next_buttons() + +Returns html for the previous and next buttons on the search results page. =cut @@ -2299,56 +2715,40 @@ END sub prev_next_buttons { my ($current_min,$show,$total,$parms) = @_; return '' if ($show eq 'all'); # No links if you get them all at once. - my $links; - ## - ## Prev - my $prev_min = $current_min - $show; - $prev_min = 1 if $prev_min < 1; - if ($prev_min < $current_min) { - $links .= qq{ -prev -}; - } else { - $links .= 'prev'; - } - ## - ## Pages.... Someday. - ## - $links .= qq{   -reload -}; - ## - ## Next - my $next_min = $current_min + $show; - $next_min = $current_min if ($next_min > $total); - if ($next_min != $current_min) { - $links .= qq{   -next -}; - } else { - $links .= ' next'; - } - return $links; + # + # Create buttons + my $buttons = ''; + $buttons .= ' 'x3; + $buttons .= 'connection; $r->print(&search_results_header($importbutton,$closebutton)); ## ## Set viewing function ## - my $viewfunction = $Views{$ENV{'form.viewselect'}}; + my $viewfunction = $Views{$env{'form.viewselect'}}; if (!defined($viewfunction)) { $r->print("Internal Error - Bad view selected.\n"); $r->rflush(); @@ -2356,34 +2756,33 @@ sub display_results { } ## ## $checkbox_num is a count of the number of checkboxes output on the - ## page this is used only during catalogmode=groupsearch. + ## page this is used only during catalogmode=import. my $checkbox_num = 0; ## ## Get the catalog controls setup ## my $action = "/adm/searchcat?phase=results"; ## - ## Deal with groupsearch - ## - if ($ENV{'form.catalogmode'} eq 'groupsearch') { + ## Deal with import by opening the import db file. + if ($env{'form.catalogmode'} eq 'import') { if (! tie(%groupsearch_db,'GDBM_File',$diropendb, &GDBM_WRCREAT(),0640)) { - $r->print('Unable to store import results.'); + $r->print('Unable to save import results.'. + &Apache::loncommon::end_page()); $r->rflush(); return; } } ## ## Prepare the table for querying - ## - my $table = $ENV{'form.table'}; + my $table = $env{'form.table'}; return if (! &ensure_db_and_table($r,$table)); ## ## Get the number of results - ## my $total_results = &Apache::lonmysql::number_of_rows($table); if (! defined($total_results)) { - $r->print("A MySQL error has occurred."); + $r->print("A MySQL error has occurred.". + &Apache::loncommon::end_page()); &Apache::lonnet::logthis("lonmysql was unable to determine the number". " of rows in table ".$table); &Apache::lonnet::logthis(&Apache::lonmysql::get_error()); @@ -2391,52 +2790,172 @@ sub display_results { } ## ## Determine how many results we need to get - ## - $ENV{'form.start'} = 1 if (! exists($ENV{'form.start'})); - $ENV{'form.show'} = 'all' if (! exists($ENV{'form.show'})); - my $min = $ENV{'form.start'}; + $env{'form.start'} = 1 if (! exists($env{'form.start'})); + $env{'form.show'} = 20 if (! exists($env{'form.show'})); + if (exists($env{'form.prev'})) { + $env{'form.start'} -= $env{'form.show'}; + } elsif (exists($env{'form.next'})) { + $env{'form.start'} += $env{'form.show'}; + } + $env{'form.start'} = 1 if ($env{'form.start'}<1); + $env{'form.start'} = $total_results if ($env{'form.start'}>$total_results); + my $min = $env{'form.start'}; my $max; - if ($ENV{'form.show'} eq 'all') { + if ($env{'form.show'} eq 'all') { $max = $total_results ; } else { - $max = $min + $ENV{'form.show'} - 1; + $max = $min + $env{'form.show'} - 1; $max = $total_results if ($max > $total_results); } ## - ## Output links (if necessary) for 'prev' and 'next' pages. + ## Output form elements + $r->print(&hidden_field('table'). + &hidden_field('phase'). + &hidden_field('persistent_db_id'). + &hidden_field('start'). + &hidden_field('area') + ); + # + # Build sorting selector + my @fields = + ( + {key=>'default' }, + {key=>'title' }, + {key =>'author' }, + {key =>'subject'}, + {key =>'url',desc=>'URL'}, + {key =>'keywords'}, + {key =>'language'}, + {key =>'creationdate'}, + {key =>'lastrevisiondate'}, + {key =>'owner'}, + {key =>'copyright'}, + {key =>'authorspace'}, + {key =>'lowestgradelevel'}, + {key =>'highestgradelevel'}, + {key =>'standards',desc=>'Standards'}, + ); + if ($area eq 'portfolio') { + push(@fields, + ( + {key => 'scope'}, + {key => 'keynum'}, + )); + } else { + push(@fields, + ( + {key =>'count',desc=>'Number of accesses'}, + {key =>'stdno',desc=>'Students Attempting'}, + {key =>'avetries',desc=>'Average Number of Tries'}, + {key =>'difficulty',desc=>'Mean Degree of Difficulty'}, + {key =>'disc',desc=>'Mean Degree of Discrimination'}, + {key =>'clear',desc=>'Evaluation: Clear'}, + {key =>'technical',desc=>'Evaluation: Technically Correct'}, + {key =>'correct',desc=>'Evaluation: Material is Correct'}, + {key =>'helpful',desc=>'Evaluation: Material is Helpful'}, + {key =>'depth',desc=>'Evaluation: Material has Depth'}, + )); + } + my %fieldnames = &Apache::lonmeta::fieldnames(); + my @field_order; + foreach my $field_data (@fields) { + push(@field_order,$field_data->{'key'}); + if (! exists($field_data->{'desc'})) { + $field_data->{'desc'}=$fieldnames{$field_data->{'key'}}; + } else { + if (! defined($field_data->{'desc'})) { + $field_data->{'desc'} = ucfirst($field_data->{'key'}); + } + $field_data->{'desc'} = &mt($field_data->{'desc'}); + } + } + my %sort_fields = map {$_->{'key'},$_->{'desc'}} @fields; + $sort_fields{'select_form_order'} = \@field_order; + $env{'form.sortorder'} = 'desc' if (! exists($env{'form.sortorder'})); + if (! exists($env{'form.sortfield'})) { + if ($area eq 'portfolio') { + $env{'form.sortfield'} = 'owner'; + } else { + $env{'form.sortfield'} = 'count'; + } + } + if (! exists($env{'form.sortorder'})) { + if ($env{'form.sortfield'}=~/^(count|stdno|disc|clear|technical|correct|helpful)$/) { + $env{'form.sortorder'}='desc'; + } else { + $env{'form.sortorder'}='asc'; + } + } + my $sortform = &mt('Sort by [_1] [_2]', + &Apache::loncommon::select_form($env{'form.sortfield'}, + 'sortfield', + %sort_fields), + &Apache::loncommon::select_form($env{'form.sortorder'}, + 'sortorder', + (asc =>&mt('Ascending'), + desc=>&mt('Descending') + )) + ); ## + ## Output links (if necessary) for 'prev' and 'next' pages. $r->print - ('
'. - &prev_next_buttons($min,$ENV{'form.show'},$total_results, - "table=".$ENV{'form.table'}. - "&phase=results". - "&persistent_db_id=".$ENV{'form.persistent_db_id'}) - ."
\n" + ('
'. + ''.$sortform.''. + ''. + &prev_next_buttons($min,$env{'form.show'},$total_results). + ''. + &viewoptions().'
' ); if ($total_results == 0) { - $r->print(''. + $r->print(''. '

'.&mt('There are currently no results').'.

'. - ""); + "". + &Apache::loncommon::end_page()); return; } else { - $r->print - ("
Results $min to $max out of $total_results
\n"); + $r->print('
'. + mt('Results [_1] to [_2] out of [_3]', + $min,$max,$total_results). + "
\n"); } ## ## Get results from MySQL table - ## - my @Results = &Apache::lonmysql::get_rows($table, - 'id>='.$min.' AND id<='.$max); + my $sort_command = 'id>='.$min.' AND id<='.$max; + my $order; + if (exists($env{'form.sortorder'})) { + if ($env{'form.sortorder'} eq 'asc') { + $order = 'ASC'; + } elsif ($env{'form.sortorder'} eq 'desc') { + $order = 'DESC'; + } else { + $order = ''; + } + } else { + $order = ''; + } + if ($env{'form.sortfield'} ne 'default' && + exists($sort_fields{$env{'form.sortfield'}})) { + $sort_command = $env{'form.sortfield'}.' IS NOT NULL '. + 'ORDER BY '.$env{'form.sortfield'}.' '.$order. + ' LIMIT '.($min-1).','.($max-$min+1); + } + my @Results = &Apache::lonmysql::get_rows($table,$sort_command); ## ## Loop through the results and output them. - ## + my $tabletype = 'metadata'; + if ($area eq 'portfolio') { + $tabletype = 'portfolio_search'; + } foreach my $row (@Results) { if ($connection->aborted()) { &cleanup(); return; } - my %Fields = %{&parse_row(@$row)}; + my %Fields = %{&parse_row($tabletype,@$row)}; my $output="

\n"; + if (! defined($Fields{'title'}) || $Fields{'title'} eq '') { + $Fields{'title'} = 'Untitled'; + } my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'}, $Fields{'id'},$checkbox_num++); # Render the result into html @@ -2450,15 +2969,15 @@ sub display_results { } else { $r->print ('

'. - &prev_next_buttons($min,$ENV{'form.show'},$total_results, - "table=".$ENV{'form.table'}. + &prev_next_buttons($min,$env{'form.show'},$total_results, + "table=".$env{'form.table'}. "&phase=results". "&persistent_db_id=". - $ENV{'form.persistent_db_id'}) + $env{'form.persistent_db_id'}) ."
\n" ); } - $r->print(""); + $r->print("".&Apache::loncommon::end_page()); $r->rflush(); untie %groupsearch_db if (tied(%groupsearch_db)); return; @@ -2472,7 +2991,7 @@ sub display_results { =item &catalogmode_output($title,$url,$fnum,$checkbox_num) Returns html needed for the various catalog modes. Gets inputs from -$ENV{'form.catalogmode'}. Stores data in %groupsearch_db. +$env{'form.catalogmode'}. Stores data in %groupsearch_db. =cut @@ -2481,21 +3000,21 @@ $ENV{'form.catalogmode'}. Stores data i sub catalogmode_output { my $output = ''; my ($title,$url,$fnum,$checkbox_num) = @_; - if ($ENV{'form.catalogmode'} eq 'interactive') { + if ($env{'form.catalogmode'} eq 'interactive') { $title=~ s/\'/\\\'/g; - if ($ENV{'form.catalogmode'} eq 'interactive') { + if ($env{'form.catalogmode'} eq 'interactive') { $output.=< + END } - } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') { + } elsif ($env{'form.catalogmode'} eq 'import') { $groupsearch_db{"pre_${fnum}_link"}=$url; $groupsearch_db{"pre_${fnum}_title"}=$title; $output.=< - END @@ -2507,7 +3026,7 @@ END =pod -=item &parse_row +=item &parse_row() Parse a row returned from the database. @@ -2516,13 +3035,16 @@ Parse a row returned from the database. ###################################################################### ###################################################################### sub parse_row { - my @Row = @_; + my ($tabletype,@Row) = @_; my %Fields; + if (! scalar(@Datatypes)) { + &set_up_table_structure($tabletype); + } for (my $i=0;$i<=$#Row;$i++) { - $Fields{$Datatypes[$i]->{'name'}}=&Apache::lonnet::unescape($Row[$i]); + $Fields{$Datatypes[$i]->{'name'}}=&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 +3060,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. @@ -2555,64 +3074,13 @@ The 'title' field is set to "Untitled" i ########################################################### ########################################################### sub parse_raw_result { - my ($result,$hostname) = @_; - # Check for a comma - if it is there then we do not need to unescape the - # string. There seems to be some kind of problem with some items in - # the database - the entire string gets sent out unescaped...? - unless ($result =~ /,/) { - $result = &Apache::lonnet::unescape($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) - ); - $Fields{'language'} = - &Apache::loncommon::languagedescription($Fields{'lang'}); - $Fields{'copyrighttag'} = - &Apache::loncommon::copyrightdescription($Fields{'copyright'}); - $Fields{'mimetag'} = - &Apache::loncommon::filedescription($Fields{'mime'}); - if ($Fields{'author'}=~/^(\s*|error)$/) { - $Fields{'author'}="Unknown Author"; - } - # Put spaces in the keyword list, if needed. - $Fields{'keywords'}=~ s/,([A-z])/, $1/g; - if ($Fields{'title'}=~ /^\s*$/ ) { - $Fields{'title'}='Untitled'; - } - unless ($ENV{'user.adv'}) { - # What is this anyway? - $Fields{'keywords'} = '- not displayed -'; - $Fields{'notes'} = '- not displayed -'; - $Fields{'abstract'} = '- not displayed -'; - $Fields{'subject'} = '- not displayed -'; - } - if (length($Fields{'abstract'})>200) { - $Fields{'abstract'} = - substr($Fields{'abstract'},0,200).'...'; - } - if (length($Fields{'keywords'})>200) { - $Fields{'keywords'} = - substr($Fields{'keywords'},0,200).'...'; - } + my ($result,$hostname,$tabletype) = @_; + # conclude from self to others regarding fields + my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash + ($tabletype, + map { + &unescape($_); + } (split(/\,/,$result)) ); return %Fields; } @@ -2632,8 +3100,8 @@ sub handle_custom_fields { my $customshow=''; my $extrashow=''; my @customfields; - if ($ENV{'form.customshow'}) { - $customshow=$ENV{'form.customshow'}; + if ($env{'form.customshow'}) { + $customshow=$env{'form.customshow'}; $customshow=~s/[^\w\s]//g; my @fields=map { "$_:"; @@ -2649,7 +3117,7 @@ sub handle_custom_fields { if ($result=~/^(custom\=.*)$/) { # grab all custom metadata my $tmp=$result; $tmp=~s/^custom\=//; - my ($k,$v)=map {&Apache::lonnet::unescape($_); + my ($k,$v)=map {&unescape($_); } split(/\,/,$tmp); $customhash{$k}=$v; } @@ -2662,12 +3130,12 @@ sub handle_custom_fields { =pod -=item &search_results_header +=item &search_results_header() Output the proper html headers and javascript code to deal with different calling modes. -Takes most inputs directly from %ENV, except $mode. +Takes most inputs directly from %env, except $mode. =over 4 @@ -2681,7 +3149,7 @@ The following environment variables are =item 'form.catalogmode' -Checked for 'interactive' and 'groupsearch'. +Checked for 'interactive' and 'import'. =item 'form.mode' @@ -2689,8 +3157,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,13 +3175,14 @@ Checked for existance & 'edit' mode. ###################################################################### sub search_results_header { my ($importbutton,$closebutton) = @_; - my $result = ''; + + my $js; # output beginning of search page # conditional output of script functions dependent on the mode in # which the search was invoked - if ($ENV{'form.catalogmode'} eq 'interactive'){ - if (! exists($ENV{'form.mode'}) || $ENV{'form.mode'} ne 'edit') { - $result.=< function select_data(title,url) { changeTitle(title); @@ -2724,17 +3201,34 @@ sub search_results_header { } SCRIPT - } elsif ($ENV{'form.mode'} eq 'edit') { - my $form = $ENV{'form.form'}; - my $element = $ENV{'form.element'}; - $result.=< 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; @@ -2747,55 +3241,46 @@ function changeURL(val) { SCRIPT } } - $result.=< SCRIPT - $result.=< -$bodytag -
- + + my $start_page = &Apache::loncommon::start_page(undef,$js, + {'only_body' =>1}); + my $result=< $importbutton END return $result; } -###################################################################### -###################################################################### -sub search_status_header { - return <Search Status -$bodytag -

Search Status

-Sending search request to LON-CAPA servers.
-ENDSTATUS -} - sub results_link { - my $basic_link = "/adm/searchcat?"."&table=".$ENV{'form.table'}. - "&persistent_db_id=".$ENV{'form.persistent_db_id'}; + my $basic_link = "/adm/searchcat?"."&table=".$env{'form.table'}. + "&persistent_db_id=".$env{'form.persistent_db_id'}; my $results_link = $basic_link."&phase=results". "&pause=1"."&start=1"; return $results_link; @@ -2805,24 +3290,31 @@ sub results_link { ###################################################################### sub print_frames_interface { my $r = shift; - my $basic_link = "/adm/searchcat?"."&table=".$ENV{'form.table'}. - "&persistent_db_id=".$ENV{'form.persistent_db_id'}; + my $basic_link = "/adm/searchcat?"."&table=".$env{'form.table'}. + "&persistent_db_id=".$env{'form.persistent_db_id'}; my $run_search_link = $basic_link."&phase=run_search"; my $results_link = &results_link(); - my $result = <<"ENDFRAMES"; - - - -LON-CAPA Digital Library Search Results - - +JS + + my $start_page = + &Apache::loncommon::start_page('LON-CAPA Digital Library Search Results', + $js, + {'frameset' => 1, + 'add_entries' => { + 'rows' => "150,*",},}); + my $end_page = + &Apache::loncommon::end_page({'frameset' => 1}); + + my $result = <<"ENDFRAMES"; +$start_page - - +$end_page ENDFRAMES $r->print($result); @@ -2832,11 +3324,47 @@ ENDFRAMES ###################################################################### ###################################################################### +sub has_stat_data { + my ($values) = @_; + if ( (defined($values->{'count'}) && $values->{'count'} ne '') || + (defined($values->{'stdno'}) && $values->{'stdno'} ne '') || + (defined($values->{'disc'}) && $values->{'disc'} ne '') || + (defined($values->{'avetries'}) && $values->{'avetries'} ne '') || + (defined($values->{'difficulty'}) && $values->{'difficulty'} ne '')) { + return 1; + } + return 0; +} + +sub statfields { + return ('count','stdno','disc','avetries','difficulty'); +} + +sub has_eval_data { + my ($values) = @_; + if ( (defined($values->{'clear'}) && $values->{'clear'} ne '') || + (defined($values->{'technical'}) && $values->{'technical'} ne '') || + (defined($values->{'correct'}) && $values->{'correct'} ne '') || + (defined($values->{'helpful'}) && $values->{'helpful'} ne '') || + (defined($values->{'depth'}) && $values->{'depth'} ne '')) { + return 1; + } + return 0; +} + +sub evalfields { + return ('clear','technical','correct','helpful','depth'); +} + +###################################################################### +###################################################################### + =pod =item Metadata Viewing Functions Output is a HTML-ified string. + Input arguments are title, author, subject, url, keywords, version, notes, short abstract, mime, language, creation date, last revision date, owner, copyright, hostname, and @@ -2852,28 +3380,116 @@ extra custom metadata to show. ###################################################################### sub detailed_citation_view { my ($prefix,%values) = @_; - my $result=<$prefix$values{'title'} -

-$values{'author'}, $values{'owner'}
- -Subject: $values{'subject'}
-Keyword(s): $values{'keywords'}
-Notes: $values{'notes'}
-MIME Type: $values{'mimetag'}
-Language: $values{'language'}
-Copyright/Distribution: $values{'cprtag'}
-

-$values{'extrashow'} -

-$values{'shortabstract'} -

-
-END + my $result; + my $jumpurl=$values{'url'}; + $jumpurl=~s|^/ext/|http://|; + $result .= ''.$prefix. + ''.' '. + ''.$values{'title'}."\n"; + $result .= "

\n"; + $result .= ''.$values{'author'}.','. + ' '.$values{'owner'}.'
'; + foreach my $field + ( + { name=>'url', + translate => 'URL: [_1]', + special => 'url link',}, + { name=>'subject', + translate => 'Subject: [_1]',}, + { name=>'keywords', + translate => 'Keywords: [_1]',}, + { name=>'notes', + translate => 'Notes: [_1]',}, + { name=>'mimetag', + translate => 'MIME Type: [_1]',}, + { name=>'standards', + translate => 'Standards:[_1]',}, + { name=>'copyrighttag', + translate => 'Copyright/Distribution: [_1]',}, + { name=>'count', + format => "%d", + translate => 'Access Count: [_1]',}, + { name=>'stdno', + format => "%d", + translate => 'Number of Students: [_1]',}, + { name=>'avetries', + format => "%.2f", + translate => 'Average Tries: [_1]',}, + { name=>'disc', + format => "%.2f", + translate => 'Degree of Discrimination: [_1]',}, + { name=>'difficulty', + format => "%.2f", + translate => 'Degree of Difficulty: [_1]',}, + { name=>'clear', + format => "%.2f", + translate => 'Clear: [_1]',}, + { name=>'depth', + format => "%.2f", + translate => 'Depth: [_1]',}, + { name=>'helpful', + format => "%.2f", + translate => 'Helpful: [_1]',}, + { name=>'correct', + format => "%.2f", + translate => 'Correct: [_1]',}, + { name=>'technical', + format => "%.2f", + translate => 'Technical: [_1]',}, + { name=>'comefrom_list', + type => 'list', + translate => 'Resources that lead up to this resource in maps',}, + { name=>'goto_list', + type => 'list', + translate => 'Resources that follow this resource in maps',}, + { name=>'sequsage_list', + type => 'list', + translate => 'Resources using or importing resource',}, + ) { + next if (! exists($values{$field->{'name'}}) || + $values{$field->{'name'}} eq ''); + if (exists($field->{'type'}) && $field->{'type'} eq 'list') { + $result .= ''.&mt($field->{'translate'}).''; + foreach my $item (split(',',$values{$field->{'name'}})){ + $item = &Apache::lonnet::clutter($item); + $result .= &display_url($item,[2,0,1]); + } + } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){ + $result.= &mt($field->{'translate'}, + sprintf($field->{'format'}, + $values{$field->{'name'}}))."
\n"; + } else { + if ($field->{'special'} eq 'url link') { + $result .= &display_url($jumpurl,[3,0,1]); + } else { + $result.= &mt($field->{'translate'}, + $values{$field->{'name'}}); + } + $result .= "
\n"; + } + } + $result .= "

"; + if (exists($values{'extrashow'}) && $values{'extrashow'} ne '') { + $result .= '

'.$values{'extrashow'}.'

'; + } + if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') { + $result .= '

'.$values{'shortabstract'}.'

'; + } + $result .= '
'."\n"; return $result; } +sub detailed_citation_preview { + my ($prefix,%values)=@_; + return '
'. + &detailed_citation_view($prefix,%values). + ''. + &Apache::lonindexer::showpreview($values{'url'}). + '

'; +} + + ###################################################################### ###################################################################### @@ -2886,11 +3502,29 @@ END ###################################################################### sub summary_view { my ($prefix,%values) = @_; - my $result=<$values{'author'}
-$values{'title'}
-$values{'owner'} -- $values{'lastrevisiondate'}
+ my $icon=&Apache::loncommon::icon($values{'url'}); + my $result=qq{$prefix}; + if (exists($env{'form.sortfield'}) && + $env{'form.sortfield'} !~ /^(default| + author| + url| + title| + owner| + lastrevisiondate| + copyright)$/x) { + my $tmp = $values{$env{'form.sortfield'}}; + if (! defined($tmp)) { $tmp = 'undefined'; } + $result .= ' '.$tmp.' '; + } + my $jumpurl=$values{'url'}; + $jumpurl=~s|^/ext/|http://|; + my $link = &display_url($jumpurl,[2,0,1]); + + $result.=<$values{'title'}
+$link
+$values{'author'}, $values{'owner'} -- $values{'lastrevisiondate'}
$values{'copyrighttag'}
$values{'extrashow'}

@@ -2899,6 +3533,15 @@ END return $result; } +sub summary_preview { + my ($prefix,%values)=@_; + return '
'. + &summary_view($prefix,%values). + ''. + &Apache::lonindexer::showpreview($values{'url'}). + '

'; +} + ###################################################################### ###################################################################### @@ -2912,14 +3555,43 @@ END ###################################################################### sub compact_view { my ($prefix,%values) = @_; - my $result=< -$values{'title'} -$values{'author'}
-END + my $jumpurl=$values{'url'}; + $jumpurl=~s|^/ext/|http://|; + + my $link = &display_url($jumpurl,[1,1,1]); + + my $result = + $prefix.''; + if (exists($env{'form.sortfield'}) && + $env{'form.sortfield'} !~ /^(default|author|url|title)$/) { + my $tmp = $values{$env{'form.sortfield'}}; + if (! defined($tmp)) { $tmp = 'undefined'; } + $result .= ' '.$tmp.' '; + } + $jumpurl = &HTML::Entities::encode($jumpurl,'<>&"'); + $result.=' '. + ''. + &HTML::Entities::encode($values{'title'},'<>&"').' '. + $link.' '.$values{'author'}.' ('.$values{'domain'}.')
'; return $result; } +sub display_url { + my ($url,$crumb_args) = @_; + my $link; + if ($url=~m|^/ext/|) { + $url=~s|^/ext/|http://|; + $link=''.$url.''; + } elsif ($url=~m{^(http://|/uploaded/)}) { + $link=''.$url.''; + } else { + $link=&Apache::lonhtmlcommon::crumbs($url, + 'preview', + '', + (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),@{$crumb_args}).' '; + } + return $link; +} ###################################################################### ###################################################################### @@ -2934,28 +3606,39 @@ END ###################################################################### sub fielded_format_view { my ($prefix,%values) = @_; + my $icon=&Apache::loncommon::icon($values{'url'}); + my %Translated = &Apache::lonmeta::fieldnames(); + my $jumpurl=$values{'url'}; + $jumpurl=~s|^/ext/|http://|; + my $result=<URL: $values{'url'} -
-Title: $values{'title'}
-Author(s): $values{'author'}
-Subject: $values{'subject'}
-Keyword(s): $values{'keywords'}
-Notes: $values{'notes'}
-MIME Type: $values{'mimetag'}
-Language: $values{'language'}
-Creation Date: $values{'creationdate'}
-Last Revision Date: $values{'lastrevisiondate'}
-Publisher/Owner: $values{'owner'}
-Copyright/Distribution: $values{'copyrighttag'}
-Repository Location: $values{'hostname'}
-Abstract: $values{'shortabstract'}
-$values{'extrashow'} -

-
-END +$prefix +
+
URL:
+
$values{'url'}
+END + foreach my $field ('title','author','domain','subject','keywords','notes', + 'mimetag','language','creationdate','lastrevisiondate', + 'owner','copyrighttag','hostname','abstract') { + $result .= (' 'x4).'
'.$Translated{$field}.'
'."\n". + (' 'x8).'
'.$values{$field}.'
'."\n"; + } + if (&has_stat_data(\%values)) { + foreach my $field (&statfields()) { + $result .= (' 'x4).'
'.$Translated{$field}.'
'."\n". + (' 'x8).'
'.$values{$field}.'
'."\n"; + } + } + if (&has_eval_data(\%values)) { + foreach my $field (&evalfields()) { + $result .= (' 'x4).'
'.$Translated{$field}.'
'."\n". + (' 'x8).'
'.$values{$field}.'
'."\n"; + } + } + $result .= "
\n"; + $result .= $values{'extrashow'}; + $result .= '
'."\n"; return $result; } @@ -2974,34 +3657,59 @@ END ###################################################################### sub xml_sgml_view { my ($prefix,%values) = @_; + my $xml = ''."\n"; + # The usual suspects + foreach my $field ('url','title','author','subject','keywords','notes','domain') { + $xml .= qq{<$field>$values{$field}}."\n"; + } + # + $xml .= "\n"; + foreach my $field ('mime','mimetag') { + $xml .= qq{<$field>$values{$field}}."\n"; + } + $xml .= "\n"; + # + $xml .= "\n"; + foreach my $field ('language','languagetag') { + $xml .= qq{<$field>$values{$field}}."\n"; + } + $xml .= "\n"; + # + foreach my $field ('creationdate','lastrevisiondate','owner') { + $xml .= qq{<$field>$values{$field}}."\n"; + } + # + $xml .= "\n"; + foreach my $field ('copyright','copyrighttag') { + $xml .= qq{<$field>$values{$field}}."\n"; + } + $xml .= "\n"; + $xml .= qq{$values{'hostname'}}. + "\n"; + $xml .= qq{$values{'shortabstract'}}."\n"; + # + if (&has_stat_data(\%values)){ + $xml .= "\n"; + foreach my $field (&statfields()) { + $xml .= qq{<$field>$values{$field}}."\n"; + } + $xml .= "\n"; + } + # + if (&has_eval_data(\%values)) { + $xml .= "\n"; + foreach my $field (&evalfields) { + $xml .= qq{<$field>$values{$field}}."\n"; + } + $xml .= "\n"; + } + # + $xml .= "\n"; + $xml = &HTML::Entities::encode($xml,'<>&'); my $result=< -<LonCapaResource> -<url>$values{'url'}</url> -<title>$values{'title'}</title> -<author>$values{'author'}</author> -<subject>$values{'subject'}</subject> -<keywords>$values{'keywords'}</keywords> -<notes>$values{'notes'}</notes> -<mimeInfo> -<mime>$values{'mime'}</mime> -<mimetag>$values{'mimetag'}</mimetag> -</mimeInfo> -<languageInfo> -<language>$values{'lang'}</language> -<languagetag>$values{'language'}</languagetag> -</languageInfo> -<creationdate>$values{'creationdate'}</creationdate> -<lastrevisiondate>$values{'lastrevisiondate'}</lastrevisiondate> -<owner>$values{'owner'}</owner> -<copyrightInfo> -<copyright>$values{'copyright'}</copyright> -<copyrighttag>$values{'copyrighttag'}</copyrighttag> -</copyrightInfo> -<repositoryLocation>$values{'hostname'}</repositoryLocation> -<shortabstract>$values{'shortabstract'}</shortabstract> -</LonCapaResource> +$xml $values{'extrashow'}
@@ -3023,11 +3731,51 @@ END sub filled { my ($field)=@_; if ($field=~/\S/ && $field ne 'any') { - return 1; + return 1; + } else { + return 0; } - else { - return 0; +} + +###################################################################### +###################################################################### + +=pod + +=item &output_unparsed_phrase_error() + +=cut + +###################################################################### +###################################################################### +sub output_unparsed_phrase_error { + my ($r,$closebutton,$parms,$hidden_fields,$field)=@_; + my $errorstring; + if ($field eq 'basicexp') { + $errorstring = &mt('Unable to understand the search phrase [_1]. Please modify your search.',$env{'form.basicexp'}); + } else { + $errorstring = &mt('Unable to understand the search phrase [_1]:[_2].',$field,$env{'form.'.$field}); } + my $heading = &mt('Unparsed Field'); + my $revise = &mt('Revise search request'); + # make query information persistent to allow for subsequent revision + my $start_page = &Apache::loncommon::start_page('Search'); + my $end_page = &Apache::loncommon::end_page(); + $r->print(< +$hidden_fields +$closebutton +
+

$heading

+

+$errorstring +

+

+$revise +

+$end_page +ENDPAGE } ###################################################################### @@ -3051,33 +3799,28 @@ $parms is extra information to include i ###################################################################### ###################################################################### sub output_blank_field_error { - my ($r,$closebutton,$parms)=@_; - # make query information persistent to allow for subsequent revision - $r->print(< - -The LearningOnline Network with CAPA -BEGINNING - $r->print(< -$bodytag - -

Search Catalog

+ my ($r,$closebutton,$parms,$hidden_fields)=@_; + my $errormsg = &mt('You did not fill in enough information for the search to be started. You need to fill in relevant fields on the search page in order for a query to be processed.'); + my $revise = &mt('Revise Search Request'); + my $heading = &mt('Unactionable Search Queary'); + my $start_page = &Apache::loncommon::start_page('Search'); + my $end_page = &Apache::loncommon::end_page(); + $r->print(< $hidden_fields -Revise search request  $closebutton
-

Unactionable search query.

+

$heading

-You did not fill in enough information for the search to be started. -You need to fill in relevant fields on the search page in order -for a query to be processed. +$errormsg

- - -RESULTS +

+$revise  +

+$end_page +ENDPAGE + return; } ###################################################################### @@ -3100,16 +3843,12 @@ 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 $start_page = &Apache::loncommon::start_page('Search'); + my $end_page = &Apache::loncommon::end_page(); $r->print(< - -The LearningOnline Network with CAPA - -$bodytag - -

Search Catalog

+$start_page $hidden_fields $message

- - +$end_page RESULTS } @@ -3155,13 +3893,13 @@ 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'); } } &untiehash(); &Apache::lonmysql::disconnect_from_db(); + return OK; } __END__ 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.