Diff for /loncom/interface/lonsearchcat.pm between versions 1.230.2.1 and 1.331.4.9

version 1.230.2.1, 2005/01/19 20:22:36 version 1.331.4.9, 2013/12/31 01:10:17
Line 52  search (on a server basis) is displayed Line 52  search (on a server basis) is displayed
   
 =head1 Internals  =head1 Internals
   
 =over 4  
   
 =cut  =cut
   
 ###############################################################################  ###############################################################################
Line 63  package Apache::lonsearchcat; Line 61  package Apache::lonsearchcat;
   
 use strict;  use strict;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::File();  use Apache::File();
 use CGI qw(:standard);  use CGI qw(:standard);
 use Text::Query;  use Text::Query;
Line 76  use Apache::lonlocal; Line 74  use Apache::lonlocal;
 use LONCAPA::lonmetadata();  use LONCAPA::lonmetadata();
 use HTML::Entities();  use HTML::Entities();
 use Parse::RecDescent;  use Parse::RecDescent;
   use Apache::lonnavmaps;
   use Apache::lonindexer();
   use Apache::lonwishlist();
   use LONCAPA;
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 92  my %persistent_db;   # gdbm hash which h Line 94  my %persistent_db;   # gdbm hash which h
 # The different view modes and associated functions  # The different view modes and associated functions
   
 my %Views = ("detailed" => \&detailed_citation_view,  my %Views = ("detailed" => \&detailed_citation_view,
                "detailedpreview" => \&detailed_citation_preview,
      "summary"  => \&summary_view,       "summary"  => \&summary_view,
                "summarypreview" => \&summary_preview,
      "fielded"  => \&fielded_format_view,       "fielded"  => \&fielded_format_view,
      "xml"      => \&xml_sgml_view,       "xml"      => \&xml_sgml_view,
      "compact"  => \&compact_view);       "compact"  => \&compact_view);
Line 112  sub handler { Line 116  sub handler {
     my $diropendb;    # The full path to the (temporary) search database file.      my $diropendb;    # The full path to the (temporary) search database file.
                       # This is set and used in &handler() and is also used in                         # This is set and used in &handler() and is also used in 
                       # &output_results().                        # &output_results().
     my $bodytag;  # LON-CAPA standard body tag, gotten from   
                   # &Apache::lonnet::bodytag.   
                   # No title, no table, just a <body> tag.  
   
     my $loaderror=&Apache::lonnet::overloaderror($r);  
     if ($loaderror) { return $loaderror; }  
     #      #
     my $closebutton;  # button that closes the search window       my $closebutton;  # button that closes the search window 
                       # This button is different for the RAT compared to                        # This button is different for the RAT compared to
Line 136  sub handler { Line 135  sub handler {
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
              ['catalogmode','launch','acts','mode','form','element','pause',               ['catalogmode','launch','acts','mode','form','element','pause',
               'phase','persistent_db_id','table','start','show',                '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 following is a trick - we wait a few seconds if asked to so
     ##     the daemon running the search can get ahead of the daemon      ##     the daemon running the search can get ahead of the daemon
     ##     printing the results.  We only need (theoretically) to do      ##     printing the results.  We only need (theoretically) to do
     ##     this once, so the pause indicator is deleted      ##     this once, so the pause indicator is deleted
     ##      ##
     if (exists($ENV{'form.pause'})) {      if (exists($env{'form.pause'})) {
         sleep(1);          sleep(1);
         delete($ENV{'form.pause'});          delete($env{'form.pause'});
     }      }
     ##      ##
     ## Initialize global variables      ## Initialize global variables
     ##      ##
     my $domain  = $r->dir_config('lonDefDomain');      my $domain  = $r->dir_config('lonDefDomain');
     $diropendb= "/home/httpd/perl/tmp/".      my $temp_file_dir = LONCAPA::tempdir();
         "$ENV{'user.domain'}_$ENV{'user.name'}_searchcat.db";      $diropendb= $temp_file_dir .
           "$env{'user.domain'}_$env{'user.name'}_sel_res.db";
     #      #
     # set the name of the persistent database      # set the name of the persistent database
     #          $ENV{'form.persistent_db_id'} can only have digits in it.      #          $env{'form.persistent_db_id'} can only have digits in it.
     if (! exists($ENV{'form.persistent_db_id'}) ||      if (! exists($env{'form.persistent_db_id'}) ||
         ($ENV{'form.persistent_db_id'} =~ /\D/) ||          ($env{'form.persistent_db_id'} =~ /\D/) ||
         ($ENV{'form.launch'} eq '1')) {          ($env{'form.launch'} eq '1')) {
         $ENV{'form.persistent_db_id'} = time;          $env{'form.persistent_db_id'} = time;
     }      }
     $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);  
     my $persistent_db_file = "/home/httpd/perl/tmp/".      my $persistent_db_file = $temp_file_dir .
         &Apache::lonnet::escape($domain).          &escape($domain).
             '_'.&Apache::lonnet::escape($ENV{'user.name'}).              '_'.&escape($env{'user.name'}).
                 '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';                  '_'.$env{'form.persistent_db_id'}.'_persistent_search.db';
     ##      ##
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
     if (exists($ENV{'request.course.id'}) && $ENV{'request.course.id'} ne '') {  
         &Apache::lonhtmlcommon::add_breadcrumb      my @allowed_searches = ('portfolio');
              ({href=>'/adm/searchcat?'.      if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) {
                    'catalogmode='.$ENV{'form.catalogmode'}.          push(@allowed_searches,'res');
                    '&launch='.$ENV{'form.launch'}.      } 
                    '&mode='.$ENV{'form.mode'},      my $crumb_text = 'Portfolio Search';
               text=>"Course and Catalog Search",      if (@allowed_searches ==2) {
               target=>'_top',         $crumb_text = 'Portfolio and Catalog Search'; 
               bug=>'Searching',});      }
     } else {      &Apache::lonhtmlcommon::add_breadcrumb
         &Apache::lonhtmlcommon::add_breadcrumb         ({href=>'/adm/searchcat?'.
              ({href=>'/adm/searchcat?'.         &Apache::loncommon::inhibit_menu_check().
                    'catalogmode='.$ENV{'form.catalogmode'}.                 '&amp;catalogmode='.$env{'form.catalogmode'}.
                    '&launch='.$ENV{'form.launch'}.                 '&amp;launch='.$env{'form.launch'}.
                    '&mode='.$ENV{'form.mode'},                 '&amp;mode='.$env{'form.mode'},
               text=>"Catalog Search",                text=>"$crumb_text",
               target=>'_top',                target=>'_top',
               bug=>'Searching',});                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 (! &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:'.                  &Apache::lonnet::logthis('lonsearchcat:'.
                                          'Unable to recover data from '.                                           'Unable to recover data from '.
                                          $persistent_db_file);                                           $persistent_db_file);
                 $r->print(<<END);   my $msg =
 <html>      'We were unable to retrieve data describing your search. '.
 <head><title>LON-CAPA Search Error</title></head>      'This is a serious error and has been logged. '.
 $bodytag      'Please alert your LON-CAPA administrator.';
 We were unable to retrieve data describing your search.  This is a serious   &Apache::loncommon::simple_error_page($r,'Search Error',
 error and has been logged.  Please alert your LON-CAPA administrator.        $msg);
 </body>   return OK;
 </html>  
 END  
                 return OK;  
             }              }
         }          }
     } else {      } else {
Line 213  END Line 209  END
     ## Clear out old values from groupsearch database      ## Clear out old values from groupsearch database
     ##      ##
     untie %groupsearch_db if (tied(%groupsearch_db));      untie %groupsearch_db if (tied(%groupsearch_db));
     if (($ENV{'form.cleargroupsort'} eq '1') ||       if (($env{'form.cleargroupsort'} eq '1') || 
         (($ENV{'form.launch'} eq '1') &&           (($env{'form.launch'} eq '1') && 
          ($ENV{'form.catalogmode'} eq 'groupsearch'))) {           ($env{'form.catalogmode'} eq 'import'))) {
  if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {   if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {
     &start_fresh_session();      &start_fresh_session();
     untie %groupsearch_db;      untie %groupsearch_db;
             delete($ENV{'form.cleargroupsort'});              delete($env{'form.cleargroupsort'});
  } else {   } else {
             # This is a stupid error to give to the user.                # This is a stupid error to give to the user.  
             # It really tells them nothing.              # It really tells them nothing.
     $r->print('<html><head></head>'.$bodytag.      my $msg = 'Unable to tie hash to db file.';
                       'Unable to tie hash to db file</body></html>');      &Apache::loncommon::simple_error_page($r,'Search Error',
     $msg);
     return OK;      return OK;
  }   }
     }      }
Line 232  END Line 229  END
     ## Configure hidden fields      ## Configure hidden fields
     ##      ##
     $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.      $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.
         $ENV{'form.persistent_db_id'}.'" />'."\n";          $env{'form.persistent_db_id'}.'" />'."\n";
     if (exists($ENV{'form.catalogmode'})) {      if (exists($env{'form.catalogmode'})) {
         $hidden_fields .= &hidden_field('catalogmode');          $hidden_fields .= &hidden_field('catalogmode');
     }      }
     if (exists($ENV{'form.form'})) {      if (exists($env{'form.form'})) {
         $hidden_fields .= &hidden_field('form');          $hidden_fields .= &hidden_field('form');
     }      }
     if (exists($ENV{'form.element'})) {      if (exists($env{'form.element'})) {
         $hidden_fields .= &hidden_field('element');          $hidden_fields .= &hidden_field('element');
     }      }
     if (exists($ENV{'form.titleelement'})) {      if (exists($env{'form.titleelement'})) {
         $hidden_fields .= &hidden_field('titleelement');          $hidden_fields .= &hidden_field('titleelement');
     }      }
     if (exists($ENV{'form.mode'})) {      if (exists($env{'form.mode'})) {
         $hidden_fields .= &hidden_field('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      ## Configure dynamic components of interface
     ##      ##
     if ($ENV{'form.catalogmode'} eq 'interactive') {      if ($env{'form.catalogmode'} eq 'interactive') {
         $closebutton="<input type='button' name='close' value='CLOSE' ";          $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";
         if ($ENV{'form.phase'} =~ /(results|run_search)/) {          if ($env{'form.phase'} =~ /(results|run_search)/) {
     $closebutton .="onClick='parent.close()'";              $closebutton .="onclick='parent.close()'";
         } else {          } else {
             $closebutton .="onClick='self.close()'";              $closebutton .="onclick='self.close()'";
         }          }
         $closebutton .=">\n";          $closebutton .=" />\n";
     } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {      } elsif ($env{'form.catalogmode'} eq 'import') {
         $closebutton="<input type='button' name='close' value='CLOSE' ";          $closebutton="<input type='button' name='close' value='".&mt('Close')."' ";
         if ($ENV{'form.phase'} =~ /(results|run_search)/) {          if ($env{'form.phase'} =~ /(results|run_search)/) {
     $closebutton .="onClick='parent.close()'";              $closebutton .="onclick='parent.close()'";
         } else {          } else {
             $closebutton .="onClick='self.close()'";              $closebutton .="onclick='self.close()'";
         }          }
         $closebutton .= ">";          $closebutton .= " />";
           my $txt_import = &mt('IMPORT');
         $importbutton=<<END;          $importbutton=<<END;
 <input type='button' name='import' value='IMPORT'  <input type='button' name='import' value='$txt_import'
 onClick='javascript:select_group()'>  onclick='javascript:select_group()' />
 END  END
     } else {      } else {
         $closebutton = '';          $closebutton = '';
Line 278  END Line 282  END
     ##      ##
     ## Sanity checks on form elements      ## Sanity checks on form elements
     ##      ##
     if (!defined($ENV{'form.viewselect'})) {      if (!defined($env{'form.viewselect'})) {
         if (($ENV{'form.catalogmode'} eq 'groupsearch') ||   $env{'form.viewselect'} ="summary";
             ($ENV{'form.catalogmode'} eq 'interactive')) {  
             $ENV{'form.viewselect'} ="Compact View";  
         } else {  
             $ENV{'form.viewselect'} ="Detailed Citation View";  
         }  
     }      }
     $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'}));      $env{'form.phase'} = 'disp_basic' if (! exists($env{'form.phase'}));
     $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'}));      $env{'form.show'} = 20 if (! exists($env{'form.show'}));
     #      #
     $ENV{'form.searchmode'} = 'basic' if (! exists($ENV{'form.searchmode'}));      $env{'form.searchmode'} = 'basic' if (! exists($env{'form.searchmode'}));
     if ($ENV{'form.phase'} eq 'adv_search' ||      if ($env{'form.phase'} eq 'adv_search' ||
         $ENV{'form.phase'} eq 'disp_adv') {          $env{'form.phase'} eq 'disp_adv') {
         $ENV{'form.searchmode'} = 'advanced';          $env{'form.searchmode'} = 'advanced';
     } elsif ($ENV{'form.phase'} eq 'course_search') {      }
         $ENV{'form.searchmode'} = 'course_search';      #
     }      if ($env{'form.searchmode'} eq 'advanced') {
     #          my $srchtype = 'Catalog';
     if ($ENV{'form.searchmode'} eq 'advanced') {          if ($env{'form.area'} eq 'portfolio') {
         &Apache::lonhtmlcommon::add_breadcrumb              $srchtype = 'Portfolio';
             ({href=>'/adm/searchcat?phase=disp_adv&'.          }
                   'catalogmode='.$ENV{'form.catalogmode'}.  
                   '&launch='.$ENV{'form.launch'}.  
                   '&mode='.$ENV{'form.mode'},  
                   text=>"Advanced Search",  
                   bug=>'Searching',});  
     } elsif ($ENV{'form.searchmode'} eq 'course search') {  
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
             ({href=>'/adm/searchcat?phase=disp_adv&'.              ({href=>'/adm/searchcat?'.&Apache::loncommon::inhibit_menu_check().
                   'catalogmode='.$ENV{'form.catalogmode'}.                    '&amp;phase=disp_adv'.
                   '&launch='.$ENV{'form.launch'}.                    '&amp;catalogmode='.$env{'form.catalogmode'}.
                   '&mode='.$ENV{'form.mode'},                    '&amp;launch='.$env{'form.launch'}.
                   text=>"Course Search",                    '&amp;mode='.$env{'form.mode'},
                     text=>"Advanced $srchtype Search",
                   bug=>'Searching',});                    bug=>'Searching',});
     }      } 
     ##      ##
     ## Switch on the phase      ## 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);          &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);          &print_advanced_search_form($r,$closebutton,$hidden_fields);
     } elsif ($ENV{'form.phase'} eq 'results') {      } elsif ($env{'form.phase'} eq 'results') {
         &display_results($r,$importbutton,$closebutton,$diropendb);          &display_results($r,$importbutton,$closebutton,$diropendb,
     } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) {                           $env{'form.area'});
         my ($query,$customquery,$customshow,$libraries,$pretty_string) =      } elsif ($env{'form.phase'} =~ /^(sort|run_search)$/) {
           my ($query,$customquery,$customshow,$libraries,$pretty_string,$domainsref) =
             &get_persistent_data($persistent_db_file,              &get_persistent_data($persistent_db_file,
                  ['query','customquery','customshow',                   ['query','customquery','customshow',
                   'libraries','pretty_string']);                    'libraries','pretty_string','domains']);
         if ($ENV{'form.phase'} eq 'sort') {          if ($env{'form.phase'} eq 'sort') {
             &print_sort_form($r,$pretty_string);              &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,              &run_search($r,$query,$customquery,$customshow,
                         $libraries,$pretty_string);                          $libraries,$pretty_string,$env{'form.area'},$domainsref);
         }          }
     } elsif ($ENV{'form.phase'} eq 'course_search') {      } elsif(($env{'form.phase'} eq 'basic_search') ||
         &course_search($r);              ($env{'form.phase'} eq 'adv_search')) {
     } elsif(($ENV{'form.phase'} eq 'basic_search') ||  
             ($ENV{'form.phase'} eq 'adv_search')) {  
         #          #
         # We are running a search, try to parse it          # We are running a search, try to parse it
         my ($query,$customquery,$customshow,$libraries) =           my ($query,$customquery,$customshow,$libraries,$domains) = 
             (undef,undef,undef,undef);              (undef,undef,undef,undef,undef);
         my $pretty_string;          my $pretty_string;
         if ($ENV{'form.phase'} eq 'basic_search') {          if ($env{'form.phase'} eq 'basic_search') {
             ($query,$pretty_string,$libraries) =               ($query,$pretty_string,$libraries,$domains) = 
                 &parse_basic_search($r,$closebutton,$hidden_fields);                  &parse_basic_search($r,$closebutton,$hidden_fields);
             return OK if (! defined($query));              return OK if (! defined($query));
             &make_persistent({ basicexp => $ENV{'form.basicexp'}},              &make_persistent({ basicexp => $env{'form.basicexp'}},
                              $persistent_db_file);                               $persistent_db_file);
         } else {                      # Advanced search          } else {                      # Advanced search
             ($query,$customquery,$customshow,$libraries,$pretty_string)               ($query,$customquery,$customshow,$libraries,$pretty_string,$domains) 
                 = &parse_advanced_search($r,$closebutton,$hidden_fields);                  = &parse_advanced_search($r,$closebutton,$hidden_fields);
             return OK if (! defined($query));              return OK if (! defined($query));
         }          }
Line 358  END Line 351  END
                            customquery => $customquery,                             customquery => $customquery,
                            customshow => $customshow,                             customshow => $customshow,
                            libraries => $libraries,                             libraries => $libraries,
                            pretty_string => $pretty_string },                             pretty_string => $pretty_string,
                              domains => $domains },
                          $persistent_db_file);                           $persistent_db_file);
         #          #
         # Set up table          # Set up table
         if (! defined(&create_results_table())) {          if (! defined(&create_results_table($env{'form.area'}))) {
     my $errorstring=&Apache::lonmysql::get_error();      my $errorstring=&Apache::lonmysql::get_error();
             &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '.              &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '.
                                      'needed table.  lonmysql error:'.                                       'needed table.  lonmysql error:'.
                                      $errorstring);                                       $errorstring);
             $r->print(<<END);  
 <html><head><title>Search Error</title></head>      my $msg = 
 $bodytag   'Unable to create table in which to save search results. '.
 Unable to create table in which to store search results.     'The search has been aborted.';
 The search has been aborted.      &Apache::loncommon::simple_error_page($r,'Search Error',
 </body>    $msg);
 </html>      return OK;
 END  
             return OK;  
         }          }
         delete($ENV{'form.launch'});          delete($env{'form.launch'});
         if (! &make_form_data_persistent($r,$persistent_db_file)) {          if (! &make_form_data_persistent($r,$persistent_db_file)) {
             $r->print(<<END);      my $msg=
 <html><head><title>Search Error</title></head>   'Unable to properly save search information. '.
 $bodytag   'The search has been aborted.';
 Unable to properly store search information.  The search has been aborted.      &Apache::loncommon::simple_error_page($r,'Search Error',
 </body>    $msg);
 </html>      return OK;
 END   }
             return OK;  
         }  
         ##          ##
         ## Print out the frames interface          ## Print out the frames interface
         ##          ##
Line 405  END Line 395  END
 # This routine sets non existant checkbox form elements to ''.  # This routine sets non existant checkbox form elements to ''.
 #  #
 sub clean_up_environment {  sub clean_up_environment {
     if ($ENV{'form.phase'} eq 'basic_search') {      if ($env{'form.phase'} eq 'basic_search') {
         if (! exists($ENV{'form.related'})) {          if (! exists($env{'form.related'})) {
             $ENV{'form.related'} = '';              $env{'form.related'} = '';
         }          }
         if (! exists($ENV{'form.domains'})) {          if (! exists($env{'form.domains'})) {
             $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',          foreach my $field ('title','keywords','notes',
                            'abstract','standards','mime') {                             'abstract','standards','mime') {
             if (! exists($ENV{'form.'.$field.'_related'})) {              if (! exists($env{'form.'.$field.'_related'})) {
                 $ENV{'form.'.$field.'_related'} = '';                  $env{'form.'.$field.'_related'} = '';
             }              }
         }          }
     } elsif ($ENV{'form.phase'} eq 'course_search') {      } elsif ($env{'form.phase'} eq 'course_search') {
         if (! exists($ENV{'form.crsrelated'})) {          if (! exists($env{'form.crsrelated'})) {
             $ENV{'form.crsrelated'} = '';              $env{'form.crsrelated'} = '';
         }          }
     }      }
 }  }
Line 429  sub clean_up_environment { Line 419  sub clean_up_environment {
 sub hidden_field {  sub hidden_field {
     my ($name,$value) = @_;      my ($name,$value) = @_;
     if (! defined($value)) {      if (! defined($value)) {
         $value = $ENV{'form.'.$name};          $value = $env{'form.'.$name};
     }      }
     return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'.$/;      return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'.$/;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  
 ##  
 ##   Course Search  
 ##  
 ######################################################################  
 ######################################################################  
 {   # Scope the course search to avoid global variables  
 #  
 # Variables For course search  
 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 = '<b>'.$ENV{'form.courseexp'}.'</b>';  
     my $search_string = $ENV{'form.courseexp'};  
     my @New_Words;  
     if ($ENV{'form.crsrelated'}) {  
         ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'});  
         if (@New_Words) {  
             $pretty_search_string .= ' '.&mt("with related words").": <b>@New_Words</b>.";  
         } else {  
             $pretty_search_string .= ' '.&mt('with no related words').".";  
         }  
     }  
     my $fulltext=$ENV{'form.crsfulltext'};  
     my @allwords=($search_string,@New_Words);  
     $totalfound=0;  
     $r->print('<html><head><title>LON-CAPA Course Search</title></head>'.  
       $bodytag.'<hr /><center><font size="+2" face="arial">'.$pretty_search_string.'</font></center><hr />');  
     $r->rflush();  
 # ======================================================= Go through the course  
     my $c=$r->connection;  
     if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",  
             &GDBM_READER(),0640)) {  
         foreach (sort(keys(%hash))) {  
             if ($c->aborted()) { last; }  
             if (($_=~/^src\_(.+)$/)) {  
  if ($hash{'randomout_'.$1} & !$ENV{'request.role.adv'}) {  
     next;   
  }  
  my $symb=&make_symb($1);  
                 &checkonthis($r,$1,$hash{$_},0,&Apache::lonnet::gettitle($symb),  
      $fulltext,$symb,@allwords);  
             }  
         }  
         untie(%hash);  
     }  
     unless ($totalfound) {  
  $r->print('<p>'.&mt('No resources found').'.</p>');  
     }  
 # =================================================== Done going through course  
     $r->print('</body></html>');  
 }  
   
 # =============================== This pulls up a resource and its dependencies  
   
 sub checkonthis {  
     my ($r,$id,$url,$level,$title,$fulltext,$symb,@allwords)=@_;  
     $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='.&Apache::lonnet::escape($symb));  
     }  
     $result=~s/\s+/ /gs;  
     my $applies=0;  
     foreach (@allwords) {  
         if ($_=~/\w/) {  
    if ($result=~/$_/si) {  
       $applies++;  
            }  
        }  
     }  
 # Does this resource apply?  
     if ($applies) {  
        $r->print('<br />');  
        for (my $i=0;$i<=$level*5;$i++) {  
            $r->print('&nbsp;');  
        }  
        my $href=$url;  
        if ($hash{'encrypted_'.$id} && !$ENV{'request.role.adv'}) {  
    $href=&Apache::lonenc::encrypted($href)  
        .'?symb='.&Apache::lonenc::encrypted($symb);  
        } else {  
    $href.='?symb='.&Apache::lonnet::escape($symb);  
        }  
        $r->print('<a href="'.$href.'" target="cat">'.($title?$title:$url).  
  '</a><br />');  
        $totalfound++;  
     } elsif ($fulltext) {  
        $r->print(' .');  
     }  
     $r->rflush();  
 # Check also the dependencies of this one  
     my $dependencies=  
                 &Apache::lonnet::metadata($url,'dependencies');  
     foreach (split(/\,/,$dependencies)) {  
        if (($_=~/^\/res\//)) {  
           &checkonthis($r,$id,$_,$level+1,'',$fulltext,undef,@allwords);  
        }  
     }  
 }  
   
 sub untiehash {  
     if (tied(%hash)) {  
         untie(%hash);  
     }  
 }  
   
 } # End of course search scoping  
   
 sub search_html_header {  
     my $Str = <<ENDHEADER;  
 <html>  
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 </head>  
 ENDHEADER  
     return $Str;  
 }  
   
 ######################################################################  =pod
 ######################################################################  
   
 =pod   =over 4
   
 =item &print_basic_search_form()   =item &print_basic_search_form() 
   
Line 590  Prints the form for the basic search.  S Line 440  Prints the form for the basic search.  S
 ######################################################################  ######################################################################
 sub print_basic_search_form {  sub print_basic_search_form {
     my ($r,$closebutton,$hidden_fields) = @_;      my ($r,$closebutton,$hidden_fields) = @_;
     my $result = ($ENV{'form.catalogmode'} ne 'groupsearch');      my $result = ($env{'form.catalogmode'} ne 'import');
     my $bodytag=&Apache::loncommon::bodytag('Search').      my $bread_crumb =
         &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Search_Basic',          &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Basic',
                                    undef,undef,      $env{'form.catalogmode'} ne 'import');
                                    $ENV{'form.catalogmode'} ne 'groupsearch');      my $scrout = &Apache::loncommon::start_page('Content Library').$bread_crumb;
     my $scrout = &search_html_header().$bodytag;  # Search form for resource space 
     if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {      if (&Apache::lonnet::allowed('bre',$env{'request.role.domain'})) {
         # Define interface components          $scrout .= &setup_basic_search($r,'res',$hidden_fields,$closebutton);
         my $userelatedwords=          $scrout .= '<hr /><br />';
             &mt('[_1] use related words',      }
                 &Apache::lonhtmlcommon::checkbox  # Search form for accessible portfolio files
                 ('related',$ENV{'form.related'},'related'));      $scrout.= &setup_basic_search($r,'portfolio',$hidden_fields,$closebutton);
         my $onlysearchdomain=      $scrout .= &Apache::loncommon::end_page();
             &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 =   
             '<a href="/adm/searchcat?'.  
             'phase=disp_adv&'.  
             'catalogmode='.$ENV{'form.catalogmode'}.  
             '&launch='.$ENV{'form.launch'}.  
             '&mode='.$ENV{'form.mode'}.  
             '">'.&mt('Advanced Search').'</a>';  
         #  
         $scrout.='<form name="loncapa_search" method="post" '.  
             'action="/adm/searchcat">'.  
             '<input type="hidden" name="phase" value="basic_search" />'.  
             $hidden_fields;  
         #  
         $scrout .= '<center>'.$/;  
         if ($ENV{'request.course.id'}) {  
             $scrout .= '<h1>'.&mt('LON-CAPA Catalog Search').'</h1>';  
         } else {  
             # No need to tell them they are searching  
             $scrout.= ('<br />'x2);  
         }  
         $scrout.='<table>'.  
             '<tr><td align="center" valign="top">'.  
             &Apache::lonhtmlcommon::textbox  
             ('basicexp',  
              &HTML::Entities::encode($ENV{'form.basicexp'},'<>&"'),50  
              ).  
              '<br />'.  
             '<font size="-1">'.&searchhelp().'</font>'.'</td>'.  
             '<td><font size="-1">'.  
             '<nobr>'.('&nbsp;'x3).$adv_search_link.'</nobr>'.'<br />'.  
             '<nobr>'.('&nbsp;'x1).$userelatedwords.'</nobr>'.'<br />'.  
             '<nobr>'.('&nbsp;'x1).$onlysearchdomain.'</nobr>'.'<br />'.  
             '</font></td>'.  
             '</tr>'.$/;  
         #  
         $scrout .= '<tr><td align="center" colspan="2">'.  
             '<font size="-1">'.  
             '<input type="submit" name="basicsubmit" '.  
             'value="'.&mt('Search').'" />'.  
             ('&nbsp;'x2).$closebutton.('&nbsp;'x2).  
             &viewoptions().  
             '</font>'.  
             '</td></tr>'.$/;  
         $scrout .= '</table>'.$/.'</center>'.'</form>';  
     }  
     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)'  
    );  
         $scrout.=(<<ENDCOURSESEARCH);  
 <form name="loncapa_search" method="post" action="/adm/searchcat">  
 <center>  
 <hr />  
 <h1>$lt{'header'}</h1>      
 <input type="hidden" name="phase" value="course_search" />  
 $hidden_fields  
 <p>  
 $lt{'note'}.  
 </p>  
 <p>  
 <table>  
 <tr><td>  
 ENDCOURSESEARCH  
         $scrout.='&nbsp;'.  
             &Apache::lonhtmlcommon::textbox('courseexp',  
                                   $ENV{'form.courseexp'},40);  
         my $crscheckbox =   
             &Apache::lonhtmlcommon::checkbox('crsfulltext',  
                                    $ENV{'form.crsfulltext'});  
         my $relcheckbox =   
             &Apache::lonhtmlcommon::checkbox('crsrelated',  
    $ENV{'form.crsrelated'});  
         $scrout.=(<<ENDENDCOURSE);  
 </td></tr>  
 <tr><td>$relcheckbox $lt{'use'}</td><td></td></tr>  
 <tr><td>$crscheckbox $lt{'full'}</td><td></td></tr>  
 </table><p>  
 &nbsp;<input type="submit" name="coursesubmit" value='$lt{'srch'}' />  
 </p>  
 </center>  
 </form>  
 ENDENDCOURSE  
     }  
     $scrout.=(<<ENDDOCUMENT);  
 </body>  
 </html>  
 ENDDOCUMENT  
     $r->print($scrout);      $r->print($scrout);
     return;      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 = '<label>'
                         .&Apache::lonhtmlcommon::checkbox(
                              'related',
                              $env{'form.related'},
                              'related')
                         .' '
                        .&mt('use related words')
                        .'</label>';
   
       $onlysearchdomain = '<label>'
                          .&Apache::lonhtmlcommon::checkbox(
                              'domains',
                              $env{'form.domains'},
                              $r->dir_config('lonDefDomain'))
                          .' '
                          .&mt('only search domain [_1]'
                                  ,'<b>'.$r->dir_config('lonDefDomain').'</b>')
                          .'</label>';
   
       $adv_search_link = '<a href="/adm/searchcat?'.
                  &Apache::loncommon::inhibit_menu_check().
          '&amp;phase=disp_adv'.
                          '&amp;catalogmode='.$env{'form.catalogmode'}.
                          '&amp;launch='.$env{'form.launch'}.
                          '&amp;mode='.$env{'form.mode'}.
                          '&amp;area='.$area.
                          '&amp;form='.$env{'form.form'}.
                          '&amp;titleelement='.$env{'form.titleelement'}.
                          '&amp;element='.$env{'form.element'}.
                          '">'.&mt('Advanced Search').'</a>';
       #
       $scrout.='<form name="loncapa_search" method="post" '.
                'action="/adm/searchcat">'.
                '<input type="hidden" name="phase" value="basic_search" />'.
                $hidden_fields;
                if (!exists($env{'form.area'})) {
                    $scrout .= '<input type="hidden" name="area" value="'.$area.'" />';
                }
       #
       $scrout .= '<div align="center">'.$/;
   #    if ($env{'request.course.id'}) {
           $scrout .= '<h1>'.$lt{$area}.'</h1>';
   #    } else {
           # No need to tell them they are searching
   #        $scrout.= ('<br />'x2);
   #    }
       $scrout.='<table>'.
                '<tr><td align="center" valign="top">'.
                &Apache::lonhtmlcommon::textbox('basicexp',
                                                $env{'form.basicexp'},50).
                '<br />'.
               '<span class="LC_fontsize_small">'.&searchhelp().'</span>'.'</td>'.
               '<td>'.
               '<span class="LC_nobreak">'.('&nbsp;'x3).$adv_search_link.'</span>'.'<br />'.
               '<span class="LC_nobreak">'.('&nbsp;'x1).$userelatedwords.'</span>'.'<br />'.
               '<span class="LC_nobreak">'.('&nbsp;'x1).$onlysearchdomain.'</span>'.'<br />'.
               '<span class="LC_nobreak">'.('&nbsp;'x1).$inclext.'</span>'.'<br />'.
                '</td>'.
               '</tr>'.
               '</table>'.$/;
       #
       $scrout .= '<p>'
                 .&viewoptions()
                 .'</p>'
                 .'<p>'
                 .'<input type="submit" name="basicsubmit" '
                 .'value="'.&mt('Search').'" />'
                 .' '
                 .$closebutton
                 .'</p>';
       #
       $scrout .= '</div>'.'</form>';
       return $scrout;
   } 
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
Line 718  Prints the advanced search form. Line 556  Prints the advanced search form.
 ######################################################################  ######################################################################
 sub print_advanced_search_form{  sub print_advanced_search_form{
     my ($r,$closebutton,$hidden_fields) = @_;      my ($r,$closebutton,$hidden_fields) = @_;
     my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search').      my $bread_crumb = 
         &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching',          &Apache::lonhtmlcommon::breadcrumbs('Searching','Search_Advanced',
                                             'Search_Advanced',      $env{'form.catalogmode'} ne 'import');
                                             undef,undef,  
                                   $ENV{'form.catalogmode'} ne 'groupsearch');  
     my %lt=&Apache::lonlocal::texthash('srch' => 'Search',      my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
        'reset' => 'Reset',         'reset' => 'Reset',
        'help' => 'Help');         'help' => 'Help');
     my $advanced_buttons=<<"END";      my $advanced_buttons=<<"END";
   <p>
 <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />  <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />
 <input type="reset" name="reset" value='$lt{"reset"}' />  <input type="reset" name="reset" value='$lt{"reset"}' />
 $closebutton  $closebutton
   </p>
 END  END
     my $scrout=&search_html_header();      my $srchtype = 'Catalog';
     $scrout .= <<"ENDHEADER";      my $jscript;
 $bodytag      if ($env{'form.area'} eq 'portfolio') {
 <form method="post" action="/adm/searchcat" name="advsearch">          $srchtype = 'Portfolio';
 <p>          $jscript = '<script type="text/javascript">
 $advanced_buttons  // <![CDATA[
 ENDHEADER  function additional_metadata() {
     $scrout.=('&nbsp;'x2).&viewoptions().'</p>'.$hidden_fields.       if (document.advsearch.newfield.checked) {
         '<input type="hidden" name="phase" value="adv_search" />';          document.advsearch.phase.value = "disp_adv";
           document.advsearch.numaddedfields.value = parseInt(document.advsearch.numaddedfields.value) +1;
           document.advsearch.submit();
       }
   }
   // ]]>
   </script>';
       }
       my $scrout= &Apache::loncommon::start_page("Advanced $srchtype Search",
                                                  $jscript);
       $scrout .= $bread_crumb;
   
       $scrout .= '<form method="post" action="/adm/searchcat" name="advsearch">'
                 .$hidden_fields 
                 .'<input type="hidden" name="phase" value="adv_search" />';
   
       $scrout .= '<fieldset>'."\n"
                 .'<legend>'.&mt('Display Options').'</legend>'."\n"
                 .&viewoptions()
                 .'</fieldset>';
   
       $scrout .= $advanced_buttons;
   
       $scrout .= &Apache::lonhtmlcommon::start_pick_box();
   
     my %fields=&Apache::lonmeta::fieldnames();      my %fields=&Apache::lonmeta::fieldnames();
     #  
     $scrout .= '<h3>'.&mt('Standard Metadata').'</h3>';      # Standard Metadata
     $scrout .= "<table>\n";      $scrout .= &Apache::lonhtmlcommon::row_headline()
     $scrout .= '<tr><td>&nbsp;</td><td colspan="2"><font size="-1">'.                .'<h3>'.&mt("Standard $srchtype Metadata").'</h3>'
         ('&nbsp;'x2).&searchhelp()."</font></td></tr>\n";                .&searchhelp()
                 .&Apache::lonhtmlcommon::row_closure();
     my %related_word_search =       my %related_word_search = 
         ('title'    => 1,          ('title'    => 1,
          'author'   => 0,           'author'   => 0,
Line 757  ENDHEADER Line 620  ENDHEADER
          'abstract' => 1,           'abstract' => 1,
          'standards'=> 1,           'standards'=> 1,
          'mime'     => 1,           'mime'     => 1,
            'subject'  => 1,
          );           );
     #      #
     foreach my $field ('title','author','owner','authorspace','modifyinguser',      foreach my $field ('title','author','subject','owner','authorspace',
      'keywords','notes','abstract','standards','mime') {                         'modifyinguser','keywords','notes','abstract',
  $scrout.='<tr><td align="right">'.&titlefield($fields{$field}).'</td><td>'.                         'standards','mime') {
     &Apache::lonmeta::prettyinput($field,          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield($fields{$field}))
                                           $ENV{'form.'.$field},                    .&Apache::lonmeta::prettyinput($field,
                                             $env{'form.'.$field},
                                           $field,                                            $field,
                                           'advsearch',                                            'advsearch',
   $related_word_search{$field},                                            $related_word_search{$field},
                                           '</td><td align="left">',                                            '',
                                           $ENV{'form.'.$field.'_related'},                                            $env{'form.'.$field.'_related'},
                                           50);                                            50);
         if ($related_word_search{$field}) {          if ($related_word_search{$field}) {
             $scrout .= 'related words';              $scrout .= &mt('related words');
         } else {          } else {
             $scrout .= '</td><td>&nbsp;';              $scrout .= '';
         }          }
         $scrout .= '</td></tr>'.$/;          $scrout .= &Apache::lonhtmlcommon::row_closure();
     }      }
     foreach my $field ('lowestgradelevel','highestgradelevel') {      foreach my $field ('lowestgradelevel','highestgradelevel') {
  $scrout.='<tr>'.          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield($fields{$field}))
             '<td align="right">'.&titlefield($fields{$field}).'</td>'.                    .&Apache::lonmeta::prettyinput($field,
             '<td colspan="2">'.                                            $env{'form.'.$field},
     &Apache::lonmeta::prettyinput($field,  
                                           $ENV{'form.'.$field},  
                                           $field,                                            $field,
                                           'advsearch',                                            'advsearch',
   0).                                            0)
                                           '</td></tr>'.$/;                    .&Apache::lonhtmlcommon::row_closure();
     }      }
     $scrout.='<tr><td align="right">'.  
  &titlefield(&mt('MIME Type Category')).'</td><td colspan="2">'.       $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('MIME Type Category')))
     &Apache::loncommon::filecategoryselect('category',                .&Apache::loncommon::filecategoryselect('category',
    $ENV{'form.category'}).                     $env{'form.category'})
     '</td></tr>'.$/;                .&Apache::lonhtmlcommon::row_closure();
     $scrout.='<tr><td align="right" valign="top">'.  
  &titlefield(&mt('Domains')).'</td><td colspan="2">'.       $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Domains')))
     &Apache::loncommon::domain_select('domains',                .&Apache::loncommon::domain_select('domains',
    $ENV{'form.domains'},1).                     $env{'form.domains'},1)
     '</td></tr>'.$/;                .&Apache::lonhtmlcommon::row_closure();
     #  
     # Misc metadata      # Misc metadata
     $scrout.='<tr><td align="right" valign="top">'.      if ($env{'form.area'} ne 'portfolio') {
  &titlefield(&mt('Copyright/Distribution')).'</td><td colspan="2">'.          $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Copyright/Distribution')))
         &Apache::lonmeta::selectbox('copyright',                    .&Apache::lonmeta::selectbox('copyright',
                                     $ENV{'form.copyright'},                                               $env{'form.copyright'},
                                     \&Apache::loncommon::copyrightdescription,                                  \&Apache::loncommon::copyrightdescription,
                                     ( undef,                                         ( undef,
                                       &Apache::loncommon::copyrightids)                                          &Apache::loncommon::copyrightids)
                                     ).'</td></tr>'.$/;                                  )
     $scrout.='<tr><td align="right" valign="top">'.                    .&Apache::lonhtmlcommon::row_closure();
  &titlefield(&mt('Language')).'</td><td colspan="2">'.      }
         &Apache::lonmeta::selectbox('language',  
                                     $ENV{'form.language'},      $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt('Language')))
                 .&Apache::lonmeta::selectbox('language',
                                       $env{'form.language'},
                                     \&Apache::loncommon::languagedescription,                                      \&Apache::loncommon::languagedescription,
                                     ('any',&Apache::loncommon::languageids)                                      ('any',&Apache::loncommon::languageids)
                                     ).'</td></tr>';                                      )
     $scrout .= "</table>\n";                    .&Apache::lonhtmlcommon::row_closure();
     #      
     # Dynamic metadata      # Portfolio Metadata
     $scrout .= '<h3>'.&mt('Problem Statistics').'</h3>';      if ($env{'form.area'} eq 'portfolio') {
     $scrout .= "<table>\n";          # Added fields
     $scrout .= '<tr><td>&nbsp;</td><td align="center">'.&mt('Minimum').'</td>'.          my $curnumadd = $env{'form.numaddedfields'};
         '<td align="center">'.&mt('Maximum').'</td></tr>'."\n";          if ($curnumadd eq '') {
     foreach my $statistic               $curnumadd = 1;
         ({ name=>'count',          }
            description=>'Network-wide number of accesses (hits)',},          $scrout .= &Apache::lonhtmlcommon::row_headline()
          { name=>'stdno',                    .'<h3>'.&mt('Custom Metadata fields').'</h3>'
            description=>                    .&Apache::lonhtmlcommon::row_closure()
                'Total number of students who have worked on this problem',},                    .&Apache::lonhtmlcommon::row_title('')
          { name => 'avetries',                    .&mt('Field Name').' | '.&mt('Field Value(s)')
            description=>'Average number of tries till solved',},                    .&Apache::lonhtmlcommon::row_closure();
          { name => 'difficulty',  
            description=>'Degree of difficulty',},          for (my $j=0; $j<$curnumadd; $j++) {
          { name => 'disc',              my $num = $j+1;
            description=>'Degree of discrimination'}) {              $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Custom metadata [_1]',$num))
         $scrout .= '<tr><td align="right">'.                        .'<input type="text"'
             &titlefield(&mt($statistic->{'description'})).                        .' name="addedfield_'.$j.'" size="10"'
             '</td><td align="center">'.                        .' value="'.$env{'form.addedfield_'.$j}.'" />'
             '<input type="text" name="'.$statistic->{'name'}.'_min" '.                        .' '
             'value="" size="6" />'.                        .'<input type="text" '
             '</td><td align="center">'.                        .'name="addedvalues_'.$j.'" size="15"'
             '<input type="text" name="'.$statistic->{'name'}.'_max" '.                        .' value="'.$env{'form.addedvalues_'.$j}.'" />'
             'value="" size="6" />'.                        .&Apache::lonhtmlcommon::row_closure();
             '</td></tr>'.$/;          }
     }          $scrout .= &Apache::lonhtmlcommon::row_title('')
     $scrout .= "</table>\n";                    .'<label>'
     $scrout .= '<h3>'.&mt('Evaluation Data').'</h3>';                    .'<input type="checkbox" name="newfield"'
     $scrout .= "<table>\n";                    .' value="1" onclick="javascript:additional_metadata()" />'
     $scrout .= '<tr><td>&nbsp;</td><td align="center">'.&mt('Minimum').'</td>'.                    .&mt('Another custom field/value pair?').'</label>'
         '<td align="center">'.&mt('Maximum').'</td></tr>'."\n";                    .'<input type="hidden" name="numaddedfields"'
     foreach my $evaluation                    .' value="'.$curnumadd.'" />'
         ( { name => 'clear',                    .&Apache::lonhtmlcommon::row_closure();
             description => 'Material presented in clear way'},  } else {
           { name =>'depth',          #
             description => 'Material covered with sufficient depth'},          # Dynamic metadata
           { name => 'helpful',          $scrout .= &Apache::lonhtmlcommon::row_headline()
             description => 'Material is helpful'},                    .'<h3>'.&mt('Problem Statistics').'</h3>'
           { name => 'correct',                    .&Apache::lonhtmlcommon::row_closure();
             description => 'Material appears to be correct'},          $scrout .= &Apache::lonhtmlcommon::row_title('')
           { name => 'technical',                    .&mt('Minimum').' | '.&mt('Maximum')
             description => 'Resource is technically correct'}){                    .&Apache::lonhtmlcommon::row_closure();
         $scrout .= '<tr><td align="right">'.          foreach my $statistic 
             &titlefield(&mt($evaluation->{'description'})).              ({ name=>'count',
             '</td><td align="center">'.                 description=>'Network-wide number of accesses (hits)',},
             '<input type="text" name="'.$evaluation->{'name'}.'_min" '.               { name=>'stdno',
             'value="" size="6" />'.                 description=>
             '</td><td align="center">'.                 'Statistics calculated for number of students',},
             '<input type="text" name="'.$evaluation->{'name'}.'_max" '.               { name => 'avetries',
             'value="" size="6" />'.                 description=>'Average number of tries till solved',},
             '</td></tr>'.$/;               { name => 'difficulty',
                  description=>'Degree of difficulty',},
                { name => 'disc',
                  description=>'Degree of discrimination'}) {
                 $scrout .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt($statistic->{'description'})))
                           .'<input type="text" name="'.$statistic->{'name'}
                           .'_min" value="" size="6" />'
                           .' '
                           .'<input type="text" name="'.$statistic->{'name'}
                           .'_max" value="" size="6" />'
                           .&Apache::lonhtmlcommon::row_closure();
           }
   
           $scrout .= &Apache::lonhtmlcommon::row_headline()
                     .'<h3>'.&mt('Evaluation Data').'</h3>'
                     .&Apache::lonhtmlcommon::row_closure();
           $scrout .= &Apache::lonhtmlcommon::row_title('')
                     .&mt('Minimum').' | '.&mt('Maximum')
                     .&Apache::lonhtmlcommon::row_closure();
           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 .= &Apache::lonhtmlcommon::row_title(&titlefield(&mt($evaluation->{'description'})))
                         .'<input type="text" name="'
                         .$evaluation->{'name'}.'_min" value="" size="6" />'
                         .' '
                         .'<input type="text" name="'
                         .$evaluation->{'name'}.'_max" value="" size="6" />'
                         .&Apache::lonhtmlcommon::row_closure();
           }
     }      }
     $scrout .= "</table>\n";  
     #      #
     # Creation/Modification date limits      # Creation/Modification date limits
     $scrout .= '<h3>'.&mt('Creation and Modification dates').'</h3>';      $scrout .= &Apache::lonhtmlcommon::row_headline()
     $scrout .= "\n<table>\n";                .'<h3>'.&mt('Creation and Modification dates').'</h3>'
                 .&Apache::lonhtmlcommon::row_closure();
       $scrout .= &Apache::lonhtmlcommon::row_title('')
                 .&mt('Month[_1]Day[_2]Year','&nbsp;'x14,'&nbsp;'x6)
                 .&Apache::lonhtmlcommon::row_closure();
   
     my $cafter =       my $cafter = 
         &Apache::lonhtmlcommon::date_setter('advsearch',         # formname          &Apache::lonhtmlcommon::date_setter('advsearch',         # formname
                                             'creationdate1', # fieldname                                              'creationdate1', # fieldname
Line 893  ENDHEADER Line 799  ENDHEADER
                                             '',          # state                                              '',          # state
                                             1,           # no_hh_mm_ss                                              1,           # no_hh_mm_ss
                                             );                                              );
     $scrout .= &mt('<tr><td align="right">Created between</td>'.      $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Created between'))
                    '<td>[_1]</td></tr>'.                .$cafter
                    '<tr><td align="right">and </td>'.                .&Apache::lonhtmlcommon::row_closure(1)
                    '<td>[_2]</td></tr>',$cafter,$cbefore);                .&Apache::lonhtmlcommon::row_title(&mt('and'))
                 .$cbefore
                 .&Apache::lonhtmlcommon::row_closure();
   
     my $lafter =       my $lafter = 
         &Apache::lonhtmlcommon::date_setter('advsearch',          &Apache::lonhtmlcommon::date_setter('advsearch',
                                             'revisiondate1',                                               'revisiondate1', 
Line 915  ENDHEADER Line 824  ENDHEADER
                                             '',          # state                                              '',          # state
                                             1,           # no_hh_mm_ss                                              1,           # no_hh_mm_ss
                                             );                                              );
     $scrout .= &mt('<tr><td align="right">Last modified between </td>'.      $scrout .= &Apache::lonhtmlcommon::row_title(&mt('Last modified between'))
                    '<td>[_1]</td></tr>'.                .$lafter
                    '<tr><td align="right">and</td>'.                .&Apache::lonhtmlcommon::row_closure(1)
                    '<td>[_2]</td></tr>',$lafter,$lbefore);                .&Apache::lonhtmlcommon::row_title(&mt('and'))
     $scrout.="</table>\n";                .$lbefore
     $scrout.=<<ENDDOCUMENT;                .&Apache::lonhtmlcommon::row_closure(1); # Last row of total pick_box
 $advanced_buttons  
 </form>      $scrout .= &Apache::lonhtmlcommon::end_pick_box();
 </body>  
 </html>      $scrout .= $advanced_buttons
 ENDDOCUMENT                .'</form>';
   
       $scrout .= &Apache::loncommon::end_page();
     $r->print($scrout);      $r->print($scrout);
     return;      return;
 }  }
Line 972  sub viewoptiontext { Line 883  sub viewoptiontext {
          'xml' => 'XML/SGML',           'xml' => 'XML/SGML',
          'compact' => 'Compact View',           'compact' => 'Compact View',
          'fielded' => 'Fielded Format',           'fielded' => 'Fielded Format',
          'summary' => 'Summary View');           'summary' => 'Summary View',
            'summarypreview' => 'Summary Preview',
            'detailedpreview' => 'Detailed Citation Preview');
     return $desc{$code};      return $desc{$code};
 }  }
   
Line 993  Outputs: text for box with view options Line 906  Outputs: text for box with view options
 ######################################################################  ######################################################################
 sub viewoptions {  sub viewoptions {
     my $scrout;      my $scrout;
     if (! defined($ENV{'form.viewselect'})) {       if (! defined($env{'form.viewselect'})) { 
         $ENV{'form.viewselect'}='detailed';           $env{'form.viewselect'}='detailed'; 
     }      }
     $scrout.=&Apache::lonmeta::selectbox('viewselect',      $scrout .= '<span class="LC_nobreak">'
  $ENV{'form.viewselect'},                .&mt('Type:').' '
  \&viewoptiontext,                .&Apache::lonmeta::selectbox('viewselect',
  sort(keys(%Views)));                     $env{'form.viewselect'},
     $scrout.= '&nbsp;&nbsp;';                     \&viewoptiontext,
                      sort(keys(%Views)))
                 .'</span>';
     my $countselect = &Apache::lonmeta::selectbox('show',      my $countselect = &Apache::lonmeta::selectbox('show',
                                                   $ENV{'form.show'},                                                    $env{'form.show'},
                                                   undef,                                                    undef,
                                                   (10,20,50,100,1000,10000));                                                    (10,20,50,100,1000,10000));
     $scrout .= ('&nbsp;'x2).&mt('[_1] Records per Page',$countselect).      $scrout .= ' <span class="LC_nobreak">'
         '</nobr>'.$/;                .&mt('Records per Page:').' '.$countselect
                 .'</span>'.$/;
     return $scrout;      return $scrout;
 }  }
   
Line 1042  Outputs: returns undef on database error Line 958  Outputs: returns undef on database error
   
 This function is the reverse of &make_persistent() for form data.  This function is the reverse of &make_persistent() for form data.
 Retrieve persistent data from %persistent_db.  Retrieved items will have their  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  overwritten.  Form values that are array references may have values appended
 to them.  to them.
   
Line 1064  sub get_persistent_form_data { Line 980  sub get_persistent_form_data {
         next if ($name !~ /^form./);          next if ($name !~ /^form./);
         # Kludgification begins!          # Kludgification begins!
         if ($name eq 'form.domains' &&           if ($name eq 'form.domains' && 
             $ENV{'form.searchmode'} eq 'basic' &&              $env{'form.searchmode'} eq 'basic' &&
             $ENV{'form.phase'} ne 'disp_basic') {              $env{'form.phase'} ne 'disp_basic') {
             next;              next;
         }          }
         # End kludge (hopefully)          # End kludge (hopefully)
         next if (exists($ENV{$name}));          next if (exists($env{$name}));
         my @values = map {           my @values = map { 
             &Apache::lonnet::unescape($_);              &unescape($_);
         } split(',',$persistent_db{$name});          } split(',',$persistent_db{$name});
         next if (@values <1);          next if (@values <1);
         if ($arrays_allowed{$name}) {          if ($arrays_allowed{$name}) {
             $ENV{$name} = [@values];              $env{$name} = [@values];
         } else {          } else {
             $ENV{$name} = $values[0] if ($values[0]);              $env{$name} = $values[0] if ($values[0]);
         }          }
     }      }
     untie (%persistent_db);      untie (%persistent_db);
Line 1097  Outputs: array of values.  Returns undef Line 1013  Outputs: array of values.  Returns undef
   
 This function is the reverse of &make_persistent();  This function is the reverse of &make_persistent();
 Retrieve persistent data from %persistent_db.  Retrieved items will have their  Retrieve persistent data from %persistent_db.  Retrieved items will have their
 values unescaped.  If the item contains commas (before unescaping), the  values unescaped.  If the item is 'domains; then the returned
 returned value will be an array pointer.   value will be a hash pointer.  Otherwise, if the item contains
   commas (before unescaping), the returned value will be an array pointer.
   
 =cut  =cut
   
Line 1116  sub get_persistent_data { Line 1033  sub get_persistent_data {
             push @Values, undef;              push @Values, undef;
             next;              next;
         }          }
         my @values = map {           if ($name eq 'domains') {
             &Apache::lonnet::unescape($_);              my %valueshash;
         } split(',',$persistent_db{$name});              my @items= map { &unescape($_); } split(',',$persistent_db{$name});
         if (@values <= 1) {              foreach my $item (@items) {
             push @Values,$values[0];                  if ($item =~ /=/) {
                       my ($key,$val) = map { &unescape($_); } split(/=/,$item);
                       $valueshash{$key} = $val;
                   }
               }
               push(@Values,\%valueshash);
         } else {          } else {
             push @Values,\@values;              my @values = map { 
                   &unescape($_);
               } split(',',$persistent_db{$name});
               if (@values <= 1) {
                   push @Values,$values[0];
               } else {
                   push @Values,\@values;
               }
         }          }
     }      }
     untie (%persistent_db);      untie (%persistent_db);
Line 1140  Inputs: Hash of values to save, filename Line 1069  Inputs: Hash of values to save, filename
   
 Store variables away to the %persistent_db.  Store variables away to the %persistent_db.
 Values will be escaped.  Values that are array pointers will have their  Values will be escaped.  Values that are array pointers will have their
 elements escaped and concatenated in a comma separated string.    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  =cut
   
Line 1152  sub make_persistent { Line 1083  sub make_persistent {
     return undef if (! tie(%persistent_db,'GDBM_File',      return undef if (! tie(%persistent_db,'GDBM_File',
                            $filename,&GDBM_WRCREAT(),0640));                             $filename,&GDBM_WRCREAT(),0640));
     foreach my $name (keys(%save)) {      foreach my $name (keys(%save)) {
         my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));          my @values=();
         # We handle array references, but not recursively.          if (ref($save{$name}) eq 'ARRAY') {
         my $store = join(',', map { &Apache::lonnet::escape($_); } @values );              @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;          $persistent_db{$name} = $store;
     }      }
     untie(%persistent_db);      untie(%persistent_db);
Line 1182  sub make_form_data_persistent { Line 1122  sub make_form_data_persistent {
     my $r = shift;      my $r = shift;
     my $filename = shift;      my $filename = shift;
     my %save;      my %save;
     foreach (keys(%ENV)) {      foreach (keys(%env)) {
         next if (!/^form/ || /submit/);          next if (!/^form/ || /submit/);
         $save{$_} = $ENV{$_};          $save{$_} = $env{$_};
     }      }
     return &make_persistent(\%save,$filename);      return &make_persistent(\%save,$filename);
 }  }
Line 1232  sub parse_advanced_search { Line 1172  sub parse_advanced_search {
    'lastrevisiondatestart_month','lastrevisiondatestart_day',     'lastrevisiondatestart_month','lastrevisiondatestart_day',
    'lastrevisiondatestart_year','lastrevisiondateend_month',     'lastrevisiondatestart_year','lastrevisiondateend_month',
    'lastrevisiondateend_day','lastrevisiondateend_year') {     'lastrevisiondateend_day','lastrevisiondateend_year') {
  $ENV{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $env{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\'.\*]//g;
     }      }
     foreach ('mode','form','element') {      foreach ('mode','form','element') {
  # is this required?  Hmmm.   # is this required?  Hmmm.
  next if (! exists($ENV{'form.'.$_}));   next if (! exists($env{'form.'.$_}));
  $ENV{'form.'.$_}=&Apache::lonnet::unescape($ENV{'form.'.$_});   $env{'form.'.$_}=&unescape($env{'form.'.$_});
  $ENV{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $env{'form.'.$_}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
     # Preprocess the category form element.      # Preprocess the category form element.
     $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) ||      $env{'form.category'} = 'any' if (! defined($env{'form.category'}) ||
                                       ref($ENV{'form.category'}));                                        ref($env{'form.category'}));
     #      #
     # Check to see if enough information was filled in      # Check to see if enough information was filled in
     foreach my $field (@BasicFields) {      foreach my $field (@BasicFields) {
  if (&filled($ENV{'form.'.$field})) {   if (&filled($env{'form.'.$field})) {
     $fillflag++;      $fillflag++;
  }   }
     }      }
     foreach my $field (@StatsFields,@EvalFields) {      foreach my $field (@StatsFields,@EvalFields) {
         if (&filled($ENV{'form.'.$field.'_max'})) {          if (&filled($env{'form.'.$field.'_max'})) {
             $fillflag++;              $fillflag++;
         }          }
         if (&filled($ENV{'form.'.$field.'_min'})) {          if (&filled($env{'form.'.$field.'_min'})) {
             $fillflag++;              $fillflag++;
         }          }
     }      }
   
     for my $field ('lowestgradelevel','highestgradelevel') {      for my $field ('lowestgradelevel','highestgradelevel') {
         if ( $ENV{'form.'.$field} =~ /^\d+$/ &&          if ( $env{'form.'.$field} =~ /^\d+$/ &&
              $ENV{'form.'.$field} > 0) {               $env{'form.'.$field} > 0) {
             $fillflag++;              $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) {      if (! $fillflag) {
  &output_blank_field_error($r,$closebutton,   &output_blank_field_error($r,$closebutton,
                                   'phase=disp_adv',$hidden_fields);                                    'phase=disp_adv',$hidden_fields);
Line 1276  sub parse_advanced_search { Line 1227  sub parse_advanced_search {
     my $font = '<font color="#800000" face="helvetica">';      my $font = '<font color="#800000" face="helvetica">';
     # Evaluate logical expression AND/OR/NOT phrase fields.      # Evaluate logical expression AND/OR/NOT phrase fields.
     foreach my $field (@BasicFields) {      foreach my $field (@BasicFields) {
  next if (!defined($ENV{'form.'.$field}) || $ENV{'form.'.$field} eq '');   next if (!defined($env{'form.'.$field}) || $env{'form.'.$field} eq '');
         my ($error,$SQLQuery) =           my ($error,$SQLQuery) = 
             &process_phrase_input($ENV{'form.'.$field},              &process_phrase_input($env{'form.'.$field},
                                   $ENV{'form.'.$field.'_related'},$field);                                    $env{'form.'.$field.'_related'},$field);
         if (defined($error)) {          if (defined($error)) {
             &output_unparsed_phrase_error($r,$closebutton,'phase=disp_adv',              &output_unparsed_phrase_error($r,$closebutton,'phase=disp_adv',
                                          $hidden_fields,$field);                                           $hidden_fields,$field);
             return;              return;
         } else {          } else {
             $pretty_search_string .=               $pretty_search_string .= 
                 $font.$field.'</font>: '.$ENV{'form.'.$field};                  $font.$field.'</font>: '.$env{'form.'.$field};
             if ($ENV{'form.'.$field.'_related'}) {              if ($env{'form.'.$field.'_related'}) {
                 my @Words =                   my @Words = 
                     &Apache::loncommon::get_related_words                      &Apache::loncommon::get_related_words
                     ($ENV{'form.'.$field});                      ($env{'form.'.$field});
                 if (@Words) {                  if (@Words) {
                     $pretty_search_string.= ' with related words: '.                      $pretty_search_string.= ' with related words: '.
                         join(', ',@Words[0..4]);                          join(', ',@Words[0..4]);
Line 1306  sub parse_advanced_search { Line 1257  sub parse_advanced_search {
     # Make the 'mime' from 'form.category' and 'form.extension'      # Make the 'mime' from 'form.category' and 'form.extension'
     #      #
     my $searchphrase;      my $searchphrase;
     if (exists($ENV{'form.category'})    &&       if (exists($env{'form.category'})    && 
         $ENV{'form.category'} !~ /^\s*$/ &&          $env{'form.category'} !~ /^\s*$/ &&
         $ENV{'form.category'} ne 'any')     {          $env{'form.category'} ne 'any')     {
         my @extensions = &Apache::loncommon::filecategorytypes          my @extensions = &Apache::loncommon::filecategorytypes
                                                    ($ENV{'form.category'});                                                     ($env{'form.category'});
         if (scalar(@extensions) > 0) {          if (scalar(@extensions) > 0) {
             $searchphrase = join(' OR ',@extensions);              $searchphrase = join(' OR ',@extensions);
         }          }
Line 1323  sub parse_advanced_search { Line 1274  sub parse_advanced_search {
     }      }
     #      #
     # Evaluate option lists      # Evaluate option lists
     if ($ENV{'form.lowestgradelevel'}        &&      if ($env{'form.lowestgradelevel'}        &&
         $ENV{'form.lowestgradelevel'} ne '0' &&          $env{'form.lowestgradelevel'} ne '0' &&
         $ENV{'form.lowestgradelevel'} =~ /^\d+$/) {          $env{'form.lowestgradelevel'} =~ /^\d+$/) {
  push(@queries,   push(@queries,
              '(lowestgradelevel>='.$ENV{'form.lowestgradelevel'}.')');               '(lowestgradelevel>='.$env{'form.lowestgradelevel'}.')');
         $pretty_search_string.="lowestgradelevel>=".          $pretty_search_string.="lowestgradelevel>=".
             $ENV{'form.lowestgradelevel'}."<br />\n";              $env{'form.lowestgradelevel'}."<br />\n";
     }      }
     if ($ENV{'form.highestgradelevel'}        &&      if ($env{'form.highestgradelevel'}        &&
         $ENV{'form.highestgradelevel'} ne '0' &&          $env{'form.highestgradelevel'} ne '0' &&
         $ENV{'form.highestgradelevel'} =~ /^\d+$/) {          $env{'form.highestgradelevel'} =~ /^\d+$/) {
  push(@queries,   push(@queries,
              '(highestgradelevel<='.$ENV{'form.highestgradelevel'}.')');               '(highestgradelevel<='.$env{'form.highestgradelevel'}.')');
         $pretty_search_string.="highestgradelevel<=".          $pretty_search_string.="highestgradelevel<=".
             $ENV{'form.highestgradelevel'}."<br />\n";              $env{'form.highestgradelevel'}."<br />\n";
     }      }
     if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {      if ($env{'form.language'} and $env{'form.language'} ne 'any') {
  push @queries,"(language like \"$ENV{'form.language'}\")";   push @queries,"(language like \"$env{'form.language'}\")";
         $pretty_search_string.=$font."language</font>= ".          $pretty_search_string.=$font."language</font>= ".
             &Apache::loncommon::languagedescription($ENV{'form.language'}).              &Apache::loncommon::languagedescription($env{'form.language'}).
                 "<br />\n";                  "<br />\n";
     }      }
     if ($ENV{'form.copyright'} and $ENV{'form.copyright'} ne 'any') {      if ($env{'form.copyright'} and $env{'form.copyright'} ne 'any') {
  push @queries,"(copyright like \"$ENV{'form.copyright'}\")";   push @queries,"(copyright like \"$env{'form.copyright'}\")";
         $pretty_search_string.=$font."copyright</font> = ".          $pretty_search_string.=$font."copyright</font> = ".
             &Apache::loncommon::copyrightdescription($ENV{'form.copyright'}).              &Apache::loncommon::copyrightdescription($env{'form.copyright'}).
                 "<br />\n";                  "<br />\n";
     }      }
     #      if ($env{'form.area'} eq 'portfolio') {
     # Statistics          #
     foreach my $field (@StatsFields,@EvalFields) {          # Added metadata fields
         my ($min,$max);          for (my $i=0; $i<$env{'form.numaddedfields'} ; $i++) {
         if (exists($ENV{'form.'.$field.'_min'}) &&               my $field = $env{'form.addedfield_'.$i};
             $ENV{'form.'.$field.'_min'} ne '') {              $field =~ s/^\s*(\S*)\s*$/$1/;
             $min = $ENV{'form.'.$field.'_min'};              $field =~ s/\W/_/g;
         }              $field =~ tr/A-Z/a-z/; 
         if (exists($ENV{'form.'.$field.'_max'}) &&              if ($field ne '') {
             $ENV{'form.'.$field.'_max'} ne '') {                  my $value = $env{'form.addedvalues_'.$i};
             $max = $ENV{'form.'.$field.'_max'};                  if ($value ne '') {
         }                      $value =~ s/'/''/g; #' stupid emacs
         next if (! defined($max) && ! defined($min));                      my ($error,$query) = 
         if (defined($min) && defined($max)) {                          &process_phrase_input($value,0,'pf.value');
             ($min,$max) = sort {$a <=>$b} ($min,$max);                      if (!defined($error)) {
         }                          push(@queries,"pf.field = '$field' AND $query");
         if (defined($min) && $min =~ /^(\d+\.\d+|\d+|\.\d+)$/) {                          $pretty_search_string .=
             push(@queries,'('.$field.'>'.$min.')');                              $font.$field.'</font>: '.
             $pretty_search_string.=$font.$field.'</font>&gt;'.$min.'<br />';                              $env{'form.addedvalues_'.$i}.'<br />';
         }                      }
         if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) {                  } else {
             push(@queries,'('.$field.'<'.$max.')');                      push(@queries,"pf.field = '$field' AND pf.value IS NULL");
             $pretty_search_string.=$font.$field.'</font>&lt;'.$max.'<br />';                  }
               }
           }
       } 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.'</font>&gt;'.$min.'<br />';
               }
               if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) {
                   push(@queries,'('.$field.'<'.$max.')');
                   $pretty_search_string.=$font.$field.'</font>&lt;'.$max.'<br />';
               }
         }          }
     }      }
     #      #
Line 1414  sub parse_advanced_search { Line 1392  sub parse_advanced_search {
     ## because I was unable to figureout exactly how it worked and could      ## because I was unable to figureout exactly how it worked and could
     ## not imagine people actually using it.  MH      ## not imagine people actually using it.  MH
     ##      ##
     # if ($ENV{'form.custommetadata'}) {      # if ($env{'form.custommetadata'}) {
     #    $pretty_search_string .=$font."Custom Metadata Search</font>: <b>".      #    $pretty_search_string .=$font."Custom Metadata Search</font>: <b>".
     #    $ENV{'form.custommetadata'}."</b><br />\n";      #    $env{'form.custommetadata'}."</b><br />\n";
     #    $customquery=&build_custommetadata_query('custommetadata',      #    $customquery=&build_custommetadata_query('custommetadata',
     #                                             $ENV{'form.custommetadata'});      #                                             $env{'form.custommetadata'});
     # }      # }
     my $customshow=undef;      my $customshow=undef;
     # if ($ENV{'form.customshow'}) {      # if ($env{'form.customshow'}) {
     # $pretty_search_string .=$font."Custom Metadata Display</font>: <b>".      # $pretty_search_string .=$font."Custom Metadata Display</font>: <b>".
     #                         $ENV{'form.customshow'}."</b><br />\n";      #                         $env{'form.customshow'}."</b><br />\n";
     #    $customshow=$ENV{'form.customshow'};      #    $customshow=$env{'form.customshow'};
     #    $customshow=~s/[^\w\s]//g;      #    $customshow=~s/[^\w\s]//g;
     #    my @fields=split(/\s+/,$customshow);      #    my @fields=split(/\s+/,$customshow);
     #    $customshow=join(" ",@fields);      #    $customshow=join(" ",@fields);
Line 1432  sub parse_advanced_search { Line 1410  sub parse_advanced_search {
     ##      ##
     ## Deal with restrictions to given domains      ## Deal with restrictions to given domains
     ##       ## 
     my ($libraries_to_query,$pretty_domains_string) =       my ($libraries_to_query,$pretty_domains_string,$domains_to_query) = 
         &parse_domain_restrictions();          &parse_domain_restrictions();
     $pretty_search_string .= $pretty_domains_string."<br />\n";      if ($pretty_domains_string) {
          $pretty_search_string .= $pretty_domains_string."<br />\n";
       }
     #      #
     if (@queries) {      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 < UTC_TIMESTAMP() AND (pa.end IS NULL OR pa.end > UTC_TIMESTAMP())) AND (".join(') AND (',@queries).'))';
           } else {
       $query="SELECT * FROM metadata WHERE (".join(") AND (",@queries).')';
           }
     } elsif ($customquery) {      } elsif ($customquery) {
         $query = '';          $query = '';
     }      }
     # &Apache::lonnet::logthis('query = '.$/.$query);      #&Apache::lonnet::logthis('advanced query = '.$/.$query);
     return ($query,$customquery,$customshow,$libraries_to_query,      return ($query,$customquery,$customshow,$libraries_to_query,
             $pretty_search_string);              $pretty_search_string,$domains_to_query);
 }  }
   
 sub parse_domain_restrictions {  sub parse_domain_restrictions {
     my $libraries_to_query = undef;      my $libraries_to_query = undef;
     # $ENV{'form.domains'} can be either a scalar or an array reference.      my $domains_to_query = undef;
       # $env{'form.domains'} can be either a scalar or an array reference.
     # We need an array.      # We need an array.
     if (! exists($ENV{'form.domains'}) || $ENV{'form.domains'} eq '') {      if (! exists($env{'form.domains'}) || $env{'form.domains'} eq '') {
         return (undef,'');          return (undef,'',undef);
     }  
     my @allowed_domains;  
     if (ref($ENV{'form.domains'})) {  
         @allowed_domains =  @{$ENV{'form.domains'}};  
     } else {  
         @allowed_domains = ($ENV{'form.domains'});  
     }      }
       my @allowed_domains = &Apache::loncommon::get_env_multiple('form.domains');
     #      #
     my %domain_hash = ();      my %domain_hash = ();
     my $pretty_domains_string;      my $pretty_domains_string;
Line 1466  sub parse_domain_restrictions { Line 1446  sub parse_domain_restrictions {
         $domain_hash{$_}++;          $domain_hash{$_}++;
     }      }
     if ($domain_hash{'any'}) {      if ($domain_hash{'any'}) {
         $pretty_domains_string = "In all LON-CAPA domains.";          $pretty_domains_string = &mt("in all LON-CAPA domains.");
     } else {      } else {
         if (@allowed_domains > 1) {          if (@allowed_domains > 1) {
             $pretty_domains_string = "In LON-CAPA domains:";              $pretty_domains_string = &mt("in LON-CAPA domains:");
         } else {          } else {
             $pretty_domains_string = "In LON-CAPA domain ";              $pretty_domains_string = &mt("in LON-CAPA domain ");
         }          }
         foreach (sort @allowed_domains) {          foreach (sort @allowed_domains) {
             $pretty_domains_string .= "<b>".$_."</b> ";              $pretty_domains_string .= "<b>".$_."</b> ";
         }          }
         foreach (keys(%Apache::lonnet::libserv)) {   my %library_servers = &Apache::lonnet::get_unique_servers(\@allowed_domains,
             if (exists($domain_hash{$Apache::lonnet::hostdom{$_}})) {                    'library');
                 push @$libraries_to_query,$_;          my (%older_library_servers,%okdoms,%domains_for_id);
           map { $okdoms{$_} = 1; } @allowed_domains;
           foreach my $key (keys(%library_servers)) {
               if (&Apache::lonnet::get_server_loncaparev('',$key) =~ /^\'?(\d+)\.(\d+)/) {
                   my $major = $1;
                   my $minor = $2;
                   if (($major < 2) || (($major == 2) && ($minor < 11))) {
                       map { $older_library_servers{$_} = 1; }
                           &Apache::lonnet::machine_ids($library_servers{$key});
                   } else {
                       my %possdoms;
                       map { $possdoms{$_}=1 if ($okdoms{$_}); }
                           &Apache::lonnet::machine_domains($library_servers{$key});
                       $domains_for_id{$key} = join(',',sort(keys(%possdoms)));
                   }
             }              }
         }          }
     }          my %servers = (%library_servers,%older_library_servers);
     return ($libraries_to_query,$pretty_domains_string);   $libraries_to_query = [keys(%servers)];
           $domains_to_query = \%domains_for_id;
       }
       return ($libraries_to_query,
               $pretty_domains_string,
               $domains_to_query);
 }  }
   
 ######################################################################  ######################################################################
Line 1503  sub parse_basic_search { Line 1502  sub parse_basic_search {
     #      #
     # Clean up fields for safety      # Clean up fields for safety
     for my $field ('basicexp') {      for my $field ('basicexp') {
  $ENV{"form.$field"}=~s/[^\w\s\'\"\!\(\)\-]//g;   $env{"form.$field"}=~s/[^\w\s\'\"\!\(\)\-\*]//g;
     }      }
     foreach ('mode','form','element') {      foreach ('mode','form','element') {
  # is this required?  Hmmm.   # is this required?  Hmmm.
  next unless (exists($ENV{"form.$_"}));   next unless (exists($env{"form.$_"}));
  $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});   $env{"form.$_"}=&unescape($env{"form.$_"});
  $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $env{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
     my ($libraries_to_query,$pretty_domains_string) =       my ($libraries_to_query,$pretty_domains_string,$domains_to_query) = 
         &parse_domain_restrictions();          &parse_domain_restrictions();
     #      #
     # Check to see if enough of a query is filled in      # Check to see if enough of a query is filled in
     my $search_string = $ENV{'form.basicexp'};      my $search_string = $env{'form.basicexp'};
     if (! &filled($search_string)) {      if (! &filled($search_string)) {
  &output_blank_field_error($r,$closebutton,'phase=disp_basic');   &output_blank_field_error($r,$closebutton,'phase=disp_basic');
  return OK;   return OK;
     }      }
     my $pretty_search_string=$search_string;      my $pretty_search_string=$search_string;
     my @Queries;      my @Queries;
     my $searchfield = 'concat_ws(" ",'.join(',',      my @fields = ('title','author','subject','notes','abstract','keywords');
                                             ('title','author','subject',      my $searchfield;
                                              'notes','abstract','keywords')      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,      my ($error,$SQLQuery) = &process_phrase_input($search_string,
                                                     $ENV{'form.related'},                                                      $env{'form.related'},
                                                     $searchfield);                                                      $searchfield);
     if ($error) {      if ($error) {
         &output_unparsed_phrase_error($r,$closebutton,'phase=disp_basic',          &output_unparsed_phrase_error($r,$closebutton,'phase=disp_basic',
Line 1538  sub parse_basic_search { Line 1540  sub parse_basic_search {
     #foreach my $q (@Queries) {      #foreach my $q (@Queries) {
     #    &Apache::lonnet::logthis('    '.$q);      #    &Apache::lonnet::logthis('    '.$q);
     #}      #}
     my $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);      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 < UTC_TIMESTAMP() AND (pa.end IS NULL OR pa.end > UTC_TIMESTAMP())) AND '.join(" AND ",@Queries).')';
       } else {
           $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);
       }
     #      #
       if ($env{'form.related'}) {
    $pretty_search_string.=' '.&mt('(including related words)');
       }
     if (defined($pretty_domains_string) && $pretty_domains_string ne '') {      if (defined($pretty_domains_string) && $pretty_domains_string ne '') {
         $pretty_search_string .= ' '.$pretty_domains_string;          $pretty_search_string .= ' '.$pretty_domains_string;
     }      }
     $pretty_search_string .= "<br />\n";      $pretty_search_string .= "<br />\n";
     $pretty_search_string =~ s:^<br /> and ::;      $pretty_search_string =~ s:^<br /> and ::;
     # &Apache::lonnet::logthis($final_query);      &Apache::lonnet::logthis('simple search final query = '.$/.$final_query);
     return ($final_query,$pretty_search_string,      return ($final_query,$pretty_search_string,
             $libraries_to_query);              $libraries_to_query,$domains_to_query);
 }  }
   
   
Line 1648  sub process_phrase_input { Line 1658  sub process_phrase_input {
             $item[1];              $item[1];
         }          }
     term:      term:
         /[\w\Q:!@#$%^&*()+_=|{}<>,.;\\\/?\E]+/ {          /[\w\Q:!@#$%^&*()+_=|{}<>,.;\\\/?\E\-]+/ {
             $item[1];              $item[1];
         }          }
 ENDGRAMMAR  ENDGRAMMAR
Line 1819  sub build_date_queries { Line 1829  sub build_date_queries {
     if ((defined($cafter)  && ! defined($cbefore)) ||      if ((defined($cafter)  && ! defined($cbefore)) ||
         (defined($cbefore) && ! defined($cafter))) {          (defined($cbefore) && ! defined($cafter))) {
         # This is bad, so let them know          # This is bad, so let them know
         $error = &mt('Incorrect entry for the creation date.  '.          $error = &mt('Incorrect entry for the creation date. '.
                     'You must specify both the beginning and ending dates.');                      'You must specify both the beginning and ending dates.');
     }      }
     if (! defined($error) &&       if (! defined($error) && 
         ((defined($mafter)  && ! defined($mbefore)) ||          ((defined($mafter)  && ! defined($mbefore)) ||
         (defined($mbefore) && ! defined($mafter)))) {          (defined($mbefore) && ! defined($mafter)))) {
         # This is also bad, so let them know          # This is also bad, so let them know
         $error = &mt('Incorrect entry for the last revision date.  '.          $error = &mt('Incorrect entry for the last revision date. '.
                      'You must specify both the beginning and ending dates.');                       'You must specify both the beginning and ending dates.');
     }      }
     if (! defined($error)) {      if (! defined($error)) {
Line 1899  sub copyright_check { Line 1909  sub copyright_check {
                                               $Metadata->{'url'});                                                $Metadata->{'url'});
     # Check for priv      # Check for priv
     if (($Metadata->{'copyright'} eq 'priv') &&       if (($Metadata->{'copyright'} eq 'priv') && 
         (($ENV{'user.name'} ne $resname) &&          (($env{'user.name'} ne $resname) &&
          ($ENV{'user.domain'} ne $resdom))) {           ($env{'user.domain'} ne $resdom))) {
         return 0;          return 0;
     }      }
     # Check for domain      # Check for domain
     if (($Metadata->{'copyright'} eq 'domain') &&      if (($Metadata->{'copyright'} eq 'domain') &&
         ($ENV{'user.domain'} ne $resdom)) {          ($env{'user.domain'} ne $resdom)) {
         return 0;          return 0;
     }      }
       # Check for custom rights
       if ($Metadata->{'copyright'} eq 'custom') {
          return &Apache::lonnet::customaccess('bre',$Metadata->{'url'});
       }
     return 1;      return 1;
 }  }
   
Line 1935  sub ensure_db_and_table { Line 1949  sub ensure_db_and_table {
     ## Sanity check the table id.      ## Sanity check the table id.
     ##      ##
     if (! defined($table) || $table eq '' || $table =~ /\D/ ) {      if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
         $r->print("Unable to retrieve search results.  ".          $r->print(&Apache::loncommon::start_page('Error')
                   "Unable to determine the table results were stored in.  ".                   .'<p class="LC_error">'
                   "</body></html>");                   .&mt('Unable to retrieve search results. '
                        .'Unable to determine the table results were saved in.')
                    .'</p>'
                    . '<p>'.&mt('Internal info:').'</p>'
                    .'<pre>'.$table.'</pre>'
                    .&Apache::loncommon::end_page()
           );
         return undef;          return undef;
     }      }
     ##      ##
Line 1945  sub ensure_db_and_table { Line 1965  sub ensure_db_and_table {
     ##      ##
     my $connection_result = &Apache::lonmysql::connect_to_db();      my $connection_result = &Apache::lonmysql::connect_to_db();
     if (!defined($connection_result)) {      if (!defined($connection_result)) {
         $r->print("Unable to connect to the MySQL database where your results".          $r->print(
                   " are stored. </body></html>");              '<p class="LC_error">'
              .&mt('Unable to connect to the MySQL database where your results are saved.')
              .'</p>'
              .&Apache::loncommon::end_page()
           );
         &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".          &Apache::lonnet::logthis("lonsearchcat: unable to get lonmysql to".
                                  " connect to database.");                                   " connect to database.");
         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());          &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
Line 1954  sub ensure_db_and_table { Line 1978  sub ensure_db_and_table {
     }      }
     my $table_check = &Apache::lonmysql::check_table($table);      my $table_check = &Apache::lonmysql::check_table($table);
     if (! defined($table_check)) {      if (! defined($table_check)) {
         $r->print("A MySQL error has occurred.</form></body></html>");          $r->print(
               '<p class="LC_error">'
              .&mt('A MySQL error has occurred.')
              .'</p></form>'
              .&Apache::loncommon::end_page());
         &Apache::lonnet::logthis("lonmysql was unable to determine the status".          &Apache::lonnet::logthis("lonmysql was unable to determine the status".
                                  " of table ".$table);                                   " of table ".$table);
         return undef;          return undef;
     } elsif (! $table_check) {      } elsif (! $table_check) {
         $r->print("The table of results could not be found.");          $r->print(
               '<p class="LC_error">'
              .&mt('The table of results could not be found.')
              .'</p>'
           );
         &Apache::lonnet::logthis("The user requested a table, ".$table.          &Apache::lonnet::logthis("The user requested a table, ".$table.
                                  ", that could not be found.");                                   ", that could not be found.");
         return undef;          return undef;
Line 1983  a link to change the search query. Line 2015  a link to change the search query.
 ######################################################################  ######################################################################
 sub print_sort_form {  sub print_sort_form {
     my ($r,$pretty_query_string) = @_;      my ($r,$pretty_query_string) = @_;
     my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1).  
         &Apache::lonhtmlcommon::breadcrumbs  
         (undef,'Searching','Searching',undef,undef,  
          $ENV{'form.catalogmode'} ne 'groupsearch');  
   
     ##      ##
     my %SortableFields=&Apache::lonlocal::texthash(       my %SortableFields=&Apache::lonlocal::texthash( 
Line 2005  sub print_sort_form { Line 2033  sub print_sort_form {
          lastrevisiondate => 'Revision Date'           lastrevisiondate => 'Revision Date'
      );       );
     ##      ##
     my $table = $ENV{'form.table'};      my $table = $env{'form.table'};
     return if (! &ensure_db_and_table($r,$table));      return if (! &ensure_db_and_table($r,$table));
     ##      ##
     ## Get the number of results       ## Get the number of results 
     ##      ##
     my $total_results = &Apache::lonmysql::number_of_rows($table);      my $total_results = &Apache::lonmysql::number_of_rows($table);
     if (! defined($total_results)) {      if (! defined($total_results)) {
         $r->print("A MySQL error has occurred.</form></body></html>");          $r->print("A MySQL error has occurred.</form>".
     &Apache::loncommon::end_page());
         &Apache::lonnet::logthis("lonmysql was unable to determine the number".          &Apache::lonnet::logthis("lonmysql was unable to determine the number".
                                  " of rows in table ".$table);                                   " of rows in table ".$table);
         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());          &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
         return;          return;
     }      }
     my $result;      my $js =<<END;
     $result.=<<END;  <script type="text/javascript">
 <html>  // <![CDATA[
 <head>  
 <script>  
     function change_sort() {      function change_sort() {
         var newloc = "/adm/searchcat?phase=results";          var newloc = "/adm/searchcat?phase=results";
         newloc += "&persistent_db_id=$ENV{'form.persistent_db_id'}";          newloc += "&persistent_db_id=$env{'form.persistent_db_id'}";
         newloc += "&sortby=";          newloc += "&sortby=";
         newloc += document.forms.statusform.elements.sortby.value;          newloc += document.forms.statusform.elements.sortby.value;
         parent.resultsframe.location= newloc;          parent.resultsframe.location= newloc;
     }      }
   // ]]>
 </script>  </script>
 <title>Results</title>  END
 </head>  
 $bodytag      my $start_page = &Apache::loncommon::start_page('Results',$js);
 <form name="statusform" action="" method="post">      my $breadcrumbs=
 <input type="hidden" name="Queue" value="" />          &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching',
       $env{'form.catalogmode'} ne 'import');
   
       my $result = <<END;
   $start_page
   $breadcrumbs
   <form name="statusform" action="" method="post" target="_top">
   <input type="hidden" name="catalogmode" value="import" />
   <input type="hidden" name="acts" value="" />
 END  END
   
 #<h2>Sort Results</h2>  #<h2>Sort Results</h2>
 #Sort by: <select size="1" name="sortby" onchange="javascript:change_sort();">  #Sort by: <select size="1" name="sortby" onchange="javascript:change_sort();">
 #    $ENV{'form.sortby'} = 'id' if (! defined($ENV{'form.sortby'}));  #    $env{'form.sortby'} = 'id' if (! defined($env{'form.sortby'}));
 #    foreach (keys(%SortableFields)) {  #    foreach (keys(%SortableFields)) {
 #        $result.="<option name=\"$_\"";  #        $result.="<option name=\"$_\"";
 #        if ($_ eq $ENV{'form.sortby'}) {  #        if ($_ eq $env{'form.sortby'}) {
 #            $result.=" selected ";  #            $result.=" selected ";
 #        }  #        }
 #        $result.=" >$SortableFields{$_}</option>\n";  #        $result.=" >$SortableFields{$_}</option>\n";
 #    }  #    }
 #    $result.="</select>\n";  #    $result.="</select>\n";
     my $revise = &revise_button();      my $revise = &revise_button();
     $result.=<<END;      $result.='<p>'
 <p>              .&mt('Total of [quant,_1,match,matches] to your query.',$total_results)
 There are $total_results matches to your query. $revise              .' '.$revise.'</p>'
 </p><p>              .'<p>'.&mt('Search: ').$pretty_query_string
 Search:$pretty_query_string              .'</p></form>';
 </p>      $r->print($result.&Apache::loncommon::end_page());
 </form>  
 </body>  
 </html>  
 END  
     $r->print($result);  
     return;      return;
 }  }
   
Line 2094  my @Fullindicies; Line 2125  my @Fullindicies;
 =item &create_results_table()  =item &create_results_table()
   
 Creates the table of search results by calling lonmysql.  Stores the  Creates the table of search results by calling lonmysql.  Stores the
 table id in $ENV{'form.table'}  table id in $env{'form.table'}
   
 Inputs: none.  Inputs: search area - either res or portfolio 
   
 Returns: the identifier of the table on success, undef on error.  Returns: the identifier of the table on success, undef on error.
   
Line 2105  Returns: the identifier of the table on Line 2136  Returns: the identifier of the table on
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub set_up_table_structure {  sub set_up_table_structure {
       my ($tabletype) = @_;
     my ($datatypes,$fullindicies) =       my ($datatypes,$fullindicies) = 
         &LONCAPA::lonmetadata::describe_metadata_storage();          &LONCAPA::lonmetadata::describe_metadata_storage($tabletype);
     # Copy the table description before modifying it...      # Copy the table description before modifying it...
     @Datatypes = @{$datatypes};      @Datatypes = @{$datatypes};
     unshift(@Datatypes,{name => 'id',        unshift(@Datatypes,{name => 'id',  
Line 2119  sub set_up_table_structure { Line 2151  sub set_up_table_structure {
 }  }
   
 sub create_results_table {  sub create_results_table {
     &set_up_table_structure();      my ($area) = @_;
       if ($area eq 'portfolio') {
           &set_up_table_structure('portfolio_search');
       } else {
           &set_up_table_structure('metadata');
       }
     my $table = &Apache::lonmysql::create_table      my $table = &Apache::lonmysql::create_table
         ( { columns => \@Datatypes,          ( { columns => \@Datatypes,
             FULLTEXT => [{'columns' => \@Fullindicies},],              FULLTEXT => [{'columns' => \@Fullindicies},],
         } );          } );
     if (defined($table)) {      if (defined($table)) {
         $ENV{'form.table'} = $table;          $env{'form.table'} = $table;
         return $table;          return $table;
     }       } 
     return undef; # Error...      return undef; # Error...
Line 2163  Returns: Nothing. Line 2200  Returns: Nothing.
 sub update_count_status {  sub update_count_status {
     my ($r,$text) = @_;      my ($r,$text) = @_;
     $text =~ s/\'/\\\'/g;      $text =~ s/\'/\\\'/g;
     $r->print      $r->print(<<SCRIPT);
         ("<script>document.statusform.count.value = ' $text'</script>\n");  <script type="text/javascript">
   // <![CDATA[
   document.statusform.count.value = ' $text'
   // ]]>
   </script>
   SCRIPT
   
     $r->rflush();      $r->rflush();
 }  }
   
 sub update_status {  sub update_status {
     my ($r,$text) = @_;      my ($r,$text) = @_;
     $text =~ s/\'/\\\'/g;      $text =~ s/\'/\\\'/g;
     $r->print      $r->print(<<SCRIPT);
         ("<script>document.statusform.status.value = ' $text'</script>\n");  <script type="text/javascript">
   // <![CDATA[
   document.statusform.status.value = ' $text'
   // ]]>
   </script>
   SCRIPT
   
     $r->rflush();      $r->rflush();
 }  }
   
 {  {
     my $max_time  = 40;  # seconds for the search to complete      my $max_time  = 300;  # seconds for the search to complete
     my $start_time = 0;      my $start_time = 0;
     my $last_time = 0;      my $last_time = 0;
   
Line 2199  sub update_seconds { Line 2248  sub update_seconds {
     my ($r) = @_;      my ($r) = @_;
     my $time = &time_left();      my $time = &time_left();
     if (($last_time-$time) > 0) {      if (($last_time-$time) > 0) {
         $r->print("<script>".          $r->print(<<SCRIPT);
                   "document.statusform.seconds.value = '$time'".  <script type="text/javascript">
                   "</script>\n");  // <![CDATA[
   document.statusform.seconds.value = '$time'
   // ]]>
   </script>
   SCRIPT
   
         $r->rflush();          $r->rflush();
     }      }
     $last_time = $time;      $last_time = $time;
Line 2225  Returns: html string for a 'revise searc Line 2279  Returns: html string for a 'revise searc
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub revise_button {  sub revise_button {
       my $revisetext = &mt('Revise search');
     my $revise_phase = 'disp_basic';      my $revise_phase = 'disp_basic';
     $revise_phase = 'disp_adv' if ($ENV{'form.searchmode'} eq 'advanced');      $revise_phase = 'disp_adv' if ($env{'form.searchmode'} eq 'advanced');
     my $newloc = '/adm/searchcat'.      my $newloc = '/adm/searchcat'.
         '?persistent_db_id='.$ENV{'form.persistent_db_id'}.          '?persistent_db_id='.$env{'form.persistent_db_id'}.
             '&cleargroupsort=1'.              '&amp;cleargroupsort=1'.
             '&phase='.$revise_phase;              '&amp;phase='.$revise_phase;
     my $result = qq{<input type="button" value="Revise search" name="revise"} .      my $result = qq{<input type="button" value="$revisetext" name="revise"} .
         qq{ onClick="parent.location='$newloc';" /> };          qq{ onclick="parent.location='$newloc';" /> };
     return $result;      return $result;
 }  }
   
Line 2251  results into MySQL. Line 2306  results into MySQL.
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub run_search {  sub run_search {
     my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;      my ($r,$query,$customquery,$customshow,$serverlist,
     my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);          $pretty_string,$area,$domainsref) = @_;
     $bodytag.=&Apache::lonhtmlcommon::breadcrumbs      my $tabletype = 'metadata';
         (undef,'Searching','Searching',undef,undef,      if ($area eq 'portfolio') {
          $ENV{'form.catalogmode'} ne 'groupsearch');          $tabletype = 'portfolio_search';
       }
     my $connection = $r->connection;      my $connection = $r->connection;
     #      #
     # Print run_search header      # Print run_search header
     #      #
       my $start_page = &Apache::loncommon::start_page('Search Status',undef);
       my $breadcrumbs =
    &Apache::lonhtmlcommon::breadcrumbs('Searching','Searching',
       $env{'form.catalogmode'} ne 'import');
     $r->print(<<END);      $r->print(<<END);
 <html>  $start_page
 <head><title>Search Status</title></head>  $breadcrumbs
 $bodytag  
 <form name="statusform" action="" method="post">  
 <input type="hidden" name="Queue" value="" />  
 END  END
     # Remove leading and trailing <br />      # Remove leading and trailing <br />
     $pretty_string =~ s:^\s*<br />::i;      $pretty_string =~ s:^\s*<br />::i;
Line 2276  END Line 2333  END
         pop(@Lines);          pop(@Lines);
     }      }
     if (@Lines > 2) {      if (@Lines > 2) {
         $pretty_string = join '<br />',(@Lines[0..2],'....<br />');          $pretty_string = join '<br />',(@Lines[0..2],'...<br />');
     }      }
     $r->print(&mt("Search: [_1]",$pretty_string));      $r->print(&mt("Search: [_1]",$pretty_string));
     $r->rflush();      $r->rflush();
     #      #
     # Determine the servers we need to contact.      # Determine the servers we need to contact.
     my @Servers_to_contact;      my (@Servers_to_contact,%domains_by_server);
     if (defined($serverlist)) {      if (defined($serverlist)) {
         if (ref($serverlist) eq 'ARRAY') {          if (ref($serverlist) eq 'ARRAY') {
             @Servers_to_contact = @$serverlist;              @Servers_to_contact = @$serverlist;
         } else {          } else {
             @Servers_to_contact = ($serverlist);              @Servers_to_contact = ($serverlist);
         }          }
           if (ref($domainsref) eq 'HASH') {
               foreach my $server (@Servers_to_contact) {
                   $domains_by_server{$server} = $domainsref->{$server};
               }
           }
     } else {      } else {
         @Servers_to_contact = sort(keys(%Apache::lonnet::libserv));   my %library_servers = &Apache::lonnet::unique_library();
           my (%all_library_servers, %older_library_servers);
           foreach my $key (keys(%library_servers)) {
               if (&Apache::lonnet::get_server_loncaparev('',$key) =~ /^\'?(\d+)\.(\d+)/) {
                   my $major = $1;
                   my $minor = $2;
                   if (($major < 2) || (($major == 2) && ($minor < 11))) {
                       map { $older_library_servers{$_} = 1; }
                           &Apache::lonnet::machine_ids($library_servers{$key});
                   }
               }
           }
           %all_library_servers = (%library_servers,%older_library_servers);
           @Servers_to_contact = sort(keys(%all_library_servers));
           foreach my $server (@Servers_to_contact) {
               my %possdoms;
               map { $possdoms{$_}=1;  } &Apache::lonnet::machine_domains($all_library_servers{$server});
               $domains_by_server{$server} =
                   join(',',sort(&Apache::lonnet::machine_domains($all_library_servers{$server})));
           }
     }      }
     my %Server_status;      my %Server_status;
     #      #
     # Check on the mysql table we will use to store results.      # 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/ ) {      if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
         $r->print("Unable to determine table id to store search results in.".          $r->print("Unable to determine table id to save search results in.".
                   "The search has been aborted.</body></html>");                    "The search has been aborted.".
     &Apache::loncommon::end_page());
         return;          return;
     }      }
     my $table_status = &Apache::lonmysql::check_table($table);      my $table_status = &Apache::lonmysql::check_table($table);
     if (! defined($table_status)) {      if (! defined($table_status)) {
         $r->print("Unable to determine status of table.</body></html>");          $r->print("Unable to determine status of table.".
     &Apache::loncommon::end_page());
         &Apache::lonnet::logthis("Bogus table id of $table for ".          &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::lonnet::logthis("lonmysql error = ".
                                  &Apache::lonmysql::get_error());                                   &Apache::lonmysql::get_error());
         return;          return;
Line 2317  END Line 2400  END
                                  &Apache::lonmysql::get_debug());                                   &Apache::lonmysql::get_debug());
         &Apache::lonnet::logthis('table status = "'.$table_status.'"');          &Apache::lonnet::logthis('table status = "'.$table_status.'"');
         $r->print("The table id,$table, we tried to use is invalid.".          $r->print("The table id,$table, we tried to use is invalid.".
                   "The search has been aborted.</body></html>");                    "The search has been aborted.".
     &Apache::loncommon::end_page());
         return;          return;
     }      }
     ##      ##
     ## Prepare for the big loop.      ## Prepare for the big loop.
     my $hitcountsum;      my $hitcountsum;
       my %matches;
     my $server;       my $server; 
     my $status;      my $status;
     my $revise = &revise_button();      my $revise = &revise_button();
     $r->print(<<END);      $r->print('<form name="statusform" action="" method="post">'."\n".
 <table>                '<input type="hidden" name="acts" value="" />'."\n".
 <tr><th>Status</th><th>Total Matches</th><th>Time Remaining</th><th></th></tr>                '<table border="0"><tr><td>'."\n".
 <tr>                &Apache::loncommon::start_data_table());
 <td><input type="text" name="status"  value="" size="30" /></td>      $r->print(&Apache::loncommon::start_data_table_header_row()
 <td><input type="text" name="count"   value="" size="10" /></td>               .'<th>'.&mt('Status').'</th>'
 <td><input type="text" name="seconds" value="" size="8" /></td>               .'<th>'.&mt('Total Matches').'</th>'
 <td>$revise</td>               .'<th>'.&mt('Time Remaining').'</th>'
 </tr>               .&Apache::loncommon::end_data_table_header_row()
 </table>               .&Apache::loncommon::start_data_table_row()
 </form>               .'<td><input type="text" name="status"  value="" size="50" readonly="readonly" /></td>'
 END               .'<td><input type="text" name="count"   value="" size="10" readonly="readonly" /></td>'
                .'<td><input type="text" name="seconds" value="" size="8" readonly="readonly" /></td>'
                .&Apache::loncommon::end_data_table_row()
                .&Apache::loncommon::end_data_table()
                .'</td><td>&nbsp;</td><td>'.$revise.'</td></tr></table></form>');
     $r->rflush();      $r->rflush();
     &reset_timing();      &reset_timing();
     &update_seconds($r);      &update_seconds($r);
Line 2352  END Line 2441  END
             my $server = shift(@Servers_to_contact);              my $server = shift(@Servers_to_contact);
             &update_status($r,&mt('contacting [_1]',$server));              &update_status($r,&mt('contacting [_1]',$server));
             my $reply=&Apache::lonnet::metadata_query($query,$customquery,              my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                       $customshow,[$server]);                                                        $customshow,[$server],\%domains_by_server);
             ($server) = keys(%$reply);              ($server) = keys(%$reply);
             $Server_status{$server} = $reply->{$server};              $Server_status{$server} = $reply->{$server};
         } else {          } else {
Line 2377  END Line 2466  END
                 delete ($Server_status{$server});                  delete ($Server_status{$server});
                 next;                  next;
             }              }
             $status=~/^([\.\w]+)$/;               $status=~s|/||g;
            my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1;  
   
   
              my $datafile=LONCAPA::tempdir().$status;
             if (-e $datafile && ! -e "$datafile.end") {              if (-e $datafile && ! -e "$datafile.end") {
                 &update_status($r,&mt('Receiving results from [_1]',$server));                  &update_status($r,&mt('Receiving results from [_1]',$server));
                 next;                  next;
Line 2406  END Line 2498  END
                     next if (! $result);                      next if (! $result);
                     #                      #
                     # Parse the result.                      # Parse the result.
                     my %Fields = &parse_raw_result($result,$server);                      my %Fields = &parse_raw_result($result,$server,$tabletype);
                     $Fields{'hostname'} = $server;                      $Fields{'hostname'} = $server;
                     #                      #
                     # Skip based on copyright                      # Skip based on copyright
                     next if (! &copyright_check(\%Fields));                      next if (! &copyright_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                      # Store the result in the mysql database
                     my $result = &Apache::lonmysql::store_row($table,\%Fields);                      my $result = &Apache::lonmysql::store_row($table,\%Fields);
Line 2435  END Line 2534  END
         last if ($connection->aborted());          last if ($connection->aborted());
         &update_seconds($r);          &update_seconds($r);
     }      }
     &update_status($r,&mt('Search Complete [_1]',$server));      &update_status($r,&mt('Search Complete on Server [_1]',$server));
     &update_seconds($r);      &update_seconds($r);
     #      #
     &Apache::lonmysql::disconnect_from_db(); # This is unneccessary      &Apache::lonmysql::disconnect_from_db(); # This is unneccessary
Line 2443  END Line 2542  END
     # We have run out of time or run out of servers to talk to and      # 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      # results to get, so let the client know the top frame needs to be
     # loaded from /adm/searchcat      # loaded from /adm/searchcat
     $r->print("</body></html>");      $r->print(&Apache::loncommon::end_page());
 #    if ($ENV{'form.catalogmode'} ne 'groupsearch') {  #    if ($env{'form.catalogmode'} ne 'import') {
         $r->print("<script>".           $r->print(<<SCRIPT);
                       "window.location='/adm/searchcat?".  <script>
                       "phase=sort&".  window.location='/adm/searchcat?phase=sort&persistent_db_id=$env{'form.persistent_db_id'}';
                       "persistent_db_id=$ENV{'form.persistent_db_id'}';".  </script>
                   "</script>");  SCRIPT
 #    }  #    }
     return;      return;
 }  }
Line 2472  sub prev_next_buttons { Line 2571  sub prev_next_buttons {
     return '' if ($show eq 'all'); # No links if you get them all at once.      return '' if ($show eq 'all'); # No links if you get them all at once.
     #      #
     # Create buttons      # Create buttons
     my $buttons = '<input type="submit" name="prev" value="'.&mt('Prev').'" ';      return '<p class="LC_nobreak">'
     $buttons .= '/>';            .'<input type="submit" name="prev" value="&lt;"'
     $buttons .= '&nbsp;'x3;            .' title="'.&mt('Previous').'" />'
     $buttons .= '<input type="submit" name="reload" '.            .' '
         'value="'.&mt('Reload').'" />';            .'<input type="submit" name="reload" value="'.&mt('Reload').'" />'
     $buttons .= '&nbsp;'x3;            .' '
     $buttons .= '<input type="submit" name="next" value="'.&mt('Next').'" ';            .'<input type="submit" name="next" value="&gt;"'
     $buttons .= '/>';            .' title="'.&mt('Next').'" />'
     return $buttons;            .'</p>';
 }  }
   
 ######################################################################  ######################################################################
Line 2497  Prints the results out for selection and Line 2596  Prints the results out for selection and
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub display_results {  sub display_results {
     my ($r,$importbutton,$closebutton,$diropendb) = @_;      my ($r,$importbutton,$closebutton,$diropendb,$area) = @_;
     my $connection = $r->connection;      my $connection = $r->connection;
     $r->print(&search_results_header($importbutton,$closebutton));      $r->print(&search_results_header($importbutton,$closebutton));
     ##      ##
     ## Set viewing function      ## Set viewing function
     ##      ##
     my $viewfunction = $Views{$ENV{'form.viewselect'}};      my $viewfunction = $Views{$env{'form.viewselect'}};
     if (!defined($viewfunction)) {      if (!defined($viewfunction)) {
         $r->print("Internal Error - Bad view selected.\n");          $r->print('<p class="LC_error">'
                    .&mt('Internal Error - Bad view selected.')
                    .'</p>'."\n");
         $r->rflush();          $r->rflush();
         return;          return;
     }      }
     ##      ##
     ## $checkbox_num is a count of the number of checkboxes output on the       ## $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;      my $checkbox_num = 0;
     ##      ##
     ## Get the catalog controls setup      ## Get the catalog controls setup
     ##      ##
     my $action = "/adm/searchcat?phase=results";      my $action = "/adm/searchcat?phase=results";
     ##      ##
     ## Deal with groupsearch by opening the groupsearch db file.      ## Deal with import by opening the import db file.
     if ($ENV{'form.catalogmode'} eq 'groupsearch') {      if ($env{'form.catalogmode'} eq 'import') {
         if (! tie(%groupsearch_db,'GDBM_File',$diropendb,          if (! tie(%groupsearch_db,'GDBM_File',$diropendb,
                   &GDBM_WRCREAT(),0640)) {                    &GDBM_WRCREAT(),0640)) {
             $r->print('Unable to store import results.</form></body></html>');              $r->print('<p class="LC_error">'.
                 &mt('Unable to save import results.').
                 '</p>'.
                 '</form>'.
         &Apache::loncommon::end_page());
             $r->rflush();              $r->rflush();
             return;              return;
         }           } 
     }      }
     ##      ##
     ## Prepare the table for querying      ## Prepare the table for querying
     my $table = $ENV{'form.table'};      my $table = $env{'form.table'};
     return if (! &ensure_db_and_table($r,$table));      return if (! &ensure_db_and_table($r,$table));
     ##      ##
     ## Get the number of results       ## Get the number of results 
     my $total_results = &Apache::lonmysql::number_of_rows($table);      my $total_results = &Apache::lonmysql::number_of_rows($table);
     if (! defined($total_results)) {      if (! defined($total_results)) {
         $r->print("A MySQL error has occurred.</form></body></html>");          $r->print('<p class="LC_error">'.
             &mt('A MySQL error has occurred.').
             '</p>'.
             '</form>'.
     &Apache::loncommon::end_page());
         &Apache::lonnet::logthis("lonmysql was unable to determine the number".          &Apache::lonnet::logthis("lonmysql was unable to determine the number".
                                  " of rows in table ".$table);                                   " of rows in table ".$table);
         &Apache::lonnet::logthis(&Apache::lonmysql::get_error());          &Apache::lonnet::logthis(&Apache::lonmysql::get_error());
Line 2543  sub display_results { Line 2652  sub display_results {
     }      }
     ##      ##
     ## Determine how many results we need to get      ## Determine how many results we need to get
     $ENV{'form.start'} = 1  if (! exists($ENV{'form.start'}));      $env{'form.start'} = 1  if (! exists($env{'form.start'}));
     $ENV{'form.show'}  = 20 if (! exists($ENV{'form.show'}));      $env{'form.show'}  = 20 if (! exists($env{'form.show'}));
     if (exists($ENV{'form.prev'})) {      if (exists($env{'form.prev'})) {
         $ENV{'form.start'} -= $ENV{'form.show'};          $env{'form.start'} -= $env{'form.show'};
     } elsif (exists($ENV{'form.next'})) {      } elsif (exists($env{'form.next'})) {
         $ENV{'form.start'} += $ENV{'form.show'};          $env{'form.start'} += $env{'form.show'};
     }      }
     $ENV{'form.start'} = 1 if ($ENV{'form.start'}<1);      $env{'form.start'} = 1 if ($env{'form.start'}<1);
     $ENV{'form.start'} = $total_results if ($ENV{'form.start'}>$total_results);      $env{'form.start'} = $total_results if ($env{'form.start'}>$total_results);
     my $min = $ENV{'form.start'};      my $min = $env{'form.start'};
     my $max;      my $max;
     if ($ENV{'form.show'} eq 'all') {      if ($env{'form.show'} eq 'all') {
         $max = $total_results ;          $max = $total_results ;
     } else {      } else {
         $max = $min + $ENV{'form.show'} - 1;          $max = $min + $env{'form.show'} - 1;
         $max = $total_results if ($max > $total_results);          $max = $total_results if ($max > $total_results);
     }      }
     ##      ##
Line 2565  sub display_results { Line 2674  sub display_results {
     $r->print(&hidden_field('table').      $r->print(&hidden_field('table').
               &hidden_field('phase').                &hidden_field('phase').
               &hidden_field('persistent_db_id').                &hidden_field('persistent_db_id').
               &hidden_field('start')                &hidden_field('start').
                 &hidden_field('area')
               );                );
     ##      #
     ## Output links (if necessary) for 'prev' and 'next' pages.      # Build sorting selector
     $r->print      my @fields = 
         ('<table width="100%"><tr><td width="50%" align="right">'.          (
          &prev_next_buttons($min,$ENV{'form.show'},$total_results).           {key=>'default' },
          '</td><td align="right">'.           {key=>'title' },
          &viewoptions().'</td></tr></table>'           {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 = '<span class="LC_nobreak">'
                     .&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')
                                                          })
                     .'</span>';
       ##
       ## Display links for 'prev' and 'next' pages (if necessary) and Display Options
       $r->print('<fieldset>'."\n"
                .'<legend>'.&mt('Display Options').'</legend>'."\n"
                .$sortform
                .' '
                .&viewoptions()
                .'</fieldset>'
                .&prev_next_buttons($min,$env{'form.show'},$total_results)
       );
   
     if ($total_results == 0) {      if ($total_results == 0) {
         $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2">'.          $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2" />'.
                   '<h3>'.&mt('There are currently no results').'.</h3>'.                    '<p class="LC_info">'.&mt('There are currently no results.').'</p>'.
                   "</form></body></html>");                    "</form>".
     &Apache::loncommon::end_page());
         return;          return;
     } else {      } else {
         $r->print          $r->print('<div>'.
             ("<center>Results $min to $max out of $total_results</center>\n");                    mt('Results [_1] to [_2] out of [_3]',
                        $min,$max,$total_results).
                     "</div>\n");
     }      }
     ##      ##
     ## Get results from MySQL table      ## Get results from MySQL table
     my @Results = &Apache::lonmysql::get_rows($table,      my $sort_command  = 'id>='.$min.' AND id<='.$max;
                                               '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.      ## Loop through the results and output them.
       my $tabletype = 'metadata';
       if ($area eq 'portfolio') {
           $tabletype = 'portfolio_search';
       }
       $r->print(&Apache::loncommon::start_data_table());
     foreach my $row (@Results) {      foreach my $row (@Results) {
         if ($connection->aborted()) {          if ($connection->aborted()) {
             &cleanup();              &cleanup();
             return;              return;
         }          }
         my %Fields = %{&parse_row(@$row)};          my %Fields = %{&parse_row($tabletype,@$row)};
         my $output="<p>\n";          my $output;
         if (! defined($Fields{'title'}) || $Fields{'title'} eq '') {          if (! defined($Fields{'title'}) || $Fields{'title'} eq '') {
             $Fields{'title'} = 'Untitled';              $Fields{'title'} = 'Untitled';
         }          }
Line 2605  sub display_results { Line 2827  sub display_results {
         # Render the result into html          # Render the result into html
         $output.= &$viewfunction($prefix,%Fields);          $output.= &$viewfunction($prefix,%Fields);
         # Print them out as they come in.          # Print them out as they come in.
         $r->print($output);          $r->print(&Apache::loncommon::start_data_table_row()
                    .'<td>'
                    .$output
                    .'</td>'
                    .&Apache::loncommon::end_data_table_row()
           );
         $r->rflush();          $r->rflush();
     }      }
       $r->print(&Apache::loncommon::end_data_table());
     if (@Results < 1) {      if (@Results < 1) {
         $r->print(&mt("There were no results matching your query"));          $r->print('<p class="LC_info">'
                    .&mt('There were no results matching your query.')
                    .'</p>');
     } else {      } else {
         $r->print          $r->print(
             ('<center>'.              &prev_next_buttons($min,$env{'form.show'},$total_results,
              &prev_next_buttons($min,$ENV{'form.show'},$total_results,                                  "table=".$env{'form.table'}.
                                 "table=".$ENV{'form.table'}.                                  "&amp;phase=results".
                                 "&phase=results".                                  "&amp;persistent_db_id=".
                                 "&persistent_db_id=".                                  $env{'form.persistent_db_id'})
                                 $ENV{'form.persistent_db_id'})          );
              ."</center>\n"  
              );  
     }      }
     $r->print("</form></body></html>");      $r->print("</form>".&Apache::loncommon::end_page());
     $r->rflush();      $r->rflush();
     untie %groupsearch_db if (tied(%groupsearch_db));      untie %groupsearch_db if (tied(%groupsearch_db));
     return;      return;
Line 2635  sub display_results { Line 2863  sub display_results {
 =item &catalogmode_output($title,$url,$fnum,$checkbox_num)  =item &catalogmode_output($title,$url,$fnum,$checkbox_num)
   
 Returns html needed for the various catalog modes.  Gets inputs from  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  =cut
   
Line 2644  $ENV{'form.catalogmode'}.  Stores data i Line 2872  $ENV{'form.catalogmode'}.  Stores data i
 sub catalogmode_output {  sub catalogmode_output {
     my $output = '';      my $output = '';
     my ($title,$url,$fnum,$checkbox_num) = @_;      my ($title,$url,$fnum,$checkbox_num) = @_;
     if ($ENV{'form.catalogmode'} eq 'interactive') {      if ($env{'form.catalogmode'} eq 'interactive') {
         $title=~ s/\'/\\\'/g;          $title=~ s/\'/\\\'/g;
         if ($ENV{'form.catalogmode'} eq 'interactive') {          if ($env{'form.catalogmode'} eq 'interactive') {
             $output.=<<END               $output.=<<END 
 <font size='-1'><INPUT TYPE="button" NAME="returnvalues" VALUE="SELECT"  <font size='-1'><input type="button" name="returnvalues" value="select"
 onClick="javascript:select_data('$title','$url')">  onclick="javascript:select_data('$title','$url')" />
 </font>  </font>
 END  END
         }          }
     } elsif ($ENV{'form.catalogmode'} eq 'groupsearch') {      } elsif ($env{'form.catalogmode'} eq 'import') {
         $groupsearch_db{"pre_${fnum}_link"}=$url;          $groupsearch_db{"pre_${fnum}_link"}=$url;
         $groupsearch_db{"pre_${fnum}_title"}=$title;          $groupsearch_db{"pre_${fnum}_title"}=$title;
         $output.=<<END;          $output.=<<END;
 <font size='-1'>  <font size='-1'>
 <input type="checkbox" name="returnvalues" value="SELECT"  <input type="checkbox" name="returnvalues" value="select"
 onClick="javascript:queue($checkbox_num,$fnum)" />  onclick="javascript:queue($checkbox_num,$fnum)" />
 </font>  </font>
 END  END
     }      }
Line 2679  Parse a row returned from the database. Line 2907  Parse a row returned from the database.
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub parse_row {  sub parse_row {
     my @Row = @_;      my ($tabletype,@Row) = @_;
     my %Fields;      my %Fields;
     if (! scalar(@Datatypes)) {      if (! scalar(@Datatypes)) {
         &set_up_table_structure();          &set_up_table_structure($tabletype);
     }      }
     for (my $i=0;$i<=$#Row;$i++) {      for (my $i=0;$i<=$#Row;$i++) {
         $Fields{$Datatypes[$i]->{'name'}}=&Apache::lonnet::unescape($Row[$i]);          $Fields{$Datatypes[$i]->{'name'}}=&unescape($Row[$i]);
     }      }
     $Fields{'language'} =       $Fields{'language'} = 
         &Apache::loncommon::languagedescription($Fields{'language'});          &Apache::loncommon::languagedescription($Fields{'language'});
Line 2718  The 'title' field is set to "Untitled" i Line 2946  The 'title' field is set to "Untitled" i
 ###########################################################  ###########################################################
 ###########################################################  ###########################################################
 sub parse_raw_result {  sub parse_raw_result {
     my ($result,$hostname) = @_;      my ($result,$hostname,$tabletype) = @_;
     # conclude from self to others regarding fields      # conclude from self to others regarding fields
     my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash      my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash
         (map {          ($tabletype,
             &Apache::lonnet::unescape($_);           map {
         } (split(/\,/,$result)) );              &unescape($_);
            } (split(/\,/,$result)) );
     return %Fields;      return %Fields;
 }  }
   
Line 2743  sub handle_custom_fields { Line 2972  sub handle_custom_fields {
     my $customshow='';      my $customshow='';
     my $extrashow='';      my $extrashow='';
     my @customfields;      my @customfields;
     if ($ENV{'form.customshow'}) {      if ($env{'form.customshow'}) {
         $customshow=$ENV{'form.customshow'};          $customshow=$env{'form.customshow'};
         $customshow=~s/[^\w\s]//g;          $customshow=~s/[^\w\s]//g;
         my @fields=map {          my @fields=map {
             "<font color=\"#008000\">$_:</font><!-- $_ -->";              "<font color=\"#008000\">$_:</font><!-- $_ -->";
Line 2760  sub handle_custom_fields { Line 2989  sub handle_custom_fields {
         if ($result=~/^(custom\=.*)$/) { # grab all custom metadata          if ($result=~/^(custom\=.*)$/) { # grab all custom metadata
             my $tmp=$result;              my $tmp=$result;
             $tmp=~s/^custom\=//;              $tmp=~s/^custom\=//;
             my ($k,$v)=map {&Apache::lonnet::unescape($_);              my ($k,$v)=map {&unescape($_);
                         } split(/\,/,$tmp);                          } split(/\,/,$tmp);
             $customhash{$k}=$v;              $customhash{$k}=$v;
         }          }
Line 2778  sub handle_custom_fields { Line 3007  sub handle_custom_fields {
 Output the proper html headers and javascript code to deal with different   Output the proper html headers and javascript code to deal with different 
 calling modes.  calling modes.
   
 Takes most inputs directly from %ENV, except $mode.    Takes most inputs directly from %env, except $mode.  
   
 =over 4  =over 4
   
Line 2792  The following environment variables are Line 3021  The following environment variables are
   
 =item 'form.catalogmode'   =item 'form.catalogmode' 
   
 Checked for 'interactive' and 'groupsearch'.  Checked for 'interactive' and 'import'.
   
 =item 'form.mode'  =item 'form.mode'
   
Line 2818  the name of the input field to put the t Line 3047  the name of the input field to put the t
 ######################################################################  ######################################################################
 sub search_results_header {  sub search_results_header {
     my ($importbutton,$closebutton) = @_;      my ($importbutton,$closebutton) = @_;
     my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);  
     my $result = '';      my $js;
     # output beginning of search page      # output beginning of search page
     # conditional output of script functions dependent on the mode in      # conditional output of script functions dependent on the mode in
     # which the search was invoked      # which the search was invoked
     if ($ENV{'form.catalogmode'} eq 'interactive'){      if ($env{'form.catalogmode'} eq 'interactive'){
  if (! exists($ENV{'form.mode'}) || $ENV{'form.mode'} ne 'edit') {   if (! exists($env{'form.mode'}) || $env{'form.mode'} ne 'edit') {
             $result.=<<SCRIPT;              $js.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
   // <![CDATA[
     function select_data(title,url) {      function select_data(title,url) {
  changeTitle(title);   changeTitle(title);
  changeURL(url);   changeURL(url);
Line 2842  sub search_results_header { Line 3072  sub search_results_header {
     parent.opener.inf.document.forms.resinfo.elements.u.value=val;      parent.opener.inf.document.forms.resinfo.elements.u.value=val;
  }   }
     }      }
   // ]]>
 </script>  </script>
 SCRIPT  SCRIPT
         } elsif ($ENV{'form.mode'} eq 'edit') {          } elsif ($env{'form.mode'} eq 'edit') {
             my $form = $ENV{'form.form'};              my $form = $env{'form.form'};
             my $element = $ENV{'form.element'};              my $element = $env{'form.element'};
             my $titleelement = $ENV{'form.titleelement'};              my $titleelement = $env{'form.titleelement'};
     my $changetitle;      my $changetitle;
     if (!$titleelement) {      if (!$titleelement) {
  $changetitle='function changeTitle(val) {}';   $changetitle='function changeTitle(val) {}';
Line 2864  function changeTitle(val) { Line 3095  function changeTitle(val) {
 END  END
             }              }
   
             $result.=<<SCRIPT;              $js.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
   // <![CDATA[
 function select_data(title,url) {  function select_data(title,url) {
     changeURL(url);      changeURL(url);
     changeTitle(title);      changeTitle(title);
Line 2880  function changeURL(val) { Line 3112  function changeURL(val) {
         alert("Unable to transfer data to "+url);          alert("Unable to transfer data to "+url);
     }      }
 }  }
   // ]]>
 </script>  </script>
 SCRIPT  SCRIPT
         }          }
     }      }
     $result.=<<SCRIPT if $ENV{'form.catalogmode'} eq 'groupsearch';      my $inhibit_menu = "&".&Apache::loncommon::inhibit_menu_check();
       $js.=<<SCRIPT if $env{'form.catalogmode'} eq 'import';
 <script type="text/javascript">  <script type="text/javascript">
   // <![CDATA[
     function queue(checkbox_num,val) {      function queue(checkbox_num,val) {
         if (document.forms.results.returnvalues.length != "undefined" &&          if (document.forms.results.returnvalues.length != "undefined" &&
             typeof(document.forms.results.returnvalues.length) == "number") {              typeof(document.forms.results.returnvalues.length) == "number") {
             if (document.forms.results.returnvalues[checkbox_num].checked) {              if (document.forms.results.returnvalues[checkbox_num].checked) {
                 parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';                  parent.statusframe.document.forms.statusform.elements.acts.value +='1a'+val+'b';
             } else {              } else {
                 parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';                  parent.statusframe.document.forms.statusform.elements.acts.value +='0a'+val+'b';
             }              }
         } else {          } else {
             if (document.forms.results.returnvalues.checked) {              if (document.forms.results.returnvalues.checked) {
                 parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';                  parent.statusframe.document.forms.statusform.elements.acts.value +='1a'+val+'b';
             } else {              } else {
                 parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';                  parent.statusframe.document.forms.statusform.elements.acts.value +='0a'+val+'b';
             }              }
         }          }
     }      }
     function select_group() {      function select_group() {
  parent.window.location=   parent.window.location=
     "/adm/groupsort?mode=$ENV{'form.mode'}&catalogmode=groupsearch&acts="+      "/adm/groupsort?mode=$env{'form.mode'}&catalogmode=import$inhibit_menu&acts="+
     parent.statusframe.document.forms.statusform.elements.Queue.value;      parent.statusframe.document.forms.statusform.elements.acts.value;
     }      }
   // ]]>
 </script>  </script>
 SCRIPT  SCRIPT
     $result.=<<END;  
 </head>      my $start_page  = &Apache::loncommon::start_page(undef,$js,
 $bodytag       {'only_body' =>1,
 <form name="results" method="post" action="/adm/searchcat" >                                                        'add_wishlist' =>1,
 <input type="hidden" name="Queue" value="" />                                                        'add_modal' =>1});
       my $result=<<END;
   $start_page
   <form name="results" method="post" action="/adm/searchcat">
 $importbutton  $importbutton
 END  END
     return $result;      return $result;
 }  }
   
 ######################################################################  
 ######################################################################  
 sub search_status_header {  
     my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);  
     return <<ENDSTATUS;  
 <html><head><title>Search Status</title></head>  
 $bodytag  
 <h3>Search Status</h3>  
 Sending search request to LON-CAPA servers.<br />  
 ENDSTATUS  
 }  
   
 sub results_link {  sub results_link {
     my $basic_link   = "/adm/searchcat?"."&table=".$ENV{'form.table'}.      my $basic_link   = "/adm/searchcat?"."&amp;table=".$env{'form.table'}.
         "&persistent_db_id=".$ENV{'form.persistent_db_id'};          "&amp;persistent_db_id=".$env{'form.persistent_db_id'};
     my $results_link = $basic_link."&phase=results".      my $results_link = $basic_link."&amp;phase=results".
         "&pause=1"."&start=1";          "&amp;pause=1"."&amp;start=1";
     return $results_link;      return $results_link;
 }  }
   
Line 2943  sub results_link { Line 3170  sub results_link {
 ######################################################################  ######################################################################
 sub print_frames_interface {  sub print_frames_interface {
     my $r = shift;      my $r = shift;
     my $basic_link = "/adm/searchcat?"."&table=".$ENV{'form.table'}.      my $basic_link = "/adm/searchcat?"."&amp;table=".$env{'form.table'}.
         "&persistent_db_id=".$ENV{'form.persistent_db_id'};          "&amp;persistent_db_id=".$env{'form.persistent_db_id'};
     my $run_search_link = $basic_link."&phase=run_search";      my $run_search_link = $basic_link."&amp;phase=run_search";
     my $results_link = &results_link();      my $results_link = &results_link();
     my $result = <<"ENDFRAMES";      my $js = <<JS;
 <html>  <script type="text/javascript">
 <head>  // <![CDATA[
 <script>  
 var targetwin = opener;  var targetwin = opener;
 var queue = '';  var queue = '';
   // ]]>
 </script>  </script>
 <title>LON-CAPA Digital Library Search Results</title>  JS
 </head>  
 <frameset rows="150,*">      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
     <frame name="statusframe"  src="$run_search_link">      <frame name="statusframe"  src="$run_search_link">
     <frame name="resultsframe" src="$results_link">      <frame name="resultsframe" src="$results_link">
 </frameset>  $end_page
 </html>  
 ENDFRAMES  ENDFRAMES
   
     $r->print($result);      $r->print($result);
Line 3005  sub evalfields { Line 3241  sub evalfields {
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
   sub display_tools {
       my ($title, $jumpurl) = @_;
       my $result;
       # Metadata
       $result.=
           &Apache::loncommon::modal_link(
               $jumpurl.'.meta?inhibitmenu=yes',
               '<img class="LC_icon" src="/res/adm/pages/catalog.png" alt="Info" />',
               500,500,'_blank',undef,&mt('Metadata'));
       # Stored Links
       $result.=
           ' <a href="javascript:;"'.
           ' onclick="set_wishlistlink('."'$title','$jumpurl'".')" '.
           'title="'.&mt('Save a link for this resource in your personal Stored Links repository').'">'.
           '<img class="LC_icon" src="/res/adm/pages/wishlist.png" '.
           'alt="Stored Links" style="width:22px;"/></a>';
       return $result;
   }
   
   ######################################################################
   ######################################################################
   
 =pod   =pod 
   
 =item Metadata Viewing Functions  =item Metadata Viewing Functions
Line 3027  extra custom metadata to show. Line 3285  extra custom metadata to show.
 sub detailed_citation_view {  sub detailed_citation_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $result;      my $result;
     $result .= '<b>'.$prefix.      my $jumpurl=$values{'url'};
         '<img src="'.&Apache::loncommon::icon($values{'url'}).' " />'.'&nbsp;'.      $jumpurl=~s|^/ext/|http://|;
         '<a href="http://'.$ENV{'HTTP_HOST'}.$values{'url'}.'" '.      $result .=
         'target="search_preview">'.$values{'title'}."</a></b>\n";          '<b>'.$prefix.
     $result .= "<p>\n";          '<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />'.'&nbsp;'.
     $result .= '<b>'.$values{'author'}.'</b>,'.          '<a href="'.$jumpurl.'?inhibitmenu=yes" '.
           'target="preview">'.$values{'title'}."</a></b>\n".
           &display_tools($values{'title'}, $jumpurl).
           "<p>\n".
           '<b>'.$values{'author'}.'</b>,'.
         ' <i>'.$values{'owner'}.'</i><br />';          ' <i>'.$values{'owner'}.'</i><br />';
     foreach my $field       foreach my $field 
         (          (
Line 3094  sub detailed_citation_view { Line 3356  sub detailed_citation_view {
         next if (! exists($values{$field->{'name'}}) ||          next if (! exists($values{$field->{'name'}}) ||
                  $values{$field->{'name'}} eq '');                   $values{$field->{'name'}} eq '');
         if (exists($field->{'type'}) && $field->{'type'} eq 'list') {          if (exists($field->{'type'}) && $field->{'type'} eq 'list') {
             $result .= '<b>'.&mt($field->{'translate'}).'</b><ul>';              $result .= '<b>'.&mt($field->{'translate'}).'</b>';
             foreach my $item (split(',',$values{$field->{'name'}})){              foreach my $item (split(',',$values{$field->{'name'}})){
                 $result .= '<li>'.                  $item = &Apache::lonnet::clutter($item);
                     '<a target="search_preview" '.                  $result .= '<br />'.&display_url($item,1).'<br />';
                     'href="/res/'.$item.'">'.$item.'</a></li>';  
             }              }
             $result .= '</ul>';  
         } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){          } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){
             $result.= &mt($field->{'translate'},              $result.= &mt($field->{'translate'},
                           sprintf($field->{'format'},                            sprintf($field->{'format'},
                                   $values{$field->{'name'}}))."<br />\n";                                    $values{$field->{'name'}}))."<br />\n";
         } else {          } else {
             if ($field->{'special'} eq 'url link') {              if ($field->{'special'} eq 'url link') {
                 $result.=                   $result .= '<br />'.&display_url($jumpurl,1).'<br />';
                      &mt($field->{'translate'},  
                          '<a href="'.$values{'url'}.'" '.  
                          'target="search_preview">'.  
                          $values{$field->{'name'}}.  
                          '</a>');  
             } else {              } else {
                 $result.= &mt($field->{'translate'},                  $result.= &mt($field->{'translate'},
                               $values{$field->{'name'}});                                $values{$field->{'name'}});
Line 3127  sub detailed_citation_view { Line 3382  sub detailed_citation_view {
     if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') {      if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') {
         $result .= '<p>'.$values{'shortabstract'}.'</p>';          $result .= '<p>'.$values{'shortabstract'}.'</p>';
     }      }
     $result .= '<hr align="left" width="200" noshade />'."\n";  
     return $result;      return $result;
 }  }
   
   sub detailed_citation_preview {
       my ($prefix,%values)=@_;
       return &detailed_citation_view($prefix,%values).
              '</td><td>'.
              &Apache::lonindexer::showpreview($values{'url'});
   }
   
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
Line 3144  sub detailed_citation_view { Line 3406  sub detailed_citation_view {
 sub summary_view {  sub summary_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $icon=&Apache::loncommon::icon($values{'url'});      my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=qq{$prefix<img src="$icon" alt="" />};
 $prefix<img src="$icon" />&nbsp;      if (exists($env{'form.sortfield'}) && 
 <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"           $env{'form.sortfield'} !~ /^(default|
    target='search_preview'>$values{'author'}</a><br />                                       author|
 $values{'title'}<br />                                       url|
 $values{'owner'} -- $values{'lastrevisiondate'}<br />                                       title|
                                        owner|
                                        lastrevisiondate|
                                        copyright)$/x) {
           my $tmp = $values{$env{'form.sortfield'}};
           if (! defined($tmp)) { $tmp = 'undefined'; }
           $result .= '&nbsp;'.$tmp.'&nbsp;';
       }
       my $jumpurl=$values{'url'};
       $jumpurl=~s|^/ext/|http://|;
       my $link = '<br />'.&display_url($jumpurl,1).'<br />';
       $result .=
           '<a href="'.$jumpurl.'?inhibitmenu=yes"'.
           ' target="preview">'.$values{'title'}.'</a>'.
           &display_tools($values{'title'}, $jumpurl).<<END;
   <br />
   $link<br />
   $values{'author'}, $values{'owner'} -- $values{'lastrevisiondate'}<br />
 $values{'copyrighttag'}<br />  $values{'copyrighttag'}<br />
 $values{'extrashow'}  $values{'extrashow'}
 </p>  
 <hr align='left' width='200' noshade />  
 END  END
     return $result;      return $result;
 }  }
   
   sub summary_preview {
       my ($prefix,%values)=@_;
       return &summary_view($prefix,%values).
              '</td><td>'.
              &Apache::lonindexer::showpreview($values{'url'});
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
Line 3171  END Line 3455  END
 ######################################################################  ######################################################################
 sub compact_view {  sub compact_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $jumpurl=$values{'url'};
       $jumpurl=~s|^/ext/|http://|;
   
       my $link = &display_url($jumpurl,1);
       
     my $result =       my $result = 
         $prefix.'<img src="'.&Apache::loncommon::icon($values{'url'}).          $prefix.'<img src="'.&Apache::loncommon::icon($values{'url'}).'" alt="" />';
         '">&nbsp;<a href="'.$values{'url'}.'" target="search_preview">'.      if (exists($env{'form.sortfield'}) && 
         $values{'title'}.'</a>'.('&nbsp;'x2).          $env{'form.sortfield'} !~ /^(default|author|url|title)$/) {
         '<b>'.$values{'author'}.'</b><br />';          my $tmp = $values{$env{'form.sortfield'}};
           if (! defined($tmp)) { $tmp = 'undefined'; }
           $result .= '&nbsp;'.$tmp.'&nbsp;';
       }
       $jumpurl = &HTML::Entities::encode($jumpurl,'<>&"');
       $result.=' <span class="LC_nobreak">'.
    '<a href="'.$jumpurl.'?inhibitmenu=yes" target="preview">'.
           &HTML::Entities::encode($values{'title'},'<>&"').'</a></span> '.
           &display_tools($values{'title'}, $jumpurl).
    $link.' <b>'.$values{'author'}.'</b> ('.$values{'domain'}.')';
     return $result;      return $result;
 }  }
   
   sub display_url {
       my ($url,$skiplast) = @_;
       my $link;
       if ($url=~m|^/ext/|) {
    $url=~s|^/ext/|http://|;
    $link='<span class="LC_filename">'.$url.'</span>';
       } elsif ($url=~m{^(http://|/uploaded/)}) {
    $link='<span class="LC_filename">'.$url.'</span>';
       } else {
           $link=&Apache::lonhtmlcommon::crumbs(
                     $url,
                     'preview',
                     '',
                     (($env{'form.catalogmode'} eq 'import')?'parent.statusframe.document.forms.statusform':''),
                     $skiplast).' ';
       }
       return $link;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 3195  sub fielded_format_view { Line 3511  sub fielded_format_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $icon=&Apache::loncommon::icon($values{'url'});      my $icon=&Apache::loncommon::icon($values{'url'});
     my %Translated = &Apache::lonmeta::fieldnames();      my %Translated = &Apache::lonmeta::fieldnames();
       my $jumpurl=$values{'url'};
       $jumpurl=~s|^/ext/|http://|;
   
     my $result=<<END;      my $result=<<END;
 $prefix <img src="$icon" />  $prefix <img src="$icon" alt="" />
 <dl>  <dl>
 <dt>URL:</dt>  <dt>URL:</dt>
     <dd><a href="http://$ENV{'HTTP_HOST'}$values{'url'}"       <dd><a href="$jumpurl?inhibitmenu=yes" 
          target='search_preview'>$values{'url'}</a></dd>           target='preview'>$values{'url'}</a>
 END  END
     foreach my $field ('title','author','subject','keywords','notes',      $result .=
           &display_tools($values{'title'}, $jumpurl).'
       </dd>';
       foreach my $field ('title','author','domain','subject','keywords','notes',
                        'mimetag','language','creationdate','lastrevisiondate',                         'mimetag','language','creationdate','lastrevisiondate',
                        'owner','copyrighttag','hostname','abstract') {                         'owner','copyrighttag','hostname','abstract') {
         $result .= (' 'x4).'<dt>'.$Translated{$field}.'</dt>'."\n".          $result .= (' 'x4).'<dt>'.$Translated{$field}.'</dt>'."\n".
Line 3222  END Line 3544  END
     }      }
     $result .= "</dl>\n";      $result .= "</dl>\n";
     $result .= $values{'extrashow'};      $result .= $values{'extrashow'};
     $result .= '<hr align="left" width="200" noshade />'."\n";  
     return $result;      return $result;
 }  }
   
Line 3243  sub xml_sgml_view { Line 3564  sub xml_sgml_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $xml = '<LonCapaResource>'."\n";      my $xml = '<LonCapaResource>'."\n";
     # The usual suspects      # 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}</$field>}."\n";          $xml .= qq{<$field>$values{$field}</$field>}."\n";
     }      }
     #      #
Line 3296  $prefix Line 3617  $prefix
 $xml  $xml
 </pre>  </pre>
 $values{'extrashow'}  $values{'extrashow'}
 <hr align='left' width='200' noshade />  
 END  END
     return $result;      return $result;
 }  }
Line 3336  sub output_unparsed_phrase_error { Line 3656  sub output_unparsed_phrase_error {
     my ($r,$closebutton,$parms,$hidden_fields,$field)=@_;      my ($r,$closebutton,$parms,$hidden_fields,$field)=@_;
     my $errorstring;      my $errorstring;
     if ($field eq 'basicexp') {      if ($field eq 'basicexp') {
         $errorstring = &mt('Unable to understand the search phrase <i>[_1]</i>.  Please modify your search.',$ENV{'form.basicexp'});          $errorstring = &mt('Unable to understand the search phrase [_1]. Please modify your search.'
                              ,'<i>'.$env{'form.basicexp'}.'</i>');
     } else {      } else {
         $errorstring = &mt('Unable to understand the search phrase <b>[_1]</b>:<i>[_2]</i>.',$field,$ENV{'form.'.$field});          $errorstring = &mt('Unable to understand the search phrase [_1]: [_2]'
                              ,'<i>'.$field.'</i>'
                              ,$env{'form.'.$field});
     }      }
     my $bodytag = &Apache::loncommon::bodytag('Search');  
     my $heading = &mt('Unparsed Field');      my $heading = &mt('Unparsed Field');
     my $revise  = &mt('Revise search request');      my $revise  = &mt('Revise search request');
     # make query information persistent to allow for subsequent revision      # 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(<<ENDPAGE);      $r->print(<<ENDPAGE);
 <html>  $start_page
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 </head>  
 $bodytag  
 <form method="post" action="/adm/searchcat">  <form method="post" action="/adm/searchcat">
 $hidden_fields  $hidden_fields
 $closebutton  $closebutton
 <hr />  <hr />
 <h2>$heading</h2>  <h2>$heading</h2>
 <p>  <p class="LC_warning">
 $errorstring  $errorstring
 </p>  </p>
 <p>  <p>
 <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}">$revise</a>  <a href="/adm/searchcat?$parms&amp;persistent_db_id=$env{'form.persistent_db_id'}">$revise</a>
 </p>  </p>
 </body>  $end_page
 </html>  
 ENDPAGE  ENDPAGE
 }  }
   
Line 3388  $parms is extra information to include i Line 3707  $parms is extra information to include i
 ######################################################################  ######################################################################
 sub output_blank_field_error {  sub output_blank_field_error {
     my ($r,$closebutton,$parms,$hidden_fields)=@_;      my ($r,$closebutton,$parms,$hidden_fields)=@_;
     my $bodytag=&Apache::loncommon::bodytag('Search');      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 $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 = '<p>'.$closebutton.'</p><hr />';
       } else {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'',
                 text=>$heading,});
           $start_page .= &Apache::lonhtmlcommon::breadcrumbs();
       }
   
     $r->print(<<ENDPAGE);      $r->print(<<ENDPAGE);
 <html>  $start_page
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 </head>  
 $bodytag  
 <form method="post" action="/adm/searchcat">  <form method="post" action="/adm/searchcat">
 $hidden_fields  $hidden_fields
 $closebutton  $closebutton
 <hr />  </form>
 <h2>$heading</h2>  <h2>$heading</h2>
 <p>  <p class="LC_warning">
 $errormsg  $errormsg
 </p>  </p>
 <p>  <p>
 <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}">$revise</a>&nbsp;  <a href="/adm/searchcat?$parms&amp;persistent_db_id=$env{'form.persistent_db_id'}">$revise</a>
 </p>  </p>
 </body>  $end_page
 </html>  
 ENDPAGE  ENDPAGE
     return;      return;
 }  }
Line 3437  Inputs: Line 3761  Inputs:
 sub output_date_error {  sub output_date_error {
     my ($r,$message,$closebutton,$hidden_fields)=@_;      my ($r,$message,$closebutton,$hidden_fields)=@_;
     # make query information persistent to allow for subsequent revision      # 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();
       my $heading = &mt('Error');
     $r->print(<<RESULTS);      $r->print(<<RESULTS);
 <html>  $start_page
 <head>  
 <title>The LearningOnline Network with CAPA</title>  
 </head>  
 $bodytag  
 <img align='right' src='/adm/lonIcons/lonlogos.gif' />  
 <h1>Search Catalog</h1>  
 <form method="post" action="/adm/searchcat">  <form method="post" action="/adm/searchcat">
 $hidden_fields  $hidden_fields
 <input type='button' value='Revise search request'  <input type='button' value='Revise search request'
 onClick='this.form.submit();' />  onclick='this.form.submit();' />
 $closebutton  $closebutton
   </form>
 <hr />  <hr />
 <h3>Error</h3>  <h3>$heading</h3>
 <p>  <p class="LC_error">
 $message  $message
 </p>  </p>
 </body>  $end_page
 </html>  
 RESULTS  RESULTS
 }  }
   
Line 3495  sub cleanup { Line 3815  sub cleanup {
   &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');    &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');
         }          }
     }      }
     &untiehash();  
     &Apache::lonmysql::disconnect_from_db();      &Apache::lonmysql::disconnect_from_db();
       return OK;
 }  }
   
 __END__  __END__

Removed from v.1.230.2.1  
changed lines
  Added in v.1.331.4.9


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>