[LON-CAPA-cvs] cvs: loncom /interface loncreateuser.pm lonuserutils.pm

raeburn raeburn at source.lon-capa.org
Tue Oct 4 17:02:16 EDT 2016


raeburn		Tue Oct  4 21:02:16 2016 EDT

  Modified files:              
    /loncom/interface	loncreateuser.pm lonuserutils.pm 
  Log:
  - Move routines for creating/modifying custom roles to lonuserutils.pm to
    facilitate re-use.
  - Changes to standard role names and privilege names when switching from 
    Course to Commmunity, when adding/modifying custom roles, with a domain 
    role active, occur client-side, and no longer require page reload.
  
  
-------------- next part --------------
Index: loncom/interface/loncreateuser.pm
diff -u loncom/interface/loncreateuser.pm:1.413 loncom/interface/loncreateuser.pm:1.414
--- loncom/interface/loncreateuser.pm:1.413	Tue Sep 27 21:47:48 2016
+++ loncom/interface/loncreateuser.pm	Tue Oct  4 21:02:16 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Create a user
 #
-# $Id: loncreateuser.pm,v 1.413 2016/09/27 21:47:48 raeburn Exp $
+# $Id: loncreateuser.pm,v 1.414 2016/10/04 21:02:16 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -531,6 +531,72 @@
            &Apache::loncommon::end_data_table();
 }
 
+sub domadhocroles {
+    my ($ccuname,$ccdomain) = @_;
+    my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'}); 
+    my %existing=&Apache::lonnet::dump('roles',$env{'request.role.domain'},
+                                       $confname,'rolesdef_');
+    my $output;
+    if (keys(%existing) > 0) {
+        my @current;
+        my $curradhoc = 'adhocroles.'.$env{'request.role.domain'}; 
+        my %userenv = &Apache::lonnet::userenvironment($ccdomain,$ccuname,$curradhoc);
+        if ($userenv{$curradhoc}) {
+            @current = split(/,/,$userenv{$curradhoc});
+        }
+        my %customroles;
+        foreach my $key (keys(%existing)) {
+            if ($key=~/^rolesdef\_(\w+)$/) {
+                my $rolename = $1;
+                my %privs;
+                ($privs{'system'},$privs{'domain'},$privs{'course'}) = split(/\_/,$existing{$key});
+                $customroles{$rolename} = \%privs;
+            }
+        }
+        $output = '<br /><h3>'.
+                  &mt('Ad Hoc Course Roles Selectable via Helpdesk Role').
+                  '</h3>'."\n".
+                  &Apache::loncommon::start_data_table().
+                  &Apache::loncommon::start_data_table_header_row().
+                  '<th>'.&mt('Action').'</th><th>'.&mt('Role').'</th>'.
+                  '<th>'.&mt('Privileges in Course').'<th>'.
+                  &Apache::loncommon::end_data_table_header_row(); 
+        foreach my $key (sort(keys(%customroles))) {
+            $output .= &Apache::loncommon::start_data_table_row();
+            if (grep(/^\Q$key\E$/, at current)) {
+                $output .= '<td><label>'.
+                           '<input type="checkbox" name="adhocroledel" value="'.$key.'" />'.
+                           &mt('Delete').'</label>'.
+                           '</td>';
+            } else {
+                $output .= '<td><label>'.
+                           '<input type="checkbox" name="adhocroleadd" value="'.$key.'" />'.
+                           &mt('Add').'</label>'.
+                           '</td>';
+            }
+            $output .= '<td>'.$key.'</td><td>';
+            foreach my $level ('course','domain','system') {
+                if ($customroles{$key}{$level}) {
+                    my $suffix;
+                    if (($level eq 'domain') || ($level eq 'system')) {
+                        $suffix = ' ('.&mt($level).')';
+                    }
+                    my @privs = split(/:/,$customroles{$key}{$level});
+                    foreach my $item (@privs) {
+                        next if ($item eq ''); 
+                        my ($priv,$cond) = split(/\&/,$item);
+                        $output .= &Apache::lonnet::plaintext($priv,'Course').$suffix.'<br />';
+                    }
+                }
+            }
+            $output .= '</td>'.
+                       &Apache::loncommon::end_data_table_row();
+        }
+        $output .= &Apache::loncommon::end_data_table();
+    }
+    return $output;
+}
+
 sub courserequest_titles {
     my %titles = &Apache::lonlocal::texthash (
                                    official   => 'Official',
@@ -1241,7 +1307,7 @@
     }
     my $title = '';
     if ($newuser) {
-        my ($portfolioform,$domroleform);
+        my ($portfolioform,$domroleform,$adhocroleform);
         if ((&Apache::lonnet::allowed('mpq',$env{'request.role.domain'})) ||
             (&Apache::lonnet::allowed('mut',$env{'request.role.domain'}))) {
             # Current user has quota or user tools modification privileges
@@ -1251,6 +1317,12 @@
             ($ccdomain eq $env{'request.role.domain'})) {
             $domroleform = '<br />'.&domainrole_req($ccuname,$ccdomain);
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $adhocroleform = &domadhocroles($ccuname,$ccdomain);
+            if ($adhocroleform) {
+                $adhocroleform = '<br />'.$adhocroleform;
+            }
+        }
         &initialize_authen_forms($ccdomain,$formname);
         my %lt=&Apache::lonlocal::texthash(
                 'lg'             => 'Login Data',
@@ -1361,7 +1433,7 @@
         } else {
             $r->print(&Apache::lonuserutils::set_login($ccdomain,$authformkrb,$authformint,$authformloc)); 
         }
-        $r->print($portfolioform.$domroleform);
+        $r->print($portfolioform.$domroleform.$adhocroleform);
         if ($env{'form.action'} eq 'singlestudent') {
             $r->print(&date_sections_select($context,$newuser,$formname,
                                             $permission,$crstype,$ccuname,
@@ -1398,7 +1470,7 @@
             $r->print(&Apache::loncommon::end_data_table());
         }
         $r->print('</div>');
-        my @order = ('auth','quota','tools','requestauthor');
+        my @order = ('auth','quota','tools','requestauthor','adhocroles');
         my %user_text;
         my ($isadv,$isauthor) = 
             &Apache::lonnet::is_advanced_user($ccuname,$ccdomain);
@@ -1407,6 +1479,9 @@
             && ($env{'request.role.domain'} eq $ccdomain)) {
             $user_text{'requestauthor'} = &domainrole_req($ccuname,$ccdomain);
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $user_text{'adhocroles'} = &domadhocroles($ccuname,$ccdomain);
+        }
         $user_text{'auth'} =  &user_authentication($ccuname,$ccdomain,$formname);
         if ((&Apache::lonnet::allowed('mpq',$ccdomain)) ||
             (&Apache::lonnet::allowed('mut',$ccdomain))) {
@@ -2699,6 +2774,12 @@
                                                     $newcustom{'requestauthor'},
                                                     \%changeHash,'requestauthor');
                 }
+                if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+                    my @adds = &Apache::loncommon::get_env_multiple('form.adhocroleadd');
+                    if (&adhocrole_changes(\%changeHash)) {
+                        $changed{'adhocroles.'.$env{'request.role.domain'}} = $changeHash{'adhocroles.'.$env{'request.role.domain'}};
+                    }  
+                }
             }
             if ($canmodify_status{'inststatus'}) {
                 if (exists($env{'form.inststatus'})) {
@@ -2762,7 +2843,8 @@
              'requestcourses.community','requestcourses.textbook',
              'reqcrsotherdom.official','reqcrsotherdom.unofficial',
              'reqcrsotherdom.community','reqcrsotherdom.textbook',
-             'reqcrsotherdom.placement','requestauthor'],
+             'reqcrsotherdom.placement','requestauthor',
+             'adhocroles.'.$env{'request.role.domain'}],
               $env{'form.ccdomain'},$env{'form.ccuname'});
         my ($tmp) = keys(%userenv);
         if ($tmp =~ /^(con_lost|error)/i) { 
@@ -2901,6 +2983,7 @@
                 &Apache::loncommon::default_quota($env{'form.ccdomain'},$oldinststatus,$name);
             ($newdefquota{$name},$newsettingstatus{$name}) = ($olddefquota{$name},$oldsettingstatus{$name});
         }
+        push(@disporder,'adhocroles');
         my %canshow;
         if (&Apache::lonnet::allowed('mpq',$env{'form.ccdomain'})) {
             $canshow{'quota'} = 1;
@@ -2919,6 +3002,9 @@
         if (&Apache::lonnet::allowed('cau',$env{'form.ccdomain'})) {
             $canshow{'requestauthor'} = 1;
         }
+        if (&Apache::lonnet::allowed('cdh',$env{'request.role.domain'})) {
+            $canshow{'adhocroles'} = 1;
+        }
         my (%changeHash,%changed);
         if ($oldinststatus eq '') {
             $oldsettings{'inststatus'} = $othertitle; 
@@ -3032,6 +3118,14 @@
                 &tool_changes('reqcrsotherdom',\@requestcourses,\%oldsettings,\%oldsettingstext,
                               \%userenv,\%changeHash,\%changed,\%newsettings,\%newsettingstext);
             }
+            if ($userenv{'adhocroles.'.$env{'request.role.domain'}}) {
+                $changeHash{'adhocroles.'.$env{'request.role.domain'}} = $userenv{'adhocroles.'.$env{'request.role.domain'}};
+            }
+            if (&adhocrole_changes(\%changeHash,\%userenv)) {
+                $changed{'adhocroles'} = 1;
+                $oldsettings{'adhocroles'} = $userenv{'adhocroles.'.$env{'request.role.domain'}};
+                $newsettings{'adhocroles'} = $changeHash{'adhocroles.'.$env{'request.role.domain'}}; 
+            }
         }
         foreach my $item (@userinfo) {
             if ($env{'form.c'.$item} ne $userenv{$item}) {
@@ -3074,6 +3168,9 @@
           &Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},
                                             $key,'reload','requestauthor');
                                 }
+                            } elsif ($key eq 'adhocroles') {
+                                $newenvhash{'adhocroles.'.$env{'request.role.domain'}} =
+                                    $changeHash{'adhocroles.'.$env{'request.role.domain'}};
                             } elsif ($key ne 'quota') {
                                 $newenvhash{'environment.tools.'.$key} = 
                                     $changeHash{'tools.'.$key};
@@ -3266,6 +3363,7 @@
          'textbook'       => 'Can Request Textbook Courses',
          'placement'      => 'Can Request Placement Tests',
          'requestauthor'  => 'Can Request Author Role',
+         'adhocroles'     => 'Ad Hoc Roles Selectable via Helpdesk Role',
          'inststatus'     => "Affiliation",
          'prvs'           => 'Previous Value:',
          'chto'           => 'Changed To:'
@@ -3631,6 +3729,70 @@
     return;
 }
 
+sub adhocrole_changes {
+    my ($changehashref,$userenv) = @_;
+    my @adds = &Apache::loncommon::get_env_multiple('form.adhocroleadd');
+    my @dels = &Apache::loncommon::get_env_multiple('form.adhocroledel');
+    my (@saved, at added, at alladhoc,$changed);
+    my $adhoc_key = 'adhocroles.'.$env{'request.role.domain'};
+    if (!$env{'form.makeuser'}) {
+        if (ref($userenv) eq 'HASH') {
+            my @current;
+            if ($userenv->{$adhoc_key}) {
+                @current = split(/,/,$userenv->{$adhoc_key});
+                if (@dels) {
+                    foreach my $curr (@current) {
+                        next if ($curr eq ''); 
+                        unless (grep(/\Q$curr\E$/, at dels)) {
+                            push(@saved,$curr);
+                        }
+                    }
+                    $changed = 1;
+                } else {
+                    @saved = @current;
+                }
+            }
+        }
+    }
+    if (@adds) {
+        my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'});
+        my %existing=&Apache::lonnet::dump('roles',$env{'request.role.domain'},
+                                           $confname,'rolesdef_');
+        foreach my $poss (@adds) {
+            if (exists($existing{'rolesdef_'.$poss})) {
+                push(@added,$poss);
+                $changed = 1;
+            }
+        }
+    }
+    if (@added) {
+        if (@saved) {
+            foreach my $add (@added) {
+                unless (grep(/^\Q$add\E$/, at saved)) {
+                    push(@alladhoc,$add);
+                }
+            }
+        } else {
+            push(@alladhoc, at added);
+        }
+    }
+    if (@saved) {
+        push(@alladhoc, at saved);
+    }
+    if (@alladhoc) {
+        my $adhocstr = join(',',sort(@alladhoc)); 
+        $changehashref->{$adhoc_key} = $adhocstr;
+    } elsif (@dels) {
+        &Apache::lonnet::del('environment',[$adhoc_key],$env{'form.ccdomain'},$env{'form.ccuname'});
+        delete($changehashref->{$adhoc_key});
+        if (($env{'form.ccdomain'} eq $env{'user.domain'}) &&
+            ($env{'form.ccuname'} eq $env{'user.name'})) {
+            &Apache::lonnet::delenv($adhoc_key);
+        }
+    }
+    return $changed;
+}
+
 sub update_roles {
     my ($r,$context,$showcredits) = @_;
     my $now=time;
@@ -4161,7 +4323,7 @@
 # ========================================================== Custom Role Editor
 
 sub custom_role_editor {
-    my ($r,$brcrum) = @_;
+    my ($r,$brcrum,$prefix) = @_;
     my $action = $env{'form.customroleaction'};
     my $rolename; 
     if ($action eq 'new') {
@@ -4176,7 +4338,7 @@
         $context = 'course';
     } else {
         $context = 'domain';
-        $crstype = $env{'form.templatecrstype'};
+        $crstype = 'course';
     }
 
     $rolename=~s/[^A-Za-z0-9]//gs;
@@ -4185,120 +4347,54 @@
         return;
     }
 
-# ------------------------------------------------------- What can be assigned?
-    my %full=();
-    my %courselevel=();
-    my %courselevelcurrent=();
-    my $syspriv='';
-    my $dompriv='';
-    my $coursepriv='';
-    my $body_top;
-    my $newrole;
+    my $formname = 'form1';
+    my %privs=();
+    my $body_top = '<h2>';
+# ------------------------------------------------------- Does this role exist?
     my ($rdummy,$roledef)=
 			 &Apache::lonnet::get('roles',["rolesdef_$rolename"]);
-# ------------------------------------------------------- Does this role exist?
-    $body_top .= '<h2>';
     if (($rdummy ne 'con_lost') && ($roledef ne '')) {
-	$body_top .= &mt('Existing Role').' "';
+        $body_top .= &mt('Existing Role').' "';
 # ------------------------------------------------- Get current role privileges
-	($syspriv,$dompriv,$coursepriv)=split(/\_/,$roledef);
-        if ($crstype eq 'Community') {
-            $syspriv =~ s/bre\&S//;   
+        ($privs{'system'},$privs{'domain'},$privs{'course'})=split(/\_/,$roledef);
+        if ($privs{'system'} =~ /bre\&S/) {
+            if ($context eq 'domain') {
+                $crstype = 'Course'; 
+            } elsif ($crstype eq 'Community') {
+                $privs{'system'} =~ s/bre\&S//;
+            }
+        } elsif ($context eq 'domain') {
+            $crstype = 'Course';
         }
     } else {
-        $newrole = 1;
-	$body_top .= &mt('New Role').' "';
-	$roledef='';
+        $body_top .= &mt('New Role').' "';
+        $roledef='';
     }
     $body_top .= $rolename.'"</h2>';
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $courselevel{$priv}=$restrict;
-        if ($coursepriv=~/\:$priv/) {
-	    $courselevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
-    my %domainlevel=();
-    my %domainlevelcurrent=();
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $domainlevel{$priv}=$restrict;
-        if ($dompriv=~/\:$priv/) {
-	    $domainlevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
-    my %systemlevel=();
-    my %systemlevelcurrent=();
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict='F'; }
-        $systemlevel{$priv}=$restrict;
-        if ($syspriv=~/\:$priv/) {
-	    $systemlevelcurrent{$priv}=1;
-	}
-	$full{$priv}=1;
-    }
+
+# ------------------------------------------------------- What can be assigned?
+    my %full=();
+    my %levels=( 
+                 course => {},
+                 domain => {},
+                 system => {},
+               );
+    my %levelscurrent=(
+                        course => {},
+                        domain => {},
+                        system => {},
+                      );
+    &Apache::lonuserutils::custom_role_privs(\%privs,\%full,\%levels,\%levelscurrent);
     my ($jsback,$elements) = &crumb_utilities();
-    my $button_code = "\n";
-    my $head_script = "\n";
-    $head_script .= '<script type="text/javascript">'."\n"
-                   .'// <![CDATA['."\n";
-    my @template_roles = ("in","ta","ep");
-    if ($context eq 'domain') {
-        push(@template_roles,"ad");
-    }
-    push(@template_roles,"st");
-    if ($crstype eq 'Community') {
-        unshift(@template_roles,'co');
-    } else {
-        unshift(@template_roles,'cc');
-    }
-    foreach my $role (@template_roles) {
-        $head_script .= &make_script_template($role,$crstype);
-        $button_code .= &make_button_code($role,$crstype).' ';
-    }
-    my $context_code;
-    if ($context eq 'domain') {
-        my $checkedCommunity = '';
-        my $checkedCourse = ' checked="checked"';
-        if ($env{'form.templatecrstype'} eq 'Community') {
-            $checkedCommunity = $checkedCourse;
-            $checkedCourse = '';
-        }
-        $context_code = '<label>'.
-                        '<input type="radio" name="templatecrstype" value="Course"'.$checkedCourse.' onclick="this.form.submit();">'.
-                        &mt('Course').
-                        '</label>'.(' ' x2).
-                        '<label>'.
-                        '<input type="radio" name="templatecrstype" value="Community"'.$checkedCommunity.' onclick="this.form.submit();">'.
-                        &mt('Community').
-                        '</label>'.
-                        '</fieldset>'.
-                        '<input type="hidden" name="customroleaction" value="'.
-                        $action.'" />';
-        if ($env{'form.customroleaction'} eq 'new') {
-            $context_code .= '<input type="hidden" name="newrolename" value="'.
-                             $rolename.'" />';
-        } else {
-            $context_code .= '<input type="hidden" name="rolename" value="'.
-                             $rolename.'" />';
-        }
-        $context_code .= '<input type="hidden" name="action" value="custom" />'.
-                         '<input type="hidden" name="phase" value="selected_custom_edit" />';
-    }
-
-    $head_script .= "\n".$jsback."\n"
-                   .'// ]]>'."\n"
-                   .'</script>'."\n";
+    my @templateroles = &Apache::lonuserutils::custom_template_roles($context,$crstype);
+    my $head_script = 
+        &Apache::lonuserutils::custom_roledefs_js($context,$crstype,$formname,
+                                                  \%full,\@templateroles,$jsback);
     push (@{$brcrum},
-              {href => "javascript:backPage(document.form1,'pickrole','')",
+              {href => "javascript:backPage(document.$formname,'pickrole','')",
                text => "Pick custom role",
                faq  => 282,bug=>'Instructor Interface',},
-              {href => "javascript:backPage(document.form1,'','')",
+              {href => "javascript:backPage(document.$formname,'','')",
                text => "Edit custom role",
                faq  => 282,
                bug  => 'Instructor Interface',
@@ -4310,57 +4406,16 @@
     $r->print(&Apache::loncommon::start_page('Custom Role Editor',
                                              $head_script,$args).
               $body_top);
-    my %lt=&Apache::lonlocal::texthash(
-		    'prv'  => "Privilege",
-		    'crl'  => "Course Level",
-                    'dml'  => "Domain Level",
-                    'ssl'  => "System Level");
-
-    $r->print('<div class="LC_left_float">'
-             .'<form action=""><fieldset>'
-             .'<legend>'.&mt('Select a Template').'</legend>'
-             .$button_code
-             .'</fieldset></form></div>');
-    if ($context_code) {
-        $r->print('<div class="LC_left_float">'
-                 .'<form action="/adm/createuser" method="post"><fieldset>'
-                 .'<legend>'.&mt('Context').'</legend>'
-                 .$context_code
-                 .'</form>'
-                 .'</div>'
-        );
-    }
-    $r->print('<br clear="all" />');
+    $r->print('<form name="'.$formname.'" method="post" action="">'."\n".
+              &Apache::lonuserutils::custom_role_header($context,$crstype,
+                                                        \@templateroles,$prefix));
 
     $r->print(<<ENDCCF);
-<form name="form1" method="post" action="">
 <input type="hidden" name="phase" value="set_custom_roles" />
 <input type="hidden" name="rolename" value="$rolename" />
 ENDCCF
-    $r->print(&Apache::loncommon::start_data_table().
-              &Apache::loncommon::start_data_table_header_row(). 
-'<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}.
-'</th><th>'.$lt{'ssl'}.'</th>'.
-              &Apache::loncommon::end_data_table_header_row());
-    foreach my $priv (sort(keys(%full))) {
-        my $privtext = &Apache::lonnet::plaintext($priv,$crstype);
-        $r->print(&Apache::loncommon::start_data_table_row().
-	          '<td>'.$privtext.'</td><td>'.
-    ($courselevel{$priv}?'<input type="checkbox" name="'.$priv.'_c"'.
-    ($courselevelcurrent{$priv}?' checked="checked"':'').' />':' ').
-    '</td><td>'.
-    ($domainlevel{$priv}?'<input type="checkbox" name="'.$priv.'_d"'.
-    ($domainlevelcurrent{$priv}?' checked="checked"':'').' />':' ').
-    '</td><td>');
-        if ($priv eq 'bre' && $crstype eq 'Community') {
-            $r->print(' ');  
-        } else {
-            $r->print($systemlevel{$priv}?'<input type="checkbox" name="'.$priv.'_s"'.
-                      ($systemlevelcurrent{$priv}?' checked="checked"':'').' />':' ');
-        }
-        $r->print('</td>'.
-                  &Apache::loncommon::end_data_table_row());
-    }
+    $r->print(&Apache::lonuserutils::custom_role_table($crstype,\%full,\%levels,
+                                                       \%levelscurrent,$prefix));
     $r->print(&Apache::loncommon::end_data_table().
    '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
    '<input type="hidden" name="startrolename" value="'.$env{'form.rolename'}.
@@ -4368,87 +4423,14 @@
    '<input type="reset" value="'.&mt("Reset").'" />'."\n".
    '<input type="submit" value="'.&mt('Save').'" /></form>');
 }
-# --------------------------------------------------------
-sub make_script_template {
-    my ($role,$crstype) = @_;
-    my %full_c=();
-    my %full_d=();
-    my %full_s=();
-    my $return_script;
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_c{$priv}=1;
-    }
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_d{$priv}=1;
-    }
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-        next if (($crstype eq 'Community') && ($item eq 'bre&S'));
-        my ($priv,$restrict)=split(/\&/,$item);
-        $full_s{$priv}=1;
-    }
-    $return_script .= 'function set_'.$role.'() {'."\n";
-    my @temp = split(/:/,$Apache::lonnet::pr{$role.':c'});
-    my %role_c;
-    foreach my $priv (@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_c{$priv_item} = 1;
-    }
-    my %role_d;
-    @temp = split(/:/,$Apache::lonnet::pr{$role.':d'});
-    foreach my $priv(@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_d{$priv_item} = 1;
-    }
-    my %role_s;
-    @temp = split(/:/,$Apache::lonnet::pr{$role.':s'});
-    foreach my $priv(@temp) {
-        my ($priv_item, $dummy) = split(/\&/,$priv);
-        $role_s{$priv_item} = 1;
-    }
-    foreach my $priv_item (keys(%full_c)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if ((exists($role_c{$priv})) || (exists($role_d{$priv})) || 
-            (exists($role_s{$priv}))) {
-            $return_script .= "document.form1.$priv"."_c.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_c.checked = false;\n";
-        }
-    }
-    foreach my $priv_item (keys(%full_d)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if ((exists($role_d{$priv})) || (exists($role_s{$priv}))) {
-            $return_script .= "document.form1.$priv"."_d.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_d.checked = false;\n";
-        }
-    }
-    foreach my $priv_item (keys(%full_s)) {
-        my ($priv, $dummy) = split(/\&/,$priv_item);
-        if (exists($role_s{$priv})) {
-            $return_script .= "document.form1.$priv"."_s.checked = true;\n";
-        } else {
-            $return_script .= "document.form1.$priv"."_s.checked = false;\n";
-        }
-    }
-    $return_script .= '}'."\n";
-    return ($return_script);
-}
-# ----------------------------------------------------------
-sub make_button_code {
-    my ($role,$crstype) = @_;
-    my $label = &Apache::lonnet::plaintext($role,$crstype);
-    my $button_code = '<input type="button" onclick="set_'.$role.'()" value="'.$label.'" />';
-    return ($button_code);
-}
+
 # ---------------------------------------------------------- Call to definerole
 sub set_custom_role {
-    my ($r,$context,$brcrum) = @_;
+    my ($r,$context,$brcrum,$prefix) = @_;
     my $rolename=$env{'form.rolename'};
     $rolename=~s/[^A-Za-z0-9]//gs;
     if (!$rolename) {
-	&custom_role_editor($r,$brcrum);
+	&custom_role_editor($r,$brcrum,$prefix);
         return;
     }
     my ($jsback,$elements) = &crumb_utilities();
@@ -4473,7 +4455,7 @@
          help => 'Course_Editing_Custom_Roles'},
         );
     my $args = { bread_crumbs           => $brcrum,
-                 bread_crumbs_component => 'User Management'}; 
+                 bread_crumbs_component => 'User Management'};
     $r->print(&Apache::loncommon::start_page('Save Custom Role',$jscript,$args));
 
     my $newrole;
@@ -4490,38 +4472,13 @@
         $newrole = 1;
     }
     $r->print($rolename.'"</h3>');
-# ------------------------------------------------------- What can be assigned?
-    my $sysrole='';
-    my $domrole='';
-    my $courole='';
-
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:c'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_c'}) {
-	    $courole.=':'.$item;
-	}
-    }
+# ------------------------------------------------- Assign role and show result
 
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:d'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_d'}) {
-	    $domrole.=':'.$item;
-	}
-    }
-
-    foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:s'})) {
-	my ($priv,$restrict)=split(/\&/,$item);
-        if (!$restrict) { $restrict=''; }
-        if ($env{'form.'.$priv.'_s'}) {
-	    $sysrole.=':'.$item;
-	}
-    }
-    # Assign role; Compile and show result
     my $errmsg;
-    my $result =
-        &Apache::lonnet::definerole($rolename,$sysrole,$domrole,$courole);
+    my %newprivs = &Apache::lonuserutils::custom_role_update($rolename,$prefix);
+    # Assign role and return result
+    my $result = &Apache::lonnet::definerole($rolename,$newprivs{'s'},$newprivs{'d'},
+                                             $newprivs{'c'});
     if ($result ne 'ok') {
         $errmsg = ': '.$result;
     }
@@ -4728,10 +4685,11 @@
                                        $brcrum);
         }
     } elsif ($env{'form.action'} eq 'custom' && $permission->{'custom'}) {
+        my $prefix;
         if ($env{'form.phase'} eq 'set_custom_roles') {
-            &set_custom_role($r,$context,$brcrum);
+            &set_custom_role($r,$context,$brcrum,$prefix);
         } else {
-            &custom_role_editor($r,$brcrum);
+            &custom_role_editor($r,$brcrum,$prefix);
         }
     } elsif (($env{'form.action'} eq 'processauthorreq') &&
              ($permission->{'cusr'}) && 
Index: loncom/interface/lonuserutils.pm
diff -u loncom/interface/lonuserutils.pm:1.174 loncom/interface/lonuserutils.pm:1.175
--- loncom/interface/lonuserutils.pm:1.174	Sun Jul 24 14:34:59 2016
+++ loncom/interface/lonuserutils.pm	Tue Oct  4 21:02:16 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA user accounts
 #
-# $Id: lonuserutils.pm,v 1.174 2016/07/24 14:34:59 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.175 2016/10/04 21:02:16 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -30,6 +30,22 @@
 
 package Apache::lonuserutils;
 
+=pod
+
+=head1 NAME
+
+Apache::lonuserutils.pm
+
+=head1 SYNOPSIS
+
+    Utilities for management of users and custom roles
+
+    Provides subroutines called by loncreateuser.pm
+
+=head1 OVERVIEW
+
+=cut
+
 use strict;
 use Apache::lonnet;
 use Apache::loncommon();
@@ -1531,10 +1547,10 @@
 # ======================================================= Existing Custom Roles
 
 sub my_custom_roles {
-    my ($crstype) = @_;
+    my ($crstype,$udom,$uname) = @_;
     my %returnhash=();
     my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
-    my %rolehash=&Apache::lonnet::dump('roles');
+    my %rolehash=&Apache::lonnet::dump('roles',$udom,$uname);
     foreach my $key (keys(%rolehash)) {
         if ($key=~/^rolesdef\_(\w+)$/) {
             if ($crstype eq 'Community') {
@@ -5794,7 +5810,7 @@
     } elsif ($context eq 'author') {
         @allroles = ('ca','aa');
     } elsif ($context eq 'domain') {
-        @allroles = ('li','ad','dg','sc','au','dc');
+        @allroles = ('li','ad','dg','dh','sc','au','dc');
     }
     return @allroles;
 }
@@ -6307,5 +6323,336 @@
     return (\@in_course,\@in_domain);
 }
 
+sub custom_role_header {
+    my ($context,$crstype,$templaterolerefs,$prefix) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+                 sele => 'Select a Template',
+    );
+    my ($context_code,$button_code);
+    if ($context eq 'domain') {
+        $context_code = &custom_coursetype_switch($crstype,$prefix);
+    }
+    if (ref($templaterolerefs) eq 'ARRAY') {
+        foreach my $role (@{$templaterolerefs}) {
+            my $display = 'inline';
+            if (($context eq 'domain') && ($role eq 'co')) {
+                $display = 'none';
+            }
+            $button_code .= &make_button_code($role,$crstype,$display,$prefix).' ';
+        }
+    }
+    return <<"END";
+<div class="LC_left_float">
+<fieldset>
+<legend>$lt{'sele'}</legend>
+$button_code
+</fieldset></div>
+$context_code
+<br clear="all" />
+END
+}
+
+sub custom_coursetype_switch {
+    my ($crstype,$prefix) = @_;
+    my ($checkedcourse,$checkedcommunity);
+    if ($crstype eq 'Community') {
+        $checkedcommunity = ' checked="checked"';
+    } else {
+        $checkedcourse = ' checked="checked"';
+    }
+    my %lt = &Apache::lonlocal::texthash(
+        cont => 'Context',
+        cour => 'Course',
+        comm => 'Community',
+    );
+    return <<"END";
+<div class="LC_left_float">
+<fieldset>
+<legend>$lt{'cont'}</legend>
+<label>
+<input type="radio" name="${prefix}_custrolecrstype" value="Course"$checkedcourse onclick="javascript:customSwitchType('$prefix');" />
+$lt{'cour'}
+</label>  
+<label>
+<input type="radio" name="${prefix}_custrolecrstype" value="Community"$checkedcommunity onclick="javascript:customSwitchType('$prefix');" />
+$lt{'comm'}
+</label>
+</fieldset>
+</div>
+END
+}
+
+sub custom_role_table {
+    my ($crstype,$full,$levels,$levelscurrent,$prefix) = @_;
+    return unless ((ref($full) eq 'HASH') && (ref($levels) eq 'HASH') &&
+                   (ref($levelscurrent) eq 'HASH'));
+    my %lt=&Apache::lonlocal::texthash (
+                    'prv'  => "Privilege",
+                    'crl'  => "Course Level",
+                    'dml'  => "Domain Level",
+                    'ssl'  => "System Level");
+    my %cr = (
+               course => '_c',
+               domain => '_d',
+               system => '_s',
+             );
+
+    my $output=&Apache::loncommon::start_data_table().
+               &Apache::loncommon::start_data_table_header_row().
+               '<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}.
+               '</th><th>'.$lt{'ssl'}.'</th>'.
+               &Apache::loncommon::end_data_table_header_row();
+    foreach my $priv (sort(keys(%{$full}))) {
+        my $privtext = &Apache::lonnet::plaintext($priv,$crstype);
+        $output .= &Apache::loncommon::start_data_table_row().
+                  '<td><span id="'.$prefix.$priv.'">'.$privtext.'</span></td>';
+        foreach my $type ('course','domain','system') {
+            if (($type eq 'system') && ($priv eq 'bre') && ($crstype eq 'Community')) {
+                $output .= '<td> </td>';
+            } else {
+                $output .= '<td>'.
+                  ($levels->{$type}{$priv}?'<input type="checkbox" id="'.$prefix.$priv.$cr{$type}.'"'.
+                  ' name="'.$prefix.$priv.$cr{$type}.'"'.
+                  ($levelscurrent->{$type}{$priv}?' checked="checked"':'').' />':' ').
+                  '</td>';
+            }
+        }
+        $output .= &Apache::loncommon::end_data_table_row();
+    }
+    $output .= &Apache::loncommon::end_data_table();
+    return $output;
+}
+
+sub custom_role_privs {
+    my ($privs,$full,$levels,$levelscurrent)= @_;
+    return unless ((ref($privs) eq 'HASH') && (ref($full) eq 'HASH') &&
+                   (ref($levels) eq 'HASH') && (ref($levelscurrent) eq 'HASH'));
+    my %cr = (
+               course => 'cr:c',
+               domain => 'cr:d',
+               system => 'cr:s',
+             );
+    foreach my $type ('course','domain','system') {
+        foreach my $item (split(/\:/,$Apache::lonnet::pr{$cr{$type}})) {
+            my ($priv,$restrict)=split(/\&/,$item);
+            if (!$restrict) { $restrict='F'; }
+            $levels->{$type}->{$priv}=$restrict;
+            if ($privs->{$type}=~/\:$priv/) {
+                $levelscurrent->{$type}->{$priv}=1;
+            }
+            $full->{$priv}=1;
+        }
+    }
+    return;
+}
+
+sub custom_template_roles {
+    my ($context,$crstype) = @_;
+    my @template_roles = ("in","ta","ep");
+    if (($context eq 'domain') || ($context eq 'domprefs')) {
+        push(@template_roles,"ad");
+    }
+    push(@template_roles,"st");
+    if ($context eq 'domain') {
+        unshift(@template_roles,('co','cc'));
+    } else {
+        if ($crstype eq 'Community') {
+            unshift(@template_roles,'co');
+        } else {
+            unshift(@template_roles,'cc');
+        }
+    }
+    return @template_roles;
+}
+
+sub custom_roledefs_js {
+    my ($context,$crstype,$formname,$full,$templaterolesref,$jsback) = @_;
+    my $button_code = "\n";
+    my $head_script = "\n";
+    my (%roletitlestr,$rolenamestr);
+    my %role_titles = (
+                        Course    => [],
+                        Community => [],
+                      );
+    $head_script .= '<script type="text/javascript">'."\n"
+                   .'// <![CDATA['."\n";
+    if (ref($templaterolesref) eq 'ARRAY') {
+        if ($context eq 'domain') {
+            $rolenamestr = join("','",@{$templaterolesref});
+        }
+        foreach my $role (@{$templaterolesref}) {
+            $head_script .= &make_script_template($role,$crstype,$formname);
+            if ($context eq 'domain') {
+                foreach my $type ('Course','Community') {
+                    push(@{$role_titles{$type}},&Apache::lonnet::plaintext($role,$type));
+                }
+            }
+        }
+    }
+    if ($context eq 'domain') {
+        foreach my $type ('Course','Community') {
+            $roletitlestr{$type} = join("','",@{$role_titles{$type}});
+        }
+        my %pt = (
+            Community => {
+                           cst => &mt('Grant/revoke role of Member'),
+                           mdc => &mt('Edit community contents'),
+                           pch => &mt('Post discussion on community resources'),
+                           pfo => &mt('Print for other users and entire community'),
+                         },
+            Course    => {
+                           cst => &mt('Grant/revoke role of Student'),
+                           mdc => &mt('Edit course contents'),
+                           pch => &mt('Post discussion on course resources'),
+                           pfo => &mt('Print for other users and entire course'),
+                         },
+        );
+        $head_script .= <<"ENDJS";
+function customSwitchType(prefix) {
+    var privnames = new Array('cst','mdc','pch','pfo');
+    var privtxtcrs = new Array('$pt{Course}{cst}','$pt{Course}{mdc}','$pt{Course}{pch}','$pt{Course}{pfo}');
+    var privtxtcom = new Array('$pt{Community}{cst}','$pt{Community}{mdc}','$pt{Community}{pch}','$pt{Community}{pfo}');
+    var rolenames = new Array('$rolenamestr');
+    var rolescrs = new Array('$roletitlestr{Course}');
+    var rolescom = new Array('$roletitlestr{Community}');
+    var radio = prefix+'_custrolecrstype';
+    if (document.$formname.elements[radio].length > 1) {
+        for (var i=0; i<document.$formname.elements[radio].length; i++) {
+            if (document.$formname.elements[radio][i].checked) {
+                if ((document.getElementById(prefix+'bre_s')) && (document.getElementById(prefix+'bro_s'))) {
+                    if (document.$formname.elements[radio][i].value == 'Community') {
+                        if (document.getElementById(prefix+'bre_s').checked) {
+                            document.getElementById(prefix+'bro_s').checked = true;
+                            document.getElementById(prefix+'bre_s').checked = false;
+
+                        }
+                        document.getElementById(prefix+'bre_s').style.visibility = 'hidden';
+                    } else {
+                        document.getElementById(prefix+'bre_s').style.visibility = 'visible';
+                        if (document.getElementById(prefix+'bro_s').checked) {
+                            document.getElementById(prefix+'bre_s').checked = true;
+                            document.getElementById(prefix+'bro_s').checked = false;
+                        }
+                    }
+                }
+                for (var j=0; j<privnames.length; j++) {
+                    if (document.getElementById(prefix+privnames[j])) {
+                        if (document.getElementById(prefix+privnames[j])) {
+                            if (document.$formname.elements[radio][i].value == 'Course') {
+                                document.getElementById(prefix+privnames[j]).innerHTML = privtxtcrs[j];
+                            } else {
+                                document.getElementById(prefix+privnames[j]).innerHTML = privtxtcom[j];
+                            }
+                        }
+                    }
+                }
+                for (var j=0; j<rolenames.length; j++) {
+                    if (document.getElementById(prefix+rolenames[j])) {
+                        if (document.getElementById(prefix+rolenames[j])) {
+                            if (document.$formname.elements[radio][i].value == 'Course') {
+                                document.getElementById(prefix+rolenames[j]).value = rolescrs[j];
+                                if (rolenames[j] == 'cc') {
+                                    document.getElementById(prefix+rolenames[j]).style.display = 'inline';
+                                }
+                                if (rolenames[j] == 'co') {
+                                    document.getElementById(prefix+rolenames[j]).style.display = 'none';
+                                }
+                            } else {
+                                document.getElementById(prefix+rolenames[j]).value = rolescom[j];
+                                if (rolenames[j] == 'cc') {
+                                    document.getElementById(prefix+rolenames[j]).style.display = 'none';
+                                }
+                                if (rolenames[j] == 'co') {
+                                    document.getElementById(prefix+rolenames[j]).style.display = 'inline';
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+ENDJS
+    }
+    $head_script .= "\n".$jsback."\n"
+                   .'// ]]>'."\n"
+                   .'</script>'."\n";
+    return $head_script;
+}
+
+# --------------------------------------------------------
+sub make_script_template {
+    my ($role,$crstype,$formname) = @_;
+    my $return_script = 'function set_'.$role.'(prefix) {'."\n";
+    my (%full_by_level,%role_priv);
+    foreach my $level ('c','d','s') {
+        foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
+            next if (($level eq 's') && ($crstype eq 'Community') && ($item eq 'bre&S'));
+            my ($priv,$restrict)=split(/\&/,$item);
+            $full_by_level{$level}{$priv}=1;
+        }
+        $role_priv{$level} = {};
+        my @temp = split(/:/,$Apache::lonnet::pr{$role.':'.$level});
+        foreach my $priv (@temp) {
+            my ($priv_item, $dummy) = split(/\&/,$priv);
+            $role_priv{$level}{$priv_item} = 1;
+        }
+    }
+    my %to_check = (
+                      c => ['c','d','s'],
+                      d => ['d','s'],
+                      s => ['s'],
+                   );
+    foreach my $level ('c','d','s') {
+        if (ref($full_by_level{$level}) eq 'HASH') {
+            foreach my $priv (keys(%{$full_by_level{$level}})) {
+                my $value = 'false';
+                if (ref($to_check{$level}) eq 'ARRAY') {
+                    foreach my $lett (@{$to_check{$level}}) {
+                        if (exists($role_priv{$lett}{$priv})) {
+                            $value = 'true';
+                            last;
+                        }
+                    }
+                    $return_script .= "document.$formname.elements[prefix+'".$priv."_".$level."'].checked = $value;\n";
+                }
+            }
+        }
+    }
+    $return_script .= '}'."\n";
+    return ($return_script);
+}
+# ----------------------------------------------------------
+sub make_button_code {
+    my ($role,$crstype,$display,$prefix) = @_;
+    my $label = &Apache::lonnet::plaintext($role,$crstype);
+    my $button_code = '<input type="button" onclick="set_'.$role."('$prefix'".')" '.
+                      'id="'.$prefix.$role.'" value="'.$label.'" '.
+                      'style="display:'.$display.'" />';
+    return ($button_code);
+}
+
+sub custom_role_update {
+    my ($rolename,$prefix) = @_;
+# ------------------------------------------------------- What can be assigned?
+    my %privs = (
+                      c => '',
+                      d => '',
+                      s => '',
+                    );
+    foreach my $level (keys(%privs)) {
+        foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
+            my ($priv,$restrict)=split(/\&/,$item);
+            if (!$restrict) { $restrict=''; }
+            if ($env{'form.'.$prefix.$priv.'_'.$level}) {
+                $privs{$level} .=':'.$item;
+            }
+        }
+    }
+    return %privs;
+}
+
 1;
 


More information about the LON-CAPA-cvs mailing list