--- loncom/interface/lonmodifycourse.pm	2016/11/10 21:57:10	1.79.2.4
+++ loncom/interface/lonmodifycourse.pm	2019/07/26 17:43:54	1.79.2.7
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # handler for DC-only modifiable course settings
 #
-# $Id: lonmodifycourse.pm,v 1.79.2.4 2016/11/10 21:57:10 raeburn Exp $
+# $Id: lonmodifycourse.pm,v 1.79.2.7 2019/07/26 17:43:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -39,6 +39,9 @@ use Apache::lonpickcourse;
 use lib '/home/httpd/lib/perl';
 use LONCAPA qw(:DEFAULT :match);
 
+my $registered_cleanup;
+my $modified_dom;
+
 sub get_dc_settable {
     my ($type,$cdom) = @_;
     if ($type eq 'Community') {
@@ -189,23 +192,20 @@ sub print_course_search_page {
            $settingsoption = &mt('View or modify course settings which only a [_1] may modify.',$dctitle);
        }
     } elsif (&Apache::lonnet::allowed('rar',$dom)) {
-        my %adhocroles = &Apache::lonnet::userenvironment($env{'user.domain'},$env{'user.name'},
-                                                         'adhocroles.'.$dom);
-        if (keys(%adhocroles)) {
-            my @adhoc = split(',',$adhocroles{'adhocroles.'.$dom});
-            if (@adhoc > 1) {
+        my ($roles_by_num,$description,$accessref,$accessinfo) = &Apache::lonnet::get_all_adhocroles($dom);
+        if ((ref($roles_by_num) eq 'ARRAY') && (ref($description) eq 'HASH')) {
+            if (@{$roles_by_num} > 1) {
                 if ($type eq 'Community') {
-                    $roleoption = &mt('Enter the community with one of the available ad hoc roles: [_1].',
-                                  join(', ',@adhoc));
+                    $roleoption = &mt('Enter the community with one of the available ad hoc roles');
                 } else {
-                    $roleoption = &mt('Enter the course with one of the available ad hoc roles: [_1].',
-                                  join(', ',@adhoc));
+                    $roleoption = &mt('Enter the course with one of the available ad hoc roles.');
                 }
             } else {
+                my $rolename = $description->{$roles_by_num->[0]};
                 if ($type eq 'Community') {
-                    $roleoption = &mt('Enter the community with the ad hoc role of: [_1]',$adhoc[0]);
+                    $roleoption = &mt('Enter the community with the ad hoc role of: [_1]',$rolename);
                 } else {
-                    $roleoption = &mt('Enter the course with the ad hoc role of: [_1]',$adhoc[0]);
+                    $roleoption = &mt('Enter the course with the ad hoc role of: [_1]',$rolename);
                 }
             }
         }
@@ -224,14 +224,133 @@ sub print_course_search_page {
 }
 
 sub print_course_selection_page {
-    my ($r,$dom,$domdesc) = @_;
+    my ($r,$dom,$domdesc,$permission) = @_;
     my $type = $env{'form.type'};
     if (!defined($type)) {
         $type = 'Course';
     }
     &print_header($r,$type);
 
-# Criteria for course search 
+    if ($permission->{'adhocrole'} eq 'custom') {
+        my %lt = &Apache::lonlocal::texthash(
+            title    => 'Ad hoc role selection',
+            preamble => 'Please choose an ad hoc role in the course.',
+            cancel   => 'Click "OK" to enter the course, or "Cancel" to choose a different course.',
+        );
+        my %jslt = &Apache::lonlocal::texthash (
+            none => 'You are not eligible to use an ad hoc role for the selected course',
+            ok   => 'OK',
+            exit => 'Cancel',
+        );
+        &js_escape(\%jslt);
+        $r->print(<<"END");
+<script type="text/javascript">
+// <![CDATA[
+\$(document).ready(function(){
+    \$( "#LC_adhocrole_chooser" ).dialog({ autoOpen: false });
+});
+
+function gochoose(cname,cdom,cdesc) {
+    document.courselist.pickedcourse.value = cdom+'_'+cname;
+    \$("#LC_choose_adhoc").empty();
+    var pickedaction = \$('input[name=phase]:checked', '#LCcoursepicker').val();
+    if (pickedaction == 'adhocrole') {
+        var http = new XMLHttpRequest();
+        var url = "/adm/pickcourse";
+        var params = "cid="+cdom+"_"+cname+"&context=adhoc";
+        http.open("POST", url, true);
+        http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+        http.onreadystatechange = function() {
+            if (http.readyState == 4 && http.status == 200) {
+                var data = \$.parseJSON(http.responseText);
+                var len = data.roles.length;
+                if (len == '' || len == null || len == 0) {
+                    alert('$jslt{none}');
+                } else {
+                    if (len == 1) {
+                        \$( '[name="adhocrole"]' )[0].value = data.roles[0].name;
+                        document.courselist.submit();
+                    } else {
+                        var str = '';
+                        \$("#LC_choose_adhoc").empty();
+                        for (var i=0; i<data.roles.length; i++) {
+                            \$("<label><input type='radio' value='"+data.roles[i].name+"' name='LC_get_role' id='LC_get_role_"+i+"' />"+data.roles[i].desc+"</label><span>&nbsp;&nbsp;</span>")
+                            .appendTo("#LC_choose_adhoc");
+                        }
+                        \$( "#LC_adhocrole_chooser" ).toggle( true );
+                        \$( "#LC_get_role_0").prop("checked", true);
+                        \$( "#LC_adhocrole_chooser" ).dialog({ autoOpen: false });
+                        \$( "#LC_adhocrole_chooser" ).dialog("open");
+                        \$( "#LC_adhocrole_chooser" ).dialog({
+                            height: 400,
+                            width: 500,
+                            modal: true,
+                            resizable: false,
+                            buttons: [
+                                  {
+                                   text: "$jslt{'ok'}",
+                                   click: function() {
+                                            var rolename = \$('input[name=LC_get_role]:checked', '#LChelpdeskpicker').val();
+                                            \$( '[name="adhocrole"]' )[0].value = rolename;
+                                            document.courselist.submit();
+                                        }
+                                  },
+                                  {
+                                   text: "$jslt{'exit'}",
+                                   click: function() {
+                                        \$("#LC_adhocrole_chooser").dialog( "close" );
+                                       }
+                                  }
+                            ],
+                        });
+                        \$( "#LC_adhocrole_chooser" ).find( "form" ).on( "submit", function( event ) {
+                            event.preventDefault();
+                            var rolename = \$('input[name=LC_get_role]:checked', '#LChelpdeskpicker').val()
+                            \$( '[name="adhocrole"]' )[0].value = rolename;
+                            document.courselist.submit();
+                            \$("#LC_adhocrole_chooser").dialog( "close" );
+                        });
+                    }
+                }
+            }
+        }
+        http.send(params);
+    } else {
+        document.courselist.submit();
+    }
+    return;
+}
+// ]]>
+</script>
+
+<div id="LC_adhocrole_chooser" title="$lt{'title'}" style="display:none">
+  <p>$lt{'preamble'}</p>
+  <form name="LChelpdeskadhoc" id="LChelpdeskpicker" action="">
+    <div id="LC_choose_adhoc">
+    </div>
+    <input type="hidden" name="adhocrole" id="LCadhocrole" value="" />
+    <input type="submit" tabindex="-1" style="position:absolute; top:-1000px" />
+  </form>
+  <p>$lt{'cancel'}</p>
+</div>
+END
+    } elsif ($permission->{'adhocrole'} eq 'coord') {
+        $r->print(<<"END");
+<script type="text/javascript">
+// <![CDATA[
+
+function gochoose(cname,cdom,cdesc) {
+    document.courselist.pickedcourse.value = cdom+'_'+cname;
+    document.courselist.submit();
+    return;
+}
+
+// ]]>
+</script>
+END
+    }
+
+# Criteria for course search
     my ($filterlist,$filter) = &get_filters();
     my $action = '/adm/modifycourse';
     my $dctitle = &Apache::lonnet::plaintext('dc');
@@ -476,29 +595,25 @@ sub print_modification_menu {
 }
 
 sub print_adhocrole_selected {
-    my ($r,$type) = @_;
+    my ($r,$type,$permission) = @_;
     &print_header($r,$type);
     my ($cdom,$cnum) = split(/_/,$env{'form.pickedcourse'});
     my ($newrole,$selectrole);
-    if (&Apache::lonnet::allowed('ccc',$cdom)) {
+    if ($permission->{'adhocrole'} eq 'coord') {
         if ($type eq 'Community') {
             $newrole = "co./$cdom/$cnum";
         } else {
             $newrole = "cc./$cdom/$cnum";
         }
         $selectrole = 1;
-    } elsif (&Apache::lonnet::allowed('rar',$cdom)) {
-        my %adhocroles = &Apache::lonnet::userenvironment($env{'user.domain'},$env{'user.name'},
-                                                         'adhocroles.'.$cdom);
-        if (keys(%adhocroles)) {
+    } elsif ($permission->{'adhocrole'} eq 'custom') {
+        my ($okroles,$description) = &Apache::lonnet::get_my_adhocroles($env{'form.pickedcourse'},1);
+        if (ref($okroles) eq 'ARRAY') {
             my $possrole = $env{'form.adhocrole'};
-            if ($possrole ne '') {
-                my @adhoc = split(',',$adhocroles{'adhocroles.'.$cdom});
-                if (grep(/^\Q$possrole\E$/,@adhoc)) {
-                    my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
-                    $newrole = "cr/$cdom/$confname/$possrole./$cdom/$cnum";
-                    $selectrole = 1;
-                }
+            if (($possrole ne '') && (grep(/^\Q$possrole\E$/,@{$okroles}))) {
+                my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
+                $newrole = "cr/$cdom/$confname/$possrole./$cdom/$cnum";
+                $selectrole = 1;
             }
         }
     }
@@ -1302,6 +1417,18 @@ sub modify_course {
             my $putres = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
             if ($putres eq 'ok') {
                 &update_coowners($cdom,$cnum,$chome,\%settings,\%newattr);
+                if ($changed{'code'}) {
+                    &Apache::lonnet::devalidate_cache_new('instcats',$cdom);
+                    # Update cache of self-cataloging courses on institution's server(s).
+                    if (&Apache::lonnet::shared_institution($cdom)) {
+                        unless ($registered_cleanup) {
+                            my $handlers = $r->get_handlers('PerlCleanupHandler');
+                            $r->set_handlers('PerlCleanupHandler' => [\&devalidate_remote_instcats,@{$handlers}]);
+                            $registered_cleanup=1;
+                            $modified_dom = $cdom;
+                        }
+                    }
+                }
             }
         }
     }
@@ -2044,13 +2171,7 @@ function changePage(formname,newphase) {
     if ($phase eq 'setparms') {
 	$js .= $javascript_validations;
     } elsif ($phase eq 'courselist') {
-        $js .= qq|
-
-function gochoose(cname,cdom,cdesc) {
-    document.courselist.pickedcourse.value = cdom+'_'+cname;
-    document.courselist.submit();
-}
-
+        $js .= <<"ENDJS";
 function hide_searching() {
     if (document.getElementById('searching')) {
         document.getElementById('searching').style.display = 'none';
@@ -2058,7 +2179,7 @@ function hide_searching() {
     return;
 }
 
-|;
+ENDJS
     } elsif ($phase eq 'setquota') {
         my $invalid = &mt('The quota you entered contained invalid characters.');
         my $alert = &mt('You must enter a number');
@@ -2322,6 +2443,7 @@ sub get_permission {
             catsettings       => 'edit',
             processcat        => 'edit',
             selfenroll        => 'edit',
+            adhocrole         => 'coord',
         );
     } elsif (&Apache::lonnet::allowed('rar',$dom)) {
         $allowed = 1;
@@ -2333,11 +2455,28 @@ sub get_permission {
             setparms      => 'view',
             catsettings   => 'view',
             selfenroll    => 'view',
+            adhocrole     => 'custom',
         );
     }
     return ($allowed,\%permission);
 }
 
+sub devalidate_remote_instcats {
+    if ($modified_dom ne '') {
+        my %servers = &Apache::lonnet::internet_dom_servers($modified_dom);
+        my %thismachine;
+        map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
+        if (keys(%servers)) {
+            foreach my $server (keys(%servers)) {
+                next if ($thismachine{$server});
+                &Apache::lonnet::remote_devalidate_cache($server,['instcats:'.$modified_dom]);
+            }
+        }
+        $modified_dom = '';
+    }
+    return;
+}
+
 sub handler {
     my $r = shift;
     if ($r->header_only) {
@@ -2346,6 +2485,9 @@ sub handler {
         return OK;
     }
 
+    $registered_cleanup=0;
+    $modified_dom = '';
+
     my $dom = $env{'request.role.domain'};
     my $domdesc = &Apache::lonnet::domain($dom,'description');
     my ($allowed,$permission) = &get_permission($dom);
@@ -2385,7 +2527,7 @@ sub handler {
               {href=>"javascript:changePage(document.$phase,'courselist')",
               text=>$choose_text});
             if ($phase eq 'courselist') {
-                &print_course_selection_page($r,$dom,$domdesc);
+                &print_course_selection_page($r,$dom,$domdesc,$permission);
             } else {
                 my ($checked,$cdesc,$coursehash) = &check_course($dom,$domdesc);
                 if ($checked eq 'ok') {
@@ -2406,7 +2548,7 @@ sub handler {
                         &Apache::lonhtmlcommon::add_breadcrumb
                          ({href=>"javascript:changePage(document.$phase,'adhocrole')",
                            text=>$enter_text});
-                        &print_adhocrole_selected($r,$type);
+                        &print_adhocrole_selected($r,$type,$permission);
                     } else {
                         &Apache::lonhtmlcommon::add_breadcrumb
                         ({href=>"javascript:changePage(document.$phase,'menu')",