--- loncom/interface/loncreatecourse.pm 2020/07/20 10:37:41 1.158.2.7.2.1 +++ loncom/interface/loncreatecourse.pm 2019/07/25 20:13:56 1.170 @@ -1,7 +1,7 @@ # The LearningOnline Network # Create a course # -# $Id: loncreatecourse.pm,v 1.158.2.7.2.1 2020/07/20 10:37:41 raeburn Exp $ +# $Id: loncreatecourse.pm,v 1.170 2019/07/25 20:13:56 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -80,13 +80,10 @@ use Apache::loncommon; use Apache::londocs; use Apache::lonlocal; use Apache::lonuserutils; +use Apache::lonclonecourse; use LONCAPA::batchcreatecourse; use LONCAPA qw(:DEFAULT :match); -my $registered_flush; -my $registered_instcats; -my $modified_dom; - # ===================================================== Phase one: fill-in form sub print_course_creation_page { @@ -94,6 +91,8 @@ sub print_course_creation_page { my $crstype = 'Community'; if ($env{'form.phase'} eq 'courseone') { $crstype = 'Course'; + } elsif ($env{'form.phase'} eq 'placementone') { + $crstype = 'Placement'; } my $defdom=$env{'request.role.domain'}; my %domdefaults = &Apache::lonnet::get_domain_defaults($defdom); @@ -102,12 +101,13 @@ sub print_course_creation_page { foreach my $server (sort(keys(%host_servers))) { $course_home .= qq{}; } $course_home .= "\n\n"; - my $domform = &Apache::loncommon::select_dom_form($defdom,'ccdomain'); + my ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('enroll',$defdom); + my $domform = &Apache::loncommon::select_dom_form($defdom,'ccdomain',undef,undef,undef,$trusted,$untrusted); my $cloneform=&Apache::loncommon::select_dom_form ($env{'request.role.domain'},'clonedomain'). &Apache::loncommon::selectcourse_link @@ -119,9 +119,7 @@ sub print_course_creation_page { my $endtime = time+(6*30*24*60*60); # 6 months from now, approx my $access_table = &Apache::lonuserutils::date_setting_table($starttime, $endtime,'create_defaultdates'); - my $openallfrom = - &Apache::lonhtmlcommon::date_setter('ccrs','openallfrom',$starttime); - if ($crstype eq 'Course') { + if (($crstype eq 'Course') || ($crstype eq 'Placement')) { $enroll_table = &Apache::lonuserutils::date_setting_table($starttime, $endtime,'create_enrolldates'); ($krbdef,$krbdefdom) = @@ -188,13 +186,8 @@ function validate(formname) { 'ncd' => "Do not clone date parameters", 'prd' => 'Clone date parameters as-is', 'shd' => 'Shift date parameters by number of days', - 'dpl' => 'URL shortcuts (for deep linking)', - 'nsl' => 'Do not clone URL shortcuts', - 'tsl' => 'Transfer URL shortcuts from existing course to new course', - 'csl' => 'Create new URL shortcuts in new course', 'assp' => "Assessment Parameters", 'oaas' => "Open all assessments", - 'sta' => "starting from:", 'mssg' => "Messaging", 'scpf' => "Set course policy feedback to Course Coordinator", 'scfc' => "Set resource content feedback to Course Coordinator", @@ -225,6 +218,7 @@ function validate(formname) { 'cgrq' => 'Set a quota for the total disk space available for storage of course group portfolio files', 'opco' => 'Open Course', 'opcm' => 'Open Community', + 'oppt' => 'Open Placement Test', ); $lt{'kaut'} = &mt('Key authority ([_1]id:domain[_2]) if other than course','',''); $lt{'toin'} = &mt('to interface with institutional data, e.g., [_1]fs13glg231[_2] for [_3]Fall 2013 Geology 231[_4]','','','',''); @@ -256,13 +250,21 @@ function validate(formname) { $lt{'cc'} = &mt('(will be assigned Coordinator role)'); $lt{'cgrs'} = &mt('Community Group Settings'); $lt{'cgrq'} = &mt('Set a quota for the total disk space available for storage of community group portfolio files'); - $lt{'tsl'} = &mt('Transfer URL shortcuts from existing community to new community'); - $lt{'csl'} = &mt('Create new URL shortcuts in new community'); + } elsif ($crstype eq 'Placement') { + $lt{'cinf'} = &mt('Placement Test Information'); + $lt{'ctit'} = &mt('Placement Test Title'); + $lt{'chsr'} = &mt('Placement Test Home Server'); + $lt{'cidn'} = &mt('Placement Test ID/Number'); + $lt{'crco'} = &mt('Placement Test Content'); + $lt{'cncr'} = &mt('Completely new placement test'); + $lt{'cecr'} = &mt('Clone an existing placement test'); + $lt{'sacr'} = &mt('Do NOT generate as standard placement test'); + $lt{'stco'} = &mt('standard placement tests only'); + $lt{'navi'} = &mt('Placement Test Contents'); + $lt{'cid'} = &mt('Placement Test ID'); } my $js = < -// $coursebrowserjs END @@ -290,6 +290,7 @@ END my %titles = &Apache::lonlocal::texthash( courseone => 'Create a New Course', groupone => 'Create a New Community', + placementone=> 'Create a New Placement Test', ); my $start_page = &Apache::loncommon::start_page($titles{$env{'form.phase'}},$js); @@ -301,7 +302,7 @@ END 'Create_Courses'); $r->print($start_page.$crumbs); - $r->print('
' + $r->print('
' .&Apache::lonhtmlcommon::start_pick_box() .&Apache::lonhtmlcommon::row_headline() @@ -334,14 +335,16 @@ END .'' .&Apache::lonhtmlcommon::row_closure() ); - if ($crstype eq 'Course') { + if (($crstype eq 'Course') || ($crstype eq 'Placement')) { $r->print(&Apache::lonhtmlcommon::row_headline() .'

'.$lt{'iinf'}.'

' - .$lt{'stat'}.' ' - .&mt('Default credits can also be specified, if different from the domain defaults (official courses: [_1]; unofficial courses: [_2]; textbook courses: [_3]).', - $domdefaults{'officialcredits'},$domdefaults{'unofficialcredits'},$domdefaults{'textbookcredits'}) - .&Apache::lonhtmlcommon::row_closure() - + .$lt{'stat'}); + if ($crstype eq 'Course') { + $r->print(' ' + .&mt('Default credits can also be specified, if different from the domain defaults (official courses: [_1]; unofficial courses: [_2]; textbook courses: [_3]).', + $domdefaults{'officialcredits'},$domdefaults{'unofficialcredits'},$domdefaults{'textbookcredits'})); + } + $r->print(&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title($lt{'ccod'}) .'' .'
('.$lt{'toin'}.')' @@ -357,7 +360,8 @@ END .'
('.$lt{'cscs'}.')' .&Apache::lonhtmlcommon::row_closure() ); - if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) { + if (($crstype eq 'Course') && ($domdefaults{'officialcredits'} || + $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'})) { $r->print(&Apache::lonhtmlcommon::row_title($lt{'ccre'}) .'' .'
('.$lt{'cred'}.')' @@ -368,9 +372,12 @@ END .'' .''.&mt('Yes').(' 'x2) .''.&mt('No') - .'' .&Apache::lonhtmlcommon::row_closure() - ); + ); + } + my $blankchk; + if ($crstype eq 'Placement') { + $blankchk = ' checked="checked"'; } # Table: New Course / Clone Course $r->print(&Apache::lonhtmlcommon::row_headline() @@ -396,15 +403,14 @@ END .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title($lt{'fres'}) .'' - .' '); + .''.$lt{'blnk'} + .''); if ($crstype eq 'Community') { - $r->print('' .' ' .&Apache::lonhtmlcommon::row_closure() - .&Apache::lonhtmlcommon::row_title($tinyurlhelp.$lt{'dpl'}) - .'
' - .'
' - .'' - .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_headline() .''.$lt{'asov'}.'' .&Apache::lonhtmlcommon::row_closure(1) @@ -478,10 +472,7 @@ END .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title($lt{'oaas'}) - .'' - .''.(' 'x2) - .''.', ' - .$lt{'sta'}.' '.$openallfrom.'' + .'' .&Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_headline() @@ -532,7 +523,7 @@ END .'' .&Apache::lonhtmlcommon::row_closure() ); - if ($crstype eq 'Course') { + unless ($crstype eq 'Community') { $r->print(&Apache::lonhtmlcommon::row_headline() .'

'.$lt{'aens'}.'

' .&Apache::lonhtmlcommon::row_closure() @@ -595,8 +586,7 @@ END

- -

' +' ); } elsif ($crstype eq 'Community') { $r->print(' @@ -606,6 +596,14 @@ END

' ); + } elsif ($crstype eq 'Placement') { + $r->print(' +

+ + + +

' + ); } $r->print(''. $end_page); @@ -618,7 +616,7 @@ sub create_course { my $ccuname =&LONCAPA::clean_username($env{'form.ccuname'}); my $ccdomain=&LONCAPA::clean_domain($env{'form.ccdomain'}); my $crstype = 'Community'; - my ($enrollstart,$enrollend,$startaccess,$endaccess,$openallfrom); + my ($enrollstart,$enrollend,$startaccess,$endaccess); my %domdefaults = &Apache::lonnet::get_domain_defaults($env{'request.role.domain'}); @@ -626,10 +624,11 @@ sub create_course { $crstype='Course'; $enrollstart=&Apache::lonhtmlcommon::get_date_from_form('startenroll'); $enrollend=&Apache::lonhtmlcommon::get_date_from_form('endenroll'); + } elsif ($env{'form.phase'} eq 'placementtwo') { + $crstype='Placement'; } $startaccess = &Apache::lonhtmlcommon::get_date_from_form('startaccess'); $endaccess = &Apache::lonhtmlcommon::get_date_from_form('endaccess'); - $openallfrom = &Apache::lonhtmlcommon::get_date_from_form('openallfrom'); my $autharg; my $authtype; @@ -670,7 +669,6 @@ sub create_course { clonedomain => $env{'form.clonedomain'}, datemode => $env{'form.datemode'}, dateshift => $env{'form.dateshift'}, - tinyurls => $env{'form.tinyurls'}, crsid => $env{'form.crsid'}, curruser => $env{'user.name'}.':'.$env{'user.domain'}, crssections => $env{'form.crssections'}, @@ -696,7 +694,6 @@ sub create_course { disresdis => $env{'form.disresdis'}, disablechat => $env{'form.disablechat'}, openall => $env{'form.openall'}, - openallfrom => $openallfrom, firstres => $env{'form.firstres'} }; @@ -738,20 +735,12 @@ sub create_course { return; } my ($courseid,$crsudom,$crsunum,$code); - my ($success,$output,$clonemsgref) = + my ($success,$output) = &Apache::loncommon::construct_course($args,\$logmsg,\$courseid, \$crsudom,\$crsunum, $env{'user.domain'}, $env{'user.name'},'dc_create',undef,undef,\$code); $r->print($output); - if (ref($clonemsgref) eq 'ARRAY') { - my $user_lh = &Apache::loncommon::user_lang($env{'user.name'},$env{'user.domain'}); - foreach my $item (@{$clonemsgref}) { - if (ref($item) eq 'HASH') { - $r->print(&mt($item->{mt},@{$item->{args}}).'
'."\n"); - } - } - } if ($success) { # # Make the requested user a course coordinator or group coordinator @@ -775,10 +764,8 @@ sub create_course { '

'.&mt('Course identifier to share with students: [_1]',$code).'

' ); } - if ($env{'form.crscode'} ne '') { - &Apache::lonnet::devalidate_cache_new('instcats',$crsudom); - } - ®ister_cleanups($r,$crsudom,$env{'form.crscode'}); + # Flush the course logs so reverse user roles immediately updated + $r->register_cleanup(\&Apache::lonnet::flushcourselogs); $r->print('

'.&mt('Roles will be active at next login').'.

'); } $r->print('

'. @@ -789,7 +776,7 @@ sub create_course { sub print_intro_page { my ($r,$show_all_choices,$cancreate,$permission) = @_; my $start_page = - &Apache::loncommon::start_page('Create a New Course or Community'); + &Apache::loncommon::start_page('Create a New Course, Community or Placement Test'); my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Creation Options','Create_Course',undef,'Create_Courses'); my $end_page = &Apache::loncommon::end_page(); @@ -821,12 +808,20 @@ sub print_intro_page { linktitle => 'Create a new collaborative community by completing an online form.' }, { - linktext => 'Create courses/communities by uploading an attributes file', + linktext => 'Create a single placement test', + url => '/adm/createcourse?phase=placementone', + permission => $permission->{'create'} && $cancreate->{'Placement'}, + #help => '', + icon => 'crsnew.png', + linktitle => 'Create a new placement test by completing an online form.' + }, + { + linktext => 'Create courses/communities/placement tests by uploading an attributes file', url => '/adm/createcourse?phase=batchone', permission => $permission->{'create'}, help => 'Batch_Creation', icon => 'uplcrs.png', - linktitle => 'Upload an attributes file containing specifications for one or more courses or communities in XML format.' + linktitle => 'Upload an attributes file containing specifications for one or more courses, communities or placement tests in XML format.' }, ] }, @@ -838,7 +833,7 @@ sub print_intro_page { permission => $show_all_choices, #help => '', icon => 'rcrs.png', - linktitle => 'Display course and community creation requests submitted by authorized users, held pending approval by a Domain Coordinator.' + linktitle => 'Display course, community creation and placement test requests submitted by authorized users, held pending approval by a Domain Coordinator.' }, { linktext => 'View pending official course requests', @@ -859,7 +854,7 @@ sub print_intro_page { permission => $show_all_choices, #help => '', icon => 'document-properties.png', - linktitle => 'Display information about when, how and by whom courses and communities were created in this domain.' + linktitle => 'Display information about when, how and by whom courses, communities and placement tests were created in this domain.' }, ] }, @@ -876,18 +871,18 @@ sub print_intro_page { sub upload_batchfile { my $r = shift; my $start_page = - &Apache::loncommon::start_page('Create a New Course or Community'); - my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Upload Course/Community Attributes File','Create_Course',undef,'Create_Courses'); + &Apache::loncommon::start_page('Create a New Course, Community, or Placement Test'); + my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Upload Course/Community/Placement Test Attributes File','Create_Course',undef,'Create_Courses'); my $end_page = &Apache::loncommon::end_page(); $r->print($start_page.$crumbs); - $r->print('

'.&mt('Upload a courses or communities attributes file').'

'); + $r->print('

'.&mt('Upload a courses, communities or placement tests attributes file').'

'); $r->print('
'. ''. '

'. '
'); + 'value="'.&mt('Create Courses/Communities/Placement Tests').'" />'); $r->print($end_page); return; } @@ -898,7 +893,7 @@ sub process_batchfile { my $uname = $env{'user.name'}; my $udom = $env{'user.domain'}; my $dir = &LONCAPA::tempdir().'addcourse'; - my ($result,$logmsg,$clonemsg,$keysmsg,$codesref,$instcodesref); + my ($result,$logmsg); if (($defdom =~ /^$match_domain$/) && ($uname =~ /^$match_username$/) && ($udom =~/^$match_domain$/)) { my $batchfilepath=&Apache::lonnet::userfileupload('coursecreatorxml',undef, 'batchupload',undef,undef, @@ -912,10 +907,9 @@ sub process_batchfile { if ((defined($filename)) && (defined($batchdir))) { my @requests = ($filename); my %courseids = (); - ($result,$logmsg,$clonemsg,$keysmsg,$codesref,$instcodesref) = - &LONCAPA::batchcreatecourse::create_courses( - \@requests,\%courseids,'web',$defdom, - $uname,$udom); + ($result,$logmsg) = &LONCAPA::batchcreatecourse::create_courses( + \@requests,\%courseids,'web',$defdom, + $uname,$udom); if (keys(%courseids) > 0) { if (!-e "$batchdir/processed") { mkdir("$batchdir/processed", 0755); @@ -929,15 +923,6 @@ sub process_batchfile { if (-e "$batchdir/processed/$filename") { unlink("$batchdir/pending/$filename"); } - my $updatecats; - if ((ref($instcodesref) eq 'HASH') && (keys(%{$instcodesref}) > 0)) { - &Apache::lonnet::devalidate_cache_new('instcats',$defdom); - $updatecats = 1; - } - ®ister_cleanups($r,$defdom,$updatecats); - } - if ($clonemsg) { - $clonemsg = '

'.$clonemsg.'

'."\n"; } } } else { @@ -955,9 +940,10 @@ sub process_batchfile { } $r->print(&Apache::loncommon::start_page('Create a New Course, Community or Placement Test'). &Apache::lonhtmlcommon::breadcrumbs('Creation Outcome','Create_Course',undef,'Create_Courses'). - $logmsg.$clonemsg.$result.'
'. + $logmsg.$result.'
'. &mt('Creation options menu').''. &Apache::loncommon::end_page()); + } sub courserequestbrowser_javascript { @@ -1041,6 +1027,8 @@ sub print_creation_logs { $crstype = '.'; } elsif ($curr{'type'} eq 'community') { $crstype = 'Community'; + } elsif ($curr{'type'} eq 'placement') { + $crstype = 'Placement'; } my ($instcodefilter,$regexpok); @@ -1131,6 +1119,8 @@ sub print_creation_logs { my $showtype; if ($courses{$cid}{type} eq 'Community') { $showtype = &mt('community'); + } elsif ($courses{$cid}{type} eq 'Placement') { + $showtype = &mt('placement test'); } else { my $instcode = $courses{$cid}{inst_code}; if ($instcode ne '') { @@ -1345,44 +1335,6 @@ sub get_permission { return ($allowed,\%permission); } -sub register_cleanups { - my ($r,$cdom,$updatecats) = @_; - # Flush the course logs so reverse user roles immediately updated - unless ($registered_flush) { - my $handlers = $r->get_handlers('PerlCleanupHandler'); - $r->set_handlers('PerlCleanupHandler' => [\&Apache::lonnet::flushcourselogs,@{$handlers}]); - $registered_flush=1; - } - # Update cache of self-cataloging courses on institution's server(s). - if ($updatecats) { - if (&Apache::lonnet::shared_institution($cdom)) { - unless ($registered_instcats) { - my $handlers = $r->get_handlers('PerlCleanupHandler'); - $r->set_handlers('PerlCleanupHandler' => [\&devalidate_remote_instcats,@{$handlers}]); - $registered_instcats=1; - $modified_dom = $cdom; - } - } - } - return; -} - -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; -} - # ===================================================================== Handler sub handler { my $r = shift; @@ -1393,23 +1345,20 @@ sub handler { return OK; } - $registered_flush = 0; - $registered_instcats = 0; - $modified_dom = ''; - my ($allowed,$permission) = &get_permission($env{'request.role.domain'}); if ($allowed) { my $show_all_choices = 0; my $primary_rev = &Apache::lonnet::get_server_loncaparev($env{'request.role.domain'}); my %cancreate = ( Community => 0, + Placement => 0, ); if (($primary_rev ne 'refused') && ($primary_rev ne 'error') && ($primary_rev ne 'unknown_cmd') && ($primary_rev ne 'no_such_host')) { $show_all_choices = 1; my ($primary_major,$primary_minor) = split(/\./,$primary_rev); foreach my $key (keys(%cancreate)) { - my ($needsmajor,$needsminor) = + my ($needsmajor,$needsminor) = split(/\./,$Apache::lonnet::needsrelease{'course:crstype:'.$key}); unless (($needsmajor > $primary_major) || (($needsmajor == $primary_major) && ($needsminor > $primary_minor))) { @@ -1430,8 +1379,10 @@ sub handler { faq=>79,bug=>'Dom Coord Interface',}); if (($permission->{'create'}) && (($env{'form.phase'} eq 'coursetwo') || - (($env{'form.phase'} eq 'grouptwo') && - ($cancreate{'Community'})))) { + (($env{'form.phase'} eq 'grouptwo') && + ($cancreate{'Community'})) || + (($env{'form.phase'} eq 'placementtwo') && + ($cancreate{'Placement'})))) { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/createcourse?phase=$env{'form.prevphase'}", text=>&mt('[_1] Creation Settings',), @@ -1442,9 +1393,11 @@ sub handler { faq=>9,bug=>'Dom Coord Interface',}); &create_course($r); } elsif (($permission->{'create'}) && - (($env{'form.phase'} eq 'courseone') || - (($env{'form.phase'} eq 'groupone') && - ($cancreate{'Community'})))) { + (($env{'form.phase'} eq 'courseone') || + (($env{'form.phase'} eq 'groupone') && + ($cancreate{'Community'})) || + (($env{'form.phase'} eq 'placementone') && + ($cancreate{'Placement'})))) { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/createcourse?phase=$env{'form.phase'}", text=>&mt('[_1] Creation Settings',), @@ -1485,7 +1438,7 @@ sub handler { $context,$env{'request.role.domain'}).'
'. &Apache::loncommon::end_page()); } elsif (($permission->{'create'}) && - ($env{'form.phase'} eq 'requestchange') && ($show_all_choices)) { + ($env{'form.phase'} eq 'requestchange') && ($show_all_choices)) { if ($env{'form.queue'} eq 'pending') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/createcourse?phase=pendingdisplay", @@ -1524,7 +1477,7 @@ sub handler { $context,$env{'request.role.domain'}).'
'. &Apache::loncommon::end_page()); } elsif (($permission->{'create'}) && - ($env{'form.phase'} eq 'requestvalidation') && ($show_all_choices)) { + ($env{'form.phase'} eq 'requestvalidation') && ($show_all_choices)) { my $js = &courserequestbrowser_javascript(); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/createcourse?phase=pendingdisplay", @@ -1534,9 +1487,7 @@ sub handler { my $start_page=&Apache::loncommon::start_page('Requests Validation Result',$js); my $crumbs = &Apache::lonhtmlcommon::breadcrumbs('Validation Attempted','Course_Requests',undef,'Course_Requests'); $r->print($start_page.$crumbs."\n".'
'. - &Apache::loncoursequeueadmin::process_official_reqs('domain',$env{'request.role.domain'}, - $env{'user.name'},$env{'user.domain'}). - '
'. + &Apache::loncoursequeueadmin::process_official_reqs('domain',$env{'request.role.domain'}).''. &Apache::loncommon::end_page()); } elsif (($env{'form.phase'} eq 'creationlog') && ($show_all_choices)) { &Apache::lonhtmlcommon::add_breadcrumb