[LON-CAPA-cvs] cvs: loncom /interface courseprefs.pm loncommon.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Thu Apr 11 11:30:42 EDT 2013


raeburn		Thu Apr 11 15:30:42 2013 EDT

  Modified files:              
    /loncom/interface	courseprefs.pm loncommon.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Efficiency improvements when checking if course personnel should be hidden.
    - Identity of privileged users (i.e., dc) in a domain cached in memcache.
    - Added course setting -- checkforpriv -- which includes comma separated
      list of domains to check for privileged users (besides course's domain).
  - Fix some xhtml in courseprefs.pm to satisfy w3c validation
  - loncommon::select_dom_form() takes additional (optional) argument --
    array ref of domains to exclude from options in the dropdown list.
  - lonnet.pm  -- eliminate Apache::lonnet:: from some calls to 
    do_cache_new() within lonnet.pm itself.
  
  
-------------- next part --------------
Index: loncom/interface/courseprefs.pm
diff -u loncom/interface/courseprefs.pm:1.55 loncom/interface/courseprefs.pm:1.56
--- loncom/interface/courseprefs.pm:1.55	Mon Apr  8 23:57:21 2013
+++ loncom/interface/courseprefs.pm	Thu Apr 11 15:30:37 2013
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set configuration settings for a course
 #
-# $Id: courseprefs.pm,v 1.55 2013/04/08 23:57:21 raeburn Exp $
+# $Id: courseprefs.pm,v 1.56 2013/04/11 15:30:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -317,6 +317,7 @@
                 stul => 'Student agreement needed to be listed',
                 clas => 'Classlists and staff listing',
                 priv => 'Privileged users (Domain Coordinators) in staff listing',
+                prdo => "Domains to check for privileged users (besides course's domain)",
                 defc => 'Default Course Spreadsheet',
                 defs => 'Default Student Spreadsheet',
                 seme => 'Send message to student when clicking Done on Tasks',
@@ -424,12 +425,14 @@
                      ordered => ['default_enrollment_start_date',
                                  'default_enrollment_end_date',
                                  'defaultcredits',
-                                 'nothideprivileged','student_classlist_view',
+                                 'nothideprivileged','checkforpriv',
+                                 'student_classlist_view',
                                  'student_classlist_opt_in','student_classlist_portfiles'],
                      itemtext => {
                          default_enrollment_start_date => 'Start date',
                          default_enrollment_end_date   => 'End date',
                          nothideprivileged             => $lt{'priv'},
+                         checkforpriv                  => $lt{'prdo'},
                          student_classlist_view        => $lt{'stuv'},
                          student_classlist_opt_in      => $lt{'stul'},
                          student_classlist_portfiles   => 'Include link to accessible portfolio files',
@@ -568,8 +571,15 @@
             exists $item->{'header'}->[0]->{'col2'}) {
 			$output .= '          
           	<tr class="LC_info_row">
-              <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
-              <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
+              <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
+            if ($action eq 'feedback') {
+                $output .= '
+                  <td class="LC_right_item" colspan="2">';
+            } else {
+                $output .= '
+                  <td class="LC_right_item">';
+            }
+            $output .= &mt($item->{'header'}->[0]->{'col2'}).'</td>
             </tr>';
         }
         $rowtotal ++;
@@ -587,8 +597,14 @@
             <table class="LC_nested">
              <tr class="LC_info_row">
               <td class="LC_left_item">'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
-        $output .= '
-              <td class="LC_right_item">'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
+        if ($action eq 'classlists') {
+            $output .= '
+              <td class="LC_right_item" colspan="2">';
+        } else {
+            $output .= '
+              <td class="LC_right_item">';
+        }
+        $output .= &mt($item->{'header'}->[1]->{'col2'}).'</td>
              </tr>';
         if ($action eq 'classlists') {
             $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype).
@@ -617,8 +633,14 @@
             exists $item->{'header'}->[0]->{'col2'}) {
 			$output .= '          
           	<tr class="LC_info_row">
-              <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
-              <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
+              <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>';
+            if (($action eq 'courseinfo') || ($action eq 'localization') ||
+                ($action eq 'print_discussion')) {
+                $output .= '<td class="LC_right_item" valign="top" colspan="2">';
+            } else {
+                $output .= '<td class="LC_right_item" valign="top">';
+            }
+            $output .= &mt($item->{'header'}->[0]->{'col2'}).'</td>
             </tr>';
         }
     }
@@ -1104,32 +1126,43 @@
                             my $newtext = $maxnum-1;
                             $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext};
                             $newvalues{$entry} = join('', at newhdr);
-                        } elsif ($entry eq 'languages') {
-                            my $langstr;
+                        } elsif (($entry eq 'languages') || 
+                                 ($entry eq 'checkforpriv')) {
+                            my $settings;
                             my $total = $env{'form.'.$entry.'_total'};
                             if ($total) {
                                 my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
                                 for (my $i=0; $i<$total; $i++) {
                                     unless (grep(/^$i$/, at deletes)) {
-                                       $langstr .= $env{'form.'.$entry.'_'.$i}.',';
+                                        $settings .= $env{'form.'.$entry.'_'.$i}.',';
                                     }
                                 }
                             } else {
                                 $total = 0;
                             }
                             if ($env{'form.'.$entry.'_'.$total} ne '') {
-                                my $newlang = $env{'form.'.$entry.'_'.$total};
-                                my %langchoices = &get_lang_choices();
-                                if ($langchoices{$newlang}) {
-                                    $langstr .= $newlang;
+                                my $new = $env{'form.'.$entry.'_'.$total};
+                                if ($entry eq 'languages') { 
+                                    my %langchoices = &get_lang_choices();
+                                    if ($langchoices{$new}) {
+                                        $settings .= $new;
+                                    } else {
+                                        $settings =~ s/,$//;
+                                        $disallowed->{'localization'}{$entry} = $new;
+                                    }
                                 } else {
-                                    $langstr =~ s/,$//;
-                                    $disallowed->{'localization'}{$entry} = $newlang;
+                                    my %domains=map { $_ => 1; } &Apache::lonnet::all_domains();
+                                    if ($domains{$new}) {
+                                        $settings .= $new;
+                                    } else {
+                                        $settings =~ s/,$//;
+                                        $disallowed->{'classlists'}{$entry} = $new;
+                                    }
                                 }
                             } else {
-                                $langstr =~ s/,$//;
+                                $settings =~ s/,$//;
                             }
-                            $newvalues{$entry} = $langstr;
+                            $newvalues{$entry} = $settings;
                         } else {
                             $newvalues{$entry} = $env{'form.'.$entry};
                         }
@@ -1662,8 +1695,10 @@
 ENDSCRIPT
     }
     $jscript = '<script type="text/javascript" language="Javascript">'."\n".
+               '// <![CDATA['."\n".  
                $browse_js."\n".$categorize_js."\n".$loncaparev_js."\n".
-               $cloners_js."\n".'</script>'."\n".$stubrowse_js."\n";
+               $cloners_js."\n".'// ]]>'."\n".
+               '</script>'."\n".$stubrowse_js."\n";
     return $jscript;
 }
 
@@ -1849,23 +1884,28 @@
     my $datatable;
     my $count = 0;
     foreach my $item (@{$ordered}) {
+        my $colspan;
         if ($item eq 'hidefromcat') {
             next if (!$can_toggle_cat);
         } elsif ($item eq 'categories') {
             next if (!$can_categorize);
         }
+        unless (($item eq 'cloners') || ($item eq 'rolenames')) {
+            $colspan = 2; 
+        }
         $count ++;
         if (exists $items{$item}{advanced} && $items{$item}{advanced} == 1) {
-        	$datatable .= &item_table_row_start($items{$item}{text},$count,"advanced");
+        	$datatable .= &item_table_row_start($items{$item}{text},$count,"advanced",$colspan);
         } else {
-        	$datatable .= &item_table_row_start($items{$item}{text},$count);
+        	$datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
         }
         if ($items{$item}{input} eq 'radio') {
             $datatable .= &yesno_radio($item,$settings);
         } elsif ($item eq 'cloners') {
             my $includeempty = 1;
             my $num = 0;
-            $datatable .= &Apache::loncommon::start_data_table().
+            $datatable .= '</td><td align="right">'.
+                          &Apache::loncommon::start_data_table().
                           &Apache::loncommon::start_data_table_row().
                           '<td><span class="LC_nobreak"><label>'.
                           &mt('Any user in any domain:').
@@ -1883,8 +1923,8 @@
                           "'cloners_all'".');"/>'.&mt('No').'</label></td>'.
                           &Apache::loncommon::end_data_table_row().
                           &Apache::loncommon::end_data_table().
-                          '<table><tr><td align="left">'.&mt('Or').
-                          '</td></tr></table>'.
+                          '<table><tr><td align="left"><b>'.&mt('Or').
+                          '</b></td></tr></table>'.
                           &Apache::loncommon::start_data_table();
             my @cloners;
             if ($settings->{$item} eq '') {
@@ -1936,8 +1976,8 @@
                           '<input type="hidden" name="cloners_total" value="'.$num.'" />'.
                           '</td>'.&Apache::loncommon::end_data_table_row().
                           &Apache::loncommon::end_data_table().
-                          '<table><tr><td align="left">'.&mt('And').
-                          '</td></tr></table>'.
+                          '<table><tr><td align="left"><b>'.&mt('And').
+                          '</b></td></tr></table>'.
                           &Apache::loncommon::start_data_table().
                           &Apache::loncommon::start_data_table_row().
                           '<td align="left">'.
@@ -1948,7 +1988,8 @@
                           '</td>'.&Apache::loncommon::end_data_table_row().
                           &Apache::loncommon::end_data_table();
         } elsif ($item eq 'rolenames') {
-            $datatable .= &Apache::loncommon::start_data_table();
+            $datatable .= '</td><td align="right">'.
+                          &Apache::loncommon::start_data_table();
             my @roles;
             if ($crstype eq 'Community') {
                 @roles = ('co');
@@ -1968,7 +2009,7 @@
             }
             $datatable .= &Apache::loncommon::end_data_table().'</td>';
         } elsif ($item eq 'categories') {
-            my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
+            my $launcher = 'onfocus="this.blur();javascript:catsbrowser();"';
             $datatable .= '<input type="hidden" name="categories" value="'.$settings->{$item}.'" />'.
                           &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
                                                           $items{$item}{size},$launcher);
@@ -2621,7 +2662,7 @@
 
 sub show_autocoowners {
     my (@currcoown) = @_;
-    my $output = '<i>'.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').'</i>';
+    my $output = '<i><span class="LC_nobreak">'.&mt('Co-ownership is set automatically when a Course Coordinator role[_1] is assigned to official course personnel (from institutional data).','</span><br /><span class="LC_nobreak">').'</span></i>';
     if (@currcoown > 0) { 
         $output .= '<br />'.&mt('Current co-owners are:').' '.
                    join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
@@ -2765,7 +2806,11 @@
     my $count = 0;
     foreach my $item (@{$ordered}) {
         $count ++;
-        $datatable .= &item_table_row_start($items{$item}{text},$count);
+        my $colspan;
+        unless ($item eq 'languages') {
+            $colspan = 2; 
+        }
+        $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
         if ($item eq 'timezone') {
             my $includeempty = 1;
             my $timezone = &Apache::lonlocal::gettimezone();
@@ -2784,12 +2829,13 @@
                                                       undef,$includeempty);
         } else {
             if ($settings->{$item} eq '') {
-                $datatable .= 
+                $datatable .= '</td><td align="right">'.
                     &Apache::loncommon::select_language('languages_0','',1);
             } else {
                 my $num = 0;
                 my @languages = split(/\s*[,;:]\s*/,$settings->{$item});
-                $datatable .= &Apache::loncommon::start_data_table();
+                $datatable .= '</td><td align="right"><br />'.
+                              &Apache::loncommon::start_data_table();
                 if (@languages > 0) {
                     my %langchoices = &get_lang_choices();
                     foreach my $lang (@languages) {
@@ -2816,7 +2862,7 @@
                               &Apache::loncommon::select_language('languages_'.$num,'',1).
                               '<input type="hidden" name="languages_total" value="'.$num.'" />'.
                               '</td>'.&Apache::loncommon::end_data_table_row().
-                              &Apache::loncommon::end_data_table();
+                              &Apache::loncommon::end_data_table().'<br />';
             }
         }
         $datatable .= &item_table_row_end();
@@ -2878,11 +2924,12 @@
         if ($position eq 'top') {
         	$datatable .= &item_table_row_start($items{$item}{text},$count);
         } else {
-        	$datatable .= &item_table_row_start($items{$item}{text}."<br/>(Custom text)",$count, "advanced");
+        	$datatable .= &item_table_row_start($items{$item}{text}."<br/>(Custom text)",$count, "advanced",2);
         }
         if ($position eq 'top') {
             my $includeempty = 0;
-            $datatable .= &user_table($cdom,$item,\@sections,
+            $datatable .=  '</td><td align="right">'.
+                           &user_table($cdom,$item,\@sections,
                                       $settings->{$item},\%lt);
         } else {
             $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
@@ -2902,7 +2949,7 @@
     } else {
         my $num = 0;
         my @curr = split(/,/,$currvalue);
-        $output .= '<table class="LC_nested_outer">';
+        $output .= '<table class="LC_data_table">';
         my ($currusers);
         foreach my $val (@curr) {
             next if ($val eq '');
@@ -3066,34 +3113,43 @@
                                           del      => 'Delete?',
                                           sec      => 'Sections:',
                                          );
-
     foreach my $item (@{$ordered}) {
         $count ++;
-        $datatable .= &item_table_row_start($items{$item}{text},$count);
+        my $colspan;
+        if ($item eq 'allow_limited_html_in_feedback') {
+            $colspan = 2;
+        } 
+        $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
         if ($item eq 'plc.roles.denied') {
-            $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
+            $datatable .= '</td><td align="right">'.
+                          '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
                           '</table>';
         } elsif ($item eq 'plc.users.denied') {
-            $datatable .= &user_table($cdom,$item,undef,
+            $datatable .=  '</td><td align="right">'.
+                           &user_table($cdom,$item,undef,
                                       $settings->{$item},\%lt);
         } elsif ($item eq 'pch.roles.denied') {
-            $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
+            $datatable .= '</td><td align="right">'.
+                          '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
                           '</table>';
         } elsif ($item eq 'pch.users.denied') {
-            $datatable .= &user_table($cdom,$item,undef,
+            $datatable .= '</td><td align="right">'.
+                          &user_table($cdom,$item,undef,
                                       $settings->{$item},\%lt);
         } elsif ($item eq 'allow_limited_html_in_feedback') {
             $datatable .= &yesno_radio($item,$settings);
         } elsif ($item eq 'allow_discussion_post_editing') {
-            $datatable .= &Apache::loncommon::start_data_table().
+            $datatable .= '</td><td align="right"><br />'.
+                          &Apache::loncommon::start_data_table().
                           &Apache::loncommon::start_data_table_row().
                           '<th align="left">'.&mt('Role').'</th><th>'.
                           &mt('Sections').'</th>'.
                           &Apache::loncommon::end_data_table_row().
                           &role_checkboxes($cdom,$cnum,$item,$settings,1).
-                          &Apache::loncommon::end_data_table();
+                          &Apache::loncommon::end_data_table().'<br />';
         } elsif ($item eq 'discussion_post_fonts') {
-            $datatable .= &Apache::loncommon::start_data_table().
+            $datatable .= '</td><td align="right"><br />'.
+                          &Apache::loncommon::start_data_table().
                           &Apache::loncommon::start_data_table_row().
                           '<th align="center">'.&mt('Sum of likes/dislikes').'</th>'.
                           '<th align="center">'.&mt('font-size').'</th>'.
@@ -3102,7 +3158,7 @@
                           '<th align="center">'.&mt('Other css').'</th>'. 
                           &Apache::loncommon::end_data_table_row().
                           &set_discussion_fonts($cdom,$cnum,$item,$settings).
-                          &Apache::loncommon::end_data_table();
+                          &Apache::loncommon::end_data_table().'<br />';
         }
         $datatable .= &item_table_row_end();
     }
@@ -3303,7 +3359,7 @@
             push(@ordered,'defaultcredits');
         }
     } elsif ($position eq 'middle') {
-        @ordered = ('nothideprivileged');
+        @ordered = ('nothideprivileged','checkforpriv');
     } else {
         @ordered = ('student_classlist_view',
                     'student_classlist_opt_in',
@@ -3343,6 +3399,11 @@
                    input => 'checkbox',
                  },
 
+        'checkforpriv' => {
+                   text => '<b>'.&mt($itemtext->{'checkforpriv'}).'</b>',
+                   input => 'selectbox',
+                 },
+
         'student_classlist_view'   => {
                    text => '<b>'.&mt($itemtext->{'student_classlist_view'}).'</b>',
                    input => 'selectbox',
@@ -3363,7 +3424,7 @@
             ($settings->{'student_classlist_view'} eq 'section')) { 
         $settings->{'student_classlist_view'} = 'disabled';
     }
-    return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'classlists');
 }
 
 sub print_appearance {
@@ -3412,7 +3473,7 @@
                    size => 40,
                  },
     );
-    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance');
 }
 
 sub print_grading {
@@ -3468,7 +3529,7 @@
                    input => 'radio',
                  },
     );
-    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'grading');
 }
 
 sub print_printouts {
@@ -3521,7 +3582,7 @@
             nullval => &mt('None specified - use domain default'),
                     }
     );
-    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'printouts');
 }
 
 sub print_spreadsheet {
@@ -3557,7 +3618,7 @@
             input => 'radio',
                          },
                 );
-    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'spreadsheet');
 }
 
 sub print_bridgetasks {
@@ -3599,7 +3660,7 @@
              input => 'radio',
                                   },
                 );
-    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
+    return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks');
 }
 
 sub print_other {
@@ -3624,7 +3685,7 @@
                             input => 'textbox',
                             size  => '30',
                            };
-    my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
+    my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'other');
 }
 
 sub get_other_items {
@@ -3651,13 +3712,18 @@
 }
 
 sub item_table_row_start {
-    my ($text,$count,$add_class) = @_;
+    my ($text,$count,$add_class,$colspan) = @_;
     my $output;
-	my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
-	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
-	$output .= '<tr class="'.$css_class.'">'."\n";;
-    $output .= '<td class="LC_left_item">'.$text.
-               '</td><td class="LC_right_item">';
+    my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
+    $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+    $output .= '<tr class="'.$css_class.'">'."\n".
+               '<td class="LC_left_item">'.$text.
+               '</td>';
+    if ($colspan) {
+        $output .= '<td class="LC_right_item" colspan="'.$colspan.'">';
+    } else {
+        $output .= '<td class="LC_right_item">';
+    }
     return $output;
 }
 
@@ -3728,16 +3794,21 @@
 }
 
 sub make_item_rows {
-    my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype) = @_;
+    my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype,$caller) = @_;
     my $datatable;
     if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) {
         my $count = 0;
         foreach my $item (@{$ordered}) {
             $count ++;
+            my $colspan;
+            if ((($caller eq 'classlists') && ($item eq 'nothideprivileged')) ||
+                (($caller eq 'printouts') && ($item ne 'print_header_format'))) {
+                $colspan = 2;
+            }
             if (exists $items->{$item}{advanced} && $items->{$item}{advanced} == 1) {
-                $datatable .= &item_table_row_start($items->{$item}{text},$count,"advanced");
+                $datatable .= &item_table_row_start($items->{$item}{text},$count,"advanced",$colspan);
             } else {
-                $datatable .= &item_table_row_start($items->{$item}{text},$count);
+                $datatable .= &item_table_row_start($items->{$item}{text},$count,undef,$colspan);
             }
             if ($item eq 'defaultcredits') {
                 my $defaultcredits = $env{'course.'.$env{'request.course.id'}.'.internal.defaultcredits'};
@@ -3750,6 +3821,8 @@
                 $datatable .= $showcredits;
             } elsif ($item eq 'nothideprivileged') {
                 $datatable .= &nothidepriv_row($cdom,$item,$settings,$crstype);
+            } elsif ($item eq 'checkforpriv') {
+                $datatable .= &checkforpriv_row($cdom,$item,$settings,$crstype);
             } elsif ($item eq 'print_header_format') {
                 $datatable .= &print_hdrfmt_row($item,$settings);
             } elsif ($items->{$item}{input} eq 'dates') {
@@ -3781,8 +3854,7 @@
 sub nothidepriv_row {
     my ($cdom,$item,$settings,$crstype) = @_;
     my ($cnum) = &get_course();
-    my %nothide;
-    my $datatable;
+    my ($datatable,%nothide, at checkdoms);
     if (ref($settings) eq 'HASH') {
         if ($settings->{$item} ne '') {
             foreach my $user (split(/\s*\,\s*/,$settings->{$item})) {
@@ -3793,38 +3865,30 @@
                 }
             }
         }
+        if ($settings->{'checkforpriv'}) {
+            @checkdoms = split(/,/,$settings->{'checkforpriv'}); 
+        }
     }
-    my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
-    my $now = time;
+    push(@checkdoms,$cdom);
+    my %coursepersonnel =
+        &Apache::lonnet::get_my_roles($cnum,$cdom,'',['previous','future','active']);
     my @privusers;
-    my %privileged;
     foreach my $person (keys(%coursepersonnel)) {
-        my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
-        $user =~ s/:$//;
-        my ($end,$start) = split(/:/,$coursepersonnel{$person});
+        my ($uname,$udom,$role) = split(/:/,$person);
+        my $user = $uname.':'.$udom;
+        my ($start,$end) = split(/:/,$coursepersonnel{$person});
         if ($end == -1 || $start == -1) {
             next;
         }
-        my ($uname,$udom) = split(':',$user);
-        unless (ref($privileged{$udom}) eq 'HASH') {
-            my %dompersonnel = &Apache::lonnet::get_domain_roles($udom,['dc'],undef,$now);
-            $privileged{$udom} = {};
-            if (keys(%dompersonnel)) {
-                foreach my $server (keys(%dompersonnel)) {
-                    foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
-                        my ($trole,$uname,$udom) = split(/:/,$user); 
-                        $privileged{$udom}{$uname} = $trole;
-                    }
+        foreach my $dom (@checkdoms) { 
+            if (&Apache::lonnet::privileged($uname,$udom,\@checkdoms,['dc','su'])) {
+                unless (grep(/^\Q$user\E$/, at privusers)) {
+                    push(@privusers,$user);
                 }
             }
         }
-        if (exists($privileged{$udom}{$uname})) {
-            unless (grep(/^\Q$user\E$/, at privusers)) {
-                push(@privusers,$user);
-            }
-        }
     }
-    if (@privusers) {
+    if (@privusers > 0) {
         $datatable .= '<table align="right">';
         foreach my $user (sort(@privusers)) {
             my $hideon = ' checked="checked" ';
@@ -3856,6 +3920,65 @@
     return $datatable;
 }
 
+sub checkforpriv_row {
+    my ($cdom,$item,$settings,$crstype) = @_;
+    my $datatable;
+    my %domains=map { $_ => 1; } &Apache::lonnet::all_domains();
+    if (keys(%domains) == 1) {
+        $datatable = '</td><td align="right">'.
+                     &mt("Course's domain is only domain");
+        return $datatable;
+    }
+    my @excdoms = ($cdom);
+    my $num = 0;
+    if ($settings->{$item} eq '') {
+        $datatable = '</td><td align="right">'.
+                     &Apache::loncommon::select_dom_form('','checkforpriv_'.$num,
+                                                         1,1,undef,undef,\@excdoms);
+    } else {
+        my @privdoms = split(/,/,$settings->{$item});
+        my %domains=map { $_ => 1; } &Apache::lonnet::all_domains();
+        $datatable = '</td><td align="right"><br />'.
+                     &Apache::loncommon::start_data_table();
+        if (@privdoms > 0) {
+            foreach my $currdom (@privdoms) {
+                next unless ($domains{$currdom});
+                my $domdesc = &Apache::lonnet::domain($currdom,'description');
+                if ($domdesc eq '') {
+                    $domdesc = $currdom;
+                } 
+                $datatable .=
+                    &Apache::loncommon::start_data_table_row().
+                    '<td align="left"><span class="LC_nobreak">'.
+                    &mt('Domain:').'<b> '.$domdesc.
+                    '</b><input type="hidden" name="checkforpriv_'.$num.
+                    '" value="'.$currdom.'" /></span><br />'.
+                    '<span class="LC_nobreak"><label><input type="checkbox" '.
+                    'name="checkforpriv_delete" value="'.$num.'" />'.
+                    &mt('Delete').'</label></span></td>'.
+                    &Apache::loncommon::end_data_table_row();
+                $num ++;
+                unless (grep(/^\Q$currdom\E$/, at excdoms)) { 
+                    push(@excdoms,$currdom);
+                }
+            }
+        }
+        if ((scalar(keys(%domains)) - scalar(@excdoms)) > 0) {
+            $datatable .= 
+                &Apache::loncommon::start_data_table_row().
+                '<td align="left"><span class="LC_nobreak">'.
+                &mt('Additional domain:'). '</span><br />'.
+                &Apache::loncommon::select_dom_form('','checkforpriv_'.$num,1,
+                                                    1,undef,undef,\@excdoms).
+                '</td>'.&Apache::loncommon::end_data_table_row();
+        }
+        $datatable .= &Apache::loncommon::end_data_table().
+                      '<input type="hidden" name="checkforpriv_total" value="'.$num.'" />'.
+                      '<br />';
+    }
+    return $datatable;
+}
+
 sub print_hdrfmt_row {
     my ($item,$settings) = @_;
     my @curr;
@@ -3928,7 +4051,8 @@
 </script>
 
 ENDJS
-    $output .= $currstr.'<table class="LC_nested_outer">';
+    $output .= '</td><td align="right"><br />'.
+               $currstr.'<table class="LC_data_table">';
     if (@curr > 0) {
         for (my $i=0; $i<@curr; $i++) {
             my $pos = $i+1;
@@ -3968,7 +4092,7 @@
                '<input type="hidden" name="printfmthdr_maxnum" value="'.
                 $maxnum.'" /></td>'.
                '</tr>'.
-               '</table>'; 
+               '</table><br />';
     return $output;
 }
 
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1120 loncom/interface/loncommon.pm:1.1121
--- loncom/interface/loncommon.pm:1.1120	Thu Apr 11 14:59:48 2013
+++ loncom/interface/loncommon.pm	Thu Apr 11 15:30:37 2013
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1120 2013/04/11 14:59:48 bisitz Exp $
+# $Id: loncommon.pm,v 1.1121 2013/04/11 15:30:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2191,7 +2191,7 @@
 
 =pod
 
-=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms)
 
 Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.  
@@ -2204,25 +2204,31 @@
 
 The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
 
-The optional $incdoms is a reference to an array of domains which will be the only available options. 
+The optional $incdoms is a reference to an array of domains which will be the only available options.
+
+The optional $excdoms is a reference to an array of domains which will be excluded from the available options.
 
 =cut
 
 #-------------------------------------------
 sub select_dom_form {
-    my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
+    my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) = @_;
     if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';
     }
-    my @domains;
+    my (@domains,%exclude);
     if (ref($incdoms) eq 'ARRAY') {
         @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
     } else {
         @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
     }
     if ($includeempty) { @domains=('', at domains); }
+    if (ref($excdoms) eq 'ARRAY') {
+        map { $exclude{$_} = 1; } @{$excdoms}; 
+    }
     my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";
     foreach my $dom (@domains) {
+        next if ($exclude{$dom});
         $selectdomain.="<option value=\"$dom\" ".
             ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom;
         if ($showdomdesc) {
@@ -8414,7 +8420,7 @@
                               active   => 'Active',
                               future   => 'Future',
                             );
-        my %nothide;
+        my (%nothide, at possdoms);
         if ($hidepriv) {
             my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum);
             foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
@@ -8424,6 +8430,10 @@
                     $nothide{$user} = 1;
                 }
             }
+            my @possdoms = ($cdom);
+            if ($coursehash{'checkforpriv'}) {
+                push(@possdoms,split(/,/,$coursehash{'checkforpriv'}));
+            }
         }
         foreach my $person (sort(keys(%coursepersonnel))) {
             my $match = 0;
@@ -8459,7 +8469,7 @@
                 }
                 if ($uname ne '' && $udom ne '') {
                     if ($hidepriv) {
-                        if ((&Apache::lonnet::privileged($uname,$udom)) &&
+                        if ((&Apache::lonnet::privileged($uname,$udom,\@possdoms)) &&
                             (!$nothide{$uname.':'.$udom})) {
                             next;
                         }
@@ -13546,6 +13556,7 @@
                    'pch.users.denied',
                    'plc.users.denied',
                    'hidefromcat',
+                   'checkforpriv',
                    'categories'],
                    $$crsudom,$$crsunum);
     }
@@ -13602,6 +13613,11 @@
 # do not hide course coordinator from staff listing, 
 # even if privileged
     $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+# add course coordinator's domain to domains to check for privileged users
+# if different to course domain
+    if ($$crsudom ne $args->{'ccdomain'}) {
+        $cenv{'checkforpriv'} = $args->{'ccdomain'};
+    }
 # add crosslistings
     if ($args->{'crsxlist'}) {
         $cenv{'internal.crosslistings'}='';
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1218 loncom/lonnet/perl/lonnet.pm:1.1219
--- loncom/lonnet/perl/lonnet.pm:1.1218	Mon Mar 11 13:33:24 2013
+++ loncom/lonnet/perl/lonnet.pm	Thu Apr 11 15:30:42 2013
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1218 2013/03/11 13:33:24 raeburn Exp $
+# $Id: lonnet.pm,v 1.1219 2013/04/11 15:30:42 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2023,8 +2023,7 @@
             $domdefaults{'hostedsessions'} = $domconfig{'usersessions'}{'hosted'};
         }
     }
-    &Apache::lonnet::do_cache_new('domdefaults',$domain,\%domdefaults,
-                                  $cachetime);
+    &do_cache_new('domdefaults',$domain,\%domdefaults,$cachetime);
     return %domdefaults;
 }
 
@@ -2858,9 +2857,13 @@
     my ($udom,$uname,$cdom,$cnum,$type,$hideprivileged) = @_;
     if ($hideprivileged) {
         my $skipuser;
-        if (&privileged($uname,$udom)) {
+        my %coursehash = &coursedescription($cdom.'_'.$cnum);
+        my @possdoms = ($cdom);  
+        if ($coursehash{'checkforpriv'}) { 
+            push(@possdoms,split(/,/,$coursehash{'checkforpriv'})); 
+        }
+        if (&privileged($uname,$udom,\@possdoms)) {
             $skipuser = 1;
-            my %coursehash = &coursedescription($cdom.'_'.$cnum);
             if ($coursehash{'nothideprivileged'}) {
                 foreach my $item (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
                     my $user;
@@ -3891,6 +3894,10 @@
             $nothide{$user}=1;
         }
     }
+    my @possdoms = ($coursehash{'domain'});
+    if ($coursehash{'checkforpriv'}) {
+        push(@possdoms,split(/,/,$coursehash{'checkforpriv'}));
+    }
     my %returnhash=();
     my %dumphash=
             &dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'});
@@ -3903,20 +3910,7 @@
         if (($tstart) && ($now<$tstart)) { next; }
         my ($role,$username,$domain,$section)=split(/\:/,$entry);
 	if ($username eq '' || $domain eq '') { next; }
-        unless (ref($privileged{$domain}) eq 'HASH') {
-            my %dompersonnel =
-                &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
-            $privileged{$domain} = {};
-            foreach my $server (keys(%dompersonnel)) {
-                if (ref($dompersonnel{$server}) eq 'HASH') {
-                    foreach my $user (keys(%{$dompersonnel{$server}})) {
-                        my ($trole,$uname,$udom) = split(/:/,$user);
-                        $privileged{$udom}{$uname} = 1;
-                    }
-                }
-            }
-        }
-        if ((exists($privileged{$domain}{$username})) && 
+        if ((&privileged($username,$domain,\@possdoms)) &&
             (!$nothide{$username.':'.$domain})) { next; }
 	if ($role eq 'cr') { next; }
         if ($codes) {
@@ -3947,8 +3941,7 @@
     if ($context eq 'userroles') {
         %dumphash = &dump('roles',$udom,$uname);
     } else {
-        %dumphash=
-            &dump('nohist_userroles',$udom,$uname);
+        %dumphash = &dump('nohist_userroles',$udom,$uname);
         if ($hidepriv) {
             my %coursehash=&coursedescription($udom.'_'.$uname);
             foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
@@ -4016,28 +4009,15 @@
             }
         }
         if ($hidepriv) {
+            my @privroles = ('dc','su');
             if ($context eq 'userroles') {
-                if ((&privileged($username,$domain)) &&
-                    (!$nothide{$username.':'.$domain})) {
-                    next;
-                }
+                next if (grep(/^\Q$role\E$/, at privroles));
             } else {
-                unless (ref($privileged{$domain}) eq 'HASH') {
-                    my %dompersonnel =
-                        &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
-                    $privileged{$domain} = {};
-                    if (keys(%dompersonnel)) {
-                        foreach my $server (keys(%dompersonnel)) {
-                            if (ref($dompersonnel{$server}) eq 'HASH') {
-                                foreach my $user (keys(%{$dompersonnel{$server}})) {
-                                    my ($trole,$uname,$udom) = split(/:/,$user);
-                                    $privileged{$udom}{$uname} = $trole;
-                                }
-                            }
-                        }
-                    }
+                my $possdoms = [$domain];
+                if (ref($roledoms) eq 'ARRAY') {
+                   push(@{$possdoms},@{$roledoms}); 
                 }
-                if (exists($privileged{$domain}{$username})) {
+                if (&privileged($username,$domain,$possdoms,\@privroles)) {
                     if (!$nothide{$username.':'.$domain}) {
                         next;
                     }
@@ -4272,7 +4252,7 @@
     }
     my $rolelist;
     if (ref($roles) eq 'ARRAY') {
-        $rolelist = join(':',@{$roles});
+        $rolelist = join('&',@{$roles});
     }
     my %personnel = ();
 
@@ -4951,22 +4931,95 @@
 # -------------------------------------------------See if a user is privileged
 
 sub privileged {
-    my ($username,$domain)=@_;
-
-    my %rolesdump = &dump("roles", $domain, $username) or return 0;
+    my ($username,$domain,$possdomains,$possroles)=@_;
     my $now = time;
+    my $roles;
+    if (ref($possroles) eq 'ARRAY') {
+        $roles = $possroles; 
+    } else {
+        $roles = ['dc','su'];
+    }
+    if (ref($possdomains) eq 'ARRAY') {
+        my %privileged = &privileged_by_domain($possdomains,$roles);
+        foreach my $dom (@{$possdomains}) {
+            if (($username =~ /^$match_username$/) && ($domain =~ /^$match_domain$/) &&
+                (ref($privileged{$dom}) eq 'HASH')) {
+                foreach my $role (@{$roles}) {
+                    if (ref($privileged{$dom}{$role}) eq 'HASH') {
+                        if (exists($privileged{$dom}{$role}{$username.':'.$domain})) {
+                            my ($end,$start) = split(/:/,$privileged{$dom}{$role}{$username.':'.$domain});
+                            return 1 unless (($end && $end < $now) ||
+                                             ($start && $start > $now));
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        my %rolesdump = &dump("roles", $domain, $username) or return 0;
+        my $now = time;
 
-    for my $role (@rolesdump{grep { ! /^rolesdef_/ } keys %rolesdump}) {
+        for my $role (@rolesdump{grep { ! /^rolesdef_/ } keys %rolesdump}) {
             my ($trole, $tend, $tstart) = split(/_/, $role);
-            if (($trole eq 'dc') || ($trole eq 'su')) {
+            if (grep(/^\Q$trole\E$/,@{$roles})) {
                 return 1 unless ($tend && $tend < $now) 
-                    or ($tstart && $tstart > $now);
+                        or ($tstart && $tstart > $now);
             }
-	}
-
+        }
+    }
     return 0;
 }
 
+sub privileged_by_domain {
+    my ($domains,$roles) = @_;
+    my %privileged = ();
+    my $cachetime = 60*60*24;
+    my $now = time;
+    unless ((ref($domains) eq 'ARRAY') && (ref($roles) eq 'ARRAY')) {
+        return %privileged;
+    }
+    foreach my $dom (@{$domains}) {
+        next if (ref($privileged{$dom}) eq 'HASH');
+        my $needroles;
+        foreach my $role (@{$roles}) {
+            my ($result,$cached)=&is_cached_new('priv_'.$role,$dom);
+            if (defined($cached)) {
+                if (ref($result) eq 'HASH') {
+                    $privileged{$dom}{$role} = $result;
+                }
+            } else {
+                $needroles = 1;
+            }
+        }
+        if ($needroles) {
+            my %dompersonnel = &get_domain_roles($dom,$roles);
+            $privileged{$dom} = {};
+            foreach my $server (keys(%dompersonnel)) {
+                if (ref($dompersonnel{$server}) eq 'HASH') {
+                    foreach my $item (keys(%{$dompersonnel{$server}})) {
+                        my ($trole,$uname,$udom,$rest) = split(/:/,$item,4);
+                        my ($end,$start) = split(/:/,$dompersonnel{$server}{$item});
+                        next if ($end && $end < $now);
+                        $privileged{$dom}{$trole}{$uname.':'.$udom} = 
+                            $dompersonnel{$server}{$item};
+                    }
+                }
+            }
+            if (ref($privileged{$dom}) eq 'HASH') {
+                foreach my $role (@{$roles}) {
+                    if (ref($privileged{$dom}{$role}) eq 'HASH') {
+                        &do_cache_new('priv_'.$role,$dom,$privileged{$dom}{$role},$cachetime);
+                    } else {
+                        my %hash = ();
+                        &do_cache_new('priv_'.$role,$dom,\%hash,$cachetime);
+                    }
+                }
+            }
+        }
+    }
+    return %privileged;
+}
+
 # -------------------------------------------------------- Get user privileges
 
 sub rolesinit {
@@ -8686,7 +8739,7 @@
     my %courses = &courseiddump($cdom, '.', 1, '.', '.', $cnum, undef, undef,
         '.');
 
-    return unless exists($courses{$cdom.'_'.$cnum});
+    return unless(exists($courses{$cdom.'_'.$cnum}));
     return wantarray ? ($cdom, $cnum) : $cdom.'_'.$cnum;
 }
 
@@ -10445,7 +10498,7 @@
         my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
         my ($tmp) = keys(%slots);
         if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
-            &Apache::lonnet::do_cache_new('allslots',$hashid,\%slots,600);
+            &do_cache_new('allslots',$hashid,\%slots,600);
             return %slots;
         }
     }
@@ -11604,7 +11657,7 @@
 	next if ($response->is_error());
 	my @content = split("\n",$response->content);
 	unless ($nocache) {
-	    &Apache::lonnet::do_cache_new('dns',$url,\@content,30*24*60*60);
+	    &do_cache_new('dns',$url,\@content,30*24*60*60);
 	}
 	&$func(\@content,$hashref);
 	return;
@@ -11979,9 +12032,9 @@
 	    }
 	    push(@{$iphost{$ip}},@{$name_to_host{$name}});
 	}
-	&Apache::lonnet::do_cache_new('iphost','iphost',
-				      [\%iphost,\%name_to_ip,\%lonid_to_ip],
-				      48*60*60);
+	&do_cache_new('iphost','iphost',
+		      [\%iphost,\%name_to_ip,\%lonid_to_ip],
+		      48*60*60);
 
 	return %iphost;
     }
@@ -12037,7 +12090,7 @@
             }
             $seen{$prim_ip} = 1;
         }
-        return &Apache::lonnet::do_cache_new('internetnames',$lonid,\@idns,12*60*60);
+        return &do_cache_new('internetnames',$lonid,\@idns,12*60*60);
     }
 
 }
@@ -12536,7 +12589,7 @@
    
 =item *
 
-get_my_roles($uname,$udom,$context,$types,$roles,$roledoms,$withsec) :
+get_my_roles($uname,$udom,$context,$types,$roles,$roledoms,$withsec,$hidepriv) :
 All arguments are optional. Returns a hash of a roles, either for
 co-author/assistant author roles for a user's Construction Space
 (default), or if $context is 'userroles', roles for the user himself,
@@ -12559,7 +12612,31 @@
 to certain user status types -- previous (expired roles), active (currently
 available roles) or future (roles available in the future), and
 $hideprivileged -- if true will not report course roles for users who
-have active Domain Coordinator or Super User roles.
+have active Domain Coordinator role in course's domain or in additional
+domains (specified in 'Domains to check for privileged users' in course
+environment -- set via:  Course Settings -> Classlists and staff listing).
+
+=item *
+
+privileged($username,$domain,$possdomains,$possroles) : returns 1 if user
+$username:$domain is a privileged user (e.g., Domain Coordinator or Super User)
+$possdomains and $possroles are optional array refs -- to domains to check and
+roles to check.  If $possdomains is not specified, a dump will be done of the
+users' roles.db to check for a dc or su role in any domain. This can be
+time consuming if &privileged is called repeatedly (e.g., when displaying a
+classlist), so in such cases, supplying a $possdomains array is preferred, as
+this then allows &privileged_by_domain() to be used, which caches the identity
+of privileged users, eliminating the need for repeated calls to &dump().
+
+=item *
+
+privileged_by_domain($possdomains,$roles) : returns a hash of a hash of a hash,
+where the outer hash keys are domains specified in the $possdomains array ref,
+next inner hash keys are privileged roles specified in the $roles array ref,
+and the innermost hash contains key = value pairs for username:domain = end:start
+for active or future "privileged" users with that role in that domain. To avoid
+repeated dumps of domain roles -- via &get_domain_roles() -- contents of the
+innerhash are cached using priv_$role and $dom as the identifiers.
 
 =back
 


More information about the LON-CAPA-cvs mailing list