--- loncom/interface/lonsearchcat.pm 2004/05/05 17:29:06 1.223 +++ loncom/interface/lonsearchcat.pm 2007/03/03 01:54:00 1.280 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Search Catalog # -# $Id: lonsearchcat.pm,v 1.223 2004/05/05 17:29:06 matthew Exp $ +# $Id: lonsearchcat.pm,v 1.280 2007/03/03 01:54:00 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -63,7 +63,7 @@ package Apache::lonsearchcat; use strict; use Apache::Constants qw(:common :http); -use Apache::lonnet(); +use Apache::lonnet; use Apache::File(); use CGI qw(:standard); use Text::Query; @@ -75,6 +75,10 @@ use Apache::lonhtmlcommon; use Apache::lonlocal; use LONCAPA::lonmetadata(); use HTML::Entities(); +use Parse::RecDescent; +use Apache::lonnavmaps; +use Apache::lonindexer(); +use LONCAPA; ###################################################################### ###################################################################### @@ -91,7 +95,9 @@ my %persistent_db; # gdbm hash which h # 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); @@ -111,9 +117,6 @@ sub handler { my $diropendb; # The full path to the (temporary) search database file. # This is set and used in &handler() and is also used in # &output_results(). - my $bodytag; # LON-CAPA standard body tag, gotten from - # &Apache::lonnet::bodytag. - # No title, no table, just a tag. my $loaderror=&Apache::lonnet::overloaderror($r); if ($loaderror) { return $loaderror; } @@ -135,72 +138,78 @@ 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','titleelement']); + 'cleargroupsort','titleelement','area']); ## ## 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"; + "$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'; + &escape($domain). + '_'.&escape($env{'user.name'}). + '_'.$env{'form.persistent_db_id'}.'_persistent_search.db'; ## &Apache::lonhtmlcommon::clear_breadcrumbs(); - if (exists($ENV{'request.course.id'}) && $ENV{'request.course.id'} ne '') { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/searchcat?'. - 'catalogmode='.$ENV{'form.catalogmode'}. - '&launch='.$ENV{'form.launch'}. - '&mode='.$ENV{'form.mode'}, - text=>"Course and Catalog Search", - bug=>'Searching',}); - } else { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/searchcat?'. - 'catalogmode='.$ENV{'form.catalogmode'}. - '&launch='.$ENV{'form.launch'}. - '&mode='.$ENV{'form.mode'}, - text=>"Catalog Search", - bug=>'Searching',}); + + 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?'. + '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 ($env{'form.phase'} !~ m/(basic|adv|course)_search/) { if (! &get_persistent_form_data($persistent_db_file)) { - if ($ENV{'form.phase'} =~ /(run_search|results)/) { + 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; + 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 { @@ -210,18 +219,19 @@ END ## 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; } } @@ -229,36 +239,39 @@ END ## Configure hidden fields ## $hidden_fields = ''."\n"; - if (exists($ENV{'form.catalogmode'})) { + $env{'form.persistent_db_id'}.'" />'."\n"; + if (exists($env{'form.catalogmode'})) { $hidden_fields .= &hidden_field('catalogmode'); } - if (exists($ENV{'form.form'})) { + if (exists($env{'form.form'})) { $hidden_fields .= &hidden_field('form'); } - if (exists($ENV{'form.element'})) { + if (exists($env{'form.element'})) { $hidden_fields .= &hidden_field('element'); } - if (exists($ENV{'form.titleelement'})) { + if (exists($env{'form.titleelement'})) { $hidden_fields .= &hidden_field('titleelement'); } - if (exists($ENV{'form.mode'})) { + if (exists($env{'form.mode'})) { $hidden_fields .= &hidden_field('mode'); } + if (exists($env{'form.area'})) { + $hidden_fields .= &hidden_field('area'); + } ## ## Configure dynamic components of interface ## - if ($ENV{'form.catalogmode'} eq 'interactive') { + if ($env{'form.catalogmode'} eq 'interactive') { $closebutton="'/adm/searchcat?phase=disp_adv&'. - 'catalogmode='.$ENV{'form.catalogmode'}. - '&launch='.$ENV{'form.launch'}. - '&mode='.$ENV{'form.mode'}, - text=>"Advanced Search", + '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') { + } elsif ($env{'form.searchmode'} eq 'course search') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/searchcat?phase=disp_adv&'. - 'catalogmode='.$ENV{'form.catalogmode'}. - '&launch='.$ENV{'form.launch'}. - '&mode='.$ENV{'form.mode'}, + 'catalogmode='.$env{'form.catalogmode'}. + '&launch='.$env{'form.launch'}. + '&mode='.$env{'form.mode'}, text=>"Course Search", bug=>'Searching',}); } ## ## Switch on the phase ## - if ($ENV{'form.phase'} eq 'disp_basic') { + if ($env{'form.phase'} eq 'disp_basic') { &print_basic_search_form($r,$closebutton,$hidden_fields); - } elsif ($ENV{'form.phase'} eq 'disp_adv') { + } 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); - } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) { + } 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')) { - # Set up table - if (! defined(&create_results_table())) { - my $errorstring=&Apache::lonmysql::get_error(); - &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '. - 'needed table. lonmysql error:'. - $errorstring); - $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,$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,$hidden_fields); @@ -381,10 +370,36 @@ 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 store 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 store 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; } @@ -396,23 +411,23 @@ END # 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 ($env{'form.phase'} eq 'basic_search') { + if (! exists($env{'form.related'})) { + $env{'form.related'} = ''; } - if (! exists($ENV{'form.domains'})) { - $ENV{'form.domains'} = ''; + if (! exists($env{'form.domains'})) { + $env{'form.domains'} = ''; } - } elsif ($ENV{'form.phase'} eq 'adv_search') { + } 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'} = ''; + 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'} = ''; + } elsif ($env{'form.phase'} eq 'course_search') { + if (! exists($env{'form.crsrelated'})) { + $env{'form.crsrelated'} = ''; } } } @@ -420,7 +435,7 @@ sub clean_up_environment { sub hidden_field { my ($name,$value) = @_; if (! defined($value)) { - $value = $ENV{'form.'.$name}; + $value = $env{'form.'.$name}; } return ''.$/; } @@ -439,78 +454,175 @@ 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 .= ' '.&mt("with related words").": @New_Words."; } else { $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 - undef %alreadyseen; - %alreadyseen=(); my $c=$r->connection; - if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db", + if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db", &GDBM_READER(),0640)) { - foreach (keys %hash) { + foreach (sort(keys(%hash))) { if ($c->aborted()) { last; } - if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) { - &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext, - @allwords); + 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').'.

'); } + +# Check discussions if requested + if ($discuss) { + my $totaldiscussions = 0; + $r->print('

'.&mt('Discussion postings').':
'); + my $navmap = Apache::lonnavmaps::navmap->new(); + 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').'.

'); + } + } + # =================================================== Done going through course - $r->print(''); + $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(' .'); @@ -520,12 +632,24 @@ 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); @@ -534,15 +658,6 @@ sub untiehash { } # End of course search scoping -sub search_html_header { - my $Str = < - -The LearningOnline Network with CAPA - -ENDHEADER - return $Str; -} ###################################################################### ###################################################################### @@ -559,78 +674,25 @@ Prints the form for the basic search. S ###################################################################### sub print_basic_search_form { my ($r,$closebutton,$hidden_fields) = @_; - my $bodytag=&Apache::loncommon::bodytag('Search'). - &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Searching', - undef,undef,! $ENV{'form.launch'}); - my $scrout = &search_html_header().$bodytag; - if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) { - # Define interface components - my $userelatedwords= - &mt('[_1] use related words', - &Apache::lonhtmlcommon::checkbox - ('related',$ENV{'form.related'},'related')); - my $onlysearchdomain= - &mt('[_1] only search domain [_2]', - &Apache::lonhtmlcommon::checkbox('domains', - $ENV{'form.domains'}, - $r->dir_config('lonDefDomain') - ), - $r->dir_config('lonDefDomain') - ); - my $adv_search_link = - ''.&mt('Advanced Search').''; - # - $scrout.='
'. - ''. - $hidden_fields; - # - $scrout .= '
'.$/; - if ($ENV{'request.course.id'}) { - $scrout .= '

'.&mt('LON-CAPA Catalog Search').'

'; - } else { - # No need to tell them they are searching - $scrout.= ('
'x2); - } - $scrout.=''. - ''. - ''. - ''.$/; - # -# $scrout .= ''.$/; - $scrout .= ''.$/; - $scrout .= '
'. - &Apache::lonhtmlcommon::textbox('basicexp', - $ENV{'form.basicexp'},50).'
'. - ''.&searchhelp().''.'
'. - ''.(' 'x3).$adv_search_link.''.'
'. - ''.(' 'x1).$userelatedwords.''.'
'. - ''.(' 'x1).$onlysearchdomain.''.'
'. - '
'. -# ''. -# $userelatedwords.(' 'x3). -# $onlysearchdomain.(' 'x2).$adv_search_link. -# ''. -# '
'. - ''. - ''. - (' 'x2).$closebutton.(' 'x2). - &viewoptions(). - ''. - '
'.$/.'
'.'
'; - } - if ($ENV{'request.course.id'}) { + my $result = ($env{'form.catalogmode'} ne 'import'); + my $bread_crumb = + &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Basic', + $env{'form.catalogmode'} ne 'import'); + my $scrout = &Apache::loncommon::start_page('Search').$bread_crumb; +# Search form for resource space + if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) { + $scrout .= &setup_basic_search($r,'res',$hidden_fields,$closebutton); + $scrout .= '

'; + } +# 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)' + 'full' =>'fulltext search (time consuming)', + 'disc' => 'search discussion postings (resources and bulletin boards)', ); $scrout.=(< @@ -648,17 +710,21 @@ $lt{'note'}. ENDCOURSESEARCH $scrout.=' '. &Apache::lonhtmlcommon::textbox('courseexp', - $ENV{'form.courseexp'},40); + $env{'form.courseexp'},40); my $crscheckbox = &Apache::lonhtmlcommon::checkbox('crsfulltext', - $ENV{'form.crsfulltext'}); + $env{'form.crsfulltext'}); my $relcheckbox = &Apache::lonhtmlcommon::checkbox('crsrelated', - $ENV{'form.crsrelated'}); + $env{'form.crsrelated'}); + my $discheckbox = + &Apache::lonhtmlcommon::checkbox('crsdiscuss', + $env{'form.crsrelated'}); $scrout.=(< -$relcheckbox $lt{'use'} -$crscheckbox $lt{'full'} + + +

 

@@ -666,13 +732,79 @@ ENDCOURSESEARCH 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 = ''; + if ($area eq 'res') { + $inclext= ''; + } + $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; +} + ###################################################################### ###################################################################### @@ -688,12 +820,9 @@ Prints the advanced search form. ###################################################################### sub print_advanced_search_form{ my ($r,$closebutton,$hidden_fields) = @_; - my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search'). - &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching', - 'Searching', - undef,undef, - ! $ENV{'form.launch'}); - + 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'); @@ -702,9 +831,24 @@ sub print_advanced_search_form{ $closebutton END - my $scrout=&search_html_header(); + 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"; -$bodytag +$bread_crumb

$advanced_buttons @@ -713,7 +857,7 @@ ENDHEADER ''; my %fields=&Apache::lonmeta::fieldnames(); # - $scrout .= '

'.&mt('Standard Metadata').'

'; + $scrout .= '

'.&mt('Standard [_1] Metadata',$srchtype).'

'; $scrout .= "\n"; $scrout .= '\n"; @@ -728,18 +872,20 @@ ENDHEADER 'abstract' => 1, 'standards'=> 1, 'mime' => 1, + 'subject' => 1, ); # - foreach my $field ('title','author','owner','authorspace','modifyinguser', - 'keywords','notes','abstract','standards','mime') { + foreach my $field ('title','author','subject','owner','authorspace', + 'modifyinguser','keywords','notes','abstract', + 'standards','mime') { $scrout.=''. ''.$/; $scrout.=''.$/; + $env{'form.domains'},1). + '
' + } + $scrout .= ''.$/; # # Misc metadata - $scrout.=''.$/; + if ($env{'form.area'} ne 'portfolio') { + $scrout.=''.$/; + } $scrout.=''; - $scrout .= "
 '. (' 'x2).&searchhelp()."
'.&titlefield($fields{$field}).''. &Apache::lonmeta::prettyinput($field, - $ENV{'form.'.$field}, + $env{'form.'.$field}, $field, 'advsearch', $related_word_search{$field}, '', - $ENV{'form.'.$field.'_related'}, + $env{'form.'.$field.'_related'}, 50); if ($related_word_search{$field}) { $scrout .= 'related words'; @@ -753,7 +899,7 @@ ENDHEADER ''.&titlefield($fields{$field}).''. &Apache::lonmeta::prettyinput($field, - $ENV{'form.'.$field}, + $env{'form.'.$field}, $field, 'advsearch', 0). @@ -762,86 +908,127 @@ ENDHEADER $scrout.='
'. &titlefield(&mt('MIME Type Category')).''. &Apache::loncommon::filecategoryselect('category', - $ENV{'form.category'}). + $env{'form.category'}). '
'. &titlefield(&mt('Domains')).''. &Apache::loncommon::domain_select('domains', - $ENV{'form.domains'},1). - '
'. - &titlefield(&mt('Copyright/Distribution')).''. - &Apache::lonmeta::selectbox('copyright', - '',, - \&Apache::loncommon::copyrightdescription, - ( undef, - &Apache::loncommon::copyrightids) - ).'
'. + &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', - 'notset',, + $env{'form.language'}, \&Apache::loncommon::languagedescription, ('any',&Apache::loncommon::languageids) ).'
\n"; - # - # 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=> - 'Total number of students who have worked on this problem',}, - { 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 .= ''.$/; + + + if ($env{'form.area'} eq 'portfolio') { + # Added fields + my $curnumadd = $env{'form.numaddedfields'}; + if ($curnumadd eq '') { + $curnumadd = 1; + } + $scrout .= '

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

'; + $scrout .= "
 '.&mt('Minimum').''.&mt('Maximum').'
'. - &titlefield(&mt($evaluation->{'description'})). - ''. - ''. - ''. - ''. - '
\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=> + 'Total number of students who have worked on this problem',}, + { 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"; } - $scrout .= "\n"; # # Creation/Modification date limits $scrout .= '

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

'; @@ -894,9 +1081,8 @@ ENDHEADER $scrout.=< - - ENDDOCUMENT + $scrout .= &Apache::loncommon::end_page(); $r->print($scrout); return; } @@ -943,7 +1129,9 @@ sub viewoptiontext { 'xml' => 'XML/SGML', 'compact' => 'Compact View', 'fielded' => 'Fielded Format', - 'summary' => 'Summary View'); + 'summary' => 'Summary View', + 'summarypreview' => 'Summary Preview', + 'detailedpreview' => 'Detailed Citation Preview'); return $desc{$code}; } @@ -964,16 +1152,16 @@ Outputs: text for box with view options ###################################################################### sub viewoptions { my $scrout; - if (! defined($ENV{'form.viewselect'})) { - $ENV{'form.viewselect'}='detailed'; + if (! defined($env{'form.viewselect'})) { + $env{'form.viewselect'}='detailed'; } $scrout.=&Apache::lonmeta::selectbox('viewselect', - $ENV{'form.viewselect'}, + $env{'form.viewselect'}, \&viewoptiontext, sort(keys(%Views))); $scrout.= '  '; my $countselect = &Apache::lonmeta::selectbox('show', - $ENV{'form.show'}, + $env{'form.show'}, undef, (10,20,50,100,1000,10000)); $scrout .= (' 'x2).&mt('[_1] Records per Page',$countselect). @@ -997,7 +1185,7 @@ Outputs: return little blurb on how to e ###################################################################### ###################################################################### sub searchhelp { - return &mt('Enter terms or phrases separated by AND, OR, or NOT'); + return &mt('Enter words and quoted phrases'); } ###################################################################### @@ -1013,7 +1201,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. @@ -1035,20 +1223,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); @@ -1088,7 +1276,7 @@ sub get_persistent_data { next; } my @values = map { - &Apache::lonnet::unescape($_); + &unescape($_); } split(',',$persistent_db{$name}); if (@values <= 1) { push @Values,$values[0]; @@ -1125,7 +1313,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); @@ -1153,9 +1341,9 @@ 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); } @@ -1188,13 +1376,13 @@ Parse advanced search form and return th sub parse_advanced_search { my ($r,$closebutton,$hidden_fields)=@_; my @BasicFields = ('title','author','subject','keywords','url','version', - 'notes','abstract','extension','owner', + 'notes','abstract','extension','owner','authorspace', # 'custommetadata','customshow', 'modifyinguser','standards','mime'); my @StatsFields = &statfields(); my @EvalFields = &evalfields(); my $fillflag=0; - my $pretty_search_string = "
\n"; + my $pretty_search_string = ""; # Clean up fields for safety for my $field (@BasicFields, 'creationdatestart_month','creationdatestart_day', @@ -1203,40 +1391,50 @@ sub parse_advanced_search { 'lastrevisiondatestart_month','lastrevisiondatestart_day', 'lastrevisiondatestart_year','lastrevisiondateend_month', 'lastrevisiondateend_day','lastrevisiondateend_year') { - $ENV{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g; - $ENV{'form.'.$field}=~s/(not\s*$|^\s*(and|or)|)//gi; + $env{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g; } foreach ('mode','form','element') { # is this required? Hmmm. - next if (! exists($ENV{'form.'.$_})); - $ENV{'form.'.$_}=&Apache::lonnet::unescape($ENV{'form.'.$_}); - $ENV{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g; + next if (! exists($env{'form.'.$_})); + $env{'form.'.$_}=&unescape($env{'form.'.$_}); + $env{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g; } # Preprocess the category form element. - $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) || - ref($ENV{'form.category'})); + $env{'form.category'} = 'any' if (! defined($env{'form.category'}) || + ref($env{'form.category'})); # # Check to see if enough information was filled in foreach my $field (@BasicFields) { - if (&filled($ENV{'form.'.$field})) { + if (&filled($env{'form.'.$field})) { $fillflag++; } } foreach my $field (@StatsFields,@EvalFields) { - if (&filled($ENV{'form.'.$field.'_max'})) { + if (&filled($env{'form.'.$field.'_max'})) { $fillflag++; } - if (&filled($ENV{'form.'.$field.'_min'})) { + if (&filled($env{'form.'.$field.'_min'})) { $fillflag++; } } for my $field ('lowestgradelevel','highestgradelevel') { - if ( $ENV{'form.'.$field} =~ /^\d+$/ && - $ENV{'form.'.$field} > 0) { + if ( $env{'form.'.$field} =~ /^\d+$/ && + $env{'form.'.$field} > 0) { $fillflag++; } } + if ($env{'form.area'} eq 'portfolio') { + # Added metadata fields + for (my $i=0; $i<$env{'form.numaddedfields'} ; $i++) { + my $field = $env{'form.addedfield_'.$i}; + $field =~ s/^\s*(\S*)\s*$/$1/; + $field =~ s/\W/_/g; + if ($field ne '') { + $fillflag++; + } + } + } if (! $fillflag) { &output_blank_field_error($r,$closebutton, 'phase=disp_adv',$hidden_fields); @@ -1248,95 +1446,131 @@ sub parse_advanced_search { my $font = ''; # Evaluate logical expression AND/OR/NOT phrase fields. foreach my $field (@BasicFields) { - if ($ENV{'form.'.$field}) { - my $searchphrase = $ENV{'form.'.$field}; - $pretty_search_string .= $font."$field contains ". - $searchphrase.""; - if ($ENV{'form.'.$field.'_related'}) { - my @New_Words; - ($searchphrase,@New_Words) = &related_version($searchphrase); - if (@New_Words) { - $pretty_search_string .= " with related words: ". - "@New_Words."; + next if (!defined($env{'form.'.$field}) || $env{'form.'.$field} eq ''); + my ($error,$SQLQuery) = + &process_phrase_input($env{'form.'.$field}, + $env{'form.'.$field.'_related'},$field); + if (defined($error)) { + &output_unparsed_phrase_error($r,$closebutton,'phase=disp_adv', + $hidden_fields,$field); + return; + } else { + $pretty_search_string .= + $font.$field.': '.$env{'form.'.$field}; + if ($env{'form.'.$field.'_related'}) { + my @Words = + &Apache::loncommon::get_related_words + ($env{'form.'.$field}); + if (@Words) { + $pretty_search_string.= ' with related words: '. + join(', ',@Words[0..4]); } else { - $pretty_search_string .= " with no related words."; + $pretty_search_string.= ' with related words.'; } } - $pretty_search_string .= "
\n"; - push @queries,&build_SQL_query($field,$searchphrase); + $pretty_search_string .= '
'; + push (@queries,$SQLQuery); } } # # Make the 'mime' from 'form.category' and 'form.extension' # my $searchphrase; - if (exists($ENV{'form.category'}) && - $ENV{'form.category'} !~ /^\s*$/ && - $ENV{'form.category'} ne 'any') { + if (exists($env{'form.category'}) && + $env{'form.category'} !~ /^\s*$/ && + $env{'form.category'} ne 'any') { my @extensions = &Apache::loncommon::filecategorytypes - ($ENV{'form.category'}); + ($env{'form.category'}); if (scalar(@extensions) > 0) { $searchphrase = join(' OR ',@extensions); } } if (defined($searchphrase)) { - push @queries,&build_SQL_query('mime',$searchphrase); + my ($error,$SQLsearch) = &process_phrase_input($searchphrase,0,'mime'); + push @queries,$SQLsearch; $pretty_search_string .=$font.'mime contains '. $searchphrase.'
'; } # # Evaluate option lists - if ($ENV{'form.lowestgradelevel'} && - $ENV{'form.lowestgradelevel'} ne '0' && - $ENV{'form.lowestgradelevel'} =~ /^\d+$/) { + if ($env{'form.lowestgradelevel'} && + $env{'form.lowestgradelevel'} ne '0' && + $env{'form.lowestgradelevel'} =~ /^\d+$/) { push(@queries, - '(lowestgradelevel>='.$ENV{'form.lowestgradelevel'}.')'); + '(lowestgradelevel>='.$env{'form.lowestgradelevel'}.')'); $pretty_search_string.="lowestgradelevel>=". - $ENV{'form.lowestgradelevel'}."
\n"; + $env{'form.lowestgradelevel'}."
\n"; } - if ($ENV{'form.highestgradelevel'} && - $ENV{'form.highestgradelevel'} ne '0' && - $ENV{'form.highestgradelevel'} =~ /^\d+$/) { + if ($env{'form.highestgradelevel'} && + $env{'form.highestgradelevel'} ne '0' && + $env{'form.highestgradelevel'} =~ /^\d+$/) { push(@queries, - '(highestgradelevel<='.$ENV{'form.highestgradelevel'}.')'); + '(highestgradelevel<='.$env{'form.highestgradelevel'}.')'); $pretty_search_string.="highestgradelevel<=". - $ENV{'form.highestgradelevel'}."
\n"; + $env{'form.highestgradelevel'}."
\n"; } - if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') { - push @queries,"(language like \"$ENV{'form.language'}\")"; + if ($env{'form.language'} and $env{'form.language'} ne 'any') { + push @queries,"(language like \"$env{'form.language'}\")"; $pretty_search_string.=$font."language= ". - &Apache::loncommon::languagedescription($ENV{'form.language'}). + &Apache::loncommon::languagedescription($env{'form.language'}). "
\n"; } - if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') { - push @queries,"(copyright like \"$ENV{'form.copyright'}\")"; + if ($env{'form.copyright'} and $env{'form.copyright'} ne 'any') { + push @queries,"(copyright like \"$env{'form.copyright'}\")"; $pretty_search_string.=$font."copyright = ". - &Apache::loncommon::copyrightdescription($ENV{'form.copyright'}). - "
\n"; + &Apache::loncommon::copyrightdescription($env{'form.copyright'}). + "
\n"; } - # - # Statistics - foreach my $field (@StatsFields,@EvalFields) { - my ($min,$max); - if (exists($ENV{'form.'.$field.'_min'}) && - $ENV{'form.'.$field.'_min'} ne '') { - $min = $ENV{'form.'.$field.'_min'}; - } - if (exists($ENV{'form.'.$field.'_max'}) && - $ENV{'form.'.$field.'_max'} ne '') { - $max = $ENV{'form.'.$field.'_max'}; - } - next if (! defined($max) && ! defined($min)); - if (defined($min) && defined($max)) { - ($min,$max) = sort {$a <=>$b} ($min,$max); - } - if (defined($min) && $min =~ /^(\d+\.\d+|\d+|\.\d+)$/) { - push(@queries,'('.$field.'>'.$min.')'); - $pretty_search_string.=$font.$field.'>'.$min.'
'; - } - if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) { - push(@queries,'('.$field.'<'.$max.')'); - $pretty_search_string.=$font.$field.'<'.$max.'
'; + if ($env{'form.area'} eq 'portfolio') { + # + # Added metadata fields + for (my $i=0; $i<$env{'form.numaddedfields'} ; $i++) { + my $field = $env{'form.addedfield_'.$i}; + $field =~ s/^\s*(\S*)\s*$/$1/; + $field =~ s/\W/_/g; + $field =~ tr/A-Z/a-z/; + if ($field ne '') { + my $value = $env{'form.addedvalues_'.$i}; + if ($value ne '') { + $value =~ s/'/''/g; #' stupid emacs + my ($error,$query) = + &process_phrase_input($value,0,'pf.value'); + if (!defined($error)) { + push(@queries,"pf.field = '$field' AND $query"); + $pretty_search_string .= + $font.$field.': '. + $env{'form.addedvalues_'.$i}.'
'; + } + } else { + push(@queries,"pf.field = '$field' AND pf.value IS NULL"); + } + } + } + } else { + # + # Statistics + foreach my $field (@StatsFields,@EvalFields) { + my ($min,$max); + if (exists($env{'form.'.$field.'_min'}) && + $env{'form.'.$field.'_min'} ne '') { + $min = $env{'form.'.$field.'_min'}; + } + if (exists($env{'form.'.$field.'_max'}) && + $env{'form.'.$field.'_max'} ne '') { + $max = $env{'form.'.$field.'_max'}; + } + next if (! defined($max) && ! defined($min)); + if (defined($min) && defined($max)) { + ($min,$max) = sort {$a <=>$b} ($min,$max); + } + if (defined($min) && $min =~ /^(\d+\.\d+|\d+|\.\d+)$/) { + push(@queries,'('.$field.'>'.$min.')'); + $pretty_search_string.=$font.$field.'>'.$min.'
'; + } + if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) { + push(@queries,'('.$field.'<'.$max.')'); + $pretty_search_string.=$font.$field.'<'.$max.'
'; + } } } # @@ -1377,17 +1611,17 @@ sub parse_advanced_search { ## because I was unable to figureout exactly how it worked and could ## not imagine people actually using it. MH ## - # if ($ENV{'form.custommetadata'}) { + # if ($env{'form.custommetadata'}) { # $pretty_search_string .=$font."Custom Metadata Search: ". - # $ENV{'form.custommetadata'}."
\n"; + # $env{'form.custommetadata'}."
\n"; # $customquery=&build_custommetadata_query('custommetadata', - # $ENV{'form.custommetadata'}); + # $env{'form.custommetadata'}); # } my $customshow=undef; - # if ($ENV{'form.customshow'}) { + # if ($env{'form.customshow'}) { # $pretty_search_string .=$font."Custom Metadata Display: ". - # $ENV{'form.customshow'}."
\n"; - # $customshow=$ENV{'form.customshow'}; + # $env{'form.customshow'}."
\n"; + # $customshow=$env{'form.customshow'}; # $customshow=~s/[^\w\s]//g; # my @fields=split(/\s+/,$customshow); # $customshow=join(" ",@fields); @@ -1395,33 +1629,33 @@ sub parse_advanced_search { ## ## Deal with restrictions to given domains ## - my ($libraries_to_query,$pretty_domains_string) = - &parse_domain_restrictions(); - $pretty_search_string .= $pretty_domains_string."
\n"; + my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions(); + if ($pretty_domains_string) { + $pretty_search_string .= $pretty_domains_string."
\n"; + } # if (@queries) { - $query="select * from metadata where ".join(" AND ",@queries); + if ($env{'form.area'} eq 'portfolio') { + $query ="SELECT pm.*,pa.keynum,pa.scope FROM portfolio_metadata pm, portfolio_access pa, portfolio_addedfields pf WHERE (pm.url = pa.url AND pf.url = pm.url AND (pa.start < NOW() AND (pa.end IS NULL OR pa.end > NOW())) AND (".join(') AND (',@queries).'))'; + } else { + $query="SELECT * FROM metadata WHERE (".join(") AND (",@queries).')'; + } } elsif ($customquery) { $query = ''; } -# &Apache::lonnet::logthis('query = '.$/.$query); + #&Apache::lonnet::logthis('advanced query = '.$/.$query); return ($query,$customquery,$customshow,$libraries_to_query, $pretty_search_string); } sub parse_domain_restrictions { my $libraries_to_query = undef; - # $ENV{'form.domains'} can be either a scalar or an array reference. + # $env{'form.domains'} can be either a scalar or an array reference. # We need an array. - if (! exists($ENV{'form.domains'}) || $ENV{'form.domains'} eq '') { - return (undef,''); - } - my @allowed_domains; - if (ref($ENV{'form.domains'})) { - @allowed_domains = @{$ENV{'form.domains'}}; - } else { - @allowed_domains = ($ENV{'form.domains'}); + if (! exists($env{'form.domains'}) || $env{'form.domains'} eq '') { + return (undef,'',undef); } + my @allowed_domains = &Apache::loncommon::get_env_multiple('form.domains'); # my %domain_hash = (); my $pretty_domains_string; @@ -1429,23 +1663,22 @@ sub parse_domain_restrictions { $domain_hash{$_}++; } if ($domain_hash{'any'}) { - $pretty_domains_string = "In all LON-CAPA domains."; + $pretty_domains_string = &mt("in all LON-CAPA domains."); } else { if (@allowed_domains > 1) { - $pretty_domains_string = "In LON-CAPA domains:"; + $pretty_domains_string = &mt("in LON-CAPA domains:"); } else { - $pretty_domains_string = "In LON-CAPA domain "; + $pretty_domains_string = &mt("in LON-CAPA domain "); } foreach (sort @allowed_domains) { $pretty_domains_string .= "".$_." "; } - foreach (keys(%Apache::lonnet::libserv)) { - if (exists($domain_hash{$Apache::lonnet::hostdom{$_}})) { - push @$libraries_to_query,$_; - } - } + my %servers = &Apache::lonnet::get_servers(\@allowed_domains, + 'library'); + $libraries_to_query = [keys(%servers)]; } - return ($libraries_to_query,$pretty_domains_string); + return ($libraries_to_query, + $pretty_domains_string); } ###################################################################### @@ -1466,52 +1699,243 @@ sub parse_basic_search { # # Clean up fields for safety for my $field ('basicexp') { - $ENV{"form.$field"}=~s/[^\w\s\(\)\-]//g; + $env{"form.$field"}=~s/[^\w\s\'\"\!\(\)\-]//g; } foreach ('mode','form','element') { # is this required? Hmmm. - next unless (exists($ENV{"form.$_"})); - $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"}); - $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g; + next unless (exists($env{"form.$_"})); + $env{"form.$_"}=&unescape($env{"form.$_"}); + $env{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g; } - my ($libraries_to_query,$pretty_domains_string) = - &parse_domain_restrictions(); + my ($libraries_to_query,$pretty_domains_string) = &parse_domain_restrictions(); # # Check to see if enough of a query is filled in - my $search_string = $ENV{'form.basicexp'}; - $search_string =~ s/(not\s*$|^\s*(and|or)|)//gi; + my $search_string = $env{'form.basicexp'}; if (! &filled($search_string)) { &output_blank_field_error($r,$closebutton,'phase=disp_basic'); return OK; } - my $pretty_search_string = ''.$ENV{'form.basicexp'}.''; - if ($ENV{'form.related'}) { - my @New_Words; - ($search_string,@New_Words) = &related_version($ENV{'form.basicexp'}); - if (@New_Words) { - $pretty_search_string .= " with related words: @New_Words."; - } else { - $pretty_search_string .= " with no related words."; - } + my $pretty_search_string=$search_string; + my @Queries; + my @fields = ('title','author','subject','notes','abstract','keywords'); + my $searchfield; + if ($env{'form.area'} eq 'portfolio') { + $searchfield = 'concat_ws(" ",pm.'.join(',pm.',@fields).')'; + } else { + $searchfield = 'concat_ws(" ",'.join(',',@fields).')'; + } + my ($error,$SQLQuery) = &process_phrase_input($search_string, + $env{'form.related'}, + $searchfield); + if ($error) { + &output_unparsed_phrase_error($r,$closebutton,'phase=disp_basic', + '','basicexp'); + return; + } + push(@Queries,$SQLQuery); + #foreach my $q (@Queries) { + # &Apache::lonnet::logthis(' '.$q); + #} + my $final_query; + if ($env{'form.area'} eq 'portfolio') { + $final_query = 'SELECT pm.*,pa.keynum,pa.scope FROM portfolio_metadata pm, portfolio_access pa WHERE (pm.url = pa.url AND (pa.start < NOW() AND (pa.end IS NULL OR pa.end > NOW())) AND '.join(" AND ",@Queries).')'; + } else { + $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries); } # - # Build SQL query string based on form page - my $query=''; - my $concatarg=join(',', - ('title', 'author', 'subject', 'notes', 'abstract', - 'keywords')); - $concatarg='title' if $ENV{'form.titleonly'}; - $query=&build_SQL_query('concat_ws(" ",'.$concatarg.')',$search_string); + if ($env{'form.related'}) { + $pretty_search_string.=' '.&mt('(including related words)'); + } if (defined($pretty_domains_string) && $pretty_domains_string ne '') { $pretty_search_string .= ' '.$pretty_domains_string; } $pretty_search_string .= "
\n"; - my $final_query = 'SELECT * FROM metadata WHERE '.$query; - # &Apache::lonnet::logthis($final_query); + $pretty_search_string =~ s:^
and ::; + &Apache::lonnet::logthis('simple search final query = '.$/.$final_query); return ($final_query,$pretty_search_string, $libraries_to_query); } + +############################################################### +############################################################### + +my @Phrases; + +sub concat { + my ($item) = @_; + my $results = ''; + foreach (@$item) { + if (ref($_) eq 'ARRAY') { + $results .= join(' ',@$_); + } + } + return $results; +} + +sub process_phrase_input { + my ($phrase,$related,$field)=@_; + #&Apache::lonnet::logthis('phrase = :'.$phrase.':'); + my $grammar = <<'ENDGRAMMAR'; + searchphrase: + expression /^\Z/ { + # &Apache::lonsearchcat::print_item(\@item,0); + [@item]; + } + expression: + phrase(s) { + [@item]; + } + phrase: + orword { + [@item]; + } + | andword { + [@item]; + } + | minusword { + unshift(@::Phrases,$item[1]->[0]); + unshift(@::Phrases,$item[1]->[1]); + [@item]; + } + | word { + unshift(@::Phrases,$item[1]); + [@item]; + } + # + orword: + word 'OR' phrase { + unshift(@::Phrases,'OR'); + unshift(@::Phrases,$item[1]); + [@item]; + } + | word 'or' phrase { + unshift(@::Phrases,'OR'); + unshift(@::Phrases,$item[1]); + [@item]; + } + | minusword 'OR' phrase { + unshift(@::Phrases,'OR'); + unshift(@::Phrases,$item[1]->[0]); + unshift(@::Phrases,$item[1]->[1]); + [@item]; + } + | minusword 'or' phrase { + unshift(@::Phrases,'OR'); + unshift(@::Phrases,$item[1]->[0]); + unshift(@::Phrases,$item[1]->[1]); + [@item]; + } + andword: + word phrase { + unshift(@::Phrases,'AND'); + unshift(@::Phrases,$item[1]); + [@item]; + } + | minusword phrase { + unshift(@::Phrases,'AND'); + unshift(@::Phrases,$item[1]->[0]); + unshift(@::Phrases,$item[1]->[1]); + [@item]; + } + # + minusword: + '-' word { + [$item[2],'NOT']; + } + word: + "'" term(s) "'" { + &Apache::lonsearchcat::concat(\@item); + } + | '"' term(s) '"' { + &Apache::lonsearchcat::concat(\@item); + } + | term { + $item[1]; + } + term: + /[\w\Q:!@#$%^&*()+_=|{}<>,.;\\\/?\E]+/ { + $item[1]; + } +ENDGRAMMAR + # + # The end result of parsing the phrase with the grammar is an array + # @::Phrases. + # $phrase = "gene splicing" or cat -> "gene splicing","OR","cat" + # $phrase = "genetic engineering" -dna -> + # "genetic engineering","AND","NOT","dna" + # $phrase = cat or dog -poodle -> "cat","OR","dog","AND","NOT","poodle" + undef(@::Phrases); + my $p = new Parse::RecDescent($grammar); + if (! defined($p->searchphrase($phrase))) { + &Apache::lonnet::logthis('lonsearchcat:unable to process:'.$phrase); + return 'Unable to process phrase '.$phrase; + } + # + # Go through the phrases and make sense of them. + # Apply modifiers NOT OR and AND to the phrases. + my @NewPhrases; + while(@::Phrases) { + my $phrase = shift(@::Phrases); + # &Apache::lonnet::logthis('phrase = '.$phrase); + my $phrasedata; + if ($phrase =~ /^(NOT|OR|AND)$/) { + if ($phrase eq 'OR') { + $phrasedata->{'or'}++; + if (! @::Phrases) { $phrasedata = undef; last; } + $phrase = shift(@::Phrases); + } elsif ($phrase eq 'AND') { + $phrasedata->{'and'}++; + if (! @::Phrases) { $phrasedata = undef; last; } + $phrase = shift(@::Phrases); + } + if ($phrase eq 'NOT') { + $phrasedata->{'negate'}++; + if (! @::Phrases) { $phrasedata = undef; last; } + $phrase = shift(@::Phrases); + } + } + $phrasedata->{'phrase'} = $phrase; + if ($related) { + my @NewWords; + (undef,@NewWords) = &related_version($phrasedata->{'phrase'}); + $phrasedata->{'related_words'} = \@NewWords; + } + push(@NewPhrases,$phrasedata); + } + # + # Actually build the sql query from the phrases + my $SQLQuery; + foreach my $phrase (@NewPhrases) { + my $query; + if ($phrase->{'negate'}) { + $query .= $field.' NOT LIKE "%'.$phrase->{'phrase'}.'%"'; + } else { + $query .= $field.' LIKE "%'.$phrase->{'phrase'}.'%"'; + } + foreach my $related (@{$phrase->{'related_words'}}) { + if ($phrase->{'negate'}) { + $query .= ' AND '.$field.' NOT LIKE "%'.$related.'%"'; + } else { + $query .= ' OR '.$field.' LIKE "%'.$related.'%"'; + } + } + if ($SQLQuery) { + if ($phrase->{'or'}) { + $SQLQuery .= ' OR ('.$query.')'; + } else { + $SQLQuery .= ' AND ('.$query.')'; + } + } else { + $SQLQuery = '('.$query.')'; + } + } + # + # &Apache::lonnet::logthis("SQLQuery = $SQLQuery"); + # + return undef,$SQLQuery; +} + ###################################################################### ###################################################################### @@ -1530,45 +1954,15 @@ Note: Using this twice on a string is pr ###################################################################### ###################################################################### sub related_version { - my $search_string = shift; - my $result = $search_string; - my %New_Words = (); - while ($search_string =~ /(\w+)/cg) { - my $word = $1; - next if (lc($word) =~ /\b(or|and|not)\b/); - my @Words = &Apache::loncommon::get_related_words($word); - @Words = ($#Words>4? @Words[0..4] : @Words); - foreach (@Words) { $New_Words{$_}++;} - my $replacement = join " OR ", ($word,@Words); - $result =~ s/(\b)$word(\b)/$1($replacement)$2/g; - } - return $result,sort(keys(%New_Words)); + my ($word) = @_; + return (undef) if (lc($word) =~ /\b(or|and|not)\b/); + my @Words = &Apache::loncommon::get_related_words($word); + # Only use 4 related words + @Words = ($#Words>4? @Words[0..4] : @Words); + my $result = join " OR ", ($word,@Words); + return $result,sort(@Words); } -###################################################################### -###################################################################### - -=pod - -=item &build_SQL_query() - -Builds a SQL query string from a logical expression with AND/OR keywords -using Text::Query and &recursive_SQL_query_builder() - -=cut - -###################################################################### -###################################################################### -sub build_SQL_query { - my ($field_name,$logic_statement)=@_; - my $q=new Text::Query('abc', - -parse => 'Text::Query::ParseAdvanced', - -build => 'Text::Query::Build'); - $q->prepare($logic_statement); - my $matchexp=${$q}{'matchexp'}; chomp $matchexp; - my $sql_query=&recursive_SQL_query_build($field_name,$matchexp); - return $sql_query; -} ###################################################################### ###################################################################### @@ -1603,47 +1997,6 @@ sub build_custommetadata_query { return $matchexp; } -###################################################################### -###################################################################### - -=pod - -=item &recursive_SQL_query_build() - -Recursively constructs an SQL query. Takes as input $dkey and $pattern. - -=cut - -###################################################################### -###################################################################### -sub recursive_SQL_query_build { - my ($dkey,$pattern)=@_; - my @matches=($pattern=~/(\[[^\]|\[]*\])/g); - return $pattern unless @matches; - foreach my $match (@matches) { - $match=~/\[ (\w+)\s(.*) \]/; - my ($key,$value)=($1,$2); - my $replacement=''; - if ($key eq 'literal') { - $replacement="($dkey LIKE \"\%$value\%\")"; - } elsif (lc($key) eq 'not') { - $value=~s/LIKE/NOT LIKE/; -# $replacement="($dkey not like $value)"; - $replacement="$value"; - } elsif ($key eq 'and') { - $value=~/(.*[\"|\)]) ([|\(|\^].*)/; - $replacement="($1 AND $2)"; - } elsif ($key eq 'or') { - $value=~/(.*[\"|\)]) ([|\(|\^].*)/; - $replacement="($1 OR $2)"; - } - substr($pattern, - index($pattern,$match), - length($match), - $replacement); - } - &recursive_SQL_query_build($dkey,$pattern); -} ###################################################################### ###################################################################### @@ -1752,13 +2105,13 @@ sub copyright_check { $Metadata->{'url'}); # Check for priv if (($Metadata->{'copyright'} eq 'priv') && - (($ENV{'user.name'} ne $resname) && - ($ENV{'user.domain'} ne $resdom))) { + (($env{'user.name'} ne $resname) && + ($env{'user.domain'} ne $resdom))) { return 0; } # Check for domain if (($Metadata->{'copyright'} eq 'domain') && - ($ENV{'user.domain'} ne $resdom)) { + ($env{'user.domain'} ne $resdom)) { return 0; } return 1; @@ -1790,7 +2143,7 @@ sub ensure_db_and_table { if (! defined($table) || $table eq '' || $table =~ /\D/ ) { $r->print("Unable to retrieve search results. ". "Unable to determine the table results were stored in. ". - ""); + &Apache::loncommon::end_page()); return undef; } ## @@ -1799,7 +2152,8 @@ sub ensure_db_and_table { my $connection_result = &Apache::lonmysql::connect_to_db(); if (!defined($connection_result)) { $r->print("Unable to connect to the MySQL database where your results". - " are stored. "); + " are stored.". + &Apache::loncommon::end_page()); &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to". " connect to database."); &Apache::lonnet::logthis(&Apache::lonmysql::get_error()); @@ -1807,7 +2161,8 @@ sub ensure_db_and_table { } my $table_check = &Apache::lonmysql::check_table($table); if (! defined($table_check)) { - $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 status". " of table ".$table); return undef; @@ -1836,7 +2191,7 @@ a link to change the search query. ###################################################################### sub print_sort_form { my ($r,$pretty_query_string) = @_; - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); + ## my %SortableFields=&Apache::lonlocal::texthash( id => 'Default', @@ -1854,45 +2209,52 @@ 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: connection; # # 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: [_1]",$pretty_string)); $r->rflush(); @@ -2137,17 +2515,19 @@ END my %Server_status; # # Check on the mysql table we will use to store results. - my $table =$ENV{'form.table'}; + 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."); + "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; @@ -2159,12 +2539,14 @@ END &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(); @@ -2172,7 +2554,7 @@ END - + @@ -2211,15 +2593,16 @@ END # # 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,&mt('Receiving results from [_1]',$server)); next; @@ -2247,11 +2630,20 @@ END 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 if external and we did not want that + next if ((! $env{'form.inclext'}) && ($Fields{'url'}=~/^\/ext\//)); # 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); @@ -2284,14 +2676,14 @@ END # We have run out of time or run out of servers to talk to and # results to get, so let the client know the top frame needs to be # loaded from /adm/searchcat - $r->print(""); - if ($ENV{'form.catalogmode'} ne 'groupsearch') { + $r->print(&Apache::loncommon::end_page()); +# if ($env{'form.catalogmode'} ne 'import') { $r->print(""); - } +# } return; } @@ -2338,13 +2730,13 @@ Prints the results out for selection and ###################################################################### ###################################################################### sub display_results { - my ($r,$importbutton,$closebutton,$diropendb) = @_; + my ($r,$importbutton,$closebutton,$diropendb,$area) = @_; my $connection = $r->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(); @@ -2352,31 +2744,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 by opening the groupsearch db file. - 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 store 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()); @@ -2384,21 +2778,21 @@ sub display_results { } ## ## Determine how many results we need to get - $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'}; + $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); } ## @@ -2406,37 +2800,146 @@ sub display_results { $r->print(&hidden_field('table'). &hidden_field('phase'). &hidden_field('persistent_db_id'). - &hidden_field('start') + &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 - ('
StatusTotal MatchesTime Remaining
$revise
'. - &prev_next_buttons($min,$ENV{'form.show'},$total_results). + ('
'. + ''.$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'; @@ -2454,15 +2957,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; @@ -2476,7 +2979,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 @@ -2485,16 +2988,16 @@ $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.=<{'name'}}=&Apache::lonnet::unescape($Row[$i]); + $Fields{$Datatypes[$i]->{'name'}}=&unescape($Row[$i]); } $Fields{'language'} = &Apache::loncommon::languagedescription($Fields{'language'}); @@ -2559,12 +3062,13 @@ The 'title' field is set to "Untitled" i ########################################################### ########################################################### sub parse_raw_result { - my ($result,$hostname) = @_; + my ($result,$hostname,$tabletype) = @_; # conclude from self to others regarding fields my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash - (map { - &Apache::lonnet::unescape($_); - } (split(/\,/,$result)) ); + ($tabletype, + map { + &unescape($_); + } (split(/\,/,$result)) ); return %Fields; } @@ -2584,8 +3088,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 { "$_:"; @@ -2601,7 +3105,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; } @@ -2619,7 +3123,7 @@ sub handle_custom_fields { 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 @@ -2633,7 +3137,7 @@ The following environment variables are =item 'form.catalogmode' -Checked for 'interactive' and 'groupsearch'. +Checked for 'interactive' and 'import'. =item 'form.mode' @@ -2659,14 +3163,14 @@ the name of the input field to put the t ###################################################################### sub search_results_header { my ($importbutton,$closebutton) = @_; - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); - 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); @@ -2685,10 +3189,10 @@ sub search_results_header { } SCRIPT - } elsif ($ENV{'form.mode'} eq 'edit') { - my $form = $ENV{'form.form'}; - my $element = $ENV{'form.element'}; - my $titleelement = $ENV{'form.titleelement'}; + } elsif ($env{'form.mode'} eq 'edit') { + my $form = $env{'form.form'}; + my $element = $env{'form.element'}; + my $titleelement = $env{'form.titleelement'}; my $changetitle; if (!$titleelement) { $changetitle='function changeTitle(val) {}'; @@ -2705,7 +3209,7 @@ function changeTitle(val) { END } - $result.=< function select_data(title,url) { changeURL(url); @@ -2725,56 +3229,45 @@ 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 { - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); - 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; @@ -2784,24 +3277,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); @@ -2811,6 +3311,41 @@ 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 @@ -2833,10 +3368,12 @@ extra custom metadata to show. sub detailed_citation_view { my ($prefix,%values) = @_; my $result; + my $jumpurl=$values{'url'}; + $jumpurl=~s|^/ext/|http://|; $result .= ''.$prefix. - ''.' '. - ''.$values{'title'}."\n"; + ''.' '. + ''.$values{'title'}."\n"; $result .= "

\n"; $result .= ''.$values{'author'}.','. ' '.$values{'owner'}.'
'; @@ -2858,41 +3395,77 @@ sub detailed_citation_view { { 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', - translate => 'Correcy: [_1]',}, + 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',}, ) { - if (exists($values{$field->{'name'}}) && - $values{$field->{'name'}} ne '') { + 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'}})){ + $result .= + &Apache::lonhtmlcommon::crumbs(&Apache::lonnet::clutter($item), + 'preview', + '', + (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),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.= - &mt($field->{'translate'}, - ''. - $values{$field->{'name'}}. - ''); + if ($jumpurl=~/^http\:\/\//) { + $result.=''.$jumpurl.''; + } else { + $result .= + &Apache::lonhtmlcommon::crumbs($jumpurl, + 'preview', + '', + (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),3,0,1); + } } else { $result.= &mt($field->{'translate'}, $values{$field->{'name'}}); } $result .= "
\n"; - } + } } $result .= "

"; if (exists($values{'extrashow'}) && $values{'extrashow'} ne '') { @@ -2905,40 +3478,15 @@ sub detailed_citation_view { return $result; } -###################################################################### -###################################################################### - -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 detailed_citation_preview { + my ($prefix,%values)=@_; + return '
'. + &detailed_citation_view($prefix,%values). + ''. + &Apache::lonindexer::showpreview($values{'url'}). + '

'; } -sub evalfields { - return ('clear','technical','correct','helpful','depth'); -} ###################################################################### ###################################################################### @@ -2953,12 +3501,34 @@ sub evalfields { sub summary_view { my ($prefix,%values) = @_; my $icon=&Apache::loncommon::icon($values{'url'}); - my $result=<  -$values{'author'}
-$values{'title'}
-$values{'owner'} -- $values{'lastrevisiondate'}
+ 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'}; + my $link; + if ($jumpurl=~m|^/ext/|) { + $jumpurl=~s|^/ext/|http://|; + $link='
'.$jumpurl.''; + } else { + $link=&Apache::lonhtmlcommon::crumbs($jumpurl, + 'preview', + '', + (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),2,0,1); + } + $result.=<$values{'title'}$link +$values{'author'}, $values{'owner'} -- $values{'lastrevisiondate'}
$values{'copyrighttag'}
$values{'extrashow'}

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

'; +} + ###################################################################### ###################################################################### @@ -2980,11 +3559,28 @@ END ###################################################################### sub compact_view { my ($prefix,%values) = @_; + my $jumpurl=$values{'url'}; + my $link; + if ($jumpurl=~m|^/ext/|) { + $jumpurl=~s|^/ext/|http://|; + $link=''.$jumpurl.''; + } else { + $link=&Apache::lonhtmlcommon::crumbs($jumpurl, + 'preview', + '', + (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),1,1,1).' '; + } my $result = - $prefix.' '. - $values{'title'}.''.(' 'x2). - ''.$values{'author'}.'
'; + $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.' '; + } + $result.=' '. + $values{'title'}.''.(' 'x2).$link. + ''.$values{'author'}.' ('.$values{'domain'}.')
'; return $result; } @@ -3004,14 +3600,17 @@ 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'}
+
$values{'url'}
END - foreach my $field ('title','author','subject','keywords','notes', + foreach my $field ('title','author','domain','subject','keywords','notes', 'mimetag','language','creationdate','lastrevisiondate', 'owner','copyrighttag','hostname','abstract') { $result .= (' 'x4).'
'.$Translated{$field}.'
'."\n". @@ -3052,7 +3651,7 @@ sub xml_sgml_view { my ($prefix,%values) = @_; my $xml = ''."\n"; # The usual suspects - foreach my $field ('url','title','author','subject','keywords','notes') { + foreach my $field ('url','title','author','subject','keywords','notes','domain') { $xml .= qq{<$field>$values{$field}}."\n"; } # @@ -3135,6 +3734,47 @@ sub filled { =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 +} + +###################################################################### +###################################################################### + +=pod + =item &output_blank_field_error() Output a complete page that indicates the user has not filled in enough @@ -3152,33 +3792,27 @@ $parms is extra information to include i ###################################################################### sub output_blank_field_error { my ($r,$closebutton,$parms,$hidden_fields)=@_; - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); - # make query information persistent to allow for subsequent revision - $r->print(< - -The LearningOnline Network with CAPA -BEGINNING - $r->print(< -$bodytag - -

Search Catalog

+ 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; } ###################################################################### @@ -3203,15 +3837,10 @@ Inputs: sub output_date_error { my ($r,$message,$closebutton,$hidden_fields)=@_; # make query information persistent to allow for subsequent revision - my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); + 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 } @@ -3263,6 +3891,7 @@ sub cleanup { } &untiehash(); &Apache::lonmysql::disconnect_from_db(); + return OK; } __END__