Diff for /loncom/interface/loncommon.pm between versions 1.134 and 1.165

version 1.134, 2003/10/24 13:35:37 version 1.165, 2003/12/27 23:55:10
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 # YEAR=2001  
 # 2/13-12/7 Guy Albertelli  
 # 12/21 Gerd Kortemeyer  
 # 12/25,12/28 Gerd Kortemeyer  
 # YEAR=2002  
 # 1/4 Gerd Kortemeyer  
 # 6/24,7/2 H. K. Ng  
   
 # Makes a table out of the previous attempts  # Makes a table out of the previous attempts
 # Inputs result_from_symbread, user, domain, course_id  # Inputs result_from_symbread, user, domain, course_id
Line 69  use Apache::Constants qw(:common :http : Line 62  use Apache::Constants qw(:common :http :
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::lonmenu();  use Apache::lonmenu();
 use Apache::lonlocal;  use Apache::lonlocal;
   use HTML::Entities;
   
 my $readit;  my $readit;
   
 =pod   ##
   ## Global Variables
 =head1 Global Variables  ##
   
 =cut  
   
 # ----------------------------------------------- Filetypes/Languages/Copyright  # ----------------------------------------------- Filetypes/Languages/Copyright
 my %language;  my %language;
Line 90  my %category_extensions; Line 82  my %category_extensions;
 my %designhash;  my %designhash;
   
 # ---------------------------------------------- Thesaurus variables  # ---------------------------------------------- Thesaurus variables
   #
 # FIXME: I don't think it's necessary to document these things;  # %Keywords:
 # they're privately used - Jeremy  #      A hash used by &keyword to determine if a word is considered a keyword.
   # $thesaurus_db_file 
 =pod  #      Scalar containing the full path to the thesaurus database.
   
 =over 4  
   
 =item * %Keywords    
   
 A hash used by &keyword to determine if a word is considered a keyword.  
   
 =item * $thesaurus_db_file  
   
 Scalar containing the full path to the thesaurus database.                   
   
 =back  
   
 =cut  
   
 my %Keywords;  my %Keywords;
 my $thesaurus_db_file;  my $thesaurus_db_file;
   
 # ----------------------------------------------------------------------- BEGIN  #
   # Initialize values from language.tab, copyright.tab, filetypes.tab,
 # FIXME: I don't think this needs to be documented, it prepares  # thesaurus.tab, and filecategories.tab.
 # private data structures - Jeremy  #
 =pod  
   
 =head1 General Subroutines  
   
 =over 4  
   
 =item * BEGIN()   
   
 Initialize values from language.tab, copyright.tab, filetypes.tab,  
 thesaurus.tab, and filecategories.tab.  
   
 =back  
   
 =cut  
   
 # ----------------------------------------------------------------------- BEGIN  
   
 BEGIN {  BEGIN {
     # Variable initialization      # Variable initialization
     $thesaurus_db_file = $Apache::lonnet::perlvar{'lonTabDir'}."/thesaurus.db";      $thesaurus_db_file = $Apache::lonnet::perlvar{'lonTabDir'}."/thesaurus.db";
Line 141  BEGIN { Line 102  BEGIN {
     unless ($readit) {      unless ($readit) {
 # ------------------------------------------------------------------- languages  # ------------------------------------------------------------------- languages
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
  '/language.tab');                                     '/language.tab';
  if ($fh) {          if ( open(my $fh,"<$langtabfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));                  my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
  $language{$key}=$val.' - '.$enc;                  $language{$key}=$val.' - '.$enc;
  if ($sup) {                  if ($sup) {
     $supported_language{$key}=$sup;                      $supported_language{$key}=$sup;
  }                  }
     }              }
  }              close($fh);
           }
     }      }
 # ------------------------------------------------------------------ copyrights  # ------------------------------------------------------------------ copyrights
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonIncludes'}.          my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
   '/copyright.tab');                                    '/copyright.tab';
  if ($fh) {          if ( open (my $fh,"<$copyrightfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$val)=(split(/\s+/,$_,2));                  my ($key,$val)=(split(/\s+/,$_,2));
  $cprtag{$key}=$val;                  $cprtag{$key}=$val;
     }              }
  }              close($fh);
           }
     }      }
   
 # -------------------------------------------------------------- domain designs  # -------------------------------------------------------------- domain designs
Line 177  BEGIN { Line 140  BEGIN {
     while ($filename=readdir(DIR)) {      while ($filename=readdir(DIR)) {
  my ($domain)=($filename=~/^(\w+)\./);   my ($domain)=($filename=~/^(\w+)\./);
     {      {
  my $fh=Apache::File->new($designdir.'/'.$filename);          my $designfile = $designdir.'/'.$filename;
  if ($fh) {          if ( open (my $fh,"<$designfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($key,$val)=(split(/\=/,$_));                  my ($key,$val)=(split(/\=/,$_));
  if ($val) { $designhash{$domain.'.'.$key}=$val; }                  if ($val) { $designhash{$domain.'.'.$key}=$val; }
     }              }
  }              close($fh);
           }
     }      }
   
     }      }
Line 194  BEGIN { Line 158  BEGIN {
   
 # ------------------------------------------------------------- file categories  # ------------------------------------------------------------- file categories
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
   '/filecategories.tab');                                    '/filecategories.tab';
  if ($fh) {          if ( open (my $fh,"<$categoryfile") ) {
     while (<$fh>) {              while (<$fh>) {
  next if /^\#/;                  next if /^\#/;
  chomp;                  chomp;
  my ($extension,$category)=(split(/\s+/,$_,2));                  my ($extension,$category)=(split(/\s+/,$_,2));
  push @{$category_extensions{lc($category)}},$extension;                  push @{$category_extensions{lc($category)}},$extension;
     }              }
  }              close($fh);
           }
   
     }      }
 # ------------------------------------------------------------------ file types  # ------------------------------------------------------------------ file types
     {      {
  my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.          my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
        '/filetypes.tab');                 '/filetypes.tab';
  if ($fh) {          if ( open (my $fh,"<$typesfile") ) {
             while (<$fh>) {              while (<$fh>) {
  next if (/^\#/);                  next if (/^\#/);
  chomp;                  chomp;
  my ($ending,$emb,$descr)=split(/\s+/,$_,3);                  my ($ending,$emb,$descr)=split(/\s+/,$_,3);
  if ($descr ne '') {                   if ($descr ne '') {
     $fe{$ending}=lc($emb);                      $fe{$ending}=lc($emb);
     $fd{$ending}=$descr;                      $fd{$ending}=$descr;
  }                  }
     }              }
  }              close($fh);
           }
     }      }
     &Apache::lonnet::logthis(      &Apache::lonnet::logthis(
               "<font color=yellow>INFO: Read file types</font>");                "<font color=yellow>INFO: Read file types</font>");
Line 245  containing javascript with two functions Line 212  containing javascript with two functions
 C<opensearcher>. Returned string does not contain E<lt>scriptE<gt>  C<opensearcher>. Returned string does not contain E<lt>scriptE<gt>
 tags.  tags.
   
 =over 4  
   
 =item * openbrowser(formname,elementname,only,omit) [javascript]  =item * openbrowser(formname,elementname,only,omit) [javascript]
   
 inputs: formname, elementname, only, omit  inputs: formname, elementname, only, omit
Line 267  Inputs: formname, elementname Line 232  Inputs: formname, elementname
 formname and elementname specify the name of the html form and the name  formname and elementname specify the name of the html form and the name
 of the element the selection from the search results will be placed in.  of the element the selection from the search results will be placed in.
   
 =back  
   
 =cut  =cut
   
 sub browser_and_searcher_javascript {  sub browser_and_searcher_javascript {
     return <<END;      return <<END;
     var editbrowser = null;      var editbrowser = null;
     function openbrowser(formname,elementname,only,omit) {      function openbrowser(formname,elementname,only,omit,titleelement) {
         var url = '/res/?';          var url = '/res/?';
         if (editbrowser == null) {          if (editbrowser == null) {
             url += 'launch=1&';              url += 'launch=1&';
Line 288  sub browser_and_searcher_javascript { Line 251  sub browser_and_searcher_javascript {
         if (omit != null) {          if (omit != null) {
             url += 'omit=' + omit + '&';              url += 'omit=' + omit + '&';
         }          }
           if (titleelement != null) {
               url += 'titleelement=' + titleelement + '&';
           }
         url += 'element=' + elementname + '';          url += 'element=' + elementname + '';
         var title = 'Browser';          var title = 'Browser';
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
Line 296  sub browser_and_searcher_javascript { Line 262  sub browser_and_searcher_javascript {
         editbrowser.focus();          editbrowser.focus();
     }      }
     var editsearcher;      var editsearcher;
     function opensearcher(formname,elementname) {      function opensearcher(formname,elementname,titleelement) {
         var url = '/adm/searchcat?';          var url = '/adm/searchcat?';
         if (editsearcher == null) {          if (editsearcher == null) {
             url += 'launch=1&';              url += 'launch=1&';
Line 304  sub browser_and_searcher_javascript { Line 270  sub browser_and_searcher_javascript {
         url += 'catalogmode=interactive&';          url += 'catalogmode=interactive&';
         url += 'mode=edit&';          url += 'mode=edit&';
         url += 'form=' + formname + '&';          url += 'form=' + formname + '&';
           if (titleelement != null) {
               url += 'titleelement=' + titleelement + '&';
           }
         url += 'element=' + elementname + '';          url += 'element=' + elementname + '';
         var title = 'Search';          var title = 'Search';
         var options = 'scrollbars=1,resizable=1,menubar=0';          var options = 'scrollbars=1,resizable=1,menubar=0';
Line 514  function select1_changed() { Line 483  function select1_changed() {
     // in with the nuclear      // in with the nuclear
     for (i=0;i<values.length; i++) {      for (i=0;i<values.length; i++) {
         $second.options[i] = new Option(values[i]);          $second.options[i] = new Option(values[i]);
           $second.options[i].value = values[i];
         $second.options[i].text = texts[i];          $second.options[i].text = texts[i];
         if (values[i] == select2def) {          if (values[i] == select2def) {
             $second.options[i].selected = true;              $second.options[i].selected = true;
Line 584  sub help_open_topic { Line 554  sub help_open_topic {
     my $template = "";      my $template = "";
     my $link;      my $link;
   
       $topic=~s/\W/\_/g;
   
     if (!$stayOnPage)      if (!$stayOnPage)
     {      {
  $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";   $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
Line 790  sub select_form { Line 762  sub select_form {
     return $selectform;      return $selectform;
 }  }
   
   sub select_level_form {
       my ($deflevel,$name)=@_;
       unless ($deflevel) { $deflevel=0; }
       return &select_form($deflevel,$name,(
    0 => 'Not specified',
    1 => 'Grade 1',
    2 => 'Grade 2',
    3 => 'Grade 3',
    4 => 'Grade 4',
    5 => 'Grade 5',
    6 => 'Grade 6',
    7 => 'Grade 7',
    8 => 'Grade 8',
    9 => 'Grade 9',
    10 => 'Grade 10',
    11 => 'Grade 11',
    12 => 'Grade 12',
    13 => 'Grade 13',
    14 => '100 Level',
    15 => '200 Level',
    16 => '300 Level',
    17 => '400 Level',
    18 => 'Graduate Level'));
   }
 #-------------------------------------------  #-------------------------------------------
   
 =pod  =pod
Line 906  Outputs: Line 901  Outputs:
   
 =back  =back
   
   =back 
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 944  sub decode_user_agent { Line 941  sub decode_user_agent {
             $clientunicode,$clientos,);              $clientunicode,$clientos,);
 }  }
   
 =pod  
   
 =back  
   
 =cut  
   
 ###############################################################  ###############################################################
 ##    Authentication changing form generation subroutines    ##  ##    Authentication changing form generation subroutines    ##
 ###############################################################  ###############################################################
Line 990  See loncreateuser.pm for invocation and Line 981  See loncreateuser.pm for invocation and
   
 =back  =back
   
   =back 
   
 =cut  =cut
   
 #-------------------------------------------  #-------------------------------------------
Line 1017  END Line 1010  END
         $Javascript_toUpperCase = "";          $Javascript_toUpperCase = "";
     }      }
   
       my $radioval = "'nochange'";
       my $argfield = 'null';
       if ( grep/^mode$/,(keys %in) ) {
           if ($in{'mode'} eq 'modifycourse')  {
               if ( grep/^curr_authtype$/,(keys %in) ) {
                   $radioval = "'$in{'curr_authtype'}'";
               }
               if ( grep/^curr_autharg$/,(keys %in) ) {
                   unless ($in{'curr_autharg'} eq '') {
                       $argfield = "'$in{'curr_autharg'}'";
                   }
               }
           }
       }
   
     $result.=<<"END";      $result.=<<"END";
 var current = new Object();  var current = new Object();
 current.radiovalue = 'nochange';  current.radiovalue = $radioval;
 current.argfield = null;  current.argfield = $argfield;
   
 function changed_radio(choice,currentform) {  function changed_radio(choice,currentform) {
     var choicearg = choice + 'arg';      var choicearg = choice + 'arg';
Line 1080  END Line 1088  END
   
 sub authform_authorwarning{  sub authform_authorwarning{
     my $result='';      my $result='';
     $result=<<"END";      $result='<i>'.
 <i>As a general rule, only authors or co-authors should be filesystem          &mt('As a general rule, only authors or co-authors should be '.
 authenticated (which allows access to the server filesystem).</i>              'filesystem authenticated '.
 END              '(which allows access to the server filesystem).')."</i>\n";
     return $result;      return $result;
 }  }
   
Line 1093  sub authform_nochange{ Line 1101  sub authform_nochange{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
           );            );
     my $result='';      my $result = &mt('[_1] Do not change login data',
     $result.=<<"END";                       '<input type="radio" name="login" value="nochange" '.
 <input type="radio" name="login" value="nochange" checked="checked"                       'checked="checked" onclick="'.
        onclick="javascript:changed_radio('nochange',$in{'formname'});" />              "javascript:changed_radio('nochange',$in{'formname'});".'" />');
 Do not change login data  
 END  
     return $result;      return $result;
 }  }
   
Line 1109  sub authform_kerberos{ Line 1115  sub authform_kerberos{
               kerb_def_auth => 'krb4',                kerb_def_auth => 'krb4',
               @_,                @_,
               );                );
     my $result='';      my ($check4,$check5,$krbarg);
     my $check4;  
     my $check5;  
     if ($in{'kerb_def_auth'} eq 'krb5') {      if ($in{'kerb_def_auth'} eq 'krb5') {
        $check5 = " checked=\"on\"";         $check5 = " checked=\"on\"";
     } else {      } else {
        $check4 = " checked=\"on\"";         $check4 = " checked=\"on\"";
     }      }
     $result.=<<"END";      $krbarg = $in{'kerb_def_dom'};
 <input type="radio" name="login" value="krb"   
        onclick="javascript:changed_radio('krb',$in{'formname'});"      my $krbcheck = "";
        onchange="javascript:changed_radio('krb',$in{'formname'});" />      if ( grep/^curr_authtype$/,(keys %in) ) {
 Kerberos authenticated with domain          if ($in{'curr_authtype'} =~ m/^krb/) {
 <input type="text" size="10" name="krbarg" value="$in{'kerb_def_dom'}"              $krbcheck = " checked=\"on\"";
        onchange="javascript:changed_text('krb',$in{'formname'});" />              if ( grep/^curr_autharg$/,(keys %in) ) {
 <input type="radio" name="krbver" value="4" $check4 />Version 4                  $krbarg = $in{'curr_autharg'};
 <input type="radio" name="krbver" value="5" $check5 />Version 5              }
 END          }
       }
   
       my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
       my $result .= &mt
           ('[_1] Kerberos authenticated with domain [_2] '.
            '[_3] Version 4 [_4] Version 5',
            '<input type="radio" name="login" value="krb" '.
                'onclick="'.$jscall.'" onchange="'.$jscall.'"'.$krbcheck.' />',
            '<input type="text" size="10" name="krbarg" '.
                'value="'.$krbarg.'" '.
                'onchange="'.$jscall.'" />',
            '<input type="radio" name="krbver" value="4" '.$check4.' />',
            '<input type="radio" name="krbver" value="5" '.$check5.' />');
     return $result;      return $result;
 }  }
   
Line 1136  sub authform_internal{ Line 1153  sub authform_internal{
                 kerb_def_dom => 'MSU.EDU',                  kerb_def_dom => 'MSU.EDU',
                 @_,                  @_,
                 );                  );
     my $result='';  
     $result.=<<"END";      my $intcheck = "";
 <input type="radio" name="login" value="int"      my $intarg = 'value=""';
        onchange="javascript:changed_radio('int',$args{'formname'});"      if ( grep/^curr_authtype$/,(keys %args) ) {
        onclick="javascript:changed_radio('int',$args{'formname'});" />          if ($args{'curr_authtype'} eq 'int') {
 Internally authenticated (with initial password               $intcheck = " checked=\"on\"";
 <input type="text" size="10" name="intarg" value=""              if ( grep/^curr_autharg$/,(keys %args) ) {
        onchange="javascript:changed_text('int',$args{'formname'});" />)                  $intarg = "value=\"$args{'curr_autharg'}\"";
 END              }
           }
       }
   
       my $jscall = "javascript:changed_radio('int',$args{'formname'});";
       my $result.=&mt
           ('[_1] Internally authenticated (with initial password [_2])',
            '<input type="radio" name="login" value="int" '.$intcheck.
                ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
            '<input type="text" size="10" name="intarg" '.$intarg.
                ' onchange="'.$jscall.'" />');
     return $result;      return $result;
 }  }
   
Line 1154  sub authform_local{ Line 1181  sub authform_local{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my $result='';  
     $result.=<<"END";      my $loccheck = "";
 <input type="radio" name="login" value="loc"      my $locarg = 'value=""';
        onchange="javascript:changed_radio('loc',$in{'formname'});"      if ( grep/^curr_authtype$/,(keys %in) ) {
        onclick="javascript:changed_radio('loc',$in{'formname'});" />          if ($in{'curr_authtype'} eq 'loc') {
 Local Authentication with argument              $loccheck = " checked=\"on\"";
 <input type="text" size="10" name="locarg" value=""              if ( grep/^curr_autharg$/,(keys %in) ) {
        onchange="javascript:changed_text('loc',$in{'formname'});" />                  $locarg = "value=\"$in{'curr_autharg'}\"";
 END              }
           }
       }
   
       my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
       my $result.=&mt('[_1] Local Authentication with argument [_2]',
                       '<input type="radio" name="login" value="loc" '.$loccheck.
                           ' onchange="'.$jscall.'" onclick="'.$jscall.'" />',
                       '<input type="text" size="10" name="locarg" '.$locarg.
                           ' onchange="'.$jscall.'" />');
     return $result;      return $result;
 }  }
   
Line 1172  sub authform_filesystem{ Line 1208  sub authform_filesystem{
               kerb_def_dom => 'MSU.EDU',                kerb_def_dom => 'MSU.EDU',
               @_,                @_,
               );                );
     my $result='';      my $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
     $result.=<<"END";      my $result.= &mt
 <input type="radio" name="login" value="fsys"           ('[_1] Filesystem Authenticated (with initial password [_2])',
        onchange="javascript:changed_radio('fsys',$in{'formname'});"           '<input type="radio" name="login" value="fsys" '.
        onclick="javascript:changed_radio('fsys',$in{'formname'});" />           'onchange="'.$jscall.'" onclick="'.$jscall.'" />',
 Filesystem authenticated (with initial password            '<input type="text" size="10" name="fsysarg" value="" '.
 <input type="text" size="10" name="fsysarg" value=""                    'onchange="'.$jscall.'" />');
        onchange="javascript:changed_text('fsys',$in{'formname'});">)  
 END  
     return $result;      return $result;
 }  }
   
 =pod  
   
 =back  
   
 =cut  
   
 ###############################################################  ###############################################################
 ##    Get Authentication Defaults for Domain                 ##  ##    Get Authentication Defaults for Domain                 ##
 ###############################################################  ###############################################################
Line 1344  sub keyword { Line 1372  sub keyword {
   
 =item * get_related_words  =item * get_related_words
   
 Look up a word in the thesaurus.  Takes a scalar arguement and returns  Look up a word in the thesaurus.  Takes a scalar argument and returns
 an array of words.  If the keyword is not in the thesaurus, an empty array  an array of words.  If the keyword is not in the thesaurus, an empty array
 will be returned.  The order of the words returned is determined by the  will be returned.  The order of the words returned is determined by the
 database which holds them.  database which holds them.
Line 1528  sub languagedescription { Line 1556  sub languagedescription {
     ($supported_language{$code}?' ('.&mt('interface available').')':'');      ($supported_language{$code}?' ('.&mt('interface available').')':'');
 }  }
   
   sub plainlanguagedescription {
       my $code=shift;
       return $language{$code};
   }
   
   sub supportedlanguagecode {
       my $code=shift;
       return $supported_language{$code};
   }
   
 =pod  =pod
   
 =item * copyrightids()   =item * copyrightids() 
Line 1764  sub get_previous_attempt { Line 1802  sub get_previous_attempt {
        } else {         } else {
   $value=$returnhash{$version.':'.$_};    $value=$returnhash{$version.':'.$_};
        }         }
        $prevattempts.='<td>'.$value.'&nbsp;</td>';            $prevattempts.='<td>'.&Apache::lonnet::unescape($value).'&nbsp;</td>';   
     }      }
  }   }
       }        }
Line 1776  sub get_previous_attempt { Line 1814  sub get_previous_attempt {
  } else {   } else {
   $value=$lasthash{$_};    $value=$lasthash{$_};
  }   }
    $value=&Apache::lonnet::unescape($value);
  if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}   if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
  $prevattempts.='<td>'.$value.'&nbsp;</td>';   $prevattempts.='<td>'.$value.'&nbsp;</td>';
       }        }
Line 1939  sub maketime { Line 1978  sub maketime {
          $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));           $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));
 }  }
   
   
 #########################################  
 #  
 # Retro-fixing of un-backward-compatible time format  
   
 sub unsqltime {  
     my $timestamp=shift;  
     if ($timestamp=~/^(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)$/) {  
        $timestamp=&maketime(  
    'year'=>$1,'month'=>$2,'day'=>$3,  
            'hours'=>$4,'minutes'=>$5,'seconds'=>$6);  
     }  
     return $timestamp;  
 }  
   
 #########################################  #########################################
   
 sub findallcourses {  sub findallcourses {
Line 2025  sub domainlogo { Line 2049  sub domainlogo {
  my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};   my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
  if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }   if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
         return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.          return '<img src="http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.
     '/adm/lonDomLogos/'.$domain.'.gif" />';      '/adm/lonDomLogos/'.$domain.'.gif" alt="'.$domain.'" />';
     } elsif(exists($Apache::lonnet::domaindescription{$domain})) {      } elsif(exists($Apache::lonnet::domaindescription{$domain})) {
         return $Apache::lonnet::domaindescription{$domain};          return $Apache::lonnet::domaindescription{$domain};
     } else {      } else {
Line 2136  sub bodytag { Line 2160  sub bodytag {
     my $sidebg=&designparm($function.'.sidebg',$domain);      my $sidebg=&designparm($function.'.sidebg',$domain);
 # Accessibility font enhance  # Accessibility font enhance
     unless ($addentries) { $addentries=''; }      unless ($addentries) { $addentries=''; }
       my $addstyle='';
     if ($ENV{'browser.fontenhance'} eq 'on') {      if ($ENV{'browser.fontenhance'} eq 'on') {
  $addentries.=' style="font-size: x-large"';   $addstyle=' font-size: x-large;';
     }      }
  # role and realm   # role and realm
     my ($role,$realm)      my ($role,$realm)
Line 2155  sub bodytag { Line 2180  sub bodytag {
     if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }      if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
 # construct main body tag  # construct main body tag
     my $bodytag = <<END;      my $bodytag = <<END;
   <style>
   h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif }
   a:focus { color: red; background: yellow } 
   </style>
 <body bgcolor="$pgbg" text="$font" alink="$alink" vlink="$vlink" link="$link"  <body bgcolor="$pgbg" text="$font" alink="$alink" vlink="$vlink" link="$link"
 $addentries>  style="margin-top: 0px;$addstyle" $addentries>
 END  END
     my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.      my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.
                    $lonhttpdPort.$img.'" />';                     $lonhttpdPort.$img.'" alt="'.$function.'" />';
     if ($bodyonly) {      if ($bodyonly) {
         return $bodytag;          return $bodytag;
     } elsif ($ENV{'browser.interface'} eq 'textual') {      } elsif ($ENV{'browser.interface'} eq 'textual') {
Line 2171  END Line 2200  END
 # No Remote  # No Remote
         return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',          return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
                                                       $forcereg).                                                        $forcereg).
                '<table bgcolor="'.$pgbg.'" width="100%" border="0" cellspacing="3" cellpadding="3"><tr><td bgcolor="'.$tabbg.'"><font size="+3" color="'.$font.'"><b>'.$title.        '<table bgcolor="'.$pgbg.'" width="100%" border="0" cellspacing="3" cellpadding="3"><tr><td bgcolor="'.$tabbg.'"><font face="Arial, Helvetica, sans-serif" size="+3" color="'.$font.'"><b>'.$title.
 '</b></font></td></tr></table>';  '</b></font></td></tr></table>';
     }      }
   
Line 2187  $upperleft</td> Line 2216  $upperleft</td>
 </tr>  </tr>
 <tr>  <tr>
 <td rowspan="3" bgcolor="$tabbg">  <td rowspan="3" bgcolor="$tabbg">
 &nbsp;<font size="5"><b>$title</b></font>  &nbsp;<font size="5" face="Arial, Helvetica, sans-serif"><b>$title</b></font>
 <td bgcolor="$tabbg"  align="right">  <td bgcolor="$tabbg" align="right">
 <font size="2">  <font size="2" face="Arial, Helvetica, sans-serif">
     $ENV{'environment.firstname'}      $ENV{'environment.firstname'}
     $ENV{'environment.middlename'}      $ENV{'environment.middlename'}
     $ENV{'environment.lastname'}      $ENV{'environment.lastname'}
Line 2198  $upperleft</td> Line 2227  $upperleft</td>
 </td>  </td>
 </tr>  </tr>
 <tr><td bgcolor="$tabbg" align="right">  <tr><td bgcolor="$tabbg" align="right">
 <font size="2">$role</font>&nbsp;  <font size="2" face="Arial, Helvetica, sans-serif">$role</font>&nbsp;
 </td></tr>  </td></tr>
 <tr>  <tr>
 <td bgcolor="$tabbg" align="right"><font size="2">$realm</font>&nbsp;</td></tr>  <td bgcolor="$tabbg" align="right"><font size="2" face="Arial, Helvetica, sans-serif">$realm</font>&nbsp;</td></tr>
 </table><br>  </table><br>
 ENDBODY  ENDBODY
 }  }
Line 2378  sub add_to_env { Line 2407  sub add_to_env {
   
 =pod  =pod
   
   =item * get_env_multiple($name) 
   
   gets $name from the %ENV hash, it seemlessly handles the cases where multiple
   values may be defined and end up as an array ref.
   
   returns an array of values
   
   =cut
   
   sub get_env_multiple {
       my ($name) = @_;
       my @values;
       if (defined($ENV{$name})) {
           # exists is it an array
           if (ref($ENV{$name})) {
               @values=@{ $ENV{$name} };
           } else {
               $values[0]=$ENV{$name};
           }
       }
       return(@values);
   }
   
   
   =pod
   
 =back   =back 
   
 =head1 CSV Upload/Handling functions  =head1 CSV Upload/Handling functions
Line 2402  sub upfile_store { Line 2457  sub upfile_store {
     my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.      my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
  '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;   '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
     {      {
  my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons').          my $datafile = $r->dir_config('lonDaemons').
  '/tmp/'.$datatoken.'.tmp');                             '/tmp/'.$datatoken.'.tmp';
  print $fh $ENV{'form.upfile'};          if ( open(my $fh,">$datafile") ) {
               print $fh $ENV{'form.upfile'};
               close($fh);
           }
     }      }
     return $datatoken;      return $datatoken;
 }  }
Line 2423  sub load_tmp_file { Line 2481  sub load_tmp_file {
     my $r=shift;      my $r=shift;
     my @studentdata=();      my @studentdata=();
     {      {
  my $fh;          my $studentfile = $r->dir_config('lonDaemons').
  if ($fh=Apache::File->new($r->dir_config('lonDaemons').                                '/tmp/'.$ENV{'form.datatoken'}.'.tmp';
   '/tmp/'.$ENV{'form.datatoken'}.'.tmp')) {          if ( open(my $fh,"<$studentfile") ) {
     @studentdata=<$fh>;              @studentdata=<$fh>;
  }              close($fh);
           }
     }      }
     $ENV{'form.upfile'}=join('',@studentdata);      $ENV{'form.upfile'}=join('',@studentdata);
 }  }
Line 2501  sub record_sep { Line 2560  sub record_sep {
     return %components;      return %components;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * upfile_select_html()  =item * upfile_select_html()
   
 return HTML code to select file and specify its type  Return HTML code to select a file from the users machine and specify 
   the file type.
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub upfile_select_html {  sub upfile_select_html {
     return (<<'ENDUPFORM');      my %Types = (
 <input type="file" name="upfile" size="50" />                   csv   => &mt('CSV (comma separated values, spreadsheet)'),
 <br />Type: <select name="upfiletype">                   space => &mt('Space separated'),
 <option value="csv">CSV (comma separated values, spreadsheet)</option>                   tab   => &mt('Tabulator separated'),
 <option value="space">Space separated</option>  #                 xml   => &mt('HTML/XML'),
 <option value="tab">Tabulator separated</option>                   );
 <option value="xml">HTML/XML</option>      my $Str = '<input type="file" name="upfile" size="50" />'.
 </select>          '<br />Type: <select name="upfiletype">';
 ENDUPFORM      foreach my $type (sort(keys(%Types))) {
           $Str .= '<option value="'.$type.'" >'.$Types{$type}."</option>\n";
       }
       $Str .= "</select>\n";
       return $Str;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_print_samples($r,$records)  =item * csv_print_samples($r,$records)
Line 2531  Apache Request ref, $records is an array Line 2603  Apache Request ref, $records is an array
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_print_samples {  sub csv_print_samples {
     my ($r,$records) = @_;      my ($r,$records) = @_;
     my (%sone,%stwo,%sthree);      my (%sone,%stwo,%sthree);
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}      if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}      if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
       #
     $r->print('Samples<br /><table border="2"><tr>');      $r->print(&mt('Samples').'<br /><table border="2"><tr>');
     foreach (sort({$a <=> $b} keys(%sone))) { $r->print('<th>Column&nbsp;'.($_+1).'</th>'); }      foreach (sort({$a <=> $b} keys(%sone))) { 
           $r->print('<th>'.&mt('Column&nbsp;[_1]',($_+1)).'</th>'); }
     $r->print('</tr>');      $r->print('</tr>');
     foreach my $hash (\%sone,\%stwo,\%sthree) {      foreach my $hash (\%sone,\%stwo,\%sthree) {
  $r->print('<tr>');   $r->print('<tr>');
Line 2553  sub csv_print_samples { Line 2628  sub csv_print_samples {
     $r->print('</tr></table><br />'."\n");      $r->print('</tr></table><br />'."\n");
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_print_select_table($r,$records,$d)  =item * csv_print_select_table($r,$records,$d)
   
 Prints a table to create associations between values and table columns.  Prints a table to create associations between values and table columns.
   
 $r is an Apache Request ref,  $r is an Apache Request ref,
 $records is an arrayref from &Apache::loncommon::upfile_record_sep,  $records is an arrayref from &Apache::loncommon::upfile_record_sep,
 $d is an array of 2 element arrays (internal name, displayed name)  $d is an array of 2 element arrays (internal name, displayed name)
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_print_select_table {  sub csv_print_select_table {
     my ($r,$records,$d) = @_;      my ($r,$records,$d) = @_;
     my $i=0;my %sone;      my $i=0;my %sone;
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     $r->print('Associate columns with student attributes.'."\n".      $r->print(&mt('Associate columns with student attributes.')."\n".
      '<table border="2"><tr><th>Attribute</th><th>Column</th></tr>'."\n");       '<table border="2"><tr>'.
                 '<th>'.&mt('Attribute').'</th>'.
                 '<th>'.&mt('Column').'</th></tr>'."\n");
     foreach (@$d) {      foreach (@$d) {
  my ($value,$display)=@{ $_ };   my ($value,$display)=@{ $_ };
  $r->print('<tr><td>'.$display.'</td>');   $r->print('<tr><td>'.$display.'</td>');
Line 2587  sub csv_print_select_table { Line 2670  sub csv_print_select_table {
     return $i;      return $i;
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item * csv_samples_select_table($r,$records,$d)  =item * csv_samples_select_table($r,$records,$d)
Line 2599  $d is an array of 2 element arrays (inte Line 2685  $d is an array of 2 element arrays (inte
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub csv_samples_select_table {  sub csv_samples_select_table {
     my ($r,$records,$d) = @_;      my ($r,$records,$d) = @_;
     my %sone; my %stwo; my %sthree;      my %sone; my %stwo; my %sthree;
     my $i=0;      my $i=0;
       #
     $r->print('<table border=2><tr><th>Field</th><th>Samples</th></tr>');      $r->print('<table border=2><tr><th>'.
                 &mt('Field').'</th><th>'.&mt('Samples').'</th></tr>');
     %sone=&record_sep($$records[0]);      %sone=&record_sep($$records[0]);
     if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}      if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
     if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}      if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
       #
     foreach (sort keys %sone) {      foreach (sort keys %sone) {
  $r->print('<tr><td><select name=f'.$i.   $r->print('<tr><td><select name="f'.$i.'"'.
   ' onchange="javascript:flip(this.form,'.$i.');">');    ' onchange="javascript:flip(this.form,'.$i.');">');
  foreach (@$d) {   foreach (@$d) {
     my ($value,$display)=@{ $_ };      my ($value,$display)=@{ $_ };
     $r->print('<option value='.$value.'>'.$display.'</option>');      $r->print('<option value="'.$value.'">'.$display.'</option>');
  }   }
  $r->print('</select></td><td>');   $r->print('</select></td><td>');
  if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }   if (defined($sone{$_})) { $r->print($sone{$_}."</br>\n"); }
Line 2627  sub csv_samples_select_table { Line 2716  sub csv_samples_select_table {
     return($i);      return($i);
 }  }
   
   ######################################################
   ######################################################
   
 =pod  =pod
   
 =item clean_excel_name($name)  =item clean_excel_name($name)
Line 2635  Returns a replacement for $name which do Line 2727  Returns a replacement for $name which do
   
 =cut  =cut
   
   ######################################################
   ######################################################
 sub clean_excel_name {  sub clean_excel_name {
     my ($name) = @_;      my ($name) = @_;
     $name =~ s/[:\*\?\/\\]//g;      $name =~ s/[:\*\?\/\\]//g;
Line 2665  sub check_if_partid_hidden { Line 2759  sub check_if_partid_hidden {
     my ($id,$symb,$udom,$uname) = @_;      my ($id,$symb,$udom,$uname) = @_;
     my $hiddenparts=&Apache::lonnet::EXT('resource.0.hiddenparts',      my $hiddenparts=&Apache::lonnet::EXT('resource.0.hiddenparts',
  $symb,$udom,$uname);   $symb,$udom,$uname);
       my $truth=1;
       #if the string starts with !, then the list is the list to show not hide
       if ($hiddenparts=~s/^\s*!//) { $truth=undef; }
     my @hiddenlist=split(/,/,$hiddenparts);      my @hiddenlist=split(/,/,$hiddenparts);
     foreach my $checkid (@hiddenlist) {      foreach my $checkid (@hiddenlist) {
  if ($checkid =~ /^\s*\Q$id\E\s*$/) { return 1; }   if ($checkid =~ /^\s*\Q$id\E\s*$/) { return $truth; }
     }      }
     return undef;      return !$truth;
   }
   
   
   ############################################################
   ############################################################
   
   =pod
   
   =back 
   
   =head1 cgi-bin script and graphing routines
   
   =over 4
   
   =item get_cgi_id
   
   Inputs: none
   
   Returns an id which can be used to pass environment variables
   to various cgi-bin scripts.  These environment variables will
   be removed from the users environment after a given time by
   the routine &Apache::lonnet::transfer_profile_to_env.
   
   =cut
   
   ############################################################
   ############################################################
   my $uniq=0;
   sub get_cgi_id {
       $uniq=($uniq+1)%100000;
       return (time.'_'.$uniq);
 }  }
   
 ############################################################  ############################################################
Line 2679  sub check_if_partid_hidden { Line 2807  sub check_if_partid_hidden {
   
 =item DrawBarGraph  =item DrawBarGraph
   
   Facilitates the plotting of data in a (stacked) bar graph.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   The bars on the plot are labeled '1','2',...,'n'.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $Max: scalar, the maximum Y value to use in the plot
   If $Max is < any data point, the graph will not be rendered.
   
   =item $colors: array ref holding the colors to be used for the data sets when
   they are plotted.  If undefined, default values will be used.
   
   =item @Values: An array of array references.  Each array reference holds data
   to be plotted in a stacked bar chart.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
 =cut  =cut
   
Line 2694  sub DrawBarGraph { Line 2852  sub DrawBarGraph {
                   ];                     ]; 
     }      }
     #      #
     my $identifier = time.'_'.int(rand(1000));      my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;        
     if (! @Values || ref($Values[0]) ne 'ARRAY') {      if (! @Values || ref($Values[0]) ne 'ARRAY') {
         return '';          return '';
     }      }
Line 2703  sub DrawBarGraph { Line 2862  sub DrawBarGraph {
     my $NumSets=1;      my $NumSets=1;
     foreach my $array (@Values) {      foreach my $array (@Values) {
         next if (! ref($array));          next if (! ref($array));
         $ValuesHash{'cgi.'.$identifier.'.data.'.$NumSets++} =           $ValuesHash{$id.'.data.'.$NumSets++} = 
             join(',',@$array);              join(',',@$array);
     }      }
     #      #
     $Title  = '' if (! defined($Title));      my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
     $xlabel = '' if (! defined($xlabel));      if ($NumBars < 10) {
     $ylabel = '' if (! defined($ylabel));          $width = 120+$NumBars*15;
     $Title  = &Apache::lonnet::escape($Title);          $xskip = 1;
     $xlabel = &Apache::lonnet::escape($xlabel);          $bar_width = 15;
     $ylabel = &Apache::lonnet::escape($ylabel);      } elsif ($NumBars <= 25) {
           $width = 120+$NumBars*11;
           $xskip = 5;
           $bar_width = 8;
       } elsif ($NumBars <= 50) {
           $width = 120+$NumBars*8;
           $xskip = 5;
           $bar_width = 4;
       } else {
           $width = 120+$NumBars*8;
           $xskip = 5;
           $bar_width = 4;
       }
       #
       my @Labels;
       for (my $i=0;$i<@{$Values[0]};$i++) {
           push (@Labels,$i+1);
       }
     #      #
     $Max = 1 if ($Max < 1);      $Max = 1 if ($Max < 1);
     if ( int($Max) < $Max ) {      if ( int($Max) < $Max ) {
         $Max++;          $Max++;
         $Max = int($Max);          $Max = int($Max);
     }      }
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       $ValuesHash{$id.'.title'}    = &Apache::lonnet::escape($Title);
       $ValuesHash{$id.'.xlabel'}   = &Apache::lonnet::escape($xlabel);
       $ValuesHash{$id.'.ylabel'}   = &Apache::lonnet::escape($ylabel);
       $ValuesHash{$id.'.y_max_value'} = $Max;
       $ValuesHash{$id.'.NumBars'}  = $NumBars;
       $ValuesHash{$id.'.NumSets'}  = $NumSets;
       $ValuesHash{$id.'.PlotType'} = 'bar';
       $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       $ValuesHash{$id.'.height'}   = $height;
       $ValuesHash{$id.'.width'}    = $width;
       $ValuesHash{$id.'.xskip'}    = $xskip;
       $ValuesHash{$id.'.bar_width'} = $bar_width;
       $ValuesHash{$id.'.labels'} = join(',',@Labels);
       #
       &Apache::lonnet::appenv(%ValuesHash);
       return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
   }
   
   ############################################################
   ############################################################
   
   =pod
   
   =item DrawXYGraph
   
   Facilitates the plotting of data in an XY graph.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $Max: scalar, the maximum Y value to use in the plot
   If $Max is < any data point, the graph will not be rendered.
   
   =item $colors: Array ref containing the hex color codes for the data to be 
   plotted in.  If undefined, default values will be used.
   
   =item $Xlabels: Array ref containing the labels to be used for the X-axis.
   
   =item $Ydata: Array ref containing Array refs.  
   Each of the contained arrays will be plotted as a seperate curve.
   
   =item %Values: hash indicating or overriding any default values which are 
   passed to graph.png.  
   Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
   =cut
   
   ############################################################
   ############################################################
   sub DrawXYGraph {
       my ($Title,$xlabel,$ylabel,$Max,$colors,$Xlabels,$Ydata,%Values)=@_;
       #
       # Create the identifier for the graph
       my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;
       #
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       my %ValuesHash = 
           (
            $id.'.title'  => &Apache::lonnet::escape($Title),
            $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
            $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
            $id.'.y_max_value'=> $Max,
            $id.'.labels'     => join(',',@$Xlabels),
            $id.'.PlotType'   => 'XY',
            );
       #
       if (defined($colors) && ref($colors) eq 'ARRAY') {
           $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       }
     #      #
     &Apache::lonnet::appenv('cgi.'.$identifier.'.title'   => $Title,      if (! ref($Ydata) || ref($Ydata) ne 'ARRAY') {
                             'cgi.'.$identifier.'.xlabel'  => $xlabel,          return '';
                             'cgi.'.$identifier.'.ylabel'  => $ylabel,      }
                             'cgi.'.$identifier.'.Max'     => $Max,      my $NumSets=1;
                             'cgi.'.$identifier.'.NumBars' => $NumBars,      foreach my $array (@{$Ydata}){
                             'cgi.'.$identifier.'.NumSets' => $NumSets,          next if (! ref($array));
                             'cgi.'.$identifier.'.Colors'  => join(',',@{$colors}),          $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
                             %ValuesHash);      }
       $ValuesHash{$id.'.NumSets'} = $NumSets-1;
       #
       # Deal with other parameters
       while (my ($key,$value) = each(%Values)) {
           $ValuesHash{$id.'.'.$key} = $value;
       }
       #
       &Apache::lonnet::appenv(%ValuesHash);
     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';      return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
 }  }
   
Line 2736  sub DrawBarGraph { Line 3011  sub DrawBarGraph {
   
 =pod  =pod
   
   =item DrawXYYGraph
   
   Facilitates the plotting of data in an XY graph with two Y axes.
   Puts plot definition data into the users environment in order for 
   graph.png to plot it.  Returns an <img> tag for the plot.
   
   Inputs:
   
   =over 4
   
   =item $Title: string, the title of the plot
   
   =item $xlabel: string, text describing the X-axis of the plot
   
   =item $ylabel: string, text describing the Y-axis of the plot
   
   =item $colors: Array ref containing the hex color codes for the data to be 
   plotted in.  If undefined, default values will be used.
   
   =item $Xlabels: Array ref containing the labels to be used for the X-axis.
   
   =item $Ydata1: The first data set
   
   =item $Min1: The minimum value of the left Y-axis
   
   =item $Max1: The maximum value of the left Y-axis
   
   =item $Ydata2: The second data set
   
   =item $Min2: The minimum value of the right Y-axis
   
   =item $Max2: The maximum value of the left Y-axis
   
   =item %Values: hash indicating or overriding any default values which are 
   passed to graph.png.  
   Possible values are: width, xskip, x_ticks, x_tick_offset, among others.
   
   =back
   
   Returns:
   
   An <img> tag which references graph.png and the appropriate identifying
   information for the plot.
   
   =cut
   
   ############################################################
   ############################################################
   sub DrawXYYGraph {
       my ($Title,$xlabel,$ylabel,$colors,$Xlabels,$Ydata1,$Min1,$Max1,
                                           $Ydata2,$Min2,$Max2,%Values)=@_;
       #
       # Create the identifier for the graph
       my $identifier = &get_cgi_id();
       my $id = 'cgi.'.$identifier;
       #
       $Title  = '' if (! defined($Title));
       $xlabel = '' if (! defined($xlabel));
       $ylabel = '' if (! defined($ylabel));
       my %ValuesHash = 
           (
            $id.'.title'  => &Apache::lonnet::escape($Title),
            $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
            $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
            $id.'.labels' => join(',',@$Xlabels),
            $id.'.PlotType' => 'XY',
            $id.'.NumSets' => 2,
            $id.'.two_axes' => 1,
            $id.'.y1_max_value' => $Max1,
            $id.'.y1_min_value' => $Min1,
            $id.'.y2_max_value' => $Max2,
            $id.'.y2_min_value' => $Min2,
            );
       #
       if (defined($colors) && ref($colors) eq 'ARRAY') {
           $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
       }
       #
       if (! ref($Ydata1) || ref($Ydata1) ne 'ARRAY' ||
           ! ref($Ydata2) || ref($Ydata2) ne 'ARRAY'){
           return '';
       }
       my $NumSets=1;
       foreach my $array ($Ydata1,$Ydata2){
           next if (! ref($array));
           $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
       }
       #
       # Deal with other parameters
       while (my ($key,$value) = each(%Values)) {
           $ValuesHash{$id.'.'.$key} = $value;
       }
       #
       &Apache::lonnet::appenv(%ValuesHash);
       return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
   }
   
   ############################################################
   ############################################################
   
   =pod
   
   =back 
   
   =head1 Statistics helper routines?  
   
   Bad place for them but what the hell.
   
   =over 4
   
   =item &chartlink
   
   Returns a link to the chart for a specific student.  
   
   Inputs:
   
   =over 4
   
   =item $linktext: The text of the link
   
   =item $sname: The students username
   
   =item $sdomain: The students domain
   
   =back
   
   =back
   
   =cut
   
   ############################################################
   ############################################################
   sub chartlink {
       my ($linktext, $sname, $sdomain) = @_;
       my $link = '<a href="/adm/statistics?reportSelected=student_assessment'.
           '&SelectedStudent='.&Apache::lonnet::escape($sname.':'.$sdomain).
           '&chartoutputmode='.HTML::Entities::encode('html, with all links').
          '">'.$linktext.'</a>';
   }
   
   #######################################################
   #######################################################
   
   =pod
   
   =head1 Course Environment Routines
   
   =over 4
   
   =item &restore_course_settings 
   
   =item &store_course_settings
   
   Restores/Store indicated form parameters from the course environment.
   Will not overwrite existing values of the form parameters.
   
   Inputs: 
   a scalar describing the data (e.g. 'chart', 'problem_analysis')
   
   a hash ref describing the data to be stored.  For example:
      
   %Save_Parameters = ('Status' => 'scalar',
       'chartoutputmode' => 'scalar',
       'chartoutputdata' => 'scalar',
       'Section' => 'array',
       'StudentData' => 'array',
       'Maps' => 'array');
   
   Returns: both routines return nothing
   
   =cut
   
   #######################################################
   #######################################################
   sub store_course_settings {
       # save to the environment
       # appenv the same items, just to be safe
       my $courseid = $ENV{'request.course.id'};
       my $coursedom = $ENV{'course.'.$courseid.'.domain'};
       my ($prefix,$Settings) = @_;
       my %SaveHash;
       my %AppHash;
       while (my ($setting,$type) = each(%$Settings)) {
           my $basename = 'env.internal.'.$prefix.'.'.$setting;
           my $envname = 'course.'.$courseid.'.'.$basename;
           if (exists($ENV{'form.'.$setting})) {
               # Save this value away
               if ($type eq 'scalar' &&
                   (! exists($ENV{$envname}) || 
                    $ENV{$envname} ne $ENV{'form.'.$setting})) {
                   $SaveHash{$basename} = $ENV{'form.'.$setting};
                   $AppHash{$envname}   = $ENV{'form.'.$setting};
               } elsif ($type eq 'array') {
                   my $stored_form;
                   if (ref($ENV{'form.'.$setting})) {
                       $stored_form = join(',',
                                           map {
                                               &Apache::lonnet::escape($_);
                                           } sort(@{$ENV{'form.'.$setting}}));
                   } else {
                       $stored_form = 
                           &Apache::lonnet::escape($ENV{'form.'.$setting});
                   }
                   # Determine if the array contents are the same.
                   if ($stored_form ne $ENV{$envname}) {
                       $SaveHash{$basename} = $stored_form;
                       $AppHash{$envname}   = $stored_form;
                   }
               }
           }
       }
       my $put_result = &Apache::lonnet::put('environment',\%SaveHash,
                                             $coursedom,
                                             $ENV{'course.'.$courseid.'.num'});
       if ($put_result !~ /^(ok|delayed)/) {
           &Apache::lonnet::logthis('unable to save form parameters, '.
                                    'got error:'.$put_result);
       }
       # Make sure these settings stick around in this session, too
       &Apache::lonnet::appenv(%AppHash);
       return;
   }
   
   sub restore_course_settings {
       my $courseid = $ENV{'request.course.id'};
       my ($prefix,$Settings) = @_;
       while (my ($setting,$type) = each(%$Settings)) {
           next if (exists($ENV{'form.'.$setting}));
           my $envname = 'course.'.$courseid.'.env.internal.'.$prefix.
               '.'.$setting;
           if (exists($ENV{$envname})) {
               if ($type eq 'scalar') {
                   $ENV{'form.'.$setting} = $ENV{$envname};
               } elsif ($type eq 'array') {
                   $ENV{'form.'.$setting} = [ 
                                              map { 
                                                  &Apache::lonnet::unescape($_); 
                                              } split(',',$ENV{$envname})
                                              ];
               }
           }
       }
   }
   
   ############################################################
   ############################################################
   
   sub propath {
       my ($udom,$uname)=@_;
       $udom=~s/\W//g;
       $uname=~s/\W//g;
       my $subdir=$uname.'__';
       $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
       my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname";
       return $proname;
   } 
   
   sub icon {
       my ($file)=@_;
       my @file_ext = split(/\./,$file);
       my $curfext = $file_ext[-1];
       my $iconname="unknown.gif";
       my $embstyle = &Apache::loncommon::fileembstyle($curfext);
       # The unless conditional that follows is a bit of overkill
       $iconname = $curfext.".gif" unless
    (!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn');
       return $Apache::lonnet::perlvar{'lonIconsURL'}."/$iconname";
   } 
   
   =pod
   
 =back  =back
   
 =cut  =cut

Removed from v.1.134  
changed lines
  Added in v.1.165


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