Diff for /loncom/interface/lonsearchcat.pm between versions 1.203 and 1.233

version 1.203, 2004/01/15 03:18:19 version 1.233, 2004/09/23 21:16:45
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 73  use Apache::lonmysql(); Line 73  use Apache::lonmysql();
 use Apache::lonmeta;  use Apache::lonmeta;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
 use Apache::lonlocal;  use Apache::lonlocal;
   use LONCAPA::lonmetadata();
   use HTML::Entities();
   use Parse::RecDescent;
   use Apache::lonnavmaps;
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 115  sub handler { Line 119  sub handler {
   
     my $loaderror=&Apache::lonnet::overloaderror($r);      my $loaderror=&Apache::lonnet::overloaderror($r);
     if ($loaderror) { return $loaderror; }      if ($loaderror) { return $loaderror; }
       #
     my $closebutton;  # button that closes the search window       my $closebutton;  # button that closes the search window 
                       # This button is different for the RAT compared to                        # This button is different for the RAT compared to
                       # normal invocation.                        # normal invocation.
Line 148  sub handler { Line 152  sub handler {
     ## Initialize global variables      ## Initialize global variables
     ##      ##
     my $domain  = $r->dir_config('lonDefDomain');      my $domain  = $r->dir_config('lonDefDomain');
     $diropendb= "/home/httpd/perl/tmp/$ENV{'user.domain'}_$ENV{'user.name'}_searchcat.db";      $diropendb= "/home/httpd/perl/tmp/".
           "$ENV{'user.domain'}_$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 163  sub handler { Line 168  sub handler {
             '_'.&Apache::lonnet::escape($ENV{'user.name'}).              '_'.&Apache::lonnet::escape($ENV{'user.name'}).
                 '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';                  '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';
     ##      ##
     if (! &get_persistent_form_data($persistent_db_file)) {      &Apache::lonhtmlcommon::clear_breadcrumbs();
         if ($ENV{'form.phase'} =~ /(run_search|results)/) {      if (exists($ENV{'request.course.id'}) && $ENV{'request.course.id'} ne '') {
             &Apache::lonnet::logthis("lonsearchcat:Unable to recover data ".          &Apache::lonhtmlcommon::add_breadcrumb
                                      "from $persistent_db_file");               ({href=>'/adm/searchcat?'.
             $r->print(<<END);                     'catalogmode='.$ENV{'form.catalogmode'}.
                      '&launch='.$ENV{'form.launch'}.
                      '&mode='.$ENV{'form.mode'},
                 text=>"Course and Catalog Search",
                 target=>'_top',
                 bug=>'Searching',});
       } else {
           &Apache::lonhtmlcommon::add_breadcrumb
                ({href=>'/adm/searchcat?'.
                      'catalogmode='.$ENV{'form.catalogmode'}.
                      '&launch='.$ENV{'form.launch'}.
                      '&mode='.$ENV{'form.mode'},
                 text=>"Catalog Search",
                 target=>'_top',
                 bug=>'Searching',});
       }
       #
       if ($ENV{'form.phase'} !~ m/(basic|adv|course)_search/) {
           if (! &get_persistent_form_data($persistent_db_file)) {
               if ($ENV{'form.phase'} =~ /(run_search|results)/) {
                   &Apache::lonnet::logthis('lonsearchcat:'.
                                            'Unable to recover data from '.
                                            $persistent_db_file);
                   $r->print(<<END);
 <html>  <html>
 <head><title>LON-CAPA Search Error</title></head>  <head><title>LON-CAPA Search Error</title></head>
 $bodytag  $bodytag
Line 176  error and has been logged.  Please alert Line 204  error and has been logged.  Please alert
 </body>  </body>
 </html>  </html>
 END  END
             return OK;                  return OK;
               }
         }          }
       } else {
           &clean_up_environment();
     }      }
     ##      ##
     ## Clear out old values from groupsearch database      ## Clear out old values from groupsearch database
Line 204  END Line 235  END
     $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.      $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.
         $ENV{'form.persistent_db_id'}.'" />'."\n";          $ENV{'form.persistent_db_id'}.'" />'."\n";
     if (exists($ENV{'form.catalogmode'})) {      if (exists($ENV{'form.catalogmode'})) {
         $hidden_fields .= '<input type="hidden" name="catalogmode" value="'.          $hidden_fields .= &hidden_field('catalogmode');
                 $ENV{'form.catalogmode'}.'" />'."\n";  
     }      }
     if (exists($ENV{'form.form'})) {      if (exists($ENV{'form.form'})) {
         $hidden_fields .= '<input type="hidden" name="form" value="'.          $hidden_fields .= &hidden_field('form');
                 $ENV{'form.form'}.'" />'."\n";  
     }      }
     if (exists($ENV{'form.element'})) {      if (exists($ENV{'form.element'})) {
         $hidden_fields .= '<input type="hidden" name="element" value="'.          $hidden_fields .= &hidden_field('element');
                 $ENV{'form.element'}.'" />'."\n";  
     }      }
     if (exists($ENV{'form.titleelement'})) {      if (exists($ENV{'form.titleelement'})) {
         $hidden_fields .= '<input type="hidden" name="titleelement" value="'.          $hidden_fields .= &hidden_field('titleelement');
                 $ENV{'form.titleelement'}.'" />'."\n";  
     }      }
     if (exists($ENV{'form.mode'})) {      if (exists($ENV{'form.mode'})) {
         $hidden_fields .= '<input type="hidden" name="mode" value="'.          $hidden_fields .= &hidden_field('mode');
                 $ENV{'form.mode'}.'" />'."\n";  
     }      }
     ##      ##
     ## Configure dynamic components of interface      ## Configure dynamic components of interface
Line 263  END Line 289  END
     }      }
     $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'}));      $ENV{'form.phase'} = 'disp_basic' if (! exists($ENV{'form.phase'}));
     $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'}));      $ENV{'form.show'} = 20 if (! exists($ENV{'form.show'}));
       #
       $ENV{'form.searchmode'} = 'basic' if (! exists($ENV{'form.searchmode'}));
       if ($ENV{'form.phase'} eq 'adv_search' ||
           $ENV{'form.phase'} eq 'disp_adv') {
           $ENV{'form.searchmode'} = 'advanced';
       } elsif ($ENV{'form.phase'} eq 'course_search') {
           $ENV{'form.searchmode'} = 'course_search';
       }
       #
       if ($ENV{'form.searchmode'} eq 'advanced') {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/searchcat?phase=disp_adv&'.
                     'catalogmode='.$ENV{'form.catalogmode'}.
                     '&launch='.$ENV{'form.launch'}.
                     '&mode='.$ENV{'form.mode'},
                     text=>"Advanced Search",
                     bug=>'Searching',});
       } elsif ($ENV{'form.searchmode'} eq 'course search') {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>'/adm/searchcat?phase=disp_adv&'.
                     'catalogmode='.$ENV{'form.catalogmode'}.
                     '&launch='.$ENV{'form.launch'}.
                     '&mode='.$ENV{'form.mode'},
                     text=>"Course Search",
                     bug=>'Searching',});
       }
     ##      ##
     ## Switch on the phase      ## Switch on the phase
     ##      ##
Line 287  END Line 339  END
         &course_search($r);          &course_search($r);
     } elsif(($ENV{'form.phase'} eq 'basic_search') ||      } elsif(($ENV{'form.phase'} eq 'basic_search') ||
             ($ENV{'form.phase'} eq 'adv_search')) {              ($ENV{'form.phase'} eq 'adv_search')) {
         $ENV{'form.searchmode'} = 'basic';          #
         if ($ENV{'form.phase'} eq 'adv_search') {          # We are running a search, try to parse it
             $ENV{'form.searchmode'} = 'advanced';          my ($query,$customquery,$customshow,$libraries) = 
               (undef,undef,undef,undef);
           my $pretty_string;
           if ($ENV{'form.phase'} eq 'basic_search') {
               ($query,$pretty_string,$libraries) = 
                   &parse_basic_search($r,$closebutton,$hidden_fields);
               return OK if (! defined($query));
               &make_persistent({ basicexp => $ENV{'form.basicexp'}},
                                $persistent_db_file);
           } else {                      # Advanced search
               ($query,$customquery,$customshow,$libraries,$pretty_string) 
                   = &parse_advanced_search($r,$closebutton,$hidden_fields);
               return OK if (! defined($query));
         }          }
           &make_persistent({ query => $query,
                              customquery => $customquery,
                              customshow => $customshow,
                              libraries => $libraries,
                              pretty_string => $pretty_string },
                            $persistent_db_file);
           #
         # Set up table          # Set up table
         if (! defined(&create_results_table())) {          if (! defined(&create_results_table())) {
     my $errorstring=&Apache::lonmysql::get_error();      my $errorstring=&Apache::lonmysql::get_error();
               &Apache::lonnet::logthis('lonsearchcat.pm: Unable to create '.
                                        'needed table.  lonmysql error:'.
                                        $errorstring);
             $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 316  Unable to properly store search informat Line 389  Unable to properly store search informat
 END  END
             return OK;              return OK;
         }          }
         #  
         # We are running a search  
         my ($query,$customquery,$customshow,$libraries) =   
             (undef,undef,undef,undef);  
         my $pretty_string;  
         if ($ENV{'form.phase'} eq 'basic_search') {  
             ($query,$pretty_string,$libraries) =   
                 &parse_basic_search($r,$closebutton,$hidden_fields);  
         } else {                      # Advanced search  
             ($query,$customquery,$customshow,$libraries,$pretty_string)   
                 = &parse_advanced_search($r,$closebutton,$hidden_fields);  
             return OK if (! defined($query));  
         }  
         &make_persistent({ query => $query,  
                            customquery => $customquery,  
                            customshow => $customshow,  
                            libraries => $libraries,  
                            pretty_string => $pretty_string },  
                          $persistent_db_file);  
         ##          ##
         ## Print out the frames interface          ## Print out the frames interface
         ##          ##
         &print_frames_interface($r);          if (defined($query)) {
               &print_frames_interface($r);
           }
     }      }
     return OK;      return OK;
 }   } 
   
   #
   # The mechanism used to store values away and retrieve them does not
   # handle the case of missing environment variables being significant.
   #
   # This routine sets non existant checkbox form elements to ''.
   #
   sub clean_up_environment {
       if ($ENV{'form.phase'} eq 'basic_search') {
           if (! exists($ENV{'form.related'})) {
               $ENV{'form.related'} = '';
           }
           if (! exists($ENV{'form.domains'})) {
               $ENV{'form.domains'} = '';
           }
       } elsif ($ENV{'form.phase'} eq 'adv_search') {
           foreach my $field ('title','keywords','notes',
                              'abstract','standards','mime') {
               if (! exists($ENV{'form.'.$field.'_related'})) {
                   $ENV{'form.'.$field.'_related'} = '';
               }
           }
       } elsif ($ENV{'form.phase'} eq 'course_search') {
           if (! exists($ENV{'form.crsrelated'})) {
               $ENV{'form.crsrelated'} = '';
           }
       }
   }
   
   sub hidden_field {
       my ($name,$value) = @_;
       if (! defined($value)) {
           $value = $ENV{'form.'.$name};
       }
       return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'.$/;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 ##  ##
Line 359  my $totalfound; Line 451  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;
Line 373  sub course_search { Line 464  sub course_search {
         }          }
     }      }
     my $fulltext=$ENV{'form.crsfulltext'};      my $fulltext=$ENV{'form.crsfulltext'};
       my $discuss=$ENV{'form.crsdiscuss'};
     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.'<hr /><center><font size="+2" face="arial">'.$pretty_search_string.'</font></center><hr />');        $bodytag.'<hr /><center><font size="+2" face="arial">'.$pretty_search_string.'</font></center><hr /><b>'.&mt('Course content').':</b><br />');
     $r->rflush();      $r->rflush();
 # ======================================================= Go through the course  # ======================================================= Go through the course
     undef %alreadyseen;      undef %alreadyseen;
Line 394  sub course_search { Line 486  sub course_search {
         untie(%hash);          untie(%hash);
     }      }
     unless ($totalfound) {      unless ($totalfound) {
  $r->print('<p>'.&mt('No resources found').'.</p>');   $r->print('<p>'.&mt('No matches found in resources').'.</p>');
       }
   
   # Check discussions if requested
       if ($discuss) {
           my $totaldiscussions = 0;
           $r->print('<br /><br /><b>'.&mt('Discussion postings').':</b><br />'); 
           my $navmap = Apache::lonnavmaps::navmap->new();
           my @allres=$navmap->retrieveResources();
           my %discussiontime = &Apache::lonnet::dump('discussiontimes',
                                  $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
                                  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
           foreach my $resource (@allres) {
               my $result = '';
               my $applies = 0;
               my $symb = $resource->symb();
               my $ressymb = $symb;
               if ($symb =~ m#(___adm/\w+/\w+)/(\d+)/bulletinboard$#) {
                   $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
                   unless ($ressymb =~ m#bulletin___\d+___adm/wrapper#) {
                       $ressymb=~s#(bulletin___\d+___)#$1adm/wrapper/#;
                   }
               }
               if (defined($discussiontime{$ressymb})) { 
                   my %contrib = &Apache::lonnet::restore($ressymb,$ENV{'request.course.id'},
                        $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
                        $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
                   if ($contrib{'version'}) {
                       for (my $id=1;$id<=$contrib{'version'};$id++) {
                           unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) { 
                               if ($contrib{$id.':subject'}) {
                                   $result .= $contrib{$id.':subject'};
                               }
                               if ($contrib{$id.':message'}) {
                                   $result .= $contrib{$id.':message'};
                               }
                               if ($contrib{$id,':attachmenturl'}) {
                                   if ($contrib{$id,':attachmenturl'} =~ m-/([^/]+)$-) {
                                       $result .= $1;
                                   }
                               }
                               $applies = &checkwords($result,$applies,@allwords);
                           }
                       }
                   }
               }
   # Does this discussion apply?
               if ($applies) {
                   my ($map,$ind,$url)=&Apache::lonnet::decode_symb($ressymb);
                   my $disctype = &mt('resource');
                   if ($url =~ m#/bulletinboard$#) {
                       if ($url =~m#^adm/wrapper/adm/.*/bulletinboard$#) {
                           $url =~s#^adm/wrapper##;
                       }
                       $disctype = &mt('bulletin board');
                   } else {
                       $url = '/res/'.$url;
                   }
                   if ($url =~ /\?/) {
                       $url .= '&symb=';
                   } else {
                       $url .= '?symb=';
                   }
                   $url .= &Apache::lonnet::escape($resource->symb());
                   my $title = $resource->compTitle();
                   $r->print('<br /><a href="'.$url.'" target="cat">'.
                        ($title?$title:$url).'</a>&nbsp;&nbsp;-&nbsp;'.$disctype.'<br />');
                   $totaldiscussions++;
               } else {
                   $r->print(' .');
               }
           }
           unless ($totaldiscussions) {
               $r->print('<p>'.&mt('No matches found in postings').'.</p>');
           }
     }      }
    
 # =================================================== Done going through course  # =================================================== Done going through course
     $r->print('</body></html>');      $r->print('</body></html>');
 }  }
Line 414  sub checkonthis { Line 581  sub checkonthis {
  $result.=&Apache::lonnet::ssi_body($url);   $result.=&Apache::lonnet::ssi_body($url);
     }      }
     $result=~s/\s+/ /gs;      $result=~s/\s+/ /gs;
     my $applies=0;      my $applies = 0;
     foreach (@allwords) {      $applies = &checkwords($result,$applies,@allwords);
         if ($_=~/\w/) {  
    if ($result=~/$_/si) {  
       $applies++;  
            }  
        }  
     }  
 # Does this resource apply?  # Does this resource apply?
     if ($applies) {      if ($applies) {
        $r->print('<br />');         $r->print('<br />');
Line 445  sub checkonthis { Line 606  sub checkonthis {
     }      }
 }  }
   
   sub checkwords {
       my ($result,$applies,@allwords) = @_;
       foreach (@allwords) {
           if ($_=~/\w/) {
               if ($result=~/$_/si) {
                   $applies++;
               }
           }
       }
       return $applies;
   }
   
 sub untiehash {  sub untiehash {
     if (tied(%hash)) {      if (tied(%hash)) {
         untie(%hash);          untie(%hash);
Line 453  sub untiehash { Line 626  sub untiehash {
   
 } # End of course search scoping  } # End of course search scoping
   
   sub search_html_header {
       my $Str = <<ENDHEADER;
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   </head>
   ENDHEADER
       return $Str;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
Line 460  sub untiehash { Line 643  sub untiehash {
   
 =item &print_basic_search_form()   =item &print_basic_search_form() 
   
 Returns a scalar which holds html for the basic search form.  Prints the form for the basic search.  Sorry the name is so cryptic.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   sub print_basic_search_form {
 sub print_basic_search_form{  
     my ($r,$closebutton,$hidden_fields) = @_;      my ($r,$closebutton,$hidden_fields) = @_;
       my $result = ($ENV{'form.catalogmode'} ne 'groupsearch');
     my $bodytag=&Apache::loncommon::bodytag('Search').      my $bodytag=&Apache::loncommon::bodytag('Search').
  &Apache::loncommon::help_open_topic('Finding_Resources').          &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching','Search_Basic',
  &Apache::loncommon::help_open_bug('Searching');                                     undef,undef,
     my $scrout=<<"ENDDOCUMENT";                                     $ENV{'form.catalogmode'} ne 'groupsearch');
 <html>      my $scrout = &search_html_header().$bodytag;
 <head>      if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {
 <title>The LearningOnline Network with CAPA</title>          # Define interface components
 <script type="text/javascript">          my $userelatedwords= '<label>'.
     function openhelp(val) {              &mt('[_1] use related words',
  openhelpwin=open('/adm/help/searchcat.html','helpscreen',                  &Apache::lonhtmlcommon::checkbox
      'scrollbars=1,width=600,height=300');                  ('related',$ENV{'form.related'},'related')).'</label>';
  openhelpwin.focus();          my $onlysearchdomain='<label>'.
     }              &mt('[_1] only search domain [_2]',
 </script>                  &Apache::lonhtmlcommon::checkbox('domains',
 </head>                                                   $ENV{'form.domains'},
 $bodytag                                                   $r->dir_config('lonDefDomain')
 ENDDOCUMENT                                                   ),
 if (&Apache::lonnet::allowed('bre',$ENV{'request.role.domain'})) {                  $r->dir_config('lonDefDomain')
     my $CatalogSearch=&mt('Catalog Search');                  ).'</label>';
     my $Statement=&searchhelp();          my $adv_search_link = 
     $scrout.=(<<ENDDOCUMENT);              '<a href="/adm/searchcat?'.
 <h1>$CatalogSearch</h1>              'phase=disp_adv&'.
 <form name="loncapa_search" method="post" action="/adm/searchcat">              'catalogmode='.$ENV{'form.catalogmode'}.
 <input type="hidden" name="phase" value="basic_search" />              '&launch='.$ENV{'form.launch'}.
 $hidden_fields              '&mode='.$ENV{'form.mode'}.
 <p>              '">'.&mt('Advanced Search').'</a>';
 $Statement.          #
 </p>          $scrout.='<form name="loncapa_search" method="post" '.
 <p>              'action="/adm/searchcat">'.
 <table>              '<input type="hidden" name="phase" value="basic_search" />'.
 <tr><td>              $hidden_fields;
 ENDDOCUMENT          #
     $scrout.='&nbsp;'.&Apache::lonhtmlcommon::textbox('basicexp',          $scrout .= '<center>'.$/;
                                             $ENV{'form.basicexp'},40).          if ($ENV{'request.course.id'}) {
         '&nbsp;';              $scrout .= '<h1>'.&mt('LON-CAPA Catalog Search').'</h1>';
     my $relatedcheckbox = &Apache::lonhtmlcommon::checkbox('related',          } else {
  $ENV{'form.related'});              # No need to tell them they are searching
     my $domain = $r->dir_config('lonDefDomain');              $scrout.= ('<br />'x2);
     my $domaincheckbox = &Apache::lonhtmlcommon::checkbox('domains',          }
  $ENV{'form.domains'});          $scrout.='<table>'.
     my $srch=&mt('Search');              '<tr><td align="center" valign="top">'.
     my $header=&mt('Advanced Search');              &Apache::lonhtmlcommon::textbox
     my $userelatedwords=&mt('use related words');              ('basicexp',
     my $onlysearchdomain=&mt('only search domain');               &HTML::Entities::encode($ENV{'form.basicexp'},'<>&"'),50
     my $view=&viewoptions();               ).
     $scrout.=<<END;               '<br />'.
 </td><td><a              '<font size="-1">'.&searchhelp().'</font>'.'</td>'.
 href="/adm/searchcat?phase=disp_adv&catalogmode=$ENV{'form.catalogmode'}&launch=$ENV{'form.launch'}&mode=$ENV{'form.mode'}"              '<td><font size="-1">'.
 >$header</a></td></tr>              '<nobr>'.('&nbsp;'x3).$adv_search_link.'</nobr>'.'<br />'.
 <tr><td>$relatedcheckbox $userelatedwords</td>              '<nobr>'.('&nbsp;'x1).$userelatedwords.'</nobr>'.'<br />'.
     <td>$domaincheckbox $onlysearchdomain <b>$domain</b></td></tr>              '<nobr>'.('&nbsp;'x1).$onlysearchdomain.'</nobr>'.'<br />'.
 </table>              '</font></td>'.
 </p>              '</tr>'.$/;
 $view          #
 <p>          $scrout .= '<tr><td align="center" colspan="2">'.
 &nbsp;<input type="submit" name="basicsubmit" value='$srch' />&nbsp;              '<font size="-1">'.
 $closebutton              '<input type="submit" name="basicsubmit" '.
 END              'value="'.&mt('Search').'" />'.
     $scrout.=<<ENDDOCUMENT;              ('&nbsp;'x2).$closebutton.('&nbsp;'x2).
 </p>              &viewoptions().
 </form>              '</font>'.
 ENDDOCUMENT              '</td></tr>'.$/;
           $scrout .= '</table>'.$/.'</center>'.'</form>';
     }      }
     if ($ENV{'request.course.id'}) {      if ($ENV{'request.course.id'}) {
  my %lt=&Apache::lonlocal::texthash(   my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
    'srch' => 'Search',  
                                            'header' => 'Course Search',                                             'header' => 'Course Search',
  'note' => 'Enter terms or phrases, then press "Search" below',   'note' => 'Enter terms or phrases, then press "Search" below',
  'use' => 'use related words',   'use' => 'use related words',
  'full' =>'fulltext search (time consuming)'   'full' =>'fulltext search (time consuming)',
            'disc' => 'search discussion postings (resources and bulletin boards)',
    );     );
         $scrout.=(<<ENDCOURSESEARCH);          $scrout.=(<<ENDCOURSESEARCH);
   <form name="loncapa_search" method="post" action="/adm/searchcat">
   <center>
 <hr />  <hr />
 <h1>$lt{'header'}</h1>      <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>
Line 562  ENDCOURSESEARCH Line 747  ENDCOURSESEARCH
         my $relcheckbox =           my $relcheckbox = 
             &Apache::lonhtmlcommon::checkbox('crsrelated',              &Apache::lonhtmlcommon::checkbox('crsrelated',
    $ENV{'form.crsrelated'});     $ENV{'form.crsrelated'});
           my $discheckbox = 
               &Apache::lonhtmlcommon::checkbox('crsdiscuss',
                                      $ENV{'form.crsrelated'});
         $scrout.=(<<ENDENDCOURSE);          $scrout.=(<<ENDENDCOURSE);
 </td></tr>  </td></tr>
 <tr><td>$relcheckbox $lt{'use'}</td><td></td></tr>  <tr><td>$relcheckbox $lt{'use'}</td><td></td></tr>
 <tr><td>$crscheckbox $lt{'full'}</td><td></td></tr>  <tr><td>$crscheckbox $lt{'full'}</td><td></td></tr>
   <tr><td>$discheckbox $lt{'disc'}</td><td></td></tr>
 </table><p>  </table><p>
 &nbsp;<input type="submit" name="coursesubmit" value='$lt{'srch'}' />  &nbsp;<input type="submit" name="coursesubmit" value='$lt{'srch'}' />
 </p>  </p>
   </center>
   </form>
 ENDENDCOURSE  ENDENDCOURSE
     }      }
     $scrout.=(<<ENDDOCUMENT);      $scrout.=(<<ENDDOCUMENT);
Line 585  ENDDOCUMENT Line 776  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,$hidden_fields) = @_;      my ($r,$closebutton,$hidden_fields) = @_;
       my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search').
           &Apache::lonhtmlcommon::breadcrumbs(undef,'Searching',
                                               'Search_Advanced',
                                               undef,undef,
                                     $ENV{'form.catalogmode'} ne 'groupsearch');
     my %lt=&Apache::lonlocal::texthash('srch' => 'Search',      my %lt=&Apache::lonlocal::texthash('srch' => 'Search',
        'reset' => 'Reset',         'reset' => 'Reset',
        'help' => 'Help');         'help' => 'Help');
     my $advanced_buttons = <<"END";      my $advanced_buttons=<<"END";
 <p>  
 <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />  <input type="submit" name="advancedsubmit" value='$lt{"srch"}' />
 <input type="reset" name="reset" value='$lt{"reset"}' />  <input type="reset" name="reset" value='$lt{"reset"}' />
 $closebutton  $closebutton
 <input type="button" value="$lt{'help'}" onClick="openhelp()" />  
 </p>  
 END  END
     my $bodytag=&Apache::loncommon::bodytag('Advanced Catalog Search');      my $scrout=&search_html_header();
     my $searchhelp=&searchhelp();      $scrout .= <<"ENDHEADER";
     my $scrout=<<"ENDHEADER";  
 <html>  
 <head>  
 <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
 $searchhelp  
 <form method="post" action="/adm/searchcat" name="advsearch">  <form method="post" action="/adm/searchcat" name="advsearch">
   <p>
 $advanced_buttons  $advanced_buttons
 $hidden_fields  
 <input type="hidden" name="phase" value="adv_search" />  
 ENDHEADER  ENDHEADER
     $scrout.=&viewoptions();      $scrout.=('&nbsp;'x2).&viewoptions().'</p>'.$hidden_fields. 
           '<input type="hidden" name="phase" value="adv_search" />';
     my %fields=&Apache::lonmeta::fieldnames();      my %fields=&Apache::lonmeta::fieldnames();
       #
     $scrout.='<table>';      $scrout .= '<h3>'.&mt('Standard Metadata').'</h3>';
     $scrout.="<tr><th>".&mt('Field').'</th><th>'.&mt('Value').'</th><th>'      $scrout .= "<table>\n";
  .&mt('Related').'<br />'.&mt('Words')."</td></tr>\n";      $scrout .= '<tr><td>&nbsp;</td><td colspan="2"><font size="-1">'.
     foreach ('title','author','owner','authorspace','modifyinguser',          ('&nbsp;'x2).&searchhelp()."</font></td></tr>\n";
      'keywords','notes','abstract','standards',      my %related_word_search = 
      'lowestgradelevel','highestgradelevel','mime') {          ('title'    => 1,
  $scrout.='<tr bgcolor="#FFFFBB"><td>'.&titlefield($fields{$_}).'</td><td>'.           'author'   => 0,
     &Apache::lonmeta::prettyinput($_,$ENV{'form.'.$_},$_,'advsearch',           'owner'    => 0,
   1,'</td><td>',$ENV{'form.'.$_.'_related'}).           'authorspace'  => 0,
     '</td></tr>';           'modifyinguser'=> 0,
            'keywords' => 1,
            'notes'    => 1,
            'abstract' => 1,
            'standards'=> 1,
            'mime'     => 1,
            );
       #
       foreach my $field ('title','author','owner','authorspace','modifyinguser',
        'keywords','notes','abstract','standards','mime') {
    $scrout.='<tr><td align="right">'.&titlefield($fields{$field}).'</td><td>'.
       &Apache::lonmeta::prettyinput($field,
                                             $ENV{'form.'.$field},
                                             $field,
                                             'advsearch',
     $related_word_search{$field},
                                             '</td><td align="left">',
                                             $ENV{'form.'.$field.'_related'},
                                             50);
           if ($related_word_search{$field}) {
               $scrout .= 'related words';
           } else {
               $scrout .= '</td><td>&nbsp;';
           }
           $scrout .= '</td></tr>'.$/;
       }
       foreach my $field ('lowestgradelevel','highestgradelevel') {
    $scrout.='<tr>'.
               '<td align="right">'.&titlefield($fields{$field}).'</td>'.
               '<td colspan="2">'.
       &Apache::lonmeta::prettyinput($field,
                                             $ENV{'form.'.$field},
                                             $field,
                                             'advsearch',
     0).
                                             '</td></tr>'.$/;
     }      }
     $scrout.='<tr bgcolor="#FFFFBB"><td>'.      $scrout.='<tr><td align="right">'.
  &titlefield(&mt('MIME Type Category')).'</td><td>'.    &titlefield(&mt('MIME Type Category')).'</td><td colspan="2">'. 
     &Apache::loncommon::filecategoryselect('category',      &Apache::loncommon::filecategoryselect('category',
    $ENV{'form.category'}).     $ENV{'form.category'}).
     '</td><td>&nbsp;</td></td></tr>';      '</td></tr>'.$/;
     $scrout.='<tr bgcolor="#FFFFBB"><td>'.      $scrout.='<tr><td align="right" valign="top">'.
  &titlefield(&mt('Limit Search to Domains')).'</td><td>'.    &titlefield(&mt('Domains')).'</td><td colspan="2">'. 
     &Apache::loncommon::domain_select('domains',      &Apache::loncommon::domain_select('domains',
    $ENV{'form.domains'},1).     $ENV{'form.domains'},1).
     '</td><td>&nbsp;</td></td></tr>';      '</td></tr>'.$/;
     my %dates=&Apache::lonlocal::texthash('creationdatestart'     => 'Creation Date After',      #
     'creationdateend'       => 'Creation Date Before',      # Misc metadata
   'lastrevisiondatestart' => 'Last Revision Date After',      $scrout.='<tr><td align="right" valign="top">'.
   'lastrevisiondateend'   => 'Last Revision Date Before');   &titlefield(&mt('Copyright/Distribution')).'</td><td colspan="2">'.
     foreach (sort keys %dates) {          &Apache::lonmeta::selectbox('copyright',
  $scrout.='<tr bgcolor="#FFFFBB"><td>'.&titlefield($dates{$_}).'</td><td>'.                                       $ENV{'form.copyright'},
     &Apache::lonhtmlcommon::date_setter('advsearch',$_,0,'',1).                                      \&Apache::loncommon::copyrightdescription,
     '</td><td>&nbsp;</td></td></tr>';                                      ( undef,
                                         &Apache::loncommon::copyrightids)
                                       ).'</td></tr>'.$/;
       $scrout.='<tr><td align="right" valign="top">'.
    &titlefield(&mt('Language')).'</td><td colspan="2">'.
           &Apache::lonmeta::selectbox('language',
                                       $ENV{'form.language'},
                                       \&Apache::loncommon::languagedescription,
                                       ('any',&Apache::loncommon::languageids)
                                       ).'</td></tr>';
       $scrout .= "</table>\n";    
       #
       # Dynamic metadata
       $scrout .= '<h3>'.&mt('Problem Statistics').'</h3>';
       $scrout .= "<table>\n";
       $scrout .= '<tr><td>&nbsp;</td><td align="center">'.&mt('Minimum').'</td>'.
           '<td align="center">'.&mt('Maximum').'</td></tr>'."\n";
       foreach my $statistic 
           ({ name=>'count',
              description=>'Network-wide number of accesses (hits)',},
            { name=>'stdno',
              description=>
                  'Total number of students who have worked on this problem',},
            { name => 'avetries',
              description=>'Average number of tries till solved',},
            { name => 'difficulty',
              description=>'Degree of difficulty',},
            { name => 'disc',
              description=>'Degree of discrimination'}) {
           $scrout .= '<tr><td align="right">'.
               &titlefield(&mt($statistic->{'description'})).
               '</td><td align="center">'.
               '<input type="text" name="'.$statistic->{'name'}.'_min" '.
               'value="" size="6" />'.
               '</td><td align="center">'.
               '<input type="text" name="'.$statistic->{'name'}.'_max" '.
               'value="" size="6" />'.
               '</td></tr>'.$/;
       }
       $scrout .= "</table>\n";
       $scrout .= '<h3>'.&mt('Evaluation Data').'</h3>';
       $scrout .= "<table>\n";
       $scrout .= '<tr><td>&nbsp;</td><td align="center">'.&mt('Minimum').'</td>'.
           '<td align="center">'.&mt('Maximum').'</td></tr>'."\n";
       foreach my $evaluation
           ( { name => 'clear',
               description => 'Material presented in clear way'},
             { name =>'depth',
               description => 'Material covered with sufficient depth'},
             { name => 'helpful',
               description => 'Material is helpful'},
             { name => 'correct',
               description => 'Material appears to be correct'},
             { name => 'technical',
               description => 'Resource is technically correct'}){
           $scrout .= '<tr><td align="right">'.
               &titlefield(&mt($evaluation->{'description'})).
               '</td><td align="center">'.
               '<input type="text" name="'.$evaluation->{'name'}.'_min" '.
               'value="" size="6" />'.
               '</td><td align="center">'.
               '<input type="text" name="'.$evaluation->{'name'}.'_max" '.
               'value="" size="6" />'.
               '</td></tr>'.$/;
     }      }
       $scrout .= "</table>\n";
       #
       # Creation/Modification date limits
       $scrout .= '<h3>'.&mt('Creation and Modification dates').'</h3>';
       $scrout .= "\n<table>\n";
       my $cafter = 
           &Apache::lonhtmlcommon::date_setter('advsearch',         # formname
                                               'creationdate1', # fieldname
                                               0,           # current value
                                               '',          # special 
                                               1,           # includeempty
                                               '',          # state
                                               1,           # no_hh_mm_ss
                                               );
       my $cbefore = 
           &Apache::lonhtmlcommon::date_setter('advsearch',         # formname
                                               'creationdate2', # fieldname
                                               0,           # current value
                                               '',          # special 
                                               1,           # includeempty
                                               '',          # state
                                               1,           # no_hh_mm_ss
                                               );
       $scrout .= &mt('<tr><td align="right">Created between</td>'.
                      '<td>[_1]</td></tr>'.
                      '<tr><td align="right">and </td>'.
                      '<td>[_2]</td></tr>',$cafter,$cbefore);
       my $lafter = 
           &Apache::lonhtmlcommon::date_setter('advsearch',
                                               'revisiondate1', 
                                               0,           # current value
                                               '',          # special 
                                               1,           # includeempty
                                               '',          # state
                                               1,           # no_hh_mm_ss
                                               );
       my $lbefore = 
           &Apache::lonhtmlcommon::date_setter('advsearch',
                                               'revisiondate2',
                                               0,           # current value
                                               '',          # special 
                                               1,           # includeempty
                                               '',          # state
                                               1,           # no_hh_mm_ss
                                               );
       $scrout .= &mt('<tr><td align="right">Last modified between </td>'.
                      '<td>[_1]</td></tr>'.
                      '<tr><td align="right">and</td>'.
                      '<td>[_2]</td></tr>',$lafter,$lbefore);
     $scrout.="</table>\n";      $scrout.="</table>\n";
   
     $scrout.=<<ENDDOCUMENT;      $scrout.=<<ENDDOCUMENT;
 $advanced_buttons  $advanced_buttons
 </form>  </form>
Line 671  ENDDOCUMENT Line 995  ENDDOCUMENT
     $r->print($scrout);      $r->print($scrout);
     return;      return;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod   =pod 
   
 =item &titlefield  =item &titlefield()
   
 Inputs: title text  Inputs: title text
   
Line 686  Outputs: titletext with font wrapper Line 1011  Outputs: titletext with font wrapper
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 sub titlefield {  sub titlefield {
     my $title=shift;      my $title=shift;
     return '<font face="arial" color="#800000">'.$title.'</font>';      return $title;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod   =pod 
   
 =item viewoptiontext  =item viewoptiontext()
   
 Inputs: codename for view option  Inputs: codename for view option
   
Line 706  Outputs: displayed text Line 1031  Outputs: displayed text
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 sub viewoptiontext {  sub viewoptiontext {
     my $code=shift;      my $code=shift;
     my %desc=&Apache::lonlocal::texthash('detailed' => "Detailed Citation View",      my %desc=&Apache::lonlocal::texthash
  'xml' => 'XML/SGML',          ('detailed' => "Detailed Citation View",
  'compact' => 'Compact View',           'xml' => 'XML/SGML',
  'fielded' => 'Fielded Format',           'compact' => 'Compact View',
  'summary' => 'Summary View');           'fielded' => 'Fielded Format',
            'summary' => 'Summary View');
     return $desc{$code};      return $desc{$code};
 }  }
   
   ######################################################################
 ######################################################################  ######################################################################
   
 =pod   =pod 
   
 =item viewoptions  =item viewoptions()
   
 Inputs: none  Inputs: none
   
Line 730  Outputs: text for box with view options Line 1057  Outputs: text for box with view options
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 sub viewoptions {  sub viewoptions {
     my $scrout="\n\n".'<table bgcolor="#FFFFBB"><tr><th>'.&mt('View Options').'</th><th>'.      my $scrout;
  &mt('Records per Page').'</th></tr><tr><td>';      if (! defined($ENV{'form.viewselect'})) { 
     unless ($ENV{'form.viewselect'}) { $ENV{'form.viewselect'}='detailed'; }          $ENV{'form.viewselect'}='detailed'; 
       }
     $scrout.=&Apache::lonmeta::selectbox('viewselect',      $scrout.=&Apache::lonmeta::selectbox('viewselect',
  $ENV{'form.viewselect'},   $ENV{'form.viewselect'},
  \&viewoptiontext,   \&viewoptiontext,
  sort(keys(%Views)));   sort(keys(%Views)));
     $scrout.='</td><td>';      $scrout.= '&nbsp;&nbsp;';
     $scrout.=&Apache::lonmeta::selectbox('show',      my $countselect = &Apache::lonmeta::selectbox('show',
  $ENV{'form.show'},                                                    $ENV{'form.show'},
  undef,                                                    undef,
  (10,20,50,100,1000,10000));                                                    (10,20,50,100,1000,10000));
     $scrout.="</td></tr></table>\n\n";      $scrout .= ('&nbsp;'x2).&mt('[_1] Records per Page',$countselect).
           '</nobr>'.$/;
     return $scrout;      return $scrout;
 }  }
   
 ######################################################################  ######################################################################
   ######################################################################
   
 =pod   =pod 
   
 =item searchhelp  =item searchhelp()
   
 Inputs: none  Inputs: none
   
Line 762  Outputs: return little blurb on how to e Line 1091  Outputs: return little blurb on how to e
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 sub searchhelp {  sub searchhelp {
     return &mt('Enter terms or phrases separated by AND, OR, or NOT');      return &mt('Enter words and quoted phrases');
 }  }
   
 ######################################################################  ######################################################################
Line 772  sub searchhelp { Line 1100  sub searchhelp {
   
 =pod   =pod 
   
 =item &get_persistent_form_data  =item &get_persistent_form_data()
   
 Inputs: filename of database  Inputs: filename of database
   
Line 827  sub get_persistent_form_data { Line 1155  sub get_persistent_form_data {
   
 =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 878  Inputs: Hash of values to save, filename Line 1206  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 910  Inputs: filename of persistent database. Line 1238  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 954  Parse advanced search form and return th Line 1282  Parse advanced search form and return th
 ######################################################################  ######################################################################
 sub parse_advanced_search {  sub parse_advanced_search {
     my ($r,$closebutton,$hidden_fields)=@_;      my ($r,$closebutton,$hidden_fields)=@_;
       my @BasicFields = ('title','author','subject','keywords','url','version',
                          'notes','abstract','extension','owner','authorspace',
   #                       'custommetadata','customshow',
                          'modifyinguser','standards','mime');
       my @StatsFields = &statfields();
       my @EvalFields = &evalfields();
     my $fillflag=0;      my $fillflag=0;
     my $pretty_search_string = "<br />\n";      my $pretty_search_string = "";
     # Clean up fields for safety      # Clean up fields for safety
     for my $field ('title','author','subject','keywords','url','version',      for my $field (@BasicFields,
    'creationdatestart_month','creationdatestart_day',                     'creationdatestart_month','creationdatestart_day',
    'creationdatestart_year','creationdateend_month',     'creationdatestart_year','creationdateend_month',
    'creationdateend_day','creationdateend_year',     'creationdateend_day','creationdateend_year',
    'lastrevisiondatestart_month','lastrevisiondatestart_day',     'lastrevisiondatestart_month','lastrevisiondatestart_day',
    'lastrevisiondatestart_year','lastrevisiondateend_month',     'lastrevisiondatestart_year','lastrevisiondateend_month',
    'lastrevisiondateend_day','lastrevisiondateend_year',     'lastrevisiondateend_day','lastrevisiondateend_year') {
    'notes','abstract','extension','language','owner',   $ENV{'form.'.$field}=~s/[^\w\/\s\(\)\=\-\"\']//g;
    'custommetadata','customshow','category') {  
  $ENV{"form.$field"}=~s/[^\w\/\s\(\)\=\-\"\']//g;  
     }      }
     foreach ('mode','form','element') {      foreach ('mode','form','element') {
  # is this required?  Hmmm.   # is this required?  Hmmm.
  next unless (exists($ENV{"form.$_"}));   next if (! exists($ENV{'form.'.$_}));
  $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;
     }      }
     # Preprocess the category form element.      # Preprocess the category form element.
     $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) ||      $ENV{'form.category'} = 'any' if (! defined($ENV{'form.category'}) ||
                                       ref($ENV{'form.category'}));                                        ref($ENV{'form.category'}));
     #      #
     # Check to see if enough information was filled in      # Check to see if enough information was filled in
     for my $field ('title','author','subject','keywords','url','version',      foreach my $field (@BasicFields) {
    'notes','abstract','category','extension','language',   if (&filled($ENV{'form.'.$field})) {
                    'owner','custommetadata') {  
  if (&filled($ENV{"form.$field"})) {  
     $fillflag++;      $fillflag++;
  }   }
     }      }
     unless ($fillflag) {      foreach my $field (@StatsFields,@EvalFields) {
  &output_blank_field_error($r,$closebutton,'phase=disp_adv',$hidden_fields);          if (&filled($ENV{'form.'.$field.'_max'})) {
               $fillflag++;
           }
           if (&filled($ENV{'form.'.$field.'_min'})) {
               $fillflag++;
           }
       }
   
       for my $field ('lowestgradelevel','highestgradelevel') {
           if ( $ENV{'form.'.$field} =~ /^\d+$/ &&
                $ENV{'form.'.$field} > 0) {
               $fillflag++;
           }
       }
       if (! $fillflag) {
    &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 995  sub parse_advanced_search { Line 1341  sub parse_advanced_search {
     my @queries;      my @queries;
     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 (@BasicFields) {
        'keywords','version','owner','standards') {   next if (!defined($ENV{'form.'.$field}) || $ENV{'form.'.$field} eq '');
  if ($ENV{'form.'.$field}) {          my ($error,$SQLQuery) = 
             my $searchphrase = $ENV{'form.'.$field};              &process_phrase_input($ENV{'form.'.$field},
             $pretty_search_string .= $font."$field</font> contains <b>".                                    $ENV{'form.'.$field.'_related'},$field);
                 $searchphrase."</b>";          if (defined($error)) {
               &output_unparsed_phrase_error($r,$closebutton,'phase=disp_adv',
                                            $hidden_fields,$field);
               return;
           } else {
               $pretty_search_string .= 
                   $font.$field.'</font>: '.$ENV{'form.'.$field};
             if ($ENV{'form.'.$field.'_related'}) {              if ($ENV{'form.'.$field.'_related'}) {
                 my @New_Words;                  my @Words = 
                 ($searchphrase,@New_Words) = &related_version($searchphrase);                      &Apache::loncommon::get_related_words
                 if (@New_Words) {                      ($ENV{'form.'.$field});
                     $pretty_search_string .= " with related words: ".                  if (@Words) {
                         "<b>@New_Words</b>.";                      $pretty_search_string.= ' with related words: '.
                           join(', ',@Words[0..4]);
                 } else {                  } else {
                     $pretty_search_string .= " with no related words.";                      $pretty_search_string.= ' with related words.';
                 }                  }
             }              }
             $pretty_search_string .= "<br />\n";              $pretty_search_string .= '<br />';
     push @queries,&build_SQL_query($field,$searchphrase);              push (@queries,$SQLQuery);
         }          }
     }      }
     #      #
Line 1028  sub parse_advanced_search { Line 1381  sub parse_advanced_search {
             $searchphrase = join(' OR ',@extensions);              $searchphrase = join(' OR ',@extensions);
         }          }
     }      }
     if (exists($ENV{'form.extension'}) && $ENV{'form.extension'} !~ /^\s*$/) {  
         $searchphrase .= ' OR ' if (defined($searchphrase));  
         my @extensions = split(/,/,$ENV{'form.extension'});  
         $searchphrase .= join(' OR ',@extensions);  
     }  
     if (defined($searchphrase)) {      if (defined($searchphrase)) {
         push @queries,&build_SQL_query('mime',$searchphrase);          my ($error,$SQLsearch) = &process_phrase_input($searchphrase,0,'mime');
           push @queries,$SQLsearch;
         $pretty_search_string .=$font.'mime</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.lowestgradelevel'}        &&
           $ENV{'form.lowestgradelevel'} ne '0' &&
           $ENV{'form.lowestgradelevel'} =~ /^\d+$/) {
    push(@queries,
                '(lowestgradelevel>='.$ENV{'form.lowestgradelevel'}.')');
           $pretty_search_string.="lowestgradelevel>=".
               $ENV{'form.lowestgradelevel'}."<br />\n";
       }
       if ($ENV{'form.highestgradelevel'}        &&
           $ENV{'form.highestgradelevel'} ne '0' &&
           $ENV{'form.highestgradelevel'} =~ /^\d+$/) {
    push(@queries,
                '(highestgradelevel<='.$ENV{'form.highestgradelevel'}.')');
           $pretty_search_string.="highestgradelevel<=".
               $ENV{'form.highestgradelevel'}."<br />\n";
       }
     if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {      if ($ENV{'form.language'} and $ENV{'form.language'} ne 'any') {
  push @queries,"(language like \"$ENV{'form.language'}\")";   push @queries,"(language like \"$ENV{'form.language'}\")";
         $pretty_search_string.=$font."language</font>= ".          $pretty_search_string.=$font."language</font>= ".
Line 1050  sub parse_advanced_search { Line 1415  sub parse_advanced_search {
  push @queries,"(copyright like \"$ENV{'form.copyright'}\")";   push @queries,"(copyright like \"$ENV{'form.copyright'}\")";
         $pretty_search_string.=$font."copyright</font> = ".          $pretty_search_string.=$font."copyright</font> = ".
             &Apache::loncommon::copyrightdescription($ENV{'form.copyright'}).              &Apache::loncommon::copyrightdescription($ENV{'form.copyright'}).
                 "<br \>\n";                  "<br />\n";
       }
       #
       # Statistics
       foreach my $field (@StatsFields,@EvalFields) {
           my ($min,$max);
           if (exists($ENV{'form.'.$field.'_min'}) && 
               $ENV{'form.'.$field.'_min'} ne '') {
               $min = $ENV{'form.'.$field.'_min'};
           }
           if (exists($ENV{'form.'.$field.'_max'}) &&
               $ENV{'form.'.$field.'_max'} ne '') {
               $max = $ENV{'form.'.$field.'_max'};
           }
           next if (! defined($max) && ! defined($min));
           if (defined($min) && defined($max)) {
               ($min,$max) = sort {$a <=>$b} ($min,$max);
           }
           if (defined($min) && $min =~ /^(\d+\.\d+|\d+|\.\d+)$/) {
               push(@queries,'('.$field.'>'.$min.')');
               $pretty_search_string.=$font.$field.'</font>&gt;'.$min.'<br />';
           }
           if (defined($max) && $max =~ /^(\d+\.\d+|\d+|\.\d+)$/) {
               push(@queries,'('.$field.'<'.$max.')');
               $pretty_search_string.=$font.$field.'</font>&lt;'.$max.'<br />';
           }
     }      }
     #      #
     # Evaluate date windows      # Evaluate date windows
     my $datequery=&build_date_queries(      my $cafter =
  $ENV{'form.creationdatestart_month'},          &Apache::lonhtmlcommon::get_date_from_form('creationdate1');
  $ENV{'form.creationdatestart_day'},      my $cbefore = 
  $ENV{'form.creationdatestart_year'},          &Apache::lonhtmlcommon::get_date_from_form('creationdate2');
  $ENV{'form.creationdateend_month'},      if ($cafter > $cbefore) {
  $ENV{'form.creationdateend_day'},          my $tmp = $cafter;
  $ENV{'form.creationdateend_year'},          $cafter = $cbefore;
  $ENV{'form.lastrevisiondatestart_month'},          $cbefore = $tmp;
  $ENV{'form.lastrevisiondatestart_day'},      }
  $ENV{'form.lastrevisiondatestart_year'},      my $mafter = 
  $ENV{'form.lastrevisiondateend_month'},          &Apache::lonhtmlcommon::get_date_from_form('revisiondate1');
  $ENV{'form.lastrevisiondateend_day'},      my $mbefore =
  $ENV{'form.lastrevisiondateend_year'},          &Apache::lonhtmlcommon::get_date_from_form('revisiondate2');
  );      if ($mafter > $mbefore) {
     # Test to see if date windows are legitimate          my $tmp = $mafter;
     if ($datequery=~/^Incorrect/) {          $mafter = $mbefore;
  &output_date_error($r,$datequery,$closebutton,$hidden_fields);          $mbefore = $tmp;
  return ;      }
     } elsif ($datequery) {      my ($datequery,$error,$prettydate)=&build_date_queries($cafter,$cbefore,
                                                              $mafter,$mbefore);
       if (defined($error)) {
           &output_date_error($r,$error,$closebutton,$hidden_fields);
       } elsif (defined($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.
           $pretty_search_string .= '<br />'.$prettydate.'<br />';
  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) =       my ($libraries_to_query,$pretty_domains_string) = 
Line 1102  sub parse_advanced_search { Line 1503  sub parse_advanced_search {
     $pretty_search_string .= $pretty_domains_string."<br />\n";      $pretty_search_string .= $pretty_domains_string."<br />\n";
     #      #
     if (@queries) {      if (@queries) {
  $query=join(" AND ",@queries);   $query="SELECT * FROM metadata WHERE (".join(") AND (",@queries).')';
  $query="select * from metadata where $query";  
     } elsif ($customquery) {      } elsif ($customquery) {
         $query = '';          $query = '';
     }      }
       # &Apache::lonnet::logthis('query = '.$/.$query);
     return ($query,$customquery,$customshow,$libraries_to_query,      return ($query,$customquery,$customshow,$libraries_to_query,
             $pretty_search_string);              $pretty_search_string);
 }  }
Line 1115  sub parse_domain_restrictions { Line 1516  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.
     if (! exists($ENV{'form.domains'})) {      if (! exists($ENV{'form.domains'}) || $ENV{'form.domains'} eq '') {
         return (undef,'');          return (undef,'');
     }      }
     my @allowed_domains;      my @allowed_domains;
Line 1124  sub parse_domain_restrictions { Line 1525  sub parse_domain_restrictions {
     } else {      } else {
         @allowed_domains = ($ENV{'form.domains'});          @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 1164  Parse the basic search form and return a Line 1566  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;
     }      }
     foreach ('mode','form','element') {      foreach ('mode','form','element') {
  # is this required?  Hmmm.   # is this required?  Hmmm.
Line 1176  sub parse_basic_search { Line 1579  sub parse_basic_search {
     }      }
     my ($libraries_to_query,$pretty_domains_string) =       my ($libraries_to_query,$pretty_domains_string) = 
         &parse_domain_restrictions();          &parse_domain_restrictions();
     # Check to see if enough is filled in      #
     unless (&filled($ENV{'form.basicexp'})) {      # Check to see if enough of a query is filled in
       my $search_string = $ENV{'form.basicexp'};
       if (! &filled($search_string)) {
  &output_blank_field_error($r,$closebutton,'phase=disp_basic');   &output_blank_field_error($r,$closebutton,'phase=disp_basic');
  return OK;   return OK;
     }      }
     my $pretty_search_string = '<b>'.$ENV{'form.basicexp'}.'</b>';      my $pretty_search_string=$search_string;
     my $search_string = $ENV{'form.basicexp'};      my @Queries;
     if ($ENV{'form.related'}) {      my $searchfield = 'concat_ws(" ",'.join(',',
         my @New_Words;                                              ('title','author','subject',
         ($search_string,@New_Words) = &related_version($ENV{'form.basicexp'});                                               'notes','abstract','keywords')
         if (@New_Words) {                                              ).')';
             $pretty_search_string .= " with related words: <b>@New_Words</b>.";      my ($error,$SQLQuery) = &process_phrase_input($search_string,
         } else {                                                      $ENV{'form.related'},
             $pretty_search_string .= " with no related words.";                                                      $searchfield);
         }      if ($error) {
           &output_unparsed_phrase_error($r,$closebutton,'phase=disp_basic',
                                         '','basicexp');
           return;
     }      }
     # Build SQL query string based on form page      push(@Queries,$SQLQuery);
     my $query='';      #foreach my $q (@Queries) {
     my $concatarg=join(',',      #    &Apache::lonnet::logthis('    '.$q);
        ('title', 'author', 'subject', 'notes', 'abstract',      #}
                         'keywords'));      my $final_query = 'SELECT * FROM metadata WHERE '.join(" AND ",@Queries);
     $concatarg='title' if $ENV{'form.titleonly'};      #
     $query=&build_SQL_query('concat_ws(" ",'.$concatarg.')',$search_string);  
     if (defined($pretty_domains_string) && $pretty_domains_string ne '') {      if (defined($pretty_domains_string) && $pretty_domains_string ne '') {
         $pretty_search_string .= ' '.$pretty_domains_string;          $pretty_search_string .= ' '.$pretty_domains_string;
     }      }
     $pretty_search_string .= "<br />\n";      $pretty_search_string .= "<br />\n";
     my $final_query = 'SELECT * FROM metadata WHERE '.$query;      $pretty_search_string =~ s:^<br /> and ::;
 #    &Apache::lonnet::logthis($final_query);      # &Apache::lonnet::logthis($final_query);
     return ($final_query,$pretty_search_string,      return ($final_query,$pretty_search_string,
             $libraries_to_query);              $libraries_to_query);
 }  }
   
   
   ###############################################################
   ###############################################################
   
   my @Phrases;
   
   sub concat {
       my ($item) = @_;
       my $results = '';
       foreach (@$item) {
           if (ref($_) eq 'ARRAY') {
               $results .= join(' ',@$_);
           }
       }
       return $results;
   }
   
   sub process_phrase_input {
       my ($phrase,$related,$field)=@_;
       #&Apache::lonnet::logthis('phrase = :'.$phrase.':');
       my $grammar = <<'ENDGRAMMAR';
       searchphrase:
           expression /^\Z/ {
               # &Apache::lonsearchcat::print_item(\@item,0);
               [@item];
           }
       expression:
           phrase(s)   {
               [@item];
           }
       phrase:
           orword {
               [@item];
           }
         | andword {
               [@item];
           }
         | minusword {
               unshift(@::Phrases,$item[1]->[0]);
               unshift(@::Phrases,$item[1]->[1]);
               [@item];
           }
         | word {
               unshift(@::Phrases,$item[1]);
               [@item];
           } 
       #
       orword:
           word 'OR' phrase {
               unshift(@::Phrases,'OR');
               unshift(@::Phrases,$item[1]);
               [@item];
           }
           | word 'or' phrase {
               unshift(@::Phrases,'OR');
               unshift(@::Phrases,$item[1]);
               [@item];
           }    
           | minusword 'OR' phrase {
               unshift(@::Phrases,'OR');
               unshift(@::Phrases,$item[1]->[0]);
               unshift(@::Phrases,$item[1]->[1]);
               [@item];
           }
           | minusword 'or' phrase {
               unshift(@::Phrases,'OR');
               unshift(@::Phrases,$item[1]->[0]);
               unshift(@::Phrases,$item[1]->[1]);
               [@item];
           }    
       andword:
           word phrase {
               unshift(@::Phrases,'AND');
               unshift(@::Phrases,$item[1]);
               [@item];
           }
           | minusword phrase {
               unshift(@::Phrases,'AND');
               unshift(@::Phrases,$item[1]->[0]);
               unshift(@::Phrases,$item[1]->[1]);
               [@item];
           }
       #
       minusword:
           '-' word {
               [$item[2],'NOT'];
           }
       word:
           "'" term(s) "'" {
             &Apache::lonsearchcat::concat(\@item);
           }
         | '"' term(s) '"' {
             &Apache::lonsearchcat::concat(\@item);
           }
         | term {
               $item[1];
           }
       term:
           /[\w\Q:!@#$%^&*()+_=|{}<>,.;\\\/?\E]+/ {
               $item[1];
           }
   ENDGRAMMAR
       #
       # The end result of parsing the phrase with the grammar is an array
       # @::Phrases.
       # $phrase = "gene splicing" or cat -> "gene splicing","OR","cat"
       # $phrase = "genetic engineering" -dna ->
       #                      "genetic engineering","AND","NOT","dna"
       # $phrase = cat or dog -poodle -> "cat","OR","dog","AND","NOT","poodle"
       undef(@::Phrases);
       my $p = new Parse::RecDescent($grammar);
       if (! defined($p->searchphrase($phrase))) {
           &Apache::lonnet::logthis('lonsearchcat:unable to process:'.$phrase);
           return 'Unable to process phrase '.$phrase;
       }
       #
       # Go through the phrases and make sense of them.  
       # Apply modifiers NOT OR and AND to the phrases.
       my @NewPhrases;
       while(@::Phrases) {
           my $phrase = shift(@::Phrases);
           # &Apache::lonnet::logthis('phrase = '.$phrase);
           my $phrasedata;
           if ($phrase =~ /^(NOT|OR|AND)$/) {
               if ($phrase eq 'OR') {
                   $phrasedata->{'or'}++;
                   if (! @::Phrases) { $phrasedata = undef; last; }
                   $phrase = shift(@::Phrases);
               } elsif ($phrase eq 'AND') {
                   $phrasedata->{'and'}++;
                   if (! @::Phrases) { $phrasedata = undef; last; }
                   $phrase = shift(@::Phrases);
               }
               if ($phrase eq 'NOT') {
                   $phrasedata->{'negate'}++;
                   if (! @::Phrases) { $phrasedata = undef; last; }
                   $phrase = shift(@::Phrases);
               }
           }
           $phrasedata->{'phrase'} = $phrase;
           if ($related) {
               my @NewWords;
               (undef,@NewWords) = &related_version($phrasedata->{'phrase'});
               $phrasedata->{'related_words'} = \@NewWords;
           }
           push(@NewPhrases,$phrasedata);
       }
       #
       # Actually build the sql query from the phrases
       my $SQLQuery;
       foreach my $phrase (@NewPhrases) {
           my $query;
           if ($phrase->{'negate'}) {
               $query .= $field.' NOT LIKE "%'.$phrase->{'phrase'}.'%"';
           } else {
               $query .= $field.' LIKE "%'.$phrase->{'phrase'}.'%"';
           }
           foreach my $related (@{$phrase->{'related_words'}}) {
               if ($phrase->{'negate'}) {
                   $query .= ' AND '.$field.' NOT LIKE "%'.$related.'%"';
               } else {
                   $query .= ' OR '.$field.' LIKE "%'.$related.'%"';
               }
           }
           if ($SQLQuery) {
               if ($phrase->{'or'}) {
                   $SQLQuery .= ' OR ('.$query.')';
               } else {
                   $SQLQuery .= ' AND ('.$query.')';
               }
           } else {
               $SQLQuery = '('.$query.')';
           }
       }
       #
       # &Apache::lonnet::logthis("SQLQuery = $SQLQuery");
       #
       return undef,$SQLQuery;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =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 1228  Note: Using this twice on a string is pr Line 1814  Note: Using this twice on a string is pr
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub related_version {  sub related_version {
     my $search_string = shift;      my ($word) = @_;
     my $result = $search_string;      return (undef) if (lc($word) =~ /\b(or|and|not)\b/);
     my %New_Words = ();      my @Words = &Apache::loncommon::get_related_words($word);
     while ($search_string =~ /(\w+)/cg) {      # Only use 4 related words
         my $word = $1;      @Words = ($#Words>4? @Words[0..4] : @Words);
         next if (lc($word) =~ /\b(or|and|not)\b/);      my $result = join " OR ", ($word,@Words);
         my @Words = &Apache::loncommon::get_related_words($word);      return $result,sort(@Words);
         @Words = ($#Words>4? @Words[0..4] : @Words);  
         foreach (@Words) { $New_Words{$_}++;}  
         my $replacement = join " OR ", ($word,@Words);  
         $result =~ s/(\b)$word(\b)/$1($replacement)$2/g;  
     }  
     return $result,sort(keys(%New_Words));  
 }  }
   
 ######################################################################  
 ######################################################################  
   
 =pod   
   
 =item &build_SQL_query()   
   
 Builds a SQL query string from a logical expression with AND/OR keywords  
 using Text::Query and &recursive_SQL_query_builder()  
   
 =cut  
   
 ######################################################################  
 ######################################################################  
 sub build_SQL_query {  
     my ($field_name,$logic_statement)=@_;  
     my $q=new Text::Query('abc',  
   -parse => 'Text::Query::ParseAdvanced',  
   -build => 'Text::Query::Build');  
     $q->prepare($logic_statement);  
     my $matchexp=${$q}{'matchexp'}; chomp $matchexp;  
     my $sql_query=&recursive_SQL_query_build($field_name,$matchexp);  
     return $sql_query;  
 }  
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 1301  sub build_custommetadata_query { Line 1857  sub build_custommetadata_query {
     return $matchexp;      return $matchexp;
 }  }
   
 ######################################################################  
 ######################################################################  
   
 =pod   
   
 =item &recursive_SQL_query_build()   
   
 Recursively constructs an SQL query.  Takes as input $dkey and $pattern.  
   
 =cut  
   
 ######################################################################  
 ######################################################################  
 sub recursive_SQL_query_build {  
     my ($dkey,$pattern)=@_;  
     my @matches=($pattern=~/(\[[^\]|\[]*\])/g);  
     return $pattern unless @matches;  
     foreach my $match (@matches) {  
         $match=~/\[ (\w+)\s(.*) \]/;  
         my ($key,$value)=($1,$2);  
         my $replacement='';  
         if ($key eq 'literal') {  
             $replacement="($dkey LIKE \"\%$value\%\")";  
         } elsif (lc($key) eq 'not') {  
             $value=~s/LIKE/NOT LIKE/;  
 #          $replacement="($dkey not like $value)";  
             $replacement="$value";  
         } elsif ($key eq 'and') {  
             $value=~/(.*[\"|\)]) ([|\(|\^].*)/;  
             $replacement="($1 AND $2)";  
  } elsif ($key eq 'or') {  
             $value=~/(.*[\"|\)]) ([|\(|\^].*)/;  
             $replacement="($1 OR $2)";  
  }  
  substr($pattern,  
                index($pattern,$match),  
                length($match),  
                $replacement);  
     }  
     &recursive_SQL_query_build($dkey,$pattern);  
 }  
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 1358  Also reports errors (check for /^Incorre Line 1873  Also reports errors (check for /^Incorre
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub build_date_queries {  sub build_date_queries {
     my ($cmonth1,$cday1,$cyear1,$cmonth2,$cday2,$cyear2,      my ($cafter,$cbefore,$mafter,$mbefore) = @_;
  $lmonth1,$lday1,$lyear1,$lmonth2,$lday2,$lyear2)=@_;      my ($result,$error,$pretty_string);
     my @queries;      #
     if ($cmonth1 or $cday1 or $cyear1 or $cmonth2 or $cday2 or $cyear2) {      # Verify the input
  unless ($cmonth1 and $cday1 and $cyear1 and      if (! defined($cafter) && ! defined($cbefore) &&
  $cmonth2 and $cday2 and $cyear2) {          ! defined($mafter) && ! defined($mbefore)) {
     return "Incorrect entry for the creation date.  You must specify ".          # This is an okay situation, so return undef for the error
    "a starting month, day, and year and an ending month, ".          return (undef,undef,undef);
    "day, and year.";      }
  }      if ((defined($cafter)  && ! defined($cbefore)) ||
  my $cnumeric1=sprintf("%d%2d%2d",$cyear1,$cmonth1,$cday1);          (defined($cbefore) && ! defined($cafter))) {
  $cnumeric1+=0;          # This is bad, so let them know
  my $cnumeric2=sprintf("%d%2d%2d",$cyear2,$cmonth2,$cday2);          $error = &mt('Incorrect entry for the creation date.  '.
  $cnumeric2+=0;                      'You must specify both the beginning and ending dates.');
  if ($cnumeric1>$cnumeric2) {      }
     return "Incorrect entry for the creation date.  The starting ".      if (! defined($error) && 
    "date must occur before the ending date.";          ((defined($mafter)  && ! defined($mbefore)) ||
  }          (defined($mbefore) && ! defined($mafter)))) {
  my $cquery="(creationdate BETWEEN '$cyear1-$cmonth1-$cday1' AND '".          # This is also bad, so let them know
            "$cyear2-$cmonth2-$cday2 23:59:59')";          $error = &mt('Incorrect entry for the last revision date.  '.
  push @queries,$cquery;                       'You must specify both the beginning and ending dates.');
     }  
     if ($lmonth1 or $lday1 or $lyear1 or $lmonth2 or $lday2 or $lyear2) {  
  unless ($lmonth1 and $lday1 and $lyear1 and  
  $lmonth2 and $lday2 and $lyear2) {  
     return "Incorrect entry for the last revision date.  You must ".  
    "specify a starting month, day, and year and an ending ".  
    "month, day, and year.";  
  }  
  my $lnumeric1=sprintf("%d%2d%2d",$lyear1,$lmonth1,$lday1);  
  $lnumeric1+=0;  
  my $lnumeric2=sprintf("%d%2d%2d",$lyear2,$lmonth2,$lday2);  
  $lnumeric2+=0;  
  if ($lnumeric1>$lnumeric2) {  
     return "Incorrect entry for the last revision date.  The ".  
    "starting date must occur before the ending date.";  
  }  
  my $lquery="(lastrevisiondate BETWEEN '$lyear1-$lmonth1-$lday1' AND '".  
            "$lyear2-$lmonth2-$lday2 23:59:59')";  
  push @queries,$lquery;  
     }      }
     if (@queries) {      if (! defined($error)) {
  return join(" AND ",@queries);          #
           # Build the queries
           my @queries;
           if (defined($cbefore) && defined($cafter)) {
               my (undef,undef,undef,$caday,$camon,$cayear) = localtime($cafter);
               my (undef,undef,undef,$cbday,$cbmon,$cbyear) = localtime($cbefore);
               # Correct for year being relative to 1900
               $cayear+=1900; $cbyear+=1900;
               my $cquery=
                   '(creationdate BETWEEN '.
                   "'".$cayear.'-'.$camon.'-'.$caday."'".
                   ' AND '.
                   "'".$cbyear.'-'.$cbmon.'-'.$cbday." 23:59:59')";
               $pretty_string .= '<br />' if (defined($pretty_string));
               $pretty_string .= 
                   &mt('created between [_1] and [_2]',
                       &Apache::lonlocal::locallocaltime($cafter),
                       &Apache::lonlocal::locallocaltime($cbefore+24*60*60-1));
               push(@queries,$cquery);
               $pretty_string =~ s/ 00:00:00//g;
           }
           if (defined($mbefore) && defined($mafter)) {
               my (undef,undef,undef,$maday,$mamon,$mayear) = localtime($mafter);
               my (undef,undef,undef,$mbday,$mbmon,$mbyear) = localtime($mbefore);
               # Correct for year being relative to 1900
               $mayear+=1900; $mbyear+=1900;
               my $mquery=
                   '(lastrevisiondate BETWEEN '.
                   "'".$mayear.'-'.$mamon.'-'.$maday."'".
                   ' AND '.
                   "'".$mbyear.'-'.$mbmon.'-'.$mbday." 23:59:59')";
               push(@queries,$mquery);
               $pretty_string .= '<br />' if (defined($pretty_string));
               $pretty_string .= 
                   &mt('last revised between [_1] and [_2]',
                       &Apache::lonlocal::locallocaltime($mafter),
                       &Apache::lonlocal::locallocaltime($mbefore+24*60*60-1));
               $pretty_string =~ s/ 00:00:00//g;
           }
           if (@queries) {
               $result .= join(" AND ",@queries);
           }
     }      }
     return '';      return ($result,$error,$pretty_string);
 }  }
   
 ######################################################################  ######################################################################
Line 1412  sub build_date_queries { Line 1949  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 1435  sub copyright_check { Line 1977  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 1497  sub ensure_db_and_table { Line 2038  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 1505  sub ensure_db_and_table { Line 2049  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 $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1).
           &Apache::lonhtmlcommon::breadcrumbs
           (undef,'Searching','Searching',undef,undef,
            $ENV{'form.catalogmode'} ne 'groupsearch');
   
     ##      ##
     my %SortableFields=&Apache::lonlocal::texthash(       my %SortableFields=&Apache::lonlocal::texthash( 
          id        => 'Default',           id        => 'Default',
Line 1598  the following format: Line 2146  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 => 'language',  type=>'TEXT'},  
       { name => 'owner',     type=>'TEXT'},  
       { name => 'copyright', type=>'TEXT'},  
       { name => 'dependencies',     type=>'TEXT'},  
       { name => 'modifyinguser', type=>'TEXT'},  
       { name => 'authorspace', type=>'TEXT'},  
       { name => 'lowestgradelevel',  type=>'INT'},  
       { name => 'highestgradelevel', type=>'INT'},  
       { name => 'standards', type=>'TEXT'},  
       { name => 'count',     type=>'INT'},  
       { name => 'course', type=>'INT'},  
       { name => 'course_list',  type=>'TEXT'},  
       { name => 'goto', type=>'INT'},  
       { name => 'goto_list',  type=>'TEXT'},  
       { name => 'comefrom', type=>'INT'},  
       { name => 'comefrom_list',  type=>'TEXT'},  
       { name => 'sequsage', type=>'INT'},  
       { name => 'sequsage_list',  type=>'TEXT'},  
       { name => 'stdno', type=>'INT'},  
       { name => 'stdno_list',  type=>'TEXT'},  
       { name => 'avetries', type=>'FLOAT'},  
       { name => 'avetries_list',  type=>'TEXT'},  
       { name => 'difficulty', type=>'FLOAT'},  
       { name => 'difficulty_list',  type=>'TEXT'},  
       { name => 'clear',  type=>'FLOAT'},  
       { name => 'technical',  type=>'FLOAT'},  
       { name => 'correct',  type=>'FLOAT'},  
       { name => 'helpful',  type=>'FLOAT'},  
       { name => 'depth',  type=>'FLOAT'},  
       { 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 1672  Returns: the identifier of the table on Line 2170  Returns: the identifier of the table on
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   sub set_up_table_structure {
       my ($datatypes,$fullindicies) = 
           &LONCAPA::lonmetadata::describe_metadata_storage();
       # Copy the table description before modifying it...
       @Datatypes = @{$datatypes};
       unshift(@Datatypes,{name => 'id',  
           type => 'MEDIUMINT',
           restrictions => 'UNSIGNED NOT NULL',
           primary_key  => 'yes',
           auto_inc     => 'yes' });
       @Fullindicies = @{$fullindicies};
       return;
   }
   
 sub create_results_table {  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 1729  sub update_status { Line 2242  sub update_status {
     $r->rflush();      $r->rflush();
 }  }
   
   {
       my $max_time  = 40;  # seconds for the search to complete
       my $start_time = 0;
       my $last_time = 0;
   
   sub reset_timing {
       $start_time = 0;
       $last_time = 0;
   }
   
   sub time_left {
       if ($start_time == 0) {
           $start_time = time;
       }
       my $time_left = $max_time - (time - $start_time);
       $time_left = 0 if ($time_left < 0);
       return $time_left;
   }
   
 sub update_seconds {  sub update_seconds {
     my ($r,$text) = @_;      my ($r) = @_;
     $text =~ s/\'/\\\'/g;      my $time = &time_left();
     $r->print      if (($last_time-$time) > 0) {
         ("<script>document.statusform.seconds.value = ' $text'</script>\n");          $r->print("<script>".
     $r->rflush();                    "document.statusform.seconds.value = '$time'".
                     "</script>\n");
           $r->rflush();
       }
       $last_time = $time;
   }
   
 }  }
   
 ######################################################################  ######################################################################
Line 1742  sub update_seconds { Line 2280  sub update_seconds {
   
 =pod  =pod
   
 =item &revise_button  =item &revise_button()
   
 Inputs: None  Inputs: None
   
Line 1769  sub revise_button { Line 2307  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 1778  sub revise_button { Line 2319  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 $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);
       $bodytag.=&Apache::lonhtmlcommon::breadcrumbs
           (undef,'Searching','Searching',undef,undef,
            $ENV{'form.catalogmode'} ne 'groupsearch');
     my $connection = $r->connection;      my $connection = $r->connection;
     #      #
     # Timing variables  
     #  
     my $starttime = time;  
     my $max_time  = 30;  # seconds for the search to complete  
     #  
     # Print run_search header      # Print run_search header
     #      #
     $r->print(<<END);      $r->print(<<END);
Line 1794  $bodytag Line 2333  $bodytag
 <form name="statusform" action="" method="post">  <form name="statusform" action="" method="post">
 <input type="hidden" name="Queue" value="" />  <input type="hidden" name="Queue" value="" />
 END  END
     # Check to see if $pretty_string has more than one carriage return.      # Remove leading and trailing <br />
     # Assume \n s are following <br /> s and truncate the value.      $pretty_string =~ s:^\s*<br />::i;
     # (there is probably a better way)...      $pretty_string =~ s:(<br />)*\s*$::im;
     my @Lines = split /<br \/>/,$pretty_string;      my @Lines = split("<br />",$pretty_string);
       # I keep getting blank items at the end of the list, hence the following:
       while ($Lines[-1] =~ /^\s*$/ && @Lines) {
           pop(@Lines);
       }
     if (@Lines > 2) {      if (@Lines > 2) {
         $pretty_string = join '<br \>',(@Lines[0..2],'....<br />');          $pretty_string = join '<br />',(@Lines[0..2],'....<br />');
     }      }
     $r->print(&mt("Search").": ".$pretty_string);      $r->print(&mt("Search: [_1]",$pretty_string));
     $r->rflush();      $r->rflush();
     #      #
     # Determine the servers we need to contact.      # Determine the servers we need to contact.
     #  
     my @Servers_to_contact;      my @Servers_to_contact;
     if (defined($serverlist)) {      if (defined($serverlist)) {
         if (ref($serverlist) eq 'ARRAY') {          if (ref($serverlist) eq 'ARRAY') {
Line 1817  END Line 2359  END
         @Servers_to_contact = sort(keys(%Apache::lonnet::libserv));          @Servers_to_contact = sort(keys(%Apache::lonnet::libserv));
     }      }
     my %Server_status;      my %Server_status;
       #
       # Check on the mysql table we will use to store results.
     my $table =$ENV{'form.table'};      my $table =$ENV{'form.table'};
     if (! defined($table) || $table eq '' || $table =~ /\D/ ) {      if (! defined($table) || $table eq '' || $table =~ /\D/ ) {
         $r->print("Unable to determine table id to store search results in.".          $r->print("Unable to determine table id to store search results in.".
Line 1833  END Line 2377  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 1857  END Line 2405  END
 </form>  </form>
 END  END
     $r->rflush();      $r->rflush();
     my $time_remaining = $max_time - (time - $starttime) ;      &reset_timing();
     my $last_time = $time_remaining;      &update_seconds($r);
     &update_seconds($r,$time_remaining);      &update_status($r,&mt('contacting [_1]',$Servers_to_contact[0]));
     &update_status($r,'contacting '.$Servers_to_contact[0]);      while (&time_left() &&
     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.          &update_seconds($r);
           #
           # Send out a search request
         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);              &update_status($r,&mt('contacting [_1]',$server));
             my $reply=&Apache::lonnet::metadata_query($query,$customquery,              my $reply=&Apache::lonnet::metadata_query($query,$customquery,
                                                       $customshow,[$server]);                                                        $customshow,[$server]);
             ($server) = keys(%$reply);              ($server) = keys(%$reply);
Line 1879  END Line 2428  END
             # left to contact.                # left to contact.  
             if (scalar (keys(%Server_status))) {              if (scalar (keys(%Server_status))) {
                 &update_status($r,                  &update_status($r,
                        &mt('waiting on').' '.(join(' ',keys(%Server_status))));                         &mt('waiting on [_1]',join(' ',keys(%Server_status))));
             }              }
             sleep(1)              sleep(1)
         }          }
         #          #
         #  
         # 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)) {          foreach my $server (keys(%Server_status)) {
             last if ($connection->aborted());              last if ($connection->aborted());
               &update_seconds($r);
               my $status = $Server_status{$server};
             if ($status eq 'con_lost') {              if ($status eq 'con_lost') {
                 delete ($Server_status{$server});                  delete ($Server_status{$server});
                 next;                  next;
Line 1896  END Line 2446  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,&mt('Receiving results from').' '.$server);                  &update_status($r,&mt('Receiving results from [_1]',$server));
                 next;                  next;
             }              }
             last if ($connection->aborted());              last if ($connection->aborted());
             if (-e "$datafile.end") {              if (-e "$datafile.end") {
                 &update_status($r,&mt('Reading results from').' '.$server);                  &update_status($r,&mt('Reading results from [_1]',$server));
                 if (-z "$datafile") {                  if (-z "$datafile") {
                     delete($Server_status{$server});                      delete($Server_status{$server});
                     next;                      next;
Line 1916  END Line 2466  END
                 # Read in the whole file.                  # Read in the whole file.
                 while (my $result = <$fh>) {                  while (my $result = <$fh>) {
                     last if ($connection->aborted());                      last if ($connection->aborted());
                     # handle custom fields?  Someday we will!                      #
                       # Records are stored one per line
                     chomp($result);                      chomp($result);
                     next unless $result;                      next if (! $result);
                       #
                     # Parse the result.                      # Parse the result.
                     my %Fields = &parse_raw_result($result,$server);                      my %Fields = &parse_raw_result($result,$server);
                     $Fields{'hostname'} = $server;                      $Fields{'hostname'} = $server;
                       #
                       # Skip based on copyright
                     next if (! &copyright_check(\%Fields));                      next if (! &copyright_check(\%Fields));
                       #
                     # Store the result in the mysql database                      # Store the result in the mysql database
                     my $result = &Apache::lonmysql::store_row($table,\%Fields);                      my $result = &Apache::lonmysql::store_row($table,\%Fields);
                     if (! defined($result)) {                      if (! defined($result)) {
                         $r->print(&Apache::lonmysql::get_error());                          $r->print(&Apache::lonmysql::get_error());
                     }                      }
                     # $r->print(&Apache::lonmysql::get_debug());                      #
                     $hitcountsum ++;                      $hitcountsum ++;
                     $time_remaining = $max_time - (time - $starttime) ;                      &update_seconds($r);
                     if ($last_time - $time_remaining > 0) {  
                         &update_seconds($r,$time_remaining);  
                         $last_time = $time_remaining;  
                     }  
                     if ($hitcountsum % 50 == 0) {                      if ($hitcountsum % 50 == 0) {
                         &update_count_status($r,$hitcountsum);                          &update_count_status($r,$hitcountsum);
                     }                      }
                 } # End of foreach (@results)                  }
                 $fh->close();                  $fh->close();
                 # $server is only deleted if the results file has been                   # $server is only deleted if the results file has been 
                 # found and (successfully) opened.  This may be a bad idea.                  # found and (successfully) opened.  This may be a bad idea.
Line 1948  END Line 2499  END
             &update_count_status($r,$hitcountsum);              &update_count_status($r,$hitcountsum);
         }          }
         last if ($connection->aborted());          last if ($connection->aborted());
         # Finished looping through the servers          &update_seconds($r);
         $starttime = time if (@Servers_to_contact);  
         $time_remaining = $max_time - (time - $starttime) ;  
         if ($last_time - $time_remaining > 0) {  
             $last_time = $time_remaining;  
             &update_seconds($r,$time_remaining);  
         }  
     }      }
     &update_status($r,&mt('Search Complete').$server);      &update_status($r,&mt('Search Complete [_1]',$server));
     &update_seconds($r,0);      &update_seconds($r);
     &Apache::lonmysql::disconnect_from_db();      #
       &Apache::lonmysql::disconnect_from_db(); # This is unneccessary
       #
     # 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, so let the client know the top frame needs to be
       # loaded from /adm/searchcat
     $r->print("</body></html>");      $r->print("</body></html>");
     if ($ENV{'form.catalogmode'} ne 'groupsearch') {  #    if ($ENV{'form.catalogmode'} ne 'groupsearch') {
         $r->print("<script>".          $r->print("<script>".
                       "window.location='/adm/searchcat?".                        "window.location='/adm/searchcat?".
                       "phase=sort&".                        "phase=sort&".
                       "persistent_db_id=$ENV{'form.persistent_db_id'}';".                        "persistent_db_id=$ENV{'form.persistent_db_id'}';".
                   "</script>");                    "</script>");
     }  #    }
     return;      return;
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =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 1985  END Line 2536  END
 sub prev_next_buttons {  sub prev_next_buttons {
     my ($current_min,$show,$total,$parms) = @_;      my ($current_min,$show,$total,$parms) = @_;
     return '' if ($show eq 'all'); # No links if you get them all at once.      return '' if ($show eq 'all'); # No links if you get them all at once.
     my $links;      #
     ##      # Create buttons
     ## Prev      my $buttons = '<input type="submit" name="prev" value="'.&mt('Prev').'" ';
     my $prev_min = $current_min - $show;      $buttons .= '/>';
     $prev_min = 1 if $prev_min < 1;      $buttons .= '&nbsp;'x3;
     if ($prev_min < $current_min) {      $buttons .= '<input type="submit" name="reload" '.
         $links .= qq{          'value="'.&mt('Reload').'" />';
 <a href="/adm/searchcat?$parms&start=$prev_min&show=$show">prev</a>      $buttons .= '&nbsp;'x3;
 };          $buttons .= '<input type="submit" name="next" value="'.&mt('Next').'" ';
     } else {      $buttons .= '/>';
         $links .= 'prev';      return $buttons;
     }  
     ##  
     ## Pages.... Someday.  
     ##  
     $links .= qq{ &nbsp;  
 <a href="/adm/searchcat?$parms&start=$current_min&$show=$show">reload</a>  
 };  
     ##  
     ## Next  
     my $next_min = $current_min + $show;  
     $next_min = $current_min if ($next_min > $total);  
     if ($next_min != $current_min) {  
         $links .= qq{ &nbsp;  
 <a href="/adm/searchcat?$parms&start=$next_min&show=$show">next</a>  
 };      
     } else {  
         $links .= '&nbsp;next';  
     }  
     return $links;  
 }  }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
 =pod  =pod
   
 =item &display_results  =item &display_results()
   
   Prints the results out for selection and perusal.
   
 =cut  =cut
   
Line 2049  sub display_results { Line 2584  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 2061  sub display_results { Line 2595  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 2077  sub display_results { Line 2609  sub display_results {
     }      }
     ##      ##
     ## Determine how many results we need to get      ## Determine how many results we need to get
     ##      $ENV{'form.start'} = 1  if (! exists($ENV{'form.start'}));
     $ENV{'form.start'} = 1      if (! exists($ENV{'form.start'}));      $ENV{'form.show'}  = 20 if (! exists($ENV{'form.show'}));
     $ENV{'form.show'}  = 'all'  if (! exists($ENV{'form.show'}));      if (exists($ENV{'form.prev'})) {
           $ENV{'form.start'} -= $ENV{'form.show'};
       } elsif (exists($ENV{'form.next'})) {
           $ENV{'form.start'} += $ENV{'form.show'};
       }
       $ENV{'form.start'} = 1 if ($ENV{'form.start'}<1);
       $ENV{'form.start'} = $total_results if ($ENV{'form.start'}>$total_results);
     my $min = $ENV{'form.start'};      my $min = $ENV{'form.start'};
     my $max;      my $max;
     if ($ENV{'form.show'} eq 'all') {      if ($ENV{'form.show'} eq 'all') {
Line 2089  sub display_results { Line 2627  sub display_results {
         $max = $total_results if ($max > $total_results);          $max = $total_results if ($max > $total_results);
     }      }
     ##      ##
     ## Output links (if necessary) for 'prev' and 'next' pages.      ## Output form elements
       $r->print(&hidden_field('table').
                 &hidden_field('phase').
                 &hidden_field('persistent_db_id').
                 &hidden_field('start')
                 );
       #
       # Build sorting selector
       my @field_order =  ('default',
                           'title',
                           'author',
                           'subject',
                           'url',
                           'keywords',
                           'version',
                           'language',
                           'creationdate'=>,
                           'lastrevisiondate',
                           'owner',
                           'copyright',
                           'authorspace',
                           'lowestgradeleve',
                           'highestgradelevel',
                           'standards',
                           'count',
                           'stdno',
                           'avetries',
                           'difficulty',
                           'disc',
                           'clear',
                           'technical',
                           'correct',
                           'helpful',
                           'depth',
                           );                                              
       my %sort_fields = ('default'     => 'Default',
                          'title'       => 'Title',
                          'author'      => 'Author',
                          'subject'     => 'Subject',
                          'url'         => 'URL',
                          'keywords'    => 'Keywords',
                          'version'     => 'Version',
                          'language'    => 'Language',
                          'creationdate'=> 'Creation Date',
                          'lastrevisiondate' => 'Last Revision Date',
                          'owner'       => 'Owner',
                          'copyright'   => 'Copyright',
                          'authorspace' => 'Authorspace',
                          'lowestgradeleve' => 'Lowest Grade Level',
                          'highestgradelevel' => 'Highest Grade Level',
                          'standards'   => 'Standards',
                          'count'       => 'Number of Accesses',
                          'stdno'       => 'Students Attempting',
                          'avetries'    => 'Average Number of Tries',
                          'difficulty'  => 'Mean Degree of Difficulty',
                          'disc'        => 'Mean Degree of Discrimination',
                          'clear'       => 'Evaluation: Clear',
                          'technical'   => 'Evaluation: Technically Correct',
                          'correct'     => 'Evaluation: Material is Correct',
                          'helpful'     => 'Evaluation: Material is Helpful',
                          'depth'       => 'Evaluation: Material has Depth',
                          'select_form_order' => \@field_order,
                          );
   
       my $sortform = &mt('Sort by [_1]',
                          &Apache::loncommon::select_form($ENV{'form.sortfield'},
                                                         'sortfield',
                                                         %sort_fields));
     ##      ##
       ## Output links (if necessary) for 'prev' and 'next' pages.
     $r->print      $r->print
         ('<center>'.          ('<table width="100%"><tr><td width="25%" align="right">'.
          &prev_next_buttons($min,$ENV{'form.show'},$total_results,           $sortform.
                             "table=".$ENV{'form.table'}.           '</td><td width="25%" align="right">'.
                             "&phase=results".           &prev_next_buttons($min,$ENV{'form.show'},$total_results).
                             "&persistent_db_id=".$ENV{'form.persistent_db_id'})           '</td><td align="right">'.
          ."</center>\n"           &viewoptions().'</td></tr></table>'
          );           );
     if ($total_results == 0) {      if ($total_results == 0) {
         $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="1">'.          $r->print('<meta HTTP-EQUIV="Refresh" CONTENT="2">'.
                   '<h3>'.&mt('There are currently no results').'.</h3>'.                    '<h3>'.&mt('There are currently no results').'.</h3>'.
                   "</form></body></html>");                    "</form></body></html>");
         return;          return;
     } else {      } else {
         $r->print          $r->print('<center>'.
             ("<center>Results $min to $max out of $total_results</center>\n");                    mt('Results [_1] to [_2] out of [_3]',
                        $min,$max,$total_results).
                     "</center>\n");
     }      }
     ##      ##
     ## Get results from MySQL table      ## Get results from MySQL table
     ##      my $sort_command  = 'id>='.$min.' AND id<='.$max;
     my @Results = &Apache::lonmysql::get_rows($table,      if ($ENV{'form.sortfield'} ne 'default' && 
                                               'id>='.$min.' AND id<='.$max);          exists($sort_fields{$ENV{'form.sortfield'}})) {
           $sort_command = $ENV{'form.sortfield'}.' IS NOT NULL '.
               'ORDER BY '.$ENV{'form.sortfield'}.
               '  LIMIT '.($min-1).','.($max-$min);
       }
       my @Results = &Apache::lonmysql::get_rows($table,$sort_command);
     ##      ##
     ## 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 2123  sub display_results { Line 2735  sub display_results {
         }          }
         my %Fields = %{&parse_row(@$row)};          my %Fields = %{&parse_row(@$row)};
         my $output="<p>\n";          my $output="<p>\n";
           if (! defined($Fields{'title'}) || $Fields{'title'} eq '') {
               $Fields{'title'} = 'Untitled';
           }
         my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'},          my $prefix=&catalogmode_output($Fields{'title'},$Fields{'url'},
                                        $Fields{'id'},$checkbox_num++);                                         $Fields{'id'},$checkbox_num++);
         # Render the result into html          # Render the result into html
Line 2193  END Line 2808  END
   
 =pod  =pod
   
 =item &parse_row  =item &parse_row()
   
 Parse a row returned from the database.  Parse a row returned from the database.
   
Line 2204  Parse a row returned from the database. Line 2819  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]);
     }      }
Line 2239  The 'title' field is set to "Untitled" i Line 2857  The 'title' field is set to "Untitled" i
 ###########################################################  ###########################################################
 sub parse_raw_result {  sub parse_raw_result {
     my ($result,$hostname) = @_;      my ($result,$hostname) = @_;
 # conclude from self to others regarding fields      # conclude from self to others regarding fields
     my %Fields=&Apache::lonmeta::metadata_col_to_hash(      my %Fields=&LONCAPA::lonmetadata::metadata_col_to_hash
  map {          (map {
  &Apache::lonnet::unescape($_);              &Apache::lonnet::unescape($_);
  } (split(/\,/,$result))          } (split(/\,/,$result)) );
       );  
     return %Fields;      return %Fields;
 }  }
   
Line 2294  sub handle_custom_fields { Line 2911  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 2433  SCRIPT Line 3050  SCRIPT
     $result.=<<END;      $result.=<<END;
 </head>  </head>
 $bodytag  $bodytag
 <form name="results" method="post" action="" >  <form name="results" method="post" action="/adm/searchcat" >
 <input type="hidden" name="Queue" value="" />  <input type="hidden" name="Queue" value="" />
 $importbutton  $importbutton
 END  END
Line 2491  ENDFRAMES Line 3108  ENDFRAMES
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
   
   sub has_stat_data {
       my ($values) = @_;
       if ( (defined($values->{'count'})      && $values->{'count'}      ne '') ||
            (defined($values->{'stdno'})      && $values->{'stdno'}      ne '') ||
            (defined($values->{'disc'})       && $values->{'disc'}       ne '') ||
            (defined($values->{'avetries'})   && $values->{'avetries'}   ne '') ||
            (defined($values->{'difficulty'}) && $values->{'difficulty'} ne '')) {
           return 1;
       }
       return 0;
   }
   
   sub statfields {
       return ('count','stdno','disc','avetries','difficulty');
   }
   
   sub has_eval_data {
       my ($values) = @_;
       if ( (defined($values->{'clear'})     && $values->{'clear'}     ne '') ||
            (defined($values->{'technical'}) && $values->{'technical'} ne '') ||
            (defined($values->{'correct'})   && $values->{'correct'}   ne '') ||
            (defined($values->{'helpful'})   && $values->{'helpful'}   ne '') ||
            (defined($values->{'depth'})     && $values->{'depth'}     ne '')) {
           return 1;
       }
       return 0;
   }
   
   sub evalfields { 
       return ('clear','technical','correct','helpful','depth');
   }
   
   ######################################################################
   ######################################################################
   
 =pod   =pod 
   
 =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 2511  extra custom metadata to show. Line 3164  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;
     my $result=<<END;      $result .= '<b>'.$prefix.
 <b>$prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}"           '<img src="'.&Apache::loncommon::icon($values{'url'}).' " />'.'&nbsp;'.
     target='search_preview'>$values{'title'}</a></b>          '<a href="http://'.$ENV{'HTTP_HOST'}.$values{'url'}.'" '.
 <p>          'target="search_preview">'.$values{'title'}."</a></b>\n";
 <b>$values{'author'}</b>, <i>$values{'owner'}</i><br />      $result .= "<p>\n";
       $result .= '<b>'.$values{'author'}.'</b>,'.
 <b>Subject:       </b> $values{'subject'}<br />          ' <i>'.$values{'owner'}.'</i><br />';
 <b>Keyword(s):    </b> $values{'keywords'}<br />      foreach my $field 
 <b>Notes:         </b> $values{'notes'}<br />          (
 <b>MIME Type:     </b> $values{'mimetag'}<br />           { name=>'url',
 <b>Language:      </b> $values{'language'}<br />             translate => '<b>URL:</b>&nbsp;[_1]',
 <b>Copyright/Distribution:</b> $values{'copyrighttag'}<br />             special => 'url link',},
 </p>           { name=>'subject',
 $values{'extrashow'}             translate => '<b>Subject:</b>&nbsp;[_1]',},
 <p>           { name=>'keywords',
 $values{'shortabstract'}             translate => '<b>Keywords:</b>&nbsp;[_1]',},
 </p>           { name=>'notes',
 <hr align='left' width='200' noshade />             translate => '<b>Notes:</b>&nbsp;[_1]',},
 END           { name=>'mimetag',
              translate => '<b>MIME Type:</b>&nbsp;[_1]',},
            { name=>'standards',
              translate => '<b>Standards:</b>[_1]',},
            { name=>'copyrighttag',
              translate => '<b>Copyright/Distribution:</b>&nbsp;[_1]',},
            { name=>'count',
              format => "%d",
              translate => '<b>Access Count:</b>&nbsp;[_1]',},
            { name=>'stdno',
              format => "%d",
              translate => '<b>Number of Students:</b>&nbsp;[_1]',},
            { name=>'avetries',
              format => "%.2f",
              translate => '<b>Average Tries:</b>&nbsp;[_1]',},
            { name=>'disc',
              format => "%.2f",
              translate => '<b>Degree of Discrimination:</b>&nbsp;[_1]',},
            { name=>'difficulty',
              format => "%.2f",
              translate => '<b>Degree of Difficulty:</b>&nbsp;[_1]',},
            { name=>'clear',
              format => "%.2f",
              translate => '<b>Clear:</b>&nbsp;[_1]',},
            { name=>'depth',
              format => "%.2f",
              translate => '<b>Depth:</b>&nbsp;[_1]',},
            { name=>'helpful',
              format => "%.2f",
              translate => '<b>Helpful:</b>&nbsp;[_1]',},
            { name=>'correct',
              format => "%.2f",
              translate => '<b>Correct:</b>&nbsp;[_1]',},
            { name=>'technical',
              format => "%.2f",
              translate => '<b>Technical:</b>&nbsp;[_1]',},
            { name=>'comefrom_list',
              type => 'list',
              translate => 'Resources that lead up to this resource in maps',},
            { name=>'goto_list',
              type => 'list',
              translate => 'Resources that follow this resource in maps',},
            { name=>'sequsage_list',
              type => 'list',
              translate => 'Resources using or importing resource',},
            ) {
           next if (! exists($values{$field->{'name'}}) ||
                    $values{$field->{'name'}} eq '');
           if (exists($field->{'type'}) && $field->{'type'} eq 'list') {
               $result .= '<b>'.&mt($field->{'translate'}).'</b><ul>';
               foreach my $item (split(',',$values{$field->{'name'}})){
                   $result .= '<li>'.
                       '<a target="search_preview" '.
                       'href="/res/'.$item.'">'.$item.'</a></li>';
               }
               $result .= '</ul>';
           } elsif (exists($field->{'format'}) && $field->{'format'} ne ''){
               $result.= &mt($field->{'translate'},
                             sprintf($field->{'format'},
                                     $values{$field->{'name'}}))."<br />\n";
           } else {
               if ($field->{'special'} eq 'url link') {
                   $result.= 
                        &mt($field->{'translate'},
                            '<a href="'.$values{'url'}.'" '.
                            'target="search_preview">'.
                            $values{$field->{'name'}}.
                            '</a>');
               } else {
                   $result.= &mt($field->{'translate'},
                                 $values{$field->{'name'}});
               }
               $result .= "<br />\n";
           }
       }
       $result .= "</p>";
       if (exists($values{'extrashow'}) && $values{'extrashow'} ne '') {
           $result .= '<p>'.$values{'extrashow'}.'</p>';
       }
       if (exists($values{'shortabstract'}) && $values{'shortabstract'} ne '') {
           $result .= '<p>'.$values{'shortabstract'}.'</p>';
       }
       $result .= '<hr align="left" width="200" noshade />'."\n";
     return $result;      return $result;
 }  }
   
Line 2548  sub summary_view { Line 3283  sub summary_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $icon=&Apache::loncommon::icon($values{'url'});      my $icon=&Apache::loncommon::icon($values{'url'});
     my $result=<<END;      my $result=<<END;
 $prefix<img src="$icon" /><a href="http://$ENV{'HTTP_HOST'}$values{'url'}"   $prefix<img src="$icon" />&nbsp;
   <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 2573  END Line 3309  END
 ######################################################################  ######################################################################
 sub compact_view {  sub compact_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $icon=&Apache::loncommon::icon($values{'url'});      my $result = 
     my $result=<<END;          $prefix.'<img src="'.&Apache::loncommon::icon($values{'url'}).
 $prefix <img src="$icon" /> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"  target='search_preview'>          '">&nbsp;<a href="'.$values{'url'}.'" target="search_preview">'.
 $values{'title'}</a>          $values{'title'}.'</a>'.('&nbsp;'x2).
 <b>$values{'author'}</b><br />          '<b>'.$values{'author'}.'</b><br />';
 END  
     return $result;      return $result;
 }  }
   
Line 2597  END Line 3332  END
 sub fielded_format_view {  sub fielded_format_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
     my $icon=&Apache::loncommon::icon($values{'url'});      my $icon=&Apache::loncommon::icon($values{'url'});
       my %Translated = &Apache::lonmeta::fieldnames();
     my $result=<<END;      my $result=<<END;
 $prefix <img src="$icon" />  $prefix <img src="$icon" />
 <b>URL: </b> <a href="http://$ENV{'HTTP_HOST'}$values{'url'}"   <dl>
               target='search_preview'>$values{'url'}</a>  <dt>URL:</dt>
 <br />      <dd><a href="http://$ENV{'HTTP_HOST'}$values{'url'}" 
 <b>Title:</b> $values{'title'}<br />           target='search_preview'>$values{'url'}</a></dd>
 <b>Author(s):</b> $values{'author'}<br />  
 <b>Subject:</b> $values{'subject'}<br />  
 <b>Keyword(s):</b> $values{'keywords'}<br />  
 <b>Notes:</b> $values{'notes'}<br />  
 <b>MIME Type:</b> $values{'mimetag'}<br />  
 <b>Language:</b> $values{'language'}<br />  
 <b>Creation Date:</b> $values{'creationdate'}<br />  
 <b>Last Revision Date:</b> $values{'lastrevisiondate'}<br />  
 <b>Publisher/Owner:</b> $values{'owner'}<br />  
 <b>Copyright/Distribution:</b> $values{'copyrighttag'}<br />  
 <b>Repository Location:</b> $values{'hostname'}<br />  
 <b>Abstract:</b> $values{'shortabstract'}<br />  
 $values{'extrashow'}  
 </p>  
 <hr align='left' width='200' noshade />  
 END  END
       foreach my $field ('title','author','subject','keywords','notes',
                          'mimetag','language','creationdate','lastrevisiondate',
                          'owner','copyrighttag','hostname','abstract') {
           $result .= (' 'x4).'<dt>'.$Translated{$field}.'</dt>'."\n".
               (' 'x8).'<dd>'.$values{$field}.'</dd>'."\n";
       }
       if (&has_stat_data(\%values)) {
           foreach my $field (&statfields()) {
               $result .= (' 'x4).'<dt>'.$Translated{$field}.'</dt>'."\n".
                   (' 'x8).'<dd>'.$values{$field}.'</dd>'."\n";
           }
       }
       if (&has_eval_data(\%values)) {
           foreach my $field (&evalfields()) {
               $result .= (' 'x4).'<dt>'.$Translated{$field}.'</dt>'."\n".
                   (' 'x8).'<dd>'.$values{$field}.'</dd>'."\n";
           }
       }
       $result .= "</dl>\n";
       $result .= $values{'extrashow'};
       $result .= '<hr align="left" width="200" noshade />'."\n";
     return $result;      return $result;
 }  }
   
Line 2637  END Line 3379  END
 ######################################################################  ######################################################################
 sub xml_sgml_view {  sub xml_sgml_view {
     my ($prefix,%values) = @_;      my ($prefix,%values) = @_;
       my $xml = '<LonCapaResource>'."\n";
       # The usual suspects
       foreach my $field ('url','title','author','subject','keywords','notes') {
           $xml .= qq{<$field>$values{$field}</$field>}."\n";
       }
       #
       $xml .= "<mimeInfo>\n";
       foreach my $field ('mime','mimetag') {
           $xml .= qq{<$field>$values{$field}</$field>}."\n";
       }
       $xml .= "</mimeInfo>\n";
       #
       $xml .= "<languageInfo>\n";
       foreach my $field ('language','languagetag') {
           $xml .= qq{<$field>$values{$field}</$field>}."\n";
       }
       $xml .= "</languageInfo>\n";
       #
       foreach my $field ('creationdate','lastrevisiondate','owner') {
           $xml .= qq{<$field>$values{$field}</$field>}."\n";
       }
       #
       $xml .= "<copyrightInfo>\n";
       foreach my $field ('copyright','copyrighttag') {
           $xml .= qq{<$field>$values{$field}</$field>}."\n";
       }
       $xml .= "</copyrightInfo>\n";
       $xml .= qq{<repositoryLocation>$values{'hostname'}</repositoryLocation>}.
           "\n";
       $xml .= qq{<shortabstract>$values{'shortabstract'}</shortabstract>}."\n";
       #
       if (&has_stat_data(\%values)){
           $xml .= "<problemstatistics>\n";
           foreach my $field (&statfields()) {
               $xml .= qq{<$field>$values{$field}</$field>}."\n";            
           }
           $xml .= "</problemstatistics>\n";
       }
       #
       if (&has_eval_data(\%values)) {
           $xml .= "<evaluation>\n";
           foreach my $field (&evalfields) {
               $xml .= qq{<$field>$values{$field}</$field>}."\n";            
           }
           $xml .= "</evaluation>\n";
       }    
       #
       $xml .= "</LonCapaResource>\n";
       $xml = &HTML::Entities::encode($xml,'<>&');
     my $result=<<END;      my $result=<<END;
 $prefix  $prefix
 <pre>  <pre>
 &lt;LonCapaResource&gt;  $xml
 &lt;url&gt;$values{'url'}&lt;/url&gt;  
 &lt;title&gt;$values{'title'}&lt;/title&gt;  
 &lt;author&gt;$values{'author'}&lt;/author&gt;  
 &lt;subject&gt;$values{'subject'}&lt;/subject&gt;  
 &lt;keywords&gt;$values{'keywords'}&lt;/keywords&gt;  
 &lt;notes&gt;$values{'notes'}&lt;/notes&gt;  
 &lt;mimeInfo&gt;  
 &lt;mime&gt;$values{'mime'}&lt;/mime&gt;  
 &lt;mimetag&gt;$values{'mimetag'}&lt;/mimetag&gt;  
 &lt;/mimeInfo&gt;  
 &lt;languageInfo&gt;  
 &lt;language&gt;$values{'language'}&lt;/language&gt;  
 &lt;languagetag&gt;$values{'languagetag'}&lt;/languagetag&gt;  
 &lt;/languageInfo&gt;  
 &lt;creationdate&gt;$values{'creationdate'}&lt;/creationdate&gt;  
 &lt;lastrevisiondate&gt;$values{'lastrevisiondate'}&lt;/lastrevisiondate&gt;  
 &lt;owner&gt;$values{'owner'}&lt;/owner&gt;  
 &lt;copyrightInfo&gt;  
 &lt;copyright&gt;$values{'copyright'}&lt;/copyright&gt;  
 &lt;copyrighttag&gt;$values{'copyrighttag'}&lt;/copyrighttag&gt;  
 &lt;/copyrightInfo&gt;  
 &lt;repositoryLocation&gt;$values{'hostname'}&lt;/repositoryLocation&gt;  
 &lt;shortabstract&gt;$values{'shortabstract'}&lt;/shortabstract&gt;  
 &lt;/LonCapaResource&gt;  
 </pre>  </pre>
 $values{'extrashow'}  $values{'extrashow'}
 <hr align='left' width='200' noshade />  <hr align='left' width='200' noshade />
Line 2686  END Line 3453  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 {
           return 0;
     }      }
     else {  }
  return 0;  
   ######################################################################
   ######################################################################
   
   =pod 
   
   =item &output_unparsed_phrase_error()
   
   =cut
   
   ######################################################################
   ######################################################################
   sub output_unparsed_phrase_error {
       my ($r,$closebutton,$parms,$hidden_fields,$field)=@_;
       my $errorstring;
       if ($field eq 'basicexp') {
           $errorstring = &mt('Unable to understand the search phrase <i>[_1]</i>.  Please modify your search.',$ENV{'form.basicexp'});
       } else {
           $errorstring = &mt('Unable to understand the search phrase <b>[_1]</b>:<i>[_2]</i>.',$field,$ENV{'form.'.$field});
     }      }
       my $bodytag = &Apache::loncommon::bodytag('Search');
       my $heading = &mt('Unparsed Field');
       my $revise  = &mt('Revise search request');
       # make query information persistent to allow for subsequent revision
       $r->print(<<ENDPAGE);
   <html>
   <head>
   <title>The LearningOnline Network with CAPA</title>
   </head>
   $bodytag
   <form method="post" action="/adm/searchcat">
   $hidden_fields
   $closebutton
   <hr />
   <h2>$heading</h2>
   <p>
   $errorstring
   </p>
   <p>
   <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}">$revise</a>
   </p>
   </body>
   </html>
   ENDPAGE
 }  }
   
 ######################################################################  ######################################################################
Line 2715  $parms is extra information to include i Line 3526  $parms is extra information to include i
 ######################################################################  ######################################################################
 sub output_blank_field_error {  sub output_blank_field_error {
     my ($r,$closebutton,$parms,$hidden_fields)=@_;      my ($r,$closebutton,$parms,$hidden_fields)=@_;
     my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1);      my $bodytag=&Apache::loncommon::bodytag('Search');
     # make query information persistent to allow for subsequent revision      my $errormsg = &mt('You did not fill in enough information for the search to be started.  You need to fill in relevant fields on the search page in order for a query to be processed.');
     $r->print(<<BEGINNING);      my $revise = &mt('Revise Search Request');
       my $heading = &mt('Unactionable Search Queary');
       $r->print(<<ENDPAGE);
 <html>  <html>
 <head>  <head>
 <title>The LearningOnline Network with CAPA</title>  <title>The LearningOnline Network with CAPA</title>
 BEGINNING  
     $r->print(<<RESULTS);  
 </head>  </head>
 $bodytag  $bodytag
 <img align='right' src='/adm/lonIcons/lonlogos.gif' />  
 <h1>Search Catalog</h1>  
 <form method="post" action="/adm/searchcat">  <form method="post" action="/adm/searchcat">
 $hidden_fields  $hidden_fields
 <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}"  
 >Revise search request</a>&nbsp;  
 $closebutton  $closebutton
 <hr />  <hr />
 <h3>Unactionable search query.</h3>  <h2>$heading</h2>
 <p>  <p>
 You did not fill in enough information for the search to be started.  $errormsg
 You need to fill in relevant fields on the search page in order   </p>
 for a query to be processed.  <p>
   <a href="/adm/searchcat?$parms&persistent_db_id=$ENV{'form.persistent_db_id'}">$revise</a>&nbsp;
 </p>  </p>
 </body>  </body>
 </html>  </html>
 RESULTS  ENDPAGE
       return;
 }  }
   
 ######################################################################  ######################################################################

Removed from v.1.203  
changed lines
  Added in v.1.233


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