--- loncom/interface/lonsearchcat.pm 2006/06/08 13:56:31 1.267
+++ loncom/interface/lonsearchcat.pm 2025/03/19 15:44:44 1.364
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Search Catalog
#
-# $Id: lonsearchcat.pm,v 1.267 2006/06/08 13:56:31 www Exp $
+# $Id: lonsearchcat.pm,v 1.364 2025/03/19 15:44:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -52,8 +52,6 @@ search (on a server basis) is displayed
=head1 Internals
-=over 4
-
=cut
###############################################################################
@@ -78,8 +76,9 @@ use HTML::Entities();
use Parse::RecDescent;
use Apache::lonnavmaps;
use Apache::lonindexer();
-use lib '/home/httpd/lib/perl/';
+use Apache::lonwishlist();
use LONCAPA;
+use Time::HiRes qw(sleep);
######################################################################
######################################################################
@@ -119,8 +118,6 @@ sub handler {
# This is set and used in &handler() and is also used in
# &output_results().
- my $loaderror=&Apache::lonnet::overloaderror($r);
- if ($loaderror) { return $loaderror; }
#
my $closebutton; # button that closes the search window
# This button is different for the RAT compared to
@@ -139,7 +136,7 @@ sub handler {
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['catalogmode','launch','acts','mode','form','element','pause',
'phase','persistent_db_id','table','start','show',
- 'cleargroupsort','titleelement']);
+ 'cleargroupsort','titleelement','area','inhibitmenu']);
##
## The following is a trick - we wait a few seconds if asked to so
## the daemon running the search can get ahead of the daemon
@@ -147,14 +144,15 @@ sub handler {
## this once, so the pause indicator is deleted
##
if (exists($env{'form.pause'})) {
- sleep(1);
+ sleep(0.1);
delete($env{'form.pause'});
}
##
## Initialize global variables
##
my $domain = $r->dir_config('lonDefDomain');
- $diropendb= "/home/httpd/perl/tmp/".
+ my $temp_file_dir = LONCAPA::tempdir();
+ $diropendb= $temp_file_dir .
"$env{'user.domain'}_$env{'user.name'}_sel_res.db";
#
# set the name of the persistent database
@@ -165,31 +163,54 @@ sub handler {
$env{'form.persistent_db_id'} = time;
}
- my $persistent_db_file = "/home/httpd/perl/tmp/".
+ my $persistent_db_file = $temp_file_dir .
&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",
- target=>'_top',
- bug=>'Searching',});
+
+ my $crumb_text;
+ my @allowed_searches;
+ if ($env{'form.catalogmode'} eq 'import') {
+ $env{'form.area'} = 'res';
+ $crumb_text = 'Content Library Search';
} else {
- &Apache::lonhtmlcommon::add_breadcrumb
- ({href=>'/adm/searchcat?'.
- 'catalogmode='.$env{'form.catalogmode'}.
- '&launch='.$env{'form.launch'}.
- '&mode='.$env{'form.mode'},
- text=>"Catalog Search",
- target=>'_top',
- bug=>'Searching',});
+ push(@allowed_searches,'portfolio');
}
+ if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'}) eq 'F') {
+ push(@allowed_searches,'res');
+ } else {
+ unless ($env{'form.catalogmode'} eq 'import') {
+ $env{'form.area'} = 'portfolio';
+ $crumb_text = 'Portfolio Search';
+ }
+ }
+ if (@allowed_searches ==2) {
+ unless (($env{'form.area'} eq 'portfolio') || ($env{'form.area'} eq 'res')) {
+ delete($env{'form.area'});
+ }
+ $crumb_text = 'Portfolio and Content Library Search';
+ }
+ my $target = '_top';
+ if ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) ||
+ (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) {
+ if ($env{'form.phase'} =~ /^(sort|run_search)$/) {
+ $target = '_parent';
+ } else {
+ $target = '_self';
+ }
+ }
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>'/adm/searchcat?'.
+ &Apache::loncommon::inhibit_menu_check().
+ '&catalogmode='.$env{'form.catalogmode'}.
+ '&launch='.$env{'form.launch'}.
+ '&mode='.$env{'form.mode'}.
+ '&area='.$env{'form.area'},
+ text=>"$crumb_text",
+ target=>$target,
+ bug=>'Searching',});
#
if ($env{'form.phase'} !~ m/(basic|adv|course)_search/) {
if (! &get_persistent_form_data($persistent_db_file)) {
@@ -197,12 +218,15 @@ sub handler {
&Apache::lonnet::logthis('lonsearchcat:'.
'Unable to recover data from '.
$persistent_db_file);
- my $msg =
- 'We were unable to retrieve data describing your search. '.
- 'This is a serious error and has been logged. '.
- 'Please alert your LON-CAPA administrator.';
- &Apache::loncommon::simple_error_page($r,'Search Error',
- $msg);
+ my $msg =
+ &mt('We were unable to retrieve data describing your search.').
+ ' '.&mt('This is a serious error and has been logged.').
+ '
'.
+ &mt('Please alert your LON-CAPA administrator.');
+ &Apache::loncommon::simple_error_page(
+ $r,'Search Error',
+ $msg,
+ {'no_auto_mt_msg' => 1});
return OK;
}
}
@@ -249,28 +273,35 @@ sub handler {
if (exists($env{'form.mode'})) {
$hidden_fields .= &hidden_field('mode');
}
+ if (exists($env{'form.area'})) {
+ $hidden_fields .= &hidden_field('area');
+ }
+ if (exists($env{'form.inhibitmenu'})) {
+ $hidden_fields .= &hidden_field('inhibitmenu');
+ }
##
## Configure dynamic components of interface
##
if ($env{'form.catalogmode'} eq 'interactive') {
- $closebutton="
+
END
} else {
$closebutton = '';
@@ -289,26 +320,34 @@ END
if ($env{'form.phase'} eq 'adv_search' ||
$env{'form.phase'} eq 'disp_adv') {
$env{'form.searchmode'} = 'advanced';
- } elsif ($env{'form.phase'} eq 'course_search') {
- $env{'form.searchmode'} = 'course_search';
}
#
if ($env{'form.searchmode'} eq 'advanced') {
+ my $srchtype = 'Content Library';
+ if ($env{'form.area'} eq 'portfolio') {
+ $srchtype = 'Portfolio';
+ }
&Apache::lonhtmlcommon::add_breadcrumb
- ({href=>'/adm/searchcat?phase=disp_adv&'.
- 'catalogmode='.$env{'form.catalogmode'}.
- '&launch='.$env{'form.launch'}.
- '&mode='.$env{'form.mode'},
- text=>"Advanced Search",
+ ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check().
+ '&phase=disp_adv'.
+ '&catalogmode='.$env{'form.catalogmode'}.
+ '&launch='.$env{'form.launch'}.
+ '&mode='.$env{'form.mode'}.
+ '&area='.$env{'form.area'},
+ text=>"Advanced $srchtype Search",
bug=>'Searching',});
- } elsif ($env{'form.searchmode'} eq 'course search') {
+ } elsif (($env{'form.phase'} eq 'results') ||
+ ($env{'form.phase'} =~ /^(sort|run_search)$/)) {
&Apache::lonhtmlcommon::add_breadcrumb
- ({href=>'/adm/searchcat?phase=disp_adv&'.
- 'catalogmode='.$env{'form.catalogmode'}.
- '&launch='.$env{'form.launch'}.
- '&mode='.$env{'form.mode'},
- text=>"Course Search",
- bug=>'Searching',});
+ ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check().
+ '&phase=disp_adv'.
+ '&catalogmode='.$env{'form.catalogmode'}.
+ '&launch='.$env{'form.launch'}.
+ '&mode='.$env{'form.mode'}.
+ '&area='.$env{'form.area'}.
+ '&searchmode='.$env{'form.searchmode'},
+ text=>"Search Results",
+ bug=>'Searching',});
}
##
## Switch on the phase
@@ -318,35 +357,34 @@ END
} 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);
+ &display_results($r,$importbutton,$closebutton,$diropendb,
+ $env{'form.area'});
} elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) {
- my ($query,$customquery,$customshow,$libraries,$pretty_string) =
+ my ($query,$customquery,$customshow,$libraries,$pretty_string,$domainsref) =
&get_persistent_data($persistent_db_file,
['query','customquery','customshow',
- 'libraries','pretty_string']);
+ 'libraries','pretty_string','domains']);
if ($env{'form.phase'} eq 'sort') {
- &print_sort_form($r,$pretty_string);
+ &print_sort_form($r,$pretty_string,$target);
} elsif ($env{'form.phase'} eq 'run_search') {
&run_search($r,$query,$customquery,$customshow,
- $libraries,$pretty_string);
+ $libraries,$pretty_string,$env{'form.area'},$domainsref,$target);
}
- } elsif ($env{'form.phase'} eq 'course_search') {
- &course_search($r);
} elsif(($env{'form.phase'} eq 'basic_search') ||
($env{'form.phase'} eq 'adv_search')) {
#
# We are running a search, try to parse it
- my ($query,$customquery,$customshow,$libraries) =
- (undef,undef,undef,undef);
+ my ($query,$customquery,$customshow,$libraries,$domains) =
+ (undef,undef,undef,undef,undef);
my $pretty_string;
if ($env{'form.phase'} eq 'basic_search') {
- ($query,$pretty_string,$libraries) =
+ ($query,$pretty_string,$libraries,$domains) =
&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)
+ ($query,$customquery,$customshow,$libraries,$pretty_string,$domains)
= &parse_advanced_search($r,$closebutton,$hidden_fields);
return OK if (! defined($query));
}
@@ -354,18 +392,19 @@ END
customquery => $customquery,
customshow => $customshow,
libraries => $libraries,
- pretty_string => $pretty_string },
+ pretty_string => $pretty_string,
+ domains => $domains },
$persistent_db_file);
#
# Set up table
- if (! defined(&create_results_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. '.
+ 'Unable to create table in which to save search results. '.
'The search has been aborted.';
&Apache::loncommon::simple_error_page($r,'Search Error',
$msg);
@@ -374,7 +413,7 @@ END
delete($env{'form.launch'});
if (! &make_form_data_persistent($r,$persistent_db_file)) {
my $msg=
- 'Unable to properly store search information. '.
+ 'Unable to properly save search information. '.
'The search has been aborted.';
&Apache::loncommon::simple_error_page($r,'Search Error',
$msg);
@@ -388,7 +427,7 @@ END
}
}
return OK;
-}
+}
#
# The mechanism used to store values away and retrieve them does not
@@ -426,230 +465,48 @@ sub hidden_field {
return ''.$/;
}
-######################################################################
-######################################################################
-##
-## Course Search
-##
-######################################################################
-######################################################################
-{ # Scope the course search to avoid global variables
-#
-# Variables For course search
-my %alreadyseen;
-my %hash;
-my $totalfound;
-
-sub make_symb {
- my ($id)=@_;
- my ($mapid,$resid)=split(/\./,$id);
- my $map=$hash{'map_id_'.$mapid};
- my $res=$hash{'src_'.$id};
- my $symb=&Apache::lonnet::encode_symb($map,$resid,$res);
- return $symb;
-}
-
-sub course_search {
- my $r=shift;
- my $pretty_search_string = ''.$env{'form.courseexp'}.'';
- my $search_string = $env{'form.courseexp'};
- my @New_Words;
- 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 $discuss=$env{'form.crsdiscuss'};
- my @allwords=($search_string,@New_Words);
- $totalfound=0;
- $r->print(&Apache::loncommon::start_page('Course Search').
- '
'.&mt('No matches found in resources').'.
'); - } - -# Check discussions if requested - if ($discuss) { - my $totaldiscussions = 0; - $r->print(''.&mt('No matches found in postings').'.
'); - } - } - -# =================================================== Done going through course - $r->print(&Apache::loncommon::end_page()); -} - -# =============================== This pulls up a resource and its dependencies - -sub checkonthis { - my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_; - $alreadyseen{$id}=1; - if (&Apache::loncommon::connection_aborted($r)) { return; } - $r->rflush(); - - 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; - $applies = &checkwords($result,$applies,@allwords); -# Does this resource apply? - if ($applies) { - $r->print(''. + &mt('Unable to save import results.'). + '
'. + ''. &Apache::loncommon::end_page()); $r->rflush(); return; } + # untie %groupsearch_db if the connection gets aborted before the end + $r->register_cleanup(sub { + untie %groupsearch_db if (tied(%groupsearch_db)); + }); } ## ## Prepare the table for querying @@ -2619,7 +2833,10 @@ sub display_results { ## 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(''. + &mt('A MySQL error has occurred.'). + '
'. + ''. &Apache::loncommon::end_page()); &Apache::lonnet::logthis("lonmysql was unable to determine the number". " of rows in table ".$table); @@ -2650,7 +2867,8 @@ 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 @@ -2671,6 +2889,16 @@ sub display_results { {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'}, @@ -2681,7 +2909,8 @@ sub display_results { {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) { @@ -2698,7 +2927,13 @@ sub display_results { my %sort_fields = map {$_->{'key'},$_->{'desc'}} @fields; $sort_fields{'select_form_order'} = \@field_order; $env{'form.sortorder'} = 'desc' if (! exists($env{'form.sortorder'})); - $env{'form.sortfield'} = 'count' if (! exists($env{'form.sortfield'})); + 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'; @@ -2706,37 +2941,40 @@ sub display_results { $env{'form.sortorder'}='asc'; } } - my $sortform = &mt('Sort by [_1] [_2]', - &Apache::loncommon::select_form($env{'form.sortfield'}, - 'sortfield', - %sort_fields), - &Apache::loncommon::select_form($env{'form.sortorder'}, - 'sortorder', - (asc =>&mt('Ascending'), - desc=>&mt('Descending') - )) - ); - ## - ## Output links (if necessary) for 'prev' and 'next' pages. - $r->print - (''.
- ' | '. - &prev_next_buttons($min,$env{'form.show'},$total_results). - ' | '. - &viewoptions().' |
\n"; + my %Fields = %{&parse_row($tabletype,@$row)}; + my $output; if (! defined($Fields{'title'}) || $Fields{'title'} eq '') { $Fields{'title'} = 'Untitled'; } @@ -2777,23 +3027,29 @@ sub display_results { # Render the result into html $output.= &$viewfunction($prefix,%Fields); # Print them out as they come in. - $r->print($output); + $r->print(&Apache::loncommon::start_data_table_row() + .'
' + .&mt('There were no results matching your query.') + .'
'); } else { - $r->print - ('\n";
- $result .= ''.$values{'author'}.','.
+ $jumpurl=~s|^/ext/|http://|;
+ $result .=
+ ''.$prefix.
+ ''.' '.
+ ''.$values{'title'}."\n".
+ &display_tools($values{'title'}, $jumpurl).
+ "
\n".
+ ''.$values{'author'}.','.
' '.$values{'owner'}.'
';
foreach my $field
(
@@ -3278,11 +3591,8 @@ sub detailed_citation_view {
if (exists($field->{'type'}) && $field->{'type'} eq 'list') {
$result .= ''.&mt($field->{'translate'}).'';
foreach my $item (split(',',$values{$field->{'name'}})){
- $result .=
- &Apache::lonhtmlcommon::crumbs($item,
- (($env{'form.catalogmode'} eq 'import')?'_top':'preview'),
- '/res',
- (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),1);
+ $item = &Apache::lonnet::clutter($item);
+ $result .= '
'.&display_url($item,1).'
';
}
} elsif (exists($field->{'format'}) && $field->{'format'} ne ''){
$result.= &mt($field->{'translate'},
@@ -3290,11 +3600,7 @@ sub detailed_citation_view {
$values{$field->{'name'}}))."
\n";
} else {
if ($field->{'special'} eq 'url link') {
- $result.=
- &Apache::lonhtmlcommon::crumbs($jumpurl,
- (($env{'form.catalogmode'} eq 'import')?'_top':'preview'),
- '',
- (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),1);
+ $result .= '
'.&display_url($jumpurl,1).'
';
} else {
$result.= &mt($field->{'translate'},
$values{$field->{'name'}});
@@ -3309,17 +3615,14 @@ sub detailed_citation_view {
if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') {
$result .= '
'.$values{'shortabstract'}.'
'; } - $result .= ''. - &detailed_citation_view($prefix,%values). + return &detailed_citation_view($prefix,%values). ' | '. - &Apache::lonindexer::showpreview($values{'url'}). - ' |
'. - &summary_view($prefix,%values). + return &summary_view($prefix,%values). ' | '. - &Apache::lonindexer::showpreview($values{'url'}). - ' |
+
$errorstring
$end_page ENDPAGE @@ -3618,23 +3945,32 @@ $parms is extra information to include i ###################################################################### sub output_blank_field_error { my ($r,$closebutton,$parms,$hidden_fields)=@_; - my $errormsg = &mt('You did not fill in enough information for the search to be started. You need to fill in relevant fields on the search page in order for a query to be processed.'); + my $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 $heading = &mt('Unactionable Search Query'); my $start_page = &Apache::loncommon::start_page('Search'); my $end_page = &Apache::loncommon::end_page(); + if ($closebutton) { + $closebutton = ''.$closebutton.'
+
$errormsg
$end_page ENDPAGE @@ -3665,16 +4001,18 @@ sub output_date_error { # make query information persistent to allow for subsequent revision my $start_page = &Apache::loncommon::start_page('Search'); my $end_page = &Apache::loncommon::end_page(); + my $heading = &mt('Error'); $r->print(<+
$message
$end_page @@ -3697,7 +4035,7 @@ Cleans the global %groupsearch_db by rem ###################################################################### sub start_fresh_session { delete $groupsearch_db{'mode_catalog'}; - foreach (keys %groupsearch_db) { + foreach (keys(%groupsearch_db)) { if ($_ =~ /^pre_/) { delete $groupsearch_db{$_}; } @@ -3715,7 +4053,6 @@ sub cleanup { &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db'); } } - &untiehash(); &Apache::lonmysql::disconnect_from_db(); return OK; }