Diff for /loncom/interface/lonsearchcat.pm between versions 1.175 and 1.208

version 1.175, 2003/05/30 20:54:28 version 1.208, 2004/04/19 14:42:24
Line 48  described at http://www.lon-capa.org. Line 48  described at http://www.lon-capa.org.
 lonsearchcat presents the user with an interface to search the LON-CAPA  lonsearchcat presents the user with an interface to search the LON-CAPA
 digital library.  lonsearchcat also initiates the execution of a search  digital library.  lonsearchcat also initiates the execution of a search
 by sending the search parameters to LON-CAPA servers.  The progress of   by sending the search parameters to LON-CAPA servers.  The progress of 
 search (on a server basis) is displayed to the user in a seperate window.  search (on a server basis) is displayed to the user in a separate window.
   
 =head1 Internals  =head1 Internals
   
Line 59  search (on a server basis) is displayed Line 59  search (on a server basis) is displayed
 ###############################################################################  ###############################################################################
 ###############################################################################  ###############################################################################
   
 ###############################################################################  
 ##                                                                           ##  
 ## ORGANIZATION OF THIS PERL MODULE                                          ##  
 ##                                                                           ##  
 ## 1. Modules used by this module                                            ##  
 ## 2. Variables used throughout the module                                   ##  
 ## 3. handler subroutine called via Apache and mod_perl                      ##  
 ## 4. Other subroutines                                                      ##  
 ##                                                                           ##  
 ###############################################################################  
   
 package Apache::lonsearchcat;  package Apache::lonsearchcat;
   
 # ------------------------------------------------- modules used by this module  
 use strict;  use strict;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use Apache::lonnet();  use Apache::lonnet();
Line 82  use Text::Query; Line 70  use Text::Query;
 use GDBM_File;  use GDBM_File;
 use Apache::loncommon();  use Apache::loncommon();
 use Apache::lonmysql();  use Apache::lonmysql();
 use Apache::lonmenu();  use Apache::lonmeta;
   use Apache::lonhtmlcommon;
 # ---------------------------------------- variables used throughout the module  use Apache::lonlocal;
   use LONCAPA::lonmetadata();
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   ##
 =pod   ## Global variables
   ##
 =item Global variables  
   
 =over 4  
   
 =item $importbutton  
   
 button to take the select results and go to group sorting  
   
 =item %groupsearch_db     
   
 Database hash used to save values for the groupsearch RAT interface.  
   
 =item $diropendb   
   
 The full path to the (temporary) search database file.  This is set and  
 used in &handler() and is also used in &output_results().  
   
 =item %Views  
   
 Hash which associates an output view description with the function  
 that produces it.  Adding a new view type should be as easy as  
 adding a line to the definition of this hash and making sure the function  
 takes the proper parameters.  
   
 =item $bodytag  
   
 LON-CAPA standard body tag, gotten from &Apache::lonnet::bodytag.  
 No title, no table, just a <body> tag.  
   
 =back   
   
 =cut  
   
 ######################################################################  
 ######################################################################  
   
 # -- dynamically rendered interface components  
 my $importbutton; # button to take the selected results and go to group sorting  
   
 # -- miscellaneous variables  
 my %groupsearch_db;     # database hash  
 my $diropendb = "";    # db file  
 #             View Description           Function Pointer  
 my %Views = ("Detailed Citation View" => \&detailed_citation_view,  
              "Summary View"           => \&summary_view,  
              "Fielded Format"         => \&fielded_format_view,  
              "XML/SGML"               => \&xml_sgml_view,  
              "Compact View"           => \&compact_view);  
 my %persistent_db;  
 my $hidden_fields;  
 my $bodytag;  
   
 #  
 # For course search  
 #  
 my %alreadyseen;  
 my $hashtied;  
 my %hash;  
 my $totalfound;  
    
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   my %groupsearch_db;  # Database hash used to save values for the 
                        # groupsearch RAT interface.
   my %persistent_db;   # gdbm hash which holds data which is supposed to
                        # persist across calls to lonsearchcat.pm
   
 =pod   # The different view modes and associated functions
   
 =item &handler() - main handler invoked by httpd child  
   
 =item Variables  
   
 =over 4  my %Views = ("detailed" => \&detailed_citation_view,
        "summary"  => \&summary_view,
 =item $hidden       "fielded"  => \&fielded_format_view,
        "xml"      => \&xml_sgml_view,
 holds 'hidden' html forms       "compact"  => \&compact_view);
   
 =item $scrout  
   
 string that holds portions of the screen output  
   
 =back   
   
 =cut  
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
   #    &set_defaults();
     #      #
       # set form defaults
       #
       my $hidden_fields;# Hold all the hidden fields used to keep track
                         # of the search system state
       my $importbutton; # button to take the selected results and go to group 
                         # sorting
       my $diropendb;    # The full path to the (temporary) search database file.
                         # This is set and used in &handler() and is also used in 
                         # &output_results().
       my $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);      my $loaderror=&Apache::lonnet::overloaderror($r);
     if ($loaderror) { return $loaderror; }      if ($loaderror) { return $loaderror; }
Line 187  sub handler { Line 121  sub handler {
                       # This button is different for the RAT compared to                        # This button is different for the RAT compared to
                       # normal invocation.                        # normal invocation.
     #      #
     $r->content_type('text/html');      &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;      $r->send_http_header;
     return OK if $r->header_only;      return OK if $r->header_only;
     ##      ##
Line 200  sub handler { Line 134  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']);                'cleargroupsort','titleelement']);
     ##      ##
     ## 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
Line 208  sub handler { Line 142  sub handler {
     ##     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(3);          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/".&Apache::lonnet::escape($domain).      $diropendb= "/home/httpd/perl/tmp/$ENV{'user.domain'}_$ENV{'user.name'}_searchcat.db";
             "\_".&Apache::lonnet::escape($ENV{'user.name'})."_searchcat.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.
Line 283  END Line 216  END
         $hidden_fields .= '<input type="hidden" name="element" value="'.          $hidden_fields .= '<input type="hidden" name="element" value="'.
                 $ENV{'form.element'}.'" />'."\n";                  $ENV{'form.element'}.'" />'."\n";
     }      }
       if (exists($ENV{'form.titleelement'})) {
           $hidden_fields .= '<input type="hidden" name="titleelement" value="'.
                   $ENV{'form.titleelement'}.'" />'."\n";
       }
     if (exists($ENV{'form.mode'})) {      if (exists($ENV{'form.mode'})) {
         $hidden_fields .= '<input type="hidden" name="mode" value="'.          $hidden_fields .= '<input type="hidden" name="mode" value="'.
                 $ENV{'form.mode'}.'" />'."\n";                  $ENV{'form.mode'}.'" />'."\n";
Line 331  END Line 268  END
     ## 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);          &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);          &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);          &display_results($r,$importbutton,$closebutton,$diropendb);
     } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) {      } elsif ($ENV{'form.phase'} =~ /^(sort|run_search)$/) {
         my ($query,$customquery,$customshow,$libraries,$pretty_string) =          my ($query,$customquery,$customshow,$libraries,$pretty_string) =
             &get_persistent_data($persistent_db_file,              &get_persistent_data($persistent_db_file,
Line 357  END Line 294  END
         }          }
         # Set up table          # Set up table
         if (! defined(&create_results_table())) {          if (! defined(&create_results_table())) {
       my $errorstring=&Apache::lonmysql::get_error();
             $r->print(<<END);              $r->print(<<END);
 <html><head><title>Search Error</title></head>  <html><head><title>Search Error</title></head>
 $bodytag  $bodytag
 Unable to create table in which to store search results.    Unable to create table in which to store search results.  
 The search has been aborted.  The search has been aborted.
   <br />$errorstring
 </body>  </body>
 </html>  </html>
 END  END
Line 384  END Line 323  END
             (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) = &parse_basic_search($r,$closebutton);              ($query,$pretty_string,$libraries) = 
                   &parse_basic_search($r,$closebutton,$hidden_fields);
         } else {                      # Advanced search          } else {                      # Advanced search
             ($query,$customquery,$customshow,$libraries,$pretty_string)               ($query,$customquery,$customshow,$libraries,$pretty_string) 
                 = &parse_advanced_search($r,$closebutton);                  = &parse_advanced_search($r,$closebutton,$hidden_fields);
             return OK if (! defined($query));              return OK if (! defined($query));
         }          }
         &make_persistent({ query => $query,          &make_persistent({ query => $query,
Line 406  END Line 346  END
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   ##
   ##   Course Search
   ##
   ######################################################################
   ######################################################################
   {   # Scope the course search to avoid global variables
   #
   # Variables For course search
   my %alreadyseen;
   my %hash;
   my $totalfound;
   
 sub course_search {  sub course_search {
     my $r=shift;      my $r=shift;
     my $bodytag=&Apache::loncommon::bodytag('Course Search');      my $bodytag=&Apache::loncommon::bodytag('Course Search').
    &Apache::loncommon::help_open_bug('Searching');
     my $pretty_search_string = '<b>'.$ENV{'form.courseexp'}.'</b>';      my $pretty_search_string = '<b>'.$ENV{'form.courseexp'}.'</b>';
     my $search_string = $ENV{'form.courseexp'};      my $search_string = $ENV{'form.courseexp'};
     my @New_Words;      my @New_Words;
     if ($ENV{'form.crsrelated'}) {      if ($ENV{'form.crsrelated'}) {
         ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'});          ($search_string,@New_Words) = &related_version($ENV{'form.courseexp'});
         if (@New_Words) {          if (@New_Words) {
             $pretty_search_string .= " with related words: <b>@New_Words</b>.";              $pretty_search_string .= ' '.&mt("with related words").": <b>@New_Words</b>.";
         } else {          } else {
             $pretty_search_string .= " with no related words.";              $pretty_search_string .= ' '.&mt('with no related words').".";
         }          }
     }      }
     my $fulltext=$ENV{'form.crsfulltext'};      my $fulltext=$ENV{'form.crsfulltext'};
     my @allwords=($search_string,@New_Words);      my @allwords=($search_string,@New_Words);
     $totalfound=0;      $totalfound=0;
     $r->print('<html><head><title>LON-CAPA Course Search</title></head>'.      $r->print('<html><head><title>LON-CAPA Course Search</title></head>'.
       $bodytag.$pretty_search_string);        $bodytag.'<hr /><center><font size="+2" face="arial">'.$pretty_search_string.'</font></center><hr />');
     $r->rflush();      $r->rflush();
 # ======================================================= Go through the course  # ======================================================= Go through the course
    $hashtied=0;      undef %alreadyseen;
    undef %alreadyseen;      %alreadyseen=();
    %alreadyseen=();  
     my $c=$r->connection;      my $c=$r->connection;
    &tiehash();      if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",
    foreach (keys %hash) {              &GDBM_READER(),0640)) {
        if ($c->aborted()) { last; }          foreach (keys %hash) {
        if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) {              if ($c->aborted()) { last; }
            &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext,@allwords);              if (($_=~/^src\_(.+)$/) && (!$alreadyseen{$hash{$_}})) {
        }                  &checkonthis($r,$hash{$_},0,$hash{'title_'.$1},$fulltext,
    }                               @allwords);
    &untiehash();              }
           }
           untie(%hash);
       }
     unless ($totalfound) {      unless ($totalfound) {
  $r->print('<p>No resources found.</p>');   $r->print('<p>'.&mt('No resources found').'.</p>');
     }      }
 # =================================================== Done going through course  # =================================================== Done going through course
     $r->print('</body></html>');      $r->print('</body></html>');
 }  }
   
 # ---------------------------------------------------------------- tie the hash  
   
 sub tiehash {  
     $hashtied=0;  
     if ($ENV{'request.course.fn'}) {  
         if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.".db",  
             &GDBM_READER(),0640)) {  
                 $hashtied=1;  
         }  
     }      
 }  
   
 sub untiehash {  
     if ($hashtied) { untie %hash; }  
     $hashtied=0;  
 }  
   
 # =============================== This pulls up a resource and its dependencies  # =============================== This pulls up a resource and its dependencies
   
 sub checkonthis {  sub checkonthis {
Line 509  sub checkonthis { Line 446  sub checkonthis {
     }      }
 }  }
   
 ######################################################################  sub untiehash {
 ######################################################################      if (tied(%hash)) {
           untie(%hash);
 =pod       }
   }
 =item &print_basic_search_form()   
   
 Returns a scalar which holds html for the basic search form.  
   
 =cut  
   
 ######################################################################  } # End of course search scoping
 ######################################################################  
   
 sub print_basic_search_form{  sub search_html_header {
     my ($r,$closebutton) = @_;      my $Str = <<ENDHEADER;
     my $bodytag=&Apache::loncommon::bodytag('Search');  
     my $scrout=<<"ENDDOCUMENT";  
 <html>  <html>
 <head>  <head>
 <title>The LearningOnline Network with CAPA</title>  <title>The LearningOnline Network with CAPA</title>
Line 538  sub print_basic_search_form{ Line 467  sub print_basic_search_form{
     }      }
 </script>  </script>
 </head>  </head>
 $bodytag  ENDHEADER
 ENDDOCUMENT      return $Str;
 if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {  }
     $scrout.=(<<ENDDOCUMENT);  
 <h1>Catalog Search</h1>  ######################################################################
 <form method="post" action="/adm/searchcat">  ######################################################################
   
   =pod 
   
   =item &print_basic_search_form() 
   
   Prints the form for the basic search.  Sorry the name is so cryptic.
   
   =cut
   
   ######################################################################
   ######################################################################
   sub print_basic_search_form {
       my ($r,$closebutton,$hidden_fields) = @_;
       my $bodytag=&Apache::loncommon::bodytag('Search').
    &Apache::loncommon::help_open_topic('Finding_Resources').
    &Apache::loncommon::help_open_bug('Searching');
       my $scrout = &search_html_header().$bodytag;
       if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {
           my $CatalogSearch=&mt('Catalog Search');
           my $Statement=&searchhelp();
           $scrout.=(<<ENDDOCUMENT);
   <h1>$CatalogSearch</h1>
   <form name="loncapa_search" method="post" action="/adm/searchcat">
 <input type="hidden" name="phase" value="basic_search" />  <input type="hidden" name="phase" value="basic_search" />
 $hidden_fields  $hidden_fields
 <p>  <p>
 Enter terms or phrases separated by AND, OR, or NOT   $Statement.
 then press SEARCH below.  
 </p>  </p>
 <p>  <p>
 <table>  <table>
 <tr><td>  <tr><td>
 ENDDOCUMENT  ENDDOCUMENT
     $scrout.='&nbsp;'.&simpletextfield('basicexp',$ENV{'form.basicexp'},40).          $scrout.='&nbsp;'.
         '&nbsp;';              &Apache::lonhtmlcommon::textbox('basicexp',
     my $checkbox = &simplecheckbox('related',$ENV{'form.related'});                                          $ENV{'form.basicexp'},40).
     $scrout.=<<END;                                          '&nbsp;';
           my $relatedcheckbox = 
               &Apache::lonhtmlcommon::checkbox('related',
                                                $ENV{'form.related'});
           my $domain = $r->dir_config('lonDefDomain');
           my $domaincheckbox = 
               &Apache::lonhtmlcommon::checkbox('domains',
                                                $ENV{'form.domains'});
           my $srch=&mt('Search');
           my $header=&mt('Advanced Search');
           my $userelatedwords=&mt('use related words');
           my $onlysearchdomain=&mt('only search domain');
           my $view=&viewoptions();
           $scrout.=<<END;
 </td><td><a  </td><td><a
 href="/adm/searchcat?phase=disp_adv&catalogmode=$ENV{'form.catalogmode'}&launch=$ENV{'form.launch'}"  href="/adm/searchcat?phase=disp_adv&catalogmode=$ENV{'form.catalogmode'}&launch=$ENV{'form.launch'}&mode=$ENV{'form.mode'}"
 >Advanced Search</a></td></tr>  >$header</a></td></tr>
 <tr><td>$checkbox use related words</td><td></td></tr>  <tr><td>$relatedcheckbox $userelatedwords</td>
       <td>$domaincheckbox $onlysearchdomain <b>$domain</b></td></tr>
 </table>  </table>
 </p>  </p>
   $view
 <p>  <p>
 &nbsp;<input type="submit" name="basicsubmit" value='SEARCH' />&nbsp;  &nbsp;<input type="submit" name="basicsubmit" value='$srch' />&nbsp;
 $closebutton  $closebutton
 END  END
     $scrout.=&selectbox(undef,'viewselect',  
  $ENV{'form.viewselect'},  
  undef,undef,undef,  
  sort(keys(%Views)));  
     $scrout.=&selectbox(undef,'show',  
  $ENV{'form.show'},  
  undef,undef,undef,  
  (10,20,50,100));  
     $scrout.=<<ENDDOCUMENT;      $scrout.=<<ENDDOCUMENT;
 per page.  
 </p>  </p>
 </form>  </form>
 ENDDOCUMENT  ENDDOCUMENT
     if ($ENV{'request.course.id'}) { $scrout.='<hr />'; }      }
 }      if ($ENV{'request.course.id'}) {
 if ($ENV{'request.course.id'}) {   my %lt=&Apache::lonlocal::texthash(
     $scrout.=(<<ENDCOURSESEARCH);     'srch' => 'Search',
 <h1>Course Search</h1>                                                 'header' => 'Course Search',
 <form method="post" action="/adm/searchcat">   'note' => 'Enter terms or phrases, then press "Search" below',
    'use' => 'use related words',
    'full' =>'fulltext search (time consuming)'
      );
           $scrout.=(<<ENDCOURSESEARCH);
   <hr />
   <h1>$lt{'header'}</h1>    
   <form name="course_search" method="post" action="/adm/searchcat">
 <input type="hidden" name="phase" value="course_search" />  <input type="hidden" name="phase" value="course_search" />
 $hidden_fields  $hidden_fields
 <p>  <p>
 Enter terms or phrases, then press SEARCH below.  $lt{'note'}.
 </p>  </p>
 <p>  <p>
 <table>  <table>
 <tr><td>  <tr><td>
 ENDCOURSESEARCH  ENDCOURSESEARCH
     $scrout.='&nbsp;'.&simpletextfield('courseexp',$ENV{'form.courseexp'},40);          $scrout.='&nbsp;'.
     my $crscheckbox = &simplecheckbox('crsfulltext',$ENV{'form.crsfulltext'});              &Apache::lonhtmlcommon::textbox('courseexp',
     my $relcheckbox = &simplecheckbox('crsrelated',$ENV{'form.crsrelated'});                                    $ENV{'form.courseexp'},40);
 $scrout.=(<<ENDENDCOURSE);          my $crscheckbox = 
               &Apache::lonhtmlcommon::checkbox('crsfulltext',
                                      $ENV{'form.crsfulltext'});
           my $relcheckbox = 
               &Apache::lonhtmlcommon::checkbox('crsrelated',
      $ENV{'form.crsrelated'});
           $scrout.=(<<ENDENDCOURSE);
 </td></tr>  </td></tr>
 <tr><td>$relcheckbox use related words</td><td></td></tr>  <tr><td>$relcheckbox $lt{'use'}</td><td></td></tr>
 <tr><td>$crscheckbox fulltext search (time consuming)</td><td></td></tr>  <tr><td>$crscheckbox $lt{'full'}</td><td></td></tr>
 </table><p>  </table><p>
 &nbsp;<input type="submit" name="coursesubmit" value='SEARCH' />  &nbsp;<input type="submit" name="coursesubmit" value='$lt{'srch'}' />
 </p>  </p>
 ENDENDCOURSE  ENDENDCOURSE
 }      }
     $scrout.=(<<ENDDOCUMENT);      $scrout.=(<<ENDDOCUMENT);
 </body>  </body>
 </html>  </html>
Line 622  ENDDOCUMENT Line 592  ENDDOCUMENT
   
 =item &advanced_search_form()   =item &advanced_search_form() 
   
 Returns a scalar which holds html for the advanced search form.  Prints the advanced search form.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 sub print_advanced_search_form{  sub print_advanced_search_form{
     my ($r,$closebutton) = @_;      my ($r,$closebutton,$hidden_fields) = @_;
       my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
          'reset' => 'Reset',
          'help' => 'Help');
     my $advanced_buttons = <<"END";      my $advanced_buttons = <<"END";
 <p>  <p>
 <input type="submit" name="advancedsubmit" value='SEARCH' />  <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />
 <input type="reset" name="reset" value='RESET' />  <input type="reset" name="reset" value='$lt{"reset"}' />
 $closebutton  $closebutton
 <input type="button" value="HELP" onClick="openhelp()" />  <input type="button" value="$lt{'help'}" onClick="openhelp()" />
 </p>  
 END  END
     if (!defined($ENV{'form.viewselect'})) {  
         $ENV{'form.viewselect'} ="Detailed Citation View";  
     }  
     my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search');      my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search');
     my $scrout=<<"ENDHEADER";      my $searchhelp=&searchhelp();
 <html>      my $scrout=&search_html_header();
 <head>      $scrout .= <<"ENDHEADER";
 <title>The LearningOnline Network with CAPA</title>  
 <script type="text/javascript">  
     function openhelp(val) {  
  openhelpwin=open('/adm/help/searchcat.html','helpscreen',  
      'scrollbars=1,width=600,height=300');  
  openhelpwin.focus();  
     }  
 </script>  
 </head>  
 $bodytag  $bodytag
 Enter terms or phrases separated by search operators   <form method="post" action="/adm/searchcat" name="advsearch">
 such as AND, OR, or NOT.<br />  
 <form method="post" action="/adm/searchcat">  
 $advanced_buttons  $advanced_buttons
 $hidden_fields  
 <input type="hidden" name="phase" value="adv_search" />  
 <table>  
 <tr><td><font color="#800000" face="helvetica"><b>VIEW:</b></font></td>  
 <td>  
 ENDHEADER  ENDHEADER
     $scrout.=&selectbox(undef,'viewselect',      $scrout.=('&nbsp;'x2).&viewoptions().'</p>'.$hidden_fields. 
  $ENV{'form.viewselect'},          '<input type="hidden" name="phase" value="adv_search" />';
  undef,undef,undef,      my %fields=&Apache::lonmeta::fieldnames();
  sort(keys(%Views)));      #
     $scrout.='&nbsp;';      $scrout.= '<p>'.$searchhelp.'</p>'.
     $scrout.=&selectbox(undef,'show',          "<table>\n";
  $ENV{'form.show'},      my %related_word_search = 
  undef,undef,undef,          ('title'=>1,
  (10,20,50,100));           'author'=>0,
     $scrout.='&nbsp;'.           'owner'=>0,
         '<font color="#800000" face="helvetica">Per Page</font>';           'authorspace'=>0,
     $scrout.="</td><td>Related<br />Words</td></tr>\n";           'modifyinguser'=>0,
     $scrout.=&searchphrasefield_with_related('title',   'title'   ,           'keywords'=>1,
                                              $ENV{'form.title'});           'notes'=>1,
     $scrout.=&searchphrasefield('author',  'author'  ,$ENV{'form.author'});           'abstract'=>1,
     $scrout.=&searchphrasefield_with_related('subject', 'subject' ,           'standards'=>1,
                                              $ENV{'form.subject'});           'mime'=>1,
     $scrout.=&searchphrasefield_with_related('keywords','keywords',           );
                                              $ENV{'form.keywords'});  
     $scrout.=&searchphrasefield('URL',     'url'     ,$ENV{'form.url'});      foreach my $field ('title','author','owner','authorspace','modifyinguser',
     $scrout.=&searchphrasefield_with_related('notes',   'notes'   ,       'keywords','notes','abstract','standards','mime') {
                                              $ENV{'form.notes'});   $scrout.='<tr><td align="right">'.&titlefield($fields{$field}).'</td><td>'.
     $scrout.=&searchphrasefield_with_related('abstract','abstract',      &Apache::lonmeta::prettyinput($field,
                                              $ENV{'form.abstract'});                                            $ENV{'form.'.$field},
     # Hack - an empty table row.                                            $field,
     $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";                                            'advsearch',
     $scrout.=&searchphrasefield('file<br />extension','extension',    $related_word_search{$field},
                         $ENV{'form.extension'});                                            '</td><td align="left">',
     $scrout.="<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";                                            $ENV{'form.'.$field.'_related'},
     $scrout.=&searchphrasefield('publisher<br />owner','owner',                                            50);
  $ENV{'form.owner'});          if ($related_word_search{$field}) {
     $scrout.="</table>\n";              $scrout .= 'related words';
     $ENV{'form.category'}='any' if (! defined($ENV{'form.category'}));          } else {
     $scrout.=&selectbox('File Category','category',              $scrout .= '</td><td>&nbsp;';
  $ENV{'form.category'},          }
  'any','Any category',          $scrout .= '</td></tr>'.$/;
  undef,  
  (&Apache::loncommon::filecategories()));  
     $ENV{'form.language'}='any' unless length($ENV{'form.language'});  
     #----------------------------------------------------------------  
     # Allow restriction to multiple domains.  
     #   I make the crazy assumption that there will never be a domain 'any'.  
     #  
     $ENV{'form.domains'} = 'any' if (! exists($ENV{'form.domains'}));  
     my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}}   
                            :  ($ENV{'form.domains'}) );  
     my %domain_hash = ();  
     foreach (@allowed_domains) {  
         $domain_hash{$_}++;  
     }      }
     my @domains =&Apache::loncommon::get_domains();      foreach my $field ('lowestgradelevel','highestgradelevel') {
     # adjust the size of the select box   $scrout.='<tr>'.
     my $size = 4;              '<td align="right">'.&titlefield($fields{$field}).'</td>'.
     $size = (scalar @domains < ($size - 1) ? scalar @domains + 1 : $size);              '<td colspan="2">'.
     $scrout.="\n".'<font color="#800000" face="helvetica"><b>'.      &Apache::lonmeta::prettyinput($field,
         'DOMAINS TO BE SEARCHED</b></font><br />'.                                            $ENV{'form.'.$field},
             '<select name="domains" size="'.$size.'" multiple>'."\n".                                            $field,
                 '<option name="any" value="any" '.                                            'advsearch',
                     ($domain_hash{'any'}? 'selected ' :'').    0).
                         '>all domains</option>'."\n";                                            '</td></tr>'.$/;
     foreach my $dom (sort @domains) {      }
         $scrout.="<option name=\"$dom\" ".      $scrout.='<tr><td align="right">'.
             ($domain_hash{$dom} ? 'selected ' :'').">$dom</option>\n";   &titlefield(&mt('MIME Type Category')).'</td><td colspan="2">'. 
     }      &Apache::loncommon::filecategoryselect('category',
     $scrout.="</select>\n";     $ENV{'form.category'}).
     #----------------------------------------------------------------      '</td></tr>'.$/;
     $scrout.=&selectbox('Limit by language','language',      $scrout.='<tr><td align="right" valign="top">'.
  $ENV{'form.language'},'any','Any Language',   &titlefield(&mt('Domains')).'</td><td colspan="2">'. 
  \&Apache::loncommon::languagedescription,      &Apache::loncommon::domain_select('domains',
  (&Apache::loncommon::languageids),     $ENV{'form.domains'},1).
  );      '</td></tr>'.$/;
 # ------------------------------------------------ Compute date selection boxes      $scrout .= "</table>\n<br />\n<table>\n";
     $scrout.=<<CREATIONDATESTART;      my %dates=&Apache::lonlocal::texthash
 <p>          ('creationdatestart'     => 'Creation Date After',
 <font color="#800000" face="helvetica"><b>LIMIT BY CREATION DATE RANGE:</b>           'creationdateend'       => 'Creation Date Before',
 </font>           'lastrevisiondatestart' => 'Last Revision Date After',
 <br />           'lastrevisiondateend'   => 'Last Revision Date Before');
 between:      foreach my $field (sort keys %dates) {
 CREATIONDATESTART   $scrout.='<tr>'.
     $scrout.=&dateboxes('creationdatestart',1,1,1976,              '<td align="right">'.&titlefield($dates{$field}).'</td><td>'. 
  $ENV{'form.creationdatestart_month'},      &Apache::lonhtmlcommon::date_setter('advsearch',$field,0,'',1).
  $ENV{'form.creationdatestart_day'},      '</td></tr>'.$/;
  $ENV{'form.creationdatestart_year'},      }
  );      $scrout.="</table>\n";
     $scrout.="and:\n";  
     $scrout.=&dateboxes('creationdateend',12,31,2051,  
  $ENV{'form.creationdateend_month'},  
  $ENV{'form.creationdateend_day'},  
  $ENV{'form.creationdateend_year'},  
  );  
     $scrout.="</p>";  
     $scrout.=<<LASTREVISIONDATESTART;  
 <p>  
 <font color="#800000" face="helvetica"><b>LIMIT BY LAST REVISION DATE RANGE:  
 </b></font>  
 <br />between:  
 LASTREVISIONDATESTART  
     $scrout.=&dateboxes('lastrevisiondatestart',1,1,1976,  
  $ENV{'form.lastrevisiondatestart_month'},  
  $ENV{'form.lastrevisiondatestart_day'},  
  $ENV{'form.lastrevisiondatestart_year'},  
  );  
     $scrout.=<<LASTREVISIONDATEEND;  
 and:  
 LASTREVISIONDATEEND  
     $scrout.=&dateboxes('lastrevisiondateend',12,31,2051,  
  $ENV{'form.lastrevisiondateend_month'},  
  $ENV{'form.lastrevisiondateend_day'},  
  $ENV{'form.lastrevisiondateend_year'},  
  );  
     $scrout.='</p>';  
     $ENV{'form.copyright'}='any' unless length($ENV{'form.copyright'});  
     $scrout.=&selectbox('Limit by copyright/distribution','copyright',  
  $ENV{'form.copyright'},  
  'any','Any copyright/distribution',  
  \&Apache::loncommon::copyrightdescription,  
  (&Apache::loncommon::copyrightids),  
  );  
 # ------------------------------------------- Compute customized metadata field  
 #    $scrout.=<<CUSTOMMETADATA;  
 #<p>  
 #<font color="#800000" face="helvetica"><b>LIMIT BY SPECIAL METADATA FIELDS:</b>  
 #</font>  
 #For resource-specific metadata, enter in an expression in the form of   
 #<i>key</i>=<i>value</i> separated by operators such as AND, OR or NOT.<br />  
 #<b>Example:</b> grandmother=75 OR grandfather=85  
 #<br />  
 #CUSTOMMETADATA  
 #    $scrout.=&simpletextfield('custommetadata',$ENV{'form.custommetadata'});  
 #    $scrout.=<<CUSTOMSHOW;  
 #<p>  
 #<font color="#800000" face="helvetica"><b>SHOW SPECIAL METADATA FIELDS:</b>  
 #</font>  
 #Enter in a space-separated list of special metadata fields to show  
 #in a fielded listing for each record result.  
 #<br />  
 #CUSTOMSHOW  
 #    $scrout.=&simpletextfield('customshow',$ENV{'form.customshow'});  
     $scrout.=<<ENDDOCUMENT;      $scrout.=<<ENDDOCUMENT;
 $advanced_buttons  $advanced_buttons
 </form>  </form>
Line 819  ENDDOCUMENT Line 704  ENDDOCUMENT
   
 =pod   =pod 
   
 =item &get_persistent_form_data  =item &titlefield()
   
   Inputs: title text
   
   Outputs: titletext with font wrapper
   
   =cut
   
   ######################################################################
   ######################################################################
   sub titlefield {
       my $title=shift;
       return $title;
   }
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item viewoptiontext()
   
   Inputs: codename for view option
   
   Outputs: displayed text
   
   =cut
   
   ######################################################################
   ######################################################################
   sub viewoptiontext {
       my $code=shift;
       my %desc=&Apache::lonlocal::texthash
           ('detailed' => "Detailed Citation View",
            'xml' => 'XML/SGML',
            'compact' => 'Compact View',
            'fielded' => 'Fielded Format',
            'summary' => 'Summary View');
       return $desc{$code};
   }
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item viewoptions()
   
   Inputs: none
   
   Outputs: text for box with view options
   
   =cut
   
   ######################################################################
   ######################################################################
   sub viewoptions {
       my $scrout="\n".'<nobr>';
       if (! defined($ENV{'form.viewselect'})) { 
           $ENV{'form.viewselect'}='detailed'; 
       }
       $scrout.=&Apache::lonmeta::selectbox('viewselect',
    $ENV{'form.viewselect'},
    \&viewoptiontext,
    sort(keys(%Views)));
       $scrout.= '&nbsp;&nbsp;';
       $scrout.=&Apache::lonmeta::selectbox('show',
    $ENV{'form.show'},
    undef,
    (10,20,50,100,1000,10000));
       $scrout .= ('&nbsp;'x2).&mt('Records per Page').'</nobr>'.$/;
       return $scrout;
   }
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item searchhelp()
   
   Inputs: none
   
   Outputs: return little blurb on how to enter searches
   
   =cut
   
   ######################################################################
   ######################################################################
   sub searchhelp {
       return &mt('Enter terms or phrases separated by AND, OR, or NOT');
   }
   
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item &get_persistent_form_data()
   
 Inputs: filename of database  Inputs: filename of database
   
Line 847  sub get_persistent_form_data { Line 830  sub get_persistent_form_data {
     # Loop through the keys, looking for 'form.'      # Loop through the keys, looking for 'form.'
     foreach my $name (keys(%persistent_db)) {      foreach my $name (keys(%persistent_db)) {
         next if ($name !~ /^form./);          next if ($name !~ /^form./);
           # Kludgification begins!
           if ($name eq 'form.domains' && 
               $ENV{'form.searchmode'} eq 'basic' &&
               $ENV{'form.phase'} ne 'disp_basic') {
               next;
           }
           # End kludge (hopefully)
         next if (exists($ENV{$name}));          next if (exists($ENV{$name}));
         my @values = map {           my @values = map { 
             &Apache::lonnet::unescape($_);              &Apache::lonnet::unescape($_);
Line 861  sub get_persistent_form_data { Line 851  sub get_persistent_form_data {
     untie (%persistent_db);      untie (%persistent_db);
     return 1;      return 1;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod   =pod 
   
 =item &get_persistent_data  =item &get_persistent_data()
   
 Inputs: filename of database, ref to array of values to recover.  Inputs: filename of database, ref to array of values to recover.
   
Line 917  Inputs: Hash of values to save, filename Line 908  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 seperated string.    elements escaped and concatenated in a comma separated string.  
   
 =cut  =cut
   
Line 949  Inputs: filename of persistent database. Line 940  Inputs: filename of persistent database.
   
 Store most form variables away to the %persistent_db.  Store most form 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 seperated string.    elements escaped and concatenated in a comma separated string.  
   
 =cut  =cut
   
Line 967  sub make_form_data_persistent { Line 958  sub make_form_data_persistent {
 }  }
   
 ######################################################################  ######################################################################
 #                HTML form building functions                        #    
 ######################################################################  
   
 =pod   
   
 =item HTML form building functions  
   
 =over 4  
   
 =cut  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &simpletextfield()   
   
 Inputs: $name,$value,$size  
   
 Returns a text input field with the given name, value, and size.    
 If size is not specified, a value of 20 is used.  
   
 =cut  
   
 ###############################################  
 ###############################################  
   
 sub simpletextfield {  
     my ($name,$value,$size)=@_;  
     $size = 20 if (! defined($size));  
     return '<input type="text" name="'.$name.  
         '" size="'.$size.'" value="'.$value.'" />';  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &simplecheckbox()  
   
 Inputs: $name,$value  
   
 Returns a simple check box with the given $name.  
 If $value eq 'on' the box is checked.  
   
 =cut  
   
 ###############################################  
 ###############################################  
   
 sub simplecheckbox {  
     my ($name,$value)=@_;  
     my $checked='';  
     $checked="checked" if $value eq 'on';  
     return '<input type="checkbox" name="'.$name.'" '. $checked . ' />';  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &fieldtitle()  
   
 Input: $title  
   
 Returns a scalar with html which will display $title as a search  
 field heading.  
   
 =cut  
   
 ###############################################  
 ###############################################  
   
 sub fieldtitle {  
     my $title = uc(shift());  
     return '<font color="#800000" face="helvetica"><b>'.$title.  
         ':&nbsp;</b></font>';  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &searchphrasefield()  
   
 Inputs: $title,$name,$value  
   
 Returns html for a title line and an input field for entering search terms.  
 The entry field (which is where the $name and $value are used) is a 50 column   
 simpletextfield.  The html returned is for a row in a three column table.  
   
 =cut  
   
 ###############################################  
 ###############################################  
       
 sub searchphrasefield {  
     my ($title,$name,$value)=@_;  
     return '<tr><td>'.&fieldtitle($title).'</td><td>'.  
         &simpletextfield($name,$value,50)."</td><td>&nbsp;</td></tr>\n";  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &searchphrasefield_with_related()  
   
 Inputs: $title,$name,$value  
   
 Returns html for a title line and an input field for entering search terms  
 and a check box for 'related words'.  The entry field (which is where the   
 $name and $value are used) is a 50 column simpletextfield.  The name of  
 the related words checkbox is "$name_related".  
   
 =cut  
   
 ###############################################  
 ###############################################  
       
 sub searchphrasefield_with_related {  
     my ($title,$name,$value)=@_;  
     return '<tr><td>'.&fieldtitle($title).'</td><td>'.  
         &simpletextfield($name,$value,50).'</td><td align="center">&nbsp;'.  
             &simplecheckbox($name.'_related',$ENV{'form.'.$name.'_related'}).  
                 "&nbsp;</td></tr>\n";  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &dateboxes()  
   
 Returns html selection form elements for the specification of   
 the day, month, and year.  
   
 =cut  
   
 ###############################################  
 ###############################################  
   
 sub dateboxes {  
     my ($name,$defaultmonth,$defaultday,$defaultyear,  
  $currentmonth,$currentday,$currentyear)=@_;  
     ($defaultmonth,$defaultday,$defaultyear)=('','','');  
     #  
     # Day  
     my $day=<<END;  
 <select name="${name}_day">  
 <option value='$defaultday'> </option>  
 END  
     for (my $i = 1; $i<=31; $i++) {  
  $day.="<option value=\"$i\">$i</option>\n";  
     }  
     $day.="</select>\n";  
     $day=~s/(\"$currentday\")/$1 SELECTED/ if length($currentday);  
     #  
     # Month  
     my $month=<<END;  
 <select name="${name}_month">  
 <option value='$defaultmonth'> </option>  
 END  
     my $i = 1;  
     foreach (qw/January February March April May June   
      July August September October November December /){  
  $month .="<option value=\"$i\">$_</option>\n";  
  $i++;  
     }  
     $month.="</select>\n";  
     $month=~s/(\"$currentmonth\")/$1 SELECTED/ if length($currentmonth);  
     #  
     # Year (obviously)  
     my $year=<<END;  
 <select name="${name}_year">  
 <option value='$defaultyear'> </option>  
 END  
     my $maxyear = 2051;   
     for (my $i = 1976; $i<=$maxyear; $i++) {  
  $year.="<option value=\"$i\">$i</option>\n";  
     }  
     $year.="</select>\n";  
     $year=~s/(\"$currentyear\")/$1 SELECTED/ if length($currentyear);  
     return "$month$day$year";  
 }  
   
 ###############################################  
 ###############################################  
   
 =pod  
   
 =item &selectbox()  
   
 Returns a scalar containing an html <select> form.    
   
 Inputs:   
   
 =over 4  
   
 =item $title   
   
 Printed above the select box, in uppercase.  If undefined, only a select  
 box will be returned, with no additional html.  
   
 =item $name   
   
 The name element of the <select> tag.  
   
 =item $default   
   
 The default value of the form.  Can be $anyvalue, or in @idlist.  
   
 =item $anyvalue   
   
 The <option value="..."> used to indicate a default of   
 none of the values.  Can be undef.  
   
 =item $anytag   
   
 The text associate with $anyvalue above.  
   
 =item $functionref   
   
 Each element in @idlist will be passed as a parameter   
 to the function referenced here.  The return value of the function should  
 be a scalar description of the items.  If this value is undefined the   
 description of each item in @idlist will be the item name.  
   
 =item @idlist   
   
 The items to be selected from.  One of these or $anyvalue will be the   
 value returned by the form element, $ENV{form.$name}.  
   
 =back  
   
 =cut  
   
 ###############################################  
   
 sub selectbox {  
     my ($title,$name,$default,$anyvalue,$anytag,$functionref,@idlist)=@_;  
     if (! defined($functionref)) { $functionref = sub { $_[0]}; }  
     my $selout='';  
     if (defined($title)) {  
         my $uctitle=uc($title);  
         $selout="\n".'<p><font color="#800000" face="helvetica">'.  
             '<b>'.$uctitle.': </b></font>';  
     }  
     $selout .= '<select name="'.$name.'">';  
     unshift @idlist,$anyvalue if (defined($anyvalue));  
     foreach (@idlist) {  
         $selout.='<option value="'.$_.'"';  
         if ($_ eq $default and !/^any$/) {  
     $selout.=' selected >'.&{$functionref}($_).'</option>';  
  }  
  elsif ($_ eq $default and /^$anyvalue$/) {  
     $selout.=' selected >'.$anytag.'</option>';  
  }  
         else {$selout.='>'.&{$functionref}($_).'</option>';}  
     }  
     return $selout.'</select>'.(defined($title)?'</p>':' ');  
 }  
   
 ######################################################################  
 #                End of HTML form building functions                 #    
 ######################################################################  
   
 =pod  
   
 =back   
   
 =cut  
   
   
 ######################################################################  
 ######################################################################  ######################################################################
   
 =pod   =pod 
Line 1273  Parse advanced search form and return th Line 983  Parse advanced search form and return th
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub parse_advanced_search {  sub parse_advanced_search {
     my ($r,$closebutton)=@_;      my ($r,$closebutton,$hidden_fields)=@_;
     my $fillflag=0;      my $fillflag=0;
     my $pretty_search_string = "<br />\n";      my $pretty_search_string = "<br />\n";
     # Clean up fields for safety      # Clean up fields for safety
Line 1307  sub parse_advanced_search { Line 1017  sub parse_advanced_search {
  }   }
     }      }
     unless ($fillflag) {      unless ($fillflag) {
  &output_blank_field_error($r,$closebutton,'phase=disp_adv');   &output_blank_field_error($r,$closebutton,
                                     'phase=disp_adv',$hidden_fields);
  return ;   return ;
     }      }
     # Turn the form input into a SQL-based query      # Turn the form input into a SQL-based query
Line 1316  sub parse_advanced_search { Line 1027  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 ('title','author','subject','notes','abstract','url',      foreach my $field ('title','author','subject','notes','abstract','url',
        'keywords','version','owner') {         'keywords','version','owner','standards') {
  if ($ENV{'form.'.$field}) {   if ($ENV{'form.'.$field}) {
             my $searchphrase = $ENV{'form.'.$field};              my $searchphrase = $ENV{'form.'.$field};
             $pretty_search_string .= $font."$field</font> contains <b>".              $pretty_search_string .= $font."$field</font> contains <b>".
Line 1358  sub parse_advanced_search { Line 1069  sub parse_advanced_search {
         $pretty_search_string .=$font.'mime</font> contains <b>'.          $pretty_search_string .=$font.'mime</font> contains <b>'.
             $searchphrase.'</b><br />';              $searchphrase.'</b><br />';
     }      }
     #####      #
     # Evaluate option lists      # Evaluate option lists
     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'}\")";
Line 1390  sub parse_advanced_search { Line 1101  sub parse_advanced_search {
  );   );
     # Test to see if date windows are legitimate      # Test to see if date windows are legitimate
     if ($datequery=~/^Incorrect/) {      if ($datequery=~/^Incorrect/) {
  &output_date_error($r,$datequery,$closebutton);   &output_date_error($r,$datequery,$closebutton,$hidden_fields);
  return ;   return ;
     } elsif ($datequery) {      } elsif ($datequery) {
         # Here is where you would set up pretty_search_string to output          # Here is where you would set up pretty_search_string to output
         # date query information.          # date query information.
  push @queries,$datequery;   push @queries,$datequery;
     }      }
       #
     # Process form information for custom metadata querying      # Process form information for custom metadata querying
     my $customquery=undef;      my $customquery=undef;
 #    if ($ENV{'form.custommetadata'}) {      ##
 #        $pretty_search_string .=$font."Custom Metadata Search</font>: <b>".      ## The custom metadata search was removed q long time ago mostly 
 #            $ENV{'form.custommetadata'}."</b><br />\n";      ## because I was unable to figureout exactly how it worked and could
 # $customquery=&build_custommetadata_query('custommetadata',      ## not imagine people actually using it.  MH
 #      $ENV{'form.custommetadata'});      ##
 #    }      # if ($ENV{'form.custommetadata'}) {
       #    $pretty_search_string .=$font."Custom Metadata Search</font>: <b>".
       #    $ENV{'form.custommetadata'}."</b><br />\n";
       #    $customquery=&build_custommetadata_query('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);
 #    }      # }
     ## ---------------------------------------------------------------      ##
     ## Deal with restrictions to given domains      ## Deal with restrictions to given domains
     ##       ## 
       my ($libraries_to_query,$pretty_domains_string) = 
           &parse_domain_restrictions();
       $pretty_search_string .= $pretty_domains_string."<br />\n";
       #
       if (@queries) {
    $query=join(" AND ",@queries);
    $query="select * from metadata where $query";
       } elsif ($customquery) {
           $query = '';
       }
       return ($query,$customquery,$customshow,$libraries_to_query,
               $pretty_search_string);
   }
   
   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.      # $ENV{'form.domains'} can be either a scalar or an array reference.
     # We need an array.      # We need an array.
     my @allowed_domains = (ref($ENV{'form.domains'}) ? @{$ENV{'form.domains'}}       if (! exists($ENV{'form.domains'})) {
                            :  ($ENV{'form.domains'}) );          return (undef,'');
       }
       my @allowed_domains;
       if (ref($ENV{'form.domains'})) {
           @allowed_domains =  @{$ENV{'form.domains'}};
       } else {
           @allowed_domains = ($ENV{'form.domains'});
       }
       #
     my %domain_hash = ();      my %domain_hash = ();
     my $pretty_domains_string;      my $pretty_domains_string;
     foreach (@allowed_domains) {      foreach (@allowed_domains) {
Line 1444  sub parse_advanced_search { Line 1184  sub parse_advanced_search {
             }              }
         }          }
     }      }
     $pretty_search_string .= $pretty_domains_string."<br />\n";      return ($libraries_to_query,$pretty_domains_string);
     #  
     if (@queries) {  
  $query=join(" AND ",@queries);  
  $query="select * from metadata where $query";  
     } elsif ($customquery) {  
         $query = '';  
     }  
     return ($query,$customquery,$customshow,$libraries_to_query,  
             $pretty_search_string);  
 }  }
   
 ######################################################################  ######################################################################
Line 1471  Parse the basic search form and return a Line 1202  Parse the basic search form and return a
 ######################################################################  ######################################################################
 sub parse_basic_search {  sub parse_basic_search {
     my ($r,$closebutton)=@_;      my ($r,$closebutton)=@_;
       #
     # 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;
Line 1481  sub parse_basic_search { Line 1213  sub parse_basic_search {
  $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});   $ENV{"form.$_"}=&Apache::lonnet::unescape($ENV{"form.$_"});
  $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;   $ENV{"form.$_"}=~s/[^\w\/\s\(\)\=\-\"\']//g;
     }      }
       my ($libraries_to_query,$pretty_domains_string) = 
     # Check to see if enough is filled in          &parse_domain_restrictions();
       #
       # Check to see if enough of a query is filled in
     unless (&filled($ENV{'form.basicexp'})) {      unless (&filled($ENV{'form.basicexp'})) {
  &output_blank_field_error($r,$closebutton,'phase=disp_basic');   &output_blank_field_error($r,$closebutton,'phase=disp_basic');
  return OK;   return OK;
Line 1498  sub parse_basic_search { Line 1232  sub parse_basic_search {
             $pretty_search_string .= " with no related words.";              $pretty_search_string .= " with no related words.";
         }          }
     }      }
       #
     # Build SQL query string based on form page      # Build SQL query string based on form page
     my $query='';      my $query='';
     my $concatarg=join(',"    ",',      my $concatarg=join(',',
        ('title', 'author', 'subject', 'notes', 'abstract',         ('title', 'author', 'subject', 'notes', 'abstract',
                         'keywords'));                          'keywords'));
     $concatarg='title' if $ENV{'form.titleonly'};      $concatarg='title' if $ENV{'form.titleonly'};
     $query=&build_SQL_query('concat('.$concatarg.')',$search_string);      $query=&build_SQL_query('concat_ws(" ",'.$concatarg.')',$search_string);
       if (defined($pretty_domains_string) && $pretty_domains_string ne '') {
           $pretty_search_string .= ' '.$pretty_domains_string;
       }
     $pretty_search_string .= "<br />\n";      $pretty_search_string .= "<br />\n";
     return 'select * from metadata where '.$query,$pretty_search_string;      my $final_query = 'SELECT * FROM metadata WHERE '.$query;
       # &Apache::lonnet::logthis($final_query);
       return ($final_query,$pretty_search_string,
               $libraries_to_query);
 }  }
   
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod   =pod 
   
 =item &related_version  =item &related_version()
   
 Modifies an input string to include related words.  Words in the string  Modifies an input string to include related words.  Words in the string
 are replaced with parenthesized lists of 'OR'd words.  For example  are replaced with parenthesized lists of 'OR'd words.  For example
Line 1623  sub recursive_SQL_query_build { Line 1363  sub recursive_SQL_query_build {
         my ($key,$value)=($1,$2);          my ($key,$value)=($1,$2);
         my $replacement='';          my $replacement='';
         if ($key eq 'literal') {          if ($key eq 'literal') {
             $replacement="($dkey like \"\%$value\%\")";              $replacement="($dkey LIKE \"\%$value\%\")";
         } elsif ($key eq 'not') {          } elsif (lc($key) eq 'not') {
             $value=~s/like/not like/;              $value=~s/LIKE/NOT LIKE/;
 #          $replacement="($dkey not like $value)";  #          $replacement="($dkey not like $value)";
             $replacement="$value";              $replacement="$value";
         } elsif ($key eq 'and') {          } elsif ($key eq 'and') {
Line 1712  sub build_date_queries { Line 1452  sub build_date_queries {
   
 =item &copyright_check()  =item &copyright_check()
   
   Inputs: $Metadata, a hash pointer of metadata for a resource.
   
   Returns: 1 if the resource is available to the user making the query, 
            0 otherwise.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
Line 1735  sub copyright_check { Line 1480  sub copyright_check {
     return 1;      return 1;
 }  }
   
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod  =pod
   
 =item &ensure_db_and_table  =item &ensure_db_and_table()
   
 Ensure we can get lonmysql to connect to the database and the table we  Ensure we can get lonmysql to connect to the database and the table we
 need exists.  need exists.
Line 1797  sub ensure_db_and_table { Line 1541  sub ensure_db_and_table {
   
 =pod  =pod
   
 =item &print_sort_form  =item &print_sort_form()
   
   The sort feature is not implemented at this time.  This form just prints 
   a link to change the search query.
   
 =cut  =cut
   
Line 1805  sub ensure_db_and_table { Line 1552  sub ensure_db_and_table {
 ######################################################################  ######################################################################
 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);
     ##      ##
     my %SortableFields =       my %SortableFields=&Apache::lonlocal::texthash( 
         (id        => 'Default',           id        => 'Default',
          title     => 'Title',           title     => 'Title',
          author    => 'Author',           author    => 'Author',
          subject   => 'Subject',           subject   => 'Subject',
Line 1819  sub print_sort_form { Line 1567  sub print_sort_form {
          copyright => 'Copyright',           copyright => 'Copyright',
          hostname  => 'Host',           hostname  => 'Host',
          creationdate     => 'Creation Date',           creationdate     => 'Creation Date',
          lastrevisiondate => 'Revision Date',           lastrevisiondate => 'Revision Date'
      );       );
     ##      ##
     my $table = $ENV{'form.table'};      my $table = $ENV{'form.table'};
Line 1897  the following format: Line 1645  the following format:
   
 #####################################################################  #####################################################################
 #####################################################################  #####################################################################
   #
 my @Datatypes =   # These should probably be scoped but I don't have time right now...
     ( { name => 'id',   #
         type => 'MEDIUMINT',  my @Datatypes;
         restrictions => 'UNSIGNED NOT NULL',  my @Fullindicies;
         primary_key  => 'yes',  
         auto_inc     => 'yes' },  
       { name => 'title',     type=>'TEXT'},  
       { name => 'author',    type=>'TEXT'},  
       { name => 'subject',   type=>'TEXT'},  
       { name => 'url',       type=>'TEXT', restrictions => 'NOT NULL' },  
       { name => 'keywords',  type=>'TEXT'},  
       { name => 'version',   type=>'TEXT'},  
       { name => 'notes',     type=>'TEXT'},  
       { name => 'abstract',  type=>'TEXT'},  
       { name => 'mime',      type=>'TEXT'},  
       { name => 'lang',      type=>'TEXT'},  
       { name => 'owner',     type=>'TEXT'},  
       { name => 'copyright', type=>'TEXT'},  
       { name => 'hostname',  type=>'TEXT'},  
       #--------------------------------------------------  
       { name => 'creationdate',     type=>'DATETIME'},  
       { name => 'lastrevisiondate', type=>'DATETIME'},  
       #--------------------------------------------------  
       );  
   
 my @Fullindicies =   
     qw/title/;  
 #    qw/title author subject abstract mime language owner copyright/;  
           
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 1945  Returns: the identifier of the table on Line 1669  Returns: the identifier of the table on
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   sub set_up_table_structure {
       my ($datatypes,$fullindicies) = 
           &LONCAPA::lonmetadata::describe_metadata_storage();
       unshift(@$datatypes,{name => 'id', 
           type => 'MEDIUMINT',
           restrictions => 'UNSIGNED NOT NULL',
           primary_key  => 'yes',
           auto_inc     => 'yes' });
       @Datatypes = @{$datatypes};
       @Fullindicies = @{$fullindicies};
       return;
   }
   
 sub create_results_table {  sub create_results_table {
       &set_up_table_structure();
     my $table = &Apache::lonmysql::create_table      my $table = &Apache::lonmysql::create_table
         ( { columns => \@Datatypes,          ( { columns => \@Datatypes,
             FULLTEXT => [{'columns' => \@Fullindicies},],              FULLTEXT => [{'columns' => \@Fullindicies},],
Line 2015  sub update_seconds { Line 1753  sub update_seconds {
   
 =pod  =pod
   
 =item &revise_button  =item &revise_button()
   
 Inputs: None  Inputs: None
   
Line 2042  sub revise_button { Line 1780  sub revise_button {
   
 =pod  =pod
   
 =item &run_search   =item &run_search()
   
   Executes a search query by sending it the the other servers and putting the
   results into MySQL.
   
 =cut  =cut
   
Line 2050  sub revise_button { Line 1791  sub revise_button {
 ######################################################################  ######################################################################
 sub run_search {  sub run_search {
     my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;      my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;
       my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);
     my $connection = $r->connection;      my $connection = $r->connection;
     #      #
     # Timing variables      # Timing variables
Line 2073  END Line 1815  END
     if (@Lines > 2) {      if (@Lines > 2) {
         $pretty_string = join '<br \>',(@Lines[0..2],'....<br />');          $pretty_string = join '<br \>',(@Lines[0..2],'....<br />');
     }      }
     $r->print("Search: ".$pretty_string);      $r->print(&mt("Search").": ".$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;
     if (defined($serverlist)) {      if (defined($serverlist)) {
         if (ref($serverlist) eq 'ARRAY') {          if (ref($serverlist) eq 'ARRAY') {
Line 2105  END Line 1846  END
         return;          return;
     }      }
     if (! $table_status) {      if (! $table_status) {
           &Apache::lonnet::logthis("lonmysql error = ".
                                    &Apache::lonmysql::get_error());
           &Apache::lonnet::logthis("lonmysql debug = ".
                                    &Apache::lonmysql::get_debug());
           &Apache::lonnet::logthis('table status = "'.$table_status.'"');
         $r->print("The table id,$table, we tried to use is invalid.".          $r->print("The table id,$table, we tried to use is invalid.".
                   "The search has been aborted.</body></html>");                    "The search has been aborted.</body></html>");
         return;          return;
     }      }
     ##      ##
     ## Prepare for the big loop.      ## Prepare for the big loop.
     ##  
     my $hitcountsum;      my $hitcountsum;
     my $server;       my $server; 
     my $status;      my $status;
Line 2132  END Line 1877  END
     my $time_remaining = $max_time - (time - $starttime) ;      my $time_remaining = $max_time - (time - $starttime) ;
     my $last_time = $time_remaining;      my $last_time = $time_remaining;
     &update_seconds($r,$time_remaining);      &update_seconds($r,$time_remaining);
       &update_status($r,'contacting '.$Servers_to_contact[0]);
     while (($time_remaining > 0) &&      while (($time_remaining > 0) &&
            ((@Servers_to_contact) || keys(%Server_status))) {             ((@Servers_to_contact) || keys(%Server_status))) {
         # Send out a search request if it needs to be done.          # Send out a search request if it needs to be done.
         if (@Servers_to_contact) {          if (@Servers_to_contact) {
             # Contact one server              # Contact one server
             my $server = shift(@Servers_to_contact);              my $server = shift(@Servers_to_contact);
               &update_status($r,&mt('contacting').' '.$server);
             my $reply=&Apache::lonnet::metadata_query($query,$customquery,              my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                       $customshow,[$server]);                                                        $customshow,[$server]);
             ($server) = keys(%$reply);              ($server) = keys(%$reply);
             $Server_status{$server} = $reply->{$server};              $Server_status{$server} = $reply->{$server};
             &update_status($r,'contacting '.$server);  
         } else {          } else {
             # wait a sec. to give time for files to be written              # wait a sec. to give time for files to be written
             # This sleep statement is here instead of outside the else               # This sleep statement is here instead of outside the else 
             # block because we do not want to pause if we have servers              # block because we do not want to pause if we have servers
             # left to contact.                # left to contact.  
               if (scalar (keys(%Server_status))) {
                   &update_status($r,
                          &mt('waiting on').' '.(join(' ',keys(%Server_status))));
               }
             sleep(1)              sleep(1)
         }          }
         #          #
         if (scalar (keys(%Server_status))) {  
             &update_status($r,'waiting on '.(join(' ',keys(%Server_status))));  
         }  
         #  
         # Loop through the servers we have contacted but do not          # Loop through the servers we have contacted but do not
         # have results from yet, looking for results.          # have results from yet, looking for results.
         while (my ($server,$status) = each(%Server_status)) {          while (my ($server,$status) = each(%Server_status)) {
Line 2166  END Line 1912  END
             $status=~/^([\.\w]+)$/;               $status=~/^([\.\w]+)$/; 
            my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1;             my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1;
             if (-e $datafile && ! -e "$datafile.end") {              if (-e $datafile && ! -e "$datafile.end") {
                 &update_status($r,'Receiving results from '.$server);                  &update_status($r,&mt('Receiving results from').' '.$server);
                 next;                  next;
             }              }
             last if ($connection->aborted());              last if ($connection->aborted());
             if (-e "$datafile.end") {              if (-e "$datafile.end") {
                 &update_status($r,'Reading results from '.$server);                  &update_status($r,&mt('Reading results from').' '.$server);
                 if (-z "$datafile") {                  if (-z "$datafile") {
                     delete($Server_status{$server});                      delete($Server_status{$server});
                     next;                      next;
Line 2226  END Line 1972  END
             &update_seconds($r,$time_remaining);              &update_seconds($r,$time_remaining);
         }          }
     }      }
     &update_status($r,'Search Complete'.$server);      &update_status($r,&mt('Search Complete').$server);
     &update_seconds($r,0);      &update_seconds($r,0);
       #
     &Apache::lonmysql::disconnect_from_db();      &Apache::lonmysql::disconnect_from_db();
       #
     # 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.        # results to get.  
     $r->print("</body></html>");      $r->print("</body></html>");
Line 2244  END Line 1992  END
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod  =pod
   
 =item &prev_next_buttons  =item &prev_next_buttons()
   
   Returns html for the previous and next buttons on the search results page.
   
 =cut  =cut
   
Line 2261  sub prev_next_buttons { Line 2012  sub prev_next_buttons {
     my $prev_min = $current_min - $show;      my $prev_min = $current_min - $show;
     $prev_min = 1 if $prev_min < 1;      $prev_min = 1 if $prev_min < 1;
     if ($prev_min < $current_min) {      if ($prev_min < $current_min) {
         $links .= qq{          $links .= 
 <a href="/adm/searchcat?$parms&start=$prev_min&show=$show">prev</a>              qq{<a href="/adm/searchcat?$parms&start=$prev_min&show=$show">}.
 };                  &mt('prev').'</a>';
     } else {      } else {
         $links .= 'prev';          $links .= &mt('prev');
     }      }
     ##      ##
     ## Pages.... Someday.      ## Pages.... Someday.
     ##      ##
     $links .= qq{ &nbsp;      $links .= 
 <a href="/adm/searchcat?$parms&start=$current_min&$show=$show">reload</a>          qq{&nbsp;
 };             <a href="/adm/searchcat?$parms&start=$current_min&$show=$show">}.
                   &mt('reload').'</a>';
     ##      ##
     ## Next      ## Next
     my $next_min = $current_min + $show;      my $next_min = $current_min + $show;
     $next_min = $current_min if ($next_min > $total);      $next_min = $current_min if ($next_min > $total);
     if ($next_min != $current_min) {      if ($next_min != $current_min) {
         $links .= qq{ &nbsp;          $links .= 
 <a href="/adm/searchcat?$parms&start=$next_min&show=$show">next</a>              qq{&nbsp;
 };                     <a href="/adm/searchcat?$parms&start=$next_min&show=$show">}.
                       &mt('next').'</a>';
     } else {      } else {
         $links .= '&nbsp;next';          $links .= '&nbsp;'.&mt('next');
     }      }
     return $links;      return $links;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod  =pod
   
 =item &display_results  =item &display_results()
   
   Prints the results out for selection and perusal.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub display_results {  sub display_results {
     my ($r,$importbutton,$closebutton) = @_;      my ($r,$importbutton,$closebutton,$diropendb) = @_;
     my $connection = $r->connection;      my $connection = $r->connection;
     $r->print(&search_results_header($importbutton,$closebutton));      $r->print(&search_results_header($importbutton,$closebutton));
     ##      ##
Line 2319  sub display_results { Line 2075  sub display_results {
     ##      ##
     my $action = "/adm/searchcat?phase=results";      my $action = "/adm/searchcat?phase=results";
     ##      ##
     ## Deal with groupsearch      ## Deal with groupsearch by opening the groupsearch db file.
     ##  
     if ($ENV{'form.catalogmode'} eq 'groupsearch') {      if ($ENV{'form.catalogmode'} eq 'groupsearch') {
         if (! tie(%groupsearch_db,'GDBM_File',$diropendb,          if (! tie(%groupsearch_db,'GDBM_File',$diropendb,
                   &GDBM_WRCREAT(),0640)) {                    &GDBM_WRCREAT(),0640)) {
Line 2331  sub display_results { Line 2086  sub display_results {
     }      }
     ##      ##
     ## 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("A MySQL error has occurred.</form></body></html>");
Line 2347  sub display_results { Line 2100  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'}  = 'all'  if (! exists($ENV{'form.show'}));      $ENV{'form.show'}  = 'all'  if (! exists($ENV{'form.show'}));
     my $min = $ENV{'form.start'};      my $min = $ENV{'form.start'};
Line 2360  sub display_results { Line 2112  sub display_results {
     }      }
     ##      ##
     ## Output links (if necessary) for 'prev' and 'next' pages.      ## Output links (if necessary) for 'prev' and 'next' pages.
     ##  
     $r->print      $r->print
         ('<center>'.          ('<center>'.
          &prev_next_buttons($min,$ENV{'form.show'},$total_results,           &prev_next_buttons($min,$ENV{'form.show'},$total_results,
Line 2370  sub display_results { Line 2121  sub display_results {
          ."</center>\n"           ."</center>\n"
          );           );
     if ($total_results == 0) {      if ($total_results == 0) {
         $r->print("There are currently no results.\n".          $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="1">'.
                     '<h3>'.&mt('There are currently no results').'.</h3>'.
                   "</form></body></html>");                    "</form></body></html>");
         return;          return;
     } else {      } else {
Line 2379  sub display_results { Line 2131  sub display_results {
     }      }
     ##      ##
     ## Get results from MySQL table      ## Get results from MySQL table
     ##  
     my @Results = &Apache::lonmysql::get_rows($table,      my @Results = &Apache::lonmysql::get_rows($table,
                                               'id>='.$min.' AND id<='.$max);                                                'id>='.$min.' AND id<='.$max);
     ##      ##
     ## Loop through the results and output them.      ## Loop through the results and output them.
     ##  
     foreach my $row (@Results) {      foreach my $row (@Results) {
         if ($connection->aborted()) {          if ($connection->aborted()) {
             &cleanup();              &cleanup();
Line 2401  sub display_results { Line 2151  sub display_results {
         $r->rflush();          $r->rflush();
     }      }
     if (@Results < 1) {      if (@Results < 1) {
         $r->print("There were no results matching your query");          $r->print(&mt("There were no results matching your query"));
     } else {      } else {
         $r->print          $r->print
             ('<center>'.              ('<center>'.
Line 2462  END Line 2212  END
   
 =pod  =pod
   
 =item &parse_row  =item &parse_row()
   
 Parse a row returned from the database.  Parse a row returned from the database.
   
Line 2473  Parse a row returned from the database. Line 2223  Parse a row returned from the database.
 sub parse_row {  sub parse_row {
     my @Row = @_;      my @Row = @_;
     my %Fields;      my %Fields;
       if (! scalar(@Datatypes)) {
           &set_up_table_structure();
       }
     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'}}=&Apache::lonnet::unescape($Row[$i]);
     }      }
     $Fields{'language'} =       $Fields{'language'} = 
         &Apache::loncommon::languagedescription($Fields{'lang'});          &Apache::loncommon::languagedescription($Fields{'language'});
     $Fields{'copyrighttag'} =      $Fields{'copyrighttag'} =
         &Apache::loncommon::copyrightdescription($Fields{'copyright'});          &Apache::loncommon::copyrightdescription($Fields{'copyright'});
     $Fields{'mimetag'} =      $Fields{'mimetag'} =
Line 2493  sub parse_row { Line 2246  sub parse_row {
 =item &parse_raw_result()  =item &parse_raw_result()
   
 Takes a line from the file of results and parse it.  Returns a hash   Takes a line from the file of results and parse it.  Returns a hash 
 with keys for the following fields:  with keys according to column labels
 'title', 'author', 'subject', 'url', 'keywords', 'version', 'notes',   
 'abstract', 'mime', 'lang', 'owner', 'copyright', 'creationdate',   
 'lastrevisiondate'.  
   
 In addition, the following tags are set by calling the appropriate   In addition, the following tags are set by calling the appropriate 
 lonnet function: 'language', 'cprtag', 'mimetag'.  lonnet function: 'language', 'copyrighttag', 'mimetag'.
   
 The 'title' field is set to "Untitled" if the title field is blank.  The 'title' field is set to "Untitled" if the title field is blank.
   
Line 2511  The 'title' field is set to "Untitled" i Line 2261  The 'title' field is set to "Untitled" i
 ###########################################################  ###########################################################
 sub parse_raw_result {  sub parse_raw_result {
     my ($result,$hostname) = @_;      my ($result,$hostname) = @_;
     # Check for a comma - if it is there then we do not need to unescape the      # conclude from self to others regarding fields
     # string.  There seems to be some kind of problem with some items in      my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash
     # the database - the entire string gets sent out unescaped...?          (map {
     unless ($result =~ /,/) {              &Apache::lonnet::unescape($_);
         $result = &Apache::lonnet::unescape($result);          } (split(/\,/,$result)) );
     }  
     my @fields=map {  
         &Apache::lonnet::unescape($_);  
     } (split(/\,/,$result));  
     my ($title,$author,$subject,$url,$keywords,$version,  
         $notes,$abstract,$mime,$lang,  
         $creationdate,$lastrevisiondate,$owner,$copyright)=@fields;  
     my %Fields =   
         ( title     => &Apache::lonnet::unescape($title),  
           author    => &Apache::lonnet::unescape($author),  
           subject   => &Apache::lonnet::unescape($subject),  
           url       => &Apache::lonnet::unescape($url),  
           keywords  => &Apache::lonnet::unescape($keywords),  
           version   => &Apache::lonnet::unescape($version),  
           notes     => &Apache::lonnet::unescape($notes),  
           abstract  => &Apache::lonnet::unescape($abstract),  
           mime      => &Apache::lonnet::unescape($mime),  
           lang      => &Apache::lonnet::unescape($lang),  
           owner     => &Apache::lonnet::unescape($owner),  
           copyright => &Apache::lonnet::unescape($copyright),  
           creationdate     => &Apache::lonnet::unescape($creationdate),  
           lastrevisiondate => &Apache::lonnet::unescape($lastrevisiondate)  
         );  
     $Fields{'language'} =   
         &Apache::loncommon::languagedescription($Fields{'lang'});  
     $Fields{'copyrighttag'} =  
         &Apache::loncommon::copyrightdescription($Fields{'copyright'});  
     $Fields{'mimetag'} =  
         &Apache::loncommon::filedescription($Fields{'mime'});  
     if ($Fields{'author'}=~/^(\s*|error)$/) {  
         $Fields{'author'}="Unknown Author";  
     }  
     # Put spaces in the keyword list, if needed.  
     $Fields{'keywords'}=~ s/,([A-z])/, $1/g;   
     if ($Fields{'title'}=~ /^\s*$/ ) {   
         $Fields{'title'}='Untitled';   
     }  
     unless ($ENV{'user.adv'}) {  
         # What is this anyway?  
         $Fields{'keywords'} = '- not displayed -';  
         $Fields{'notes'}    = '- not displayed -';  
         $Fields{'abstract'} = '- not displayed -';  
         $Fields{'subject'}  = '- not displayed -';  
     }  
     if (length($Fields{'abstract'})>200) {  
         $Fields{'abstract'} =   
             substr($Fields{'abstract'},0,200).'...';  
     }  
     if (length($Fields{'keywords'})>200) {  
         $Fields{'keywords'} =  
             substr($Fields{'keywords'},0,200).'...';  
     }  
     return %Fields;      return %Fields;
 }  }
   
Line 2617  sub handle_custom_fields { Line 2315  sub handle_custom_fields {
   
 =pod  =pod
   
 =item &search_results_header  =item &search_results_header()
   
 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.
Line 2644  Checked for existance & 'edit' mode. Line 2342  Checked for existance & 'edit' mode.
   
 =item 'form.form'  =item 'form.form'
   
   Contains the name of the form that has the input fields to set
   
 =item 'form.element'  =item 'form.element'
   
   the name of the input field to put the URL into
   
   =item 'form.titleelement'
   
   the name of the input field to put the title into
   
 =back  =back
   
 =cut  =cut
Line 2654  Checked for existance & 'edit' mode. Line 2360  Checked for existance & 'edit' mode.
 ######################################################################  ######################################################################
 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 $result = '';
     # 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
Line 2682  SCRIPT Line 2389  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 $changetitle;
       if (!$titleelement) {
    $changetitle='function changeTitle(val) {}';
       } else {
       $changetitle=<<END;
   function changeTitle(val) {
       if (parent.targetwin.document) {
           parent.targetwin.document.forms["$form"].elements["$titleelement"].value=val;
       } else {
    var url = 'forms[\"$form\"].elements[\"$titleelement\"].value';
           alert("Unable to transfer data to "+url);
       }
   }
   END
               }
   
             $result.=<<SCRIPT;              $result.=<<SCRIPT;
 <script type="text/javascript">  <script type="text/javascript">
 function select_data(title,url) {  function select_data(title,url) {
     changeURL(url);      changeURL(url);
       changeTitle(title);
     parent.close();      parent.close();
 }  }
 function changeTitle(val) {  $changetitle
 }  
 function changeURL(val) {  function changeURL(val) {
     if (parent.targetwin.document) {      if (parent.targetwin.document) {
         parent.targetwin.document.forms["$form"].elements["$element"].value=val;          parent.targetwin.document.forms["$form"].elements["$element"].value=val;
Line 2705  SCRIPT Line 2429  SCRIPT
     $result.=<<SCRIPT if $ENV{'form.catalogmode'} eq 'groupsearch';      $result.=<<SCRIPT if $ENV{'form.catalogmode'} eq 'groupsearch';
 <script type="text/javascript">  <script type="text/javascript">
     function queue(checkbox_num,val) {      function queue(checkbox_num,val) {
         if (document.forms.results.returnvalues[checkbox_num].checked) {          if (document.forms.results.returnvalues.length != "undefined" &&
             parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';              typeof(document.forms.results.returnvalues.length) == "number") {
               if (document.forms.results.returnvalues[checkbox_num].checked) {
                   parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';
               } else {
                   parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';
               }
         } else {          } else {
             parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';              if (document.forms.results.returnvalues.checked) {
                   parent.statusframe.document.forms.statusform.elements.Queue.value +='1a'+val+'b';
               } else {
                   parent.statusframe.document.forms.statusform.elements.Queue.value +='0a'+val+'b';
               }
         }          }
     }      }
     function select_group() {      function select_group() {
Line 2731  END Line 2464  END
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub search_status_header {  sub search_status_header {
       my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);
     return <<ENDSTATUS;      return <<ENDSTATUS;
 <html><head><title>Search Status</title></head>  <html><head><title>Search Status</title></head>
 $bodytag  $bodytag
Line 2755  sub print_frames_interface { Line 2489  sub print_frames_interface {
         "&persistent_db_id=".$ENV{'form.persistent_db_id'};          "&persistent_db_id=".$ENV{'form.persistent_db_id'};
     my $run_search_link = $basic_link."&phase=run_search";      my $run_search_link = $basic_link."&phase=run_search";
     my $results_link = &results_link();      my $results_link = &results_link();
     my $loadevents=&Apache::lonmenu::loadevents();  
     my $unloadevents=&Apache::lonmenu::unloadevents();  
     my $addscript=&Apache::lonmenu::registerurl();  
     my $result = <<"ENDFRAMES";      my $result = <<"ENDFRAMES";
 <html>  <html>
 <head>  <head>
Line 2765  sub print_frames_interface { Line 2496  sub print_frames_interface {
 var targetwin = opener;  var targetwin = opener;
 var queue = '';  var queue = '';
 </script>  </script>
 $addscript  
 <title>LON-CAPA Digital Library Search Results</title>  <title>LON-CAPA Digital Library Search Results</title>
 </head>  </head>
 <frameset rows="150,*" onLoad="$loadevents" onUnload="$unloadevents">  <frameset rows="150,*">
     <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>  </frameset>
Line 2787  ENDFRAMES Line 2517  ENDFRAMES
 =item Metadata Viewing Functions  =item Metadata Viewing Functions
   
 Output is a HTML-ified string.  Output is a HTML-ified string.
   
 Input arguments are title, author, subject, url, keywords, version,  Input arguments are title, author, subject, url, keywords, version,
 notes, short abstract, mime, language, creation date,  notes, short abstract, mime, language, creation date,
 last revision date, owner, copyright, hostname, and  last revision date, owner, copyright, hostname, and
Line 2802  extra custom metadata to show. Line 2533  extra custom metadata to show.
 ######################################################################  ######################################################################
 sub detailed_citation_view {  sub detailed_citation_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=<<END;
 <b>$prefix<a href="http://$ENV{'HTTP_HOST'}$values{'url'}"   <b>$prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
     target='search_preview'>$values{'title'}</a></b>      target='search_preview'>$values{'title'}</a></b>
 <p>  <p>
 <b>$values{'author'}</b>, <i>$values{'owner'}</i><br />  <b>$values{'author'}</b>, <i>$values{'owner'}</i><br />
Line 2813  sub detailed_citation_view { Line 2545  sub detailed_citation_view {
 <b>Notes:         </b> $values{'notes'}<br />  <b>Notes:         </b> $values{'notes'}<br />
 <b>MIME Type:     </b> $values{'mimetag'}<br />  <b>MIME Type:     </b> $values{'mimetag'}<br />
 <b>Language:      </b> $values{'language'}<br />  <b>Language:      </b> $values{'language'}<br />
 <b>Copyright/Distribution:</b> $values{'cprtag'}<br />  <b>Copyright/Distribution:</b> $values{'copyrighttag'}<br />
 </p>  </p>
 $values{'extrashow'}  $values{'extrashow'}
 <p>  <p>
Line 2836  END Line 2568  END
 ######################################################################  ######################################################################
 sub summary_view {  sub summary_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=<<END;
 $prefix<a href="http://$ENV{'HTTP_HOST'}$values{'url'}"   $prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
    target='search_preview'>$values{'author'}</a><br />     target='search_preview'>$values{'author'}</a><br />
 $values{'title'}<br />  $values{'title'}<br />
 $values{'owner'} -- $values{'lastrevisiondate'}<br />  $values{'owner'} -- $values{'lastrevisiondate'}<br />
Line 2862  END Line 2595  END
 ######################################################################  ######################################################################
 sub compact_view {  sub compact_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=<<END;
 $prefix <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"  target='search_preview'>  $prefix <img src="$icon" /> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"  target='search_preview'>
 $values{'title'}</a>  $values{'title'}</a>
 <b>$values{'author'}</b><br />  <b>$values{'author'}</b><br />
 END  END
Line 2884  END Line 2618  END
 ######################################################################  ######################################################################
 sub fielded_format_view {  sub fielded_format_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=<<END;
 $prefix  $prefix <img src="$icon" />
 <b>URL: </b> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"   <b>URL: </b> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
               target='search_preview'>$values{'url'}</a>                target='search_preview'>$values{'url'}</a>
 <br />  <br />
Line 2939  $prefix Line 2674  $prefix
 &lt;mimetag&gt;$values{'mimetag'}&lt;/mimetag&gt;  &lt;mimetag&gt;$values{'mimetag'}&lt;/mimetag&gt;
 &lt;/mimeInfo&gt;  &lt;/mimeInfo&gt;
 &lt;languageInfo&gt;  &lt;languageInfo&gt;
 &lt;language&gt;$values{'lang'}&lt;/language&gt;  &lt;language&gt;$values{'language'}&lt;/language&gt;
 &lt;languagetag&gt;$values{'language'}&lt;/languagetag&gt;  &lt;languagetag&gt;$values{'languagetag'}&lt;/languagetag&gt;
 &lt;/languageInfo&gt;  &lt;/languageInfo&gt;
 &lt;creationdate&gt;$values{'creationdate'}&lt;/creationdate&gt;  &lt;creationdate&gt;$values{'creationdate'}&lt;/creationdate&gt;
 &lt;lastrevisiondate&gt;$values{'lastrevisiondate'}&lt;/lastrevisiondate&gt;  &lt;lastrevisiondate&gt;$values{'lastrevisiondate'}&lt;/lastrevisiondate&gt;
Line 2973  END Line 2708  END
 sub filled {  sub filled {
     my ($field)=@_;      my ($field)=@_;
     if ($field=~/\S/ && $field ne 'any') {      if ($field=~/\S/ && $field ne 'any') {
  return 1;          return 1;
     }      } else {
     else {          return 0;
  return 0;  
     }      }
 }  }
   
Line 3001  $parms is extra information to include i Line 2735  $parms is extra information to include i
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub output_blank_field_error {  sub output_blank_field_error {
     my ($r,$closebutton,$parms)=@_;      my ($r,$closebutton,$parms,$hidden_fields)=@_;
       my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);
     # make query information persistent to allow for subsequent revision      # make query information persistent to allow for subsequent revision
     $r->print(<<BEGINNING);      $r->print(<<BEGINNING);
 <html>  <html>
Line 3050  Inputs: Line 2785  Inputs:
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub output_date_error {  sub output_date_error {
     my ($r,$message,$closebutton)=@_;      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);
     $r->print(<<RESULTS);      $r->print(<<RESULTS);
 <html>  <html>
 <head>  <head>
Line 3105  sub start_fresh_session { Line 2841  sub start_fresh_session {
   
 sub cleanup {  sub cleanup {
     if (tied(%groupsearch_db)) {      if (tied(%groupsearch_db)) {
  &Apache::lonnet::logthis('Cleanup searchcat: groupsearch_db');  
         unless (untie(%groupsearch_db)) {          unless (untie(%groupsearch_db)) {
   &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');    &Apache::lonnet::logthis('Failed cleanup searchcat: groupsearch_db');
         }          }

Removed from v.1.175  
changed lines
  Added in v.1.208


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