+ + +$closebutton +
+END + 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 .= $bread_crumb; + + $scrout .= ''; + + $scrout .= &Apache::loncommon::end_page(); + $r->print($scrout); + return; +} + +###################################################################### +###################################################################### + +=pod + +=item &titlefield() + +Inputs: title text + +Outputs: titletext with font wrapper + +=cut + +###################################################################### +###################################################################### +sub titlefield { + my $title=shift; + return $title; +} + +###################################################################### +###################################################################### + +=pod + +=item viewoptiontext() + +Inputs: codename for view option + +Outputs: displayed text + +=cut + +###################################################################### +###################################################################### +sub viewoptiontext { + my $code=shift; + my %desc=&Apache::lonlocal::texthash + ('detailed' => "Detailed Citation View", + 'xml' => 'XML/SGML', + 'compact' => 'Compact View', + 'fielded' => 'Fielded Format', + 'summary' => 'Summary View', + 'summarypreview' => 'Summary Preview', + 'detailedpreview' => 'Detailed Citation Preview'); + return $desc{$code}; +} + +###################################################################### +###################################################################### + +=pod + +=item viewoptions() + +Inputs: none + +Outputs: text for box with view options + +=cut + +###################################################################### +###################################################################### +sub viewoptions { + my $scrout; + if (! defined($env{'form.viewselect'})) { + $env{'form.viewselect'}='detailed'; + } + $scrout .= '' + .&mt('Type:').' ' + .&Apache::lonmeta::selectbox('viewselect', + $env{'form.viewselect'},'', + \&viewoptiontext, + sort(keys(%Views))) + .''; + my $countselect = &Apache::lonmeta::selectbox('show', + $env{'form.show'},'', + undef, + (10,20,50,100,1000,10000)); + $scrout .= ' ' + .&mt('Records per Page:').' '.$countselect + .''.$/; + return $scrout; +} + +###################################################################### +###################################################################### + +=pod + +=item searchhelp() + +Inputs: none + +Outputs: return little blurb on how to enter searches + +=cut + +###################################################################### +###################################################################### +sub searchhelp { + return &mt('Enter words and quoted phrases'); +} + +###################################################################### +###################################################################### + +=pod + +=item &get_persistent_form_data() + +Inputs: filename of database + +Outputs: returns undef on database errors. + +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 +overwritten. Form values that are array references may have values appended +to them. + +=cut + +###################################################################### +###################################################################### +sub get_persistent_form_data { + my $filename = shift; + return 0 if (! -e $filename); + return undef if (! tie(%persistent_db,'GDBM_File',$filename, + &GDBM_READER(),0640)); + # + # These make sure we do not get array references printed out as 'values'. + my %arrays_allowed = ('form.domains'=>1); + # + # Loop through the keys, looking for 'form.' + foreach my $name (keys(%persistent_db)) { + next if ($name !~ /^form./); + # Kludgification begins! + if ($name eq 'form.domains' && + $env{'form.searchmode'} eq 'basic' && + $env{'form.phase'} ne 'disp_basic') { + next; + } + # End kludge (hopefully) + next if (exists($env{$name})); + my @values = map { + &unescape($_); + } split(',',$persistent_db{$name}); + next if (@values <1); + if ($arrays_allowed{$name}) { + $env{$name} = [@values]; + } else { + $env{$name} = $values[0] if ($values[0]); + } + } + untie (%persistent_db); + return 1; +} + +###################################################################### +###################################################################### + +=pod + +=item &get_persistent_data() + +Inputs: filename of database, ref to array of values to recover. + +Outputs: array of values. Returns undef on error. + +This function is the reverse of &make_persistent(); +Retrieve persistent data from %persistent_db. Retrieved items will have their +values unescaped. If the item is 'domains; then the returned +value will be a hash pointer. Otherwise, if the item contains +commas (before unescaping), the returned value will be an array pointer. + +=cut + +###################################################################### +###################################################################### +sub get_persistent_data { + my $filename = shift; + my @Vars = @{shift()}; + my @Values; # Return array + return undef if (! -e $filename); + return undef if (! tie(%persistent_db,'GDBM_File',$filename, + &GDBM_READER(),0640)); + foreach my $name (@Vars) { + if (! exists($persistent_db{$name})) { + push @Values, undef; + next; + } + if ($name eq 'domains') { + my %valueshash; + my @items= map { &unescape($_); } split(',',$persistent_db{$name}); + foreach my $item (@items) { + if ($item =~ /=/) { + my ($key,$val) = map { &unescape($_); } split(/=/,$item); + $valueshash{$key} = $val; + } + } + push(@Values,\%valueshash); + } else { + my @values = map { + &unescape($_); + } split(',',$persistent_db{$name}); + if (@values <= 1) { + push @Values,$values[0]; + } else { + push @Values,\@values; + } + } + } + untie (%persistent_db); + return @Values; +} + +###################################################################### +###################################################################### + +=pod + +=item &make_persistent() + +Inputs: Hash of values to save, filename of persistent database. + +Store variables away to the %persistent_db. +Values will be escaped. Values that are array pointers will have their +elements escaped and concatenated in a comma separated string. Values +that are hash pointers will have their keys and values escaped and +concatenated in a comma separated string. + +=cut + +###################################################################### +###################################################################### +sub make_persistent { + my %save = %{shift()}; + my $filename = shift; + return undef if (! tie(%persistent_db,'GDBM_File', + $filename,&GDBM_WRCREAT(),0640)); + foreach my $name (keys(%save)) { + my @values=(); + if (ref($save{$name}) eq 'ARRAY') { + @values = @{$save{$name}}; + } elsif (ref($save{$name}) eq 'HASH') { + foreach my $key (%{$save{$name}}) { + push(@values,&escape($key).'='.&escape($save{$name}{$key})); + } + } else { + @values = $save{$name}; + } + # We handle array and hash references, but not recursively. + my $store = join(',', map { &escape($_); } @values ); + $persistent_db{$name} = $store; + } + untie(%persistent_db); + return 1; +} + +###################################################################### +###################################################################### + +=pod + +=item &make_form_data_persistent() + +Inputs: filename of persistent database. + +Store most form variables away to the %persistent_db. +Values will be escaped. Values that are array pointers will have their +elements escaped and concatenated in a comma separated string. + +=cut + +###################################################################### +###################################################################### +sub make_form_data_persistent { + my $r = shift; + my $filename = shift; + my %save; + foreach (keys(%env)) { + next if (!/^form/ || /submit/); + $save{$_} = $env{$_}; + } + return &make_persistent(\%save,$filename); +} + +###################################################################### +###################################################################### + +=pod + +=item &parse_advanced_search() + +Parse advanced search form and return the following: + +=over 4 + +=item $query Scalar containing an SQL query. + +=item $customquery Scalar containing a custom query. + +=item $customshow Scalar containing commands to show custom metadata. + +=item $libraries_to_query Reference to array of domains to search. + +=back + +=cut + +###################################################################### +###################################################################### +sub parse_advanced_search { + my ($r,$closebutton,$hidden_fields)=@_; + my @BasicFields = ('title','author','subject','keywords','url','version', + 'notes','abstract','extension','owner','authorspace', +# 'custommetadata','customshow', + 'modifyinguser','standards','mime'); + my @StatsFields = &statfields(); + my @EvalFields = &evalfields(); + my $fillflag=0; + my $pretty_search_string = ""; + # Clean up fields for safety + for my $field (@BasicFields, + 'creationdatestart_month','creationdatestart_day', + 'creationdatestart_year','creationdateend_month', + 'creationdateend_day','creationdateend_year', + 'lastrevisiondatestart_month','lastrevisiondatestart_day', + 'lastrevisiondatestart_year','lastrevisiondateend_month', + 'lastrevisiondateend_day','lastrevisiondateend_year') { + $env{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\'.\*]//g; + } + foreach ('mode','form','element') { + # is this required? Hmmm. + 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'})); + # + # Check to see if enough information was filled in + foreach my $field (@BasicFields) { + if (&filled($env{'form.'.$field})) { + $fillflag++; + } + } + foreach my $field (@StatsFields,@EvalFields) { + if (&filled($env{'form.'.$field.'_max'})) { + $fillflag++; + } + if (&filled($env{'form.'.$field.'_min'})) { + $fillflag++; + } + } + + for my $field ('lowestgradelevel','highestgradelevel') { + 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); + return ; + } + # Turn the form input into a SQL-based query + my $query=''; + my @queries; + my $font = ''; + # Evaluate logical expression AND/OR/NOT phrase fields. + foreach my $field (@BasicFields) { + 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 related words.'; + } + } + $pretty_search_string .= '' + .&mt('Unable to retrieve search results. ' + .'Unable to determine the table results were saved in.') + .'
' + . ''.&mt('Internal info:').'
' + .''.$table.'' + .&Apache::loncommon::end_page() + ); + return undef; + } + ## + ## Make sure we can connect and the table exists. + ## + my $connection_result = &Apache::lonmysql::connect_to_db(); + if (!defined($connection_result)) { + $r->print( + '
' + .&mt('Unable to connect to the MySQL database where your results are saved.') + .'
' + .&Apache::loncommon::end_page() + ); + &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to". + " connect to database."); + &Apache::lonnet::logthis(&Apache::lonmysql::get_error()); + return undef; + } + my $table_check = &Apache::lonmysql::check_table($table); + if (! defined($table_check)) { + $r->print( + '' + .&mt('A MySQL error has occurred.') + .'
' + .&Apache::loncommon::end_page()); + &Apache::lonnet::logthis("lonmysql was unable to determine the status". + " of table ".$table); + return undef; + } elsif (! $table_check) { + $r->print( + '' + .&mt('The table of results could not be found.') + .'
' + ); + &Apache::lonnet::logthis("The user requested a table, ".$table. + ", that could not be found."); + return undef; + } + return 1; +} + +###################################################################### +###################################################################### + +=pod + +=item &print_sort_form() + +The sort feature is not implemented at this time. This form just prints +a link to change the search query. + +=cut + +###################################################################### +###################################################################### +sub print_sort_form { + my ($r,$pretty_query_string,$target) = @_; + + ## + my %SortableFields=&Apache::lonlocal::texthash( + id => 'Default', + title => 'Title', + author => 'Author', + subject => 'Subject', + url => 'URL', + version => 'Version Number', + mime => 'Mime type', + lang => 'Language', + owner => 'Owner/Publisher', + copyright => 'Copyright', + hostname => 'Host', + creationdate => 'Creation Date', + lastrevisiondate => 'Revision Date' + ); + ## + 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.". + &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 $args; + if ($target eq '_parent') { + $args = {'links_target' => $target}; + } + my $start_page = &Apache::loncommon::start_page('Results',undef,$args); + my $breadcrumbs= + &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching', + $env{'form.catalogmode'} ne 'import', + '','','','','','',$target); + + my $result = <' + .&mt('Total of [quant,_1,match,matches] to your query.',$total_results) + .' '.$revise.'
' + .''.&mt('Search: ').$pretty_query_string + .'
'; + $r->print($result.&Apache::loncommon::end_page()); + return; +} + +##################################################################### +##################################################################### + +=pod + +=item MySQL Table Description + +MySQL table creation requires a precise description of the data to be +stored. The use of the correct types to hold data is vital to efficient +storage and quick retrieval of records. The columns must be described in +the following format: + +=cut + +##################################################################### +##################################################################### +# +# These should probably be scoped but I don't have time right now... +# +my @Datatypes; +my @Fullindicies; + +###################################################################### +###################################################################### + +=pod + +=item &create_results_table() + +Creates the table of search results by calling lonmysql. Stores the +table id in $env{'form.table'} + +Inputs: search area - either res or portfolio + +Returns: the identifier of the table on success, undef on error. + +=cut + +###################################################################### +###################################################################### +sub set_up_table_structure { + my ($tabletype) = @_; + my ($datatypes,$fullindicies) = + &LONCAPA::lonmetadata::describe_metadata_storage($tabletype); + # Copy the table description before modifying it... + @Datatypes = @{$datatypes}; + unshift(@Datatypes,{name => 'id', + type => 'MEDIUMINT', + restrictions => 'UNSIGNED NOT NULL', + primary_key => 'yes', + auto_inc => 'yes' }); + @Fullindicies = @{$fullindicies}; + return; +} + +sub create_results_table { + my ($area) = @_; + if ($area eq 'portfolio') { + &set_up_table_structure('portfolio_search'); + } else { + &set_up_table_structure('metadata'); + } + my $table = &Apache::lonmysql::create_table + ( { columns => \@Datatypes, + FULLTEXT => [{'columns' => \@Fullindicies},], + } ); + if (defined($table)) { + $env{'form.table'} = $table; + return $table; + } + return undef; # Error... +} + +###################################################################### +###################################################################### + +=pod + +=item Search Status update functions + +Each of the following functions changes the values of one of the +input fields used to display the search status to the user. The names +should be explanatory. + +Inputs: Apache request handler ($r), text to display. + +Returns: Nothing. + +=over 4 + +=item &update_count_status() + +=item &update_status() + +=item &update_seconds() + +=back + +=cut + +###################################################################### +###################################################################### +sub update_count_status { + my ($r,$text) = @_; + $text =~ s/\'/\\\'/g; + $r->print(< +SCRIPT + + $r->rflush(); +} + +sub update_status { + my ($r,$text) = @_; + $text =~ s/\'/\\\'/g; + $r->print(< +SCRIPT + + $r->rflush(); +} + +sub reload_result_frame { + my ($r) = @_; + my $newloc = '/adm/searchcat?phase=results&persistent_db_id='. + $env{'form.persistent_db_id'}; + $r->print(< +SCRIPT + + $r->rflush(); +} + +{ + my $max_time = 60; # seconds for the search to complete + my $start_time = 0; + my $last_time = 0; + +sub reset_timing { + $start_time = 0; + $last_time = 0; +} + +sub time_left { + if ($start_time == 0) { + $start_time = time; + } + my $time_left = $max_time - (time - $start_time); + $time_left = 0 if ($time_left < 0); + return $time_left; +} + +sub update_seconds { + my ($r) = @_; + my $time = &time_left(); + if (($last_time-$time) > 0) { + $r->print(< +SCRIPT + + $r->rflush(); + } + $last_time = $time; +} + +} + +###################################################################### +###################################################################### + +=pod + +=item &revise_button() + +Inputs: None + +Returns: html string for a 'revise search' button. + +=cut + +###################################################################### +###################################################################### +sub revise_button { + my $revisetext = &mt('Revise search'); + my $revise_phase = 'disp_basic'; + $revise_phase = 'disp_adv' if ($env{'form.searchmode'} eq 'advanced'); + my $newloc = '/adm/searchcat'. + '?persistent_db_id='.$env{'form.persistent_db_id'}. + '&cleargroupsort=1'. + '&phase='.$revise_phase; + my $result = qq{ }; + return $result; +} + +###################################################################### +###################################################################### + +=pod + +=item &run_search() + +Executes a search query by sending it the the other servers and putting the +results into MySQL. + +=cut + +###################################################################### +###################################################################### +sub run_search { + my ($r,$query,$customquery,$customshow,$serverlist, + $pretty_string,$area,$domainsref,$target) = @_; + my $tabletype = 'metadata'; + if ($area eq 'portfolio') { + $tabletype = 'portfolio_search'; + } + my $connection = $r->connection; + # + # Print run_search header + # + my $args; + if ($target eq '_parent') { + $args = {'links_target' => $target}; + } + my $start_page = &Apache::loncommon::start_page('Search Status',undef,$args); + my $breadcrumbs = + &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching', + $env{'form.catalogmode'} ne 'import', + '','','','','','',$target); + $r->print(<' + .'' + .' ' + .'' + .' ' + .'' + .'
'; +} + +###################################################################### +###################################################################### + +=pod + +=item &display_results() + +Prints the results out for selection and perusal. + +=cut + +###################################################################### +###################################################################### +sub display_results { + 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'}}; + if (!defined($viewfunction)) { + $r->print('' + .&mt('Internal Error - Bad view selected.') + .'
'."\n"); + $r->rflush(); + return; + } + ## + ## $checkbox_num is a count of the number of checkboxes output on the + ## 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 import by opening the import db file. + if ($env{'form.catalogmode'} eq 'import') { + if (! tie(%groupsearch_db,'GDBM_File',$diropendb, + &GDBM_WRCREAT(),0640)) { + # NOTE: this can happen when a previous request to searchcat?phase=results gets interrupted + # (%groupsearch_db is not untied) + $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 + 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(''. + &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); + &Apache::lonnet::logthis(&Apache::lonmysql::get_error()); + return; + } + ## + ## 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'}; + my $max; + if ($env{'form.show'} eq 'all') { + $max = $total_results ; + } else { + $max = $min + $env{'form.show'} - 1; + $max = $total_results if ($max > $total_results); + } + ## + ## Output form elements + $r->print(&hidden_field('table'). + &hidden_field('phase'). + &hidden_field('persistent_db_id'). + &hidden_field('start'). + &hidden_field('area') + ); + # + # Build sorting selector + my @fields = + ( + {key=>'default' }, + {key=>'title' }, + {key =>'author' }, + {key =>'subject'}, + {key =>'url',desc=>'URL'}, + {key =>'keywords'}, + {key =>'language'}, + {key =>'creationdate'}, + {key =>'lastrevisiondate'}, + {key =>'owner'}, + {key =>'copyright'}, + {key =>'authorspace'}, + {key =>'lowestgradelevel'}, + {key =>'highestgradelevel'}, + {key =>'standards',desc=>'Standards'}, + ); + if ($area eq 'portfolio') { + push(@fields, + ( + {key => 'scope'}, + {key => 'keynum'}, + )); + } else { + push(@fields, + ( + {key =>'count',desc=>'Number of accesses'}, + {key =>'stdno',desc=>'Students Attempting'}, + {key =>'avetries',desc=>'Average Number of Tries'}, + {key =>'difficulty',desc=>'Mean Degree of Difficulty'}, + {key =>'disc',desc=>'Mean Degree of Discrimination'}, + {key =>'clear',desc=>'Evaluation: Clear'}, + {key =>'technical',desc=>'Evaluation: Technically Correct'}, + {key =>'correct',desc=>'Evaluation: Material is Correct'}, + {key =>'helpful',desc=>'Evaluation: Material is Helpful'}, + {key =>'depth',desc=>'Evaluation: Material has Depth'}, + )); + } + my %fieldnames = &Apache::lonmeta::fieldnames(); + my @field_order; + foreach my $field_data (@fields) { + push(@field_order,$field_data->{'key'}); + if (! exists($field_data->{'desc'})) { + $field_data->{'desc'}=$fieldnames{$field_data->{'key'}}; + } else { + if (! defined($field_data->{'desc'})) { + $field_data->{'desc'} = ucfirst($field_data->{'key'}); + } + $field_data->{'desc'} = &mt($field_data->{'desc'}); + } + } + my %sort_fields = map {$_->{'key'},$_->{'desc'}} @fields; + $sort_fields{'select_form_order'} = \@field_order; + $env{'form.sortorder'} = 'desc' if (! exists($env{'form.sortorder'})); + if (! exists($env{'form.sortfield'})) { + if ($area eq 'portfolio') { + $env{'form.sortfield'} = 'owner'; + } else { + $env{'form.sortfield'} = 'count'; + } + } + if (! exists($env{'form.sortorder'})) { + if ($env{'form.sortfield'}=~/^(count|stdno|disc|clear|technical|correct|helpful)$/) { + $env{'form.sortorder'}='desc'; + } else { + $env{'form.sortorder'}='asc'; + } + } + my $sortform = '' + .&mt('Sort by:').' ' + .&Apache::loncommon::select_form($env{'form.sortfield'}, + 'sortfield', + \%sort_fields) + .' ' + .&Apache::loncommon::select_form($env{'form.sortorder'}, + 'sortorder', + {asc =>&mt('Ascending'), + desc=>&mt('Descending') + }) + .''; + ## + ## Display links for 'prev' and 'next' pages (if necessary) and Display Options + $r->print('' + .&prev_next_buttons($min,$env{'form.show'},$total_results) + ); + + if ($total_results == 0) { + $r->print(''.&mt('There are currently no results.').'
'. + "". + &Apache::loncommon::end_page()); + return; + } else { + $r->print('' + .&mt('There were no results matching your query.') + .'
'); + } else { + $r->print( + &prev_next_buttons($min,$env{'form.show'},$total_results, + "table=".$env{'form.table'}. + "&phase=results". + "&persistent_db_id=". + $env{'form.persistent_db_id'}) + ); + } + $r->print("".&Apache::loncommon::end_page()); + $r->rflush(); + untie %groupsearch_db if (tied(%groupsearch_db)); + return; +} + +###################################################################### +###################################################################### + +=pod + +=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. + +=cut + +###################################################################### +###################################################################### +sub catalogmode_output { + my $output = ''; + my ($title,$url,$fnum,$checkbox_num) = @_; + if ($env{'form.catalogmode'} eq 'interactive') { + $title=~ s/\'/\\\'/g; + if ($env{'form.catalogmode'} eq 'interactive') { + $output.=<\n".
+ ''.$values{'author'}.','.
+ ' '.$values{'owner'}.'
';
+ foreach my $field
+ (
+ { name=>'url',
+ translate => 'URL: [_1]',
+ special => 'url link',},
+ { name=>'subject',
+ translate => 'Subject: [_1]',},
+ { name=>'keywords',
+ translate => 'Keywords: [_1]',},
+ { name=>'notes',
+ translate => 'Notes: [_1]',},
+ { name=>'mimetag',
+ translate => 'MIME Type: [_1]',},
+ { name=>'standards',
+ translate => 'Standards:[_1]',},
+ { name=>'copyrighttag',
+ translate => 'Copyright/Distribution: [_1]',},
+ { name=>'count',
+ format => "%d",
+ translate => 'Access Count: [_1]',},
+ { name=>'stdno',
+ format => "%d",
+ translate => 'Number of Students: [_1]',},
+ { name=>'avetries',
+ format => "%.2f",
+ translate => 'Average Tries: [_1]',},
+ { name=>'disc',
+ format => "%.2f",
+ translate => 'Degree of Discrimination: [_1]',},
+ { name=>'difficulty',
+ format => "%.2f",
+ translate => 'Degree of Difficulty: [_1]',},
+ { name=>'clear',
+ format => "%.2f",
+ translate => 'Clear: [_1]',},
+ { name=>'depth',
+ format => "%.2f",
+ translate => 'Depth: [_1]',},
+ { name=>'helpful',
+ format => "%.2f",
+ translate => 'Helpful: [_1]',},
+ { name=>'correct',
+ format => "%.2f",
+ translate => 'Correct: [_1]',},
+ { name=>'technical',
+ format => "%.2f",
+ translate => 'Technical: [_1]',},
+ { name=>'comefrom_list',
+ type => 'list',
+ translate => 'Resources that lead up to this resource in maps',},
+ { name=>'goto_list',
+ type => 'list',
+ translate => 'Resources that follow this resource in maps',},
+ { name=>'sequsage_list',
+ type => 'list',
+ translate => 'Resources using or importing resource',},
+ ) {
+ next if (! exists($values{$field->{'name'}}) ||
+ $values{$field->{'name'}} eq '');
+ if (exists($field->{'type'}) && $field->{'type'} eq 'list') {
+ $result .= ''.&mt($field->{'translate'}).'';
+ foreach my $item (split(',',$values{$field->{'name'}})){
+ $item = &Apache::lonnet::clutter($item);
+ $result .= '
'.&display_url($item,1).'
';
+ }
+ } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){
+ $result.= &mt($field->{'translate'},
+ sprintf($field->{'format'},
+ $values{$field->{'name'}}))."
\n";
+ } else {
+ if ($field->{'special'} eq 'url link') {
+ $result .= '
'.&display_url($jumpurl,1).'
';
+ } else {
+ $result.= &mt($field->{'translate'},
+ $values{$field->{'name'}});
+ }
+ $result .= "
\n";
+ }
+ }
+ $result .= "
'.$values{'extrashow'}.'
'; + } + if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') { + $result .= ''.$values{'shortabstract'}.'
'; + } + return $result; +} + +sub detailed_citation_preview { + my ($prefix,%values)=@_; + return &detailed_citation_view($prefix,%values). + '+$errorstring +
++$revise +
+$end_page +ENDPAGE +} + +###################################################################### +###################################################################### + +=pod + +=item &output_blank_field_error() + +Output a complete page that indicates the user has not filled in enough +information to do a search. + +Inputs: $r (Apache request handle), $closebutton, $parms. + +Returns: nothing + +$parms is extra information to include in the 'Revise search request' link. + +=cut + +###################################################################### +###################################################################### +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 $revise = &mt('Revise Search Request'); + 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 +
++$revise +
+$end_page +ENDPAGE + return; +} + +###################################################################### +###################################################################### + +=pod + +=item &output_date_error() + +Output a full html page with an error message. + +Inputs: + + $r, the request pointer. + $message, the error message for the user. + $closebutton, the specialized close button needed for groupsearch. + +=cut + +###################################################################### +###################################################################### +sub output_date_error { + my ($r,$message,$closebutton,$hidden_fields)=@_; + # make query information persistent to allow for subsequent revision + my $start_page = &Apache::loncommon::start_page('Search'); + my $end_page = &Apache::loncommon::end_page(); + my $heading = &mt('Error'); + $r->print(<+$message +
+$end_page +RESULTS +} + +###################################################################### +###################################################################### + +=pod + +=item &start_fresh_session() + +Cleans the global %groupsearch_db by removing all fields which begin with +'pre_' or 'store'. + +=cut + +###################################################################### +###################################################################### +sub start_fresh_session { + delete $groupsearch_db{'mode_catalog'}; + foreach (keys(%groupsearch_db)) { + if ($_ =~ /^pre_/) { + delete $groupsearch_db{$_}; + } + if ($_ =~ /^store/) { + delete $groupsearch_db{$_}; + } + } +} + 1; + +sub cleanup { + if (tied(%groupsearch_db)) { + unless (untie(%groupsearch_db)) { + &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db'); + } + } + &Apache::lonmysql::disconnect_from_db(); + return OK; +} + __END__ + +=pod + +=back + +=cut