Annotation of loncom/interface/lonrelrequtils.pm, revision 1.1

1.1     ! raeburn     1: #!/usr/bin/perl
        !             2: # The LearningOnline Network
        !             3: #
        !             4: # $Id: lonrelrequtils.pm,v 1.1 2014/06/04 16:10:51 raeburn Exp $
        !             5: #
        !             6: # Copyright Michigan State University Board of Trustees
        !             7: #
        !             8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
        !             9: #
        !            10: # LON-CAPA is free software; you can redistribute it and/or modify
        !            11: # it under the terms of the GNU General Public License as published by
        !            12: # the Free Software Foundation; either version 2 of the License, or
        !            13: # (at your option) any later version.
        !            14: #
        !            15: # LON-CAPA is distributed in the hope that it will be useful,
        !            16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            18: # GNU General Public License for more details.
        !            19: #
        !            20: # You should have received a copy of the GNU General Public License
        !            21: # along with LON-CAPA; if not, write to the Free Software
        !            22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !            23: #
        !            24: # /home/httpd/html/adm/gpl.txt
        !            25: #
        !            26: # http://www.lon-capa.org/
        !            27: #
        !            28: #################################################
        !            29: 
        !            30: =pod
        !            31: 
        !            32: =head1 NAME
        !            33: 
        !            34: lonrelrequtils.pm
        !            35: 
        !            36: =head1 SYNOPSIS
        !            37: 
        !            38: Contains utilities used to determine the LON-CAPA version 
        !            39: requirement in a course, based on course type, parameters,
        !            40: responsetypes, and communication blocking events.
        !            41: 
        !            42: =head1 DESCRIPTION
        !            43: 
        !            44: lonrelrequtilities.pm includes a main subroutine:
        !            45: get_release_req() which will return the current major
        !            46: version and minor version requirement (if it exists).
        !            47: 
        !            48: =head1 SUBROUTINES
        !            49: 
        !            50: =over
        !            51: 
        !            52: =item &init_global_hashes()
        !            53: 
        !            54: Initializes package hashes containing version requirements for 
        !            55: parameters, responsetypes, course types, anonsurvey 
        !            56: parameter, and randomizetry parameter.
        !            57: 
        !            58: =item &get_release_req()
        !            59: 
        !            60: Returns current major version and minor version requirements for a course,
        !            61: based on: coursetype, parameters in use, responsetypes in use in course
        !            62: content, and communication blocking features in use in blocks with end dates
        !            63: in the future, or in blocks triggered by activation of a timer in a timed quiz.
        !            64: 
        !            65: Inputs: 5
        !            66: 
        !            67: =over
        !            68: 
        !            69: =item $cnum - course "number"
        !            70: 
        !            71: =item $cdom - course domain
        !            72: 
        !            73: =item $crstype - course type: Community or Course
        !            74: 
        !            75: =item $readmap - boolean; if true, read course's top level map, and any
        !            76:                  included maps recursively.
        !            77: 
        !            78: =item $globals_set - boolean: if false, call init_global_hashes
        !            79: 
        !            80: =back
        !            81: 
        !            82: 
        !            83: =item &parameter_constraints()
        !            84: 
        !            85: Returns major version and minor version requirements for a course,
        !            86: based on parameters in use in the course. (Parameters which have
        !            87: version requirements are listed in /home/httpd/lonTabs/releaseslist.xml
        !            88: 
        !            89: Inputs: 2
        !            90: 
        !            91: =over
        !            92: 
        !            93: =item $cnum - course "number"
        !            94: 
        !            95: =item $cdom - course domain
        !            96: 
        !            97: =back
        !            98: 
        !            99: 
        !           100: =item &coursetype_constraints()
        !           101: 
        !           102: Returns major version and minor version requirements for a course,
        !           103: taking into account course type (Community or Course).
        !           104: 
        !           105: Inputs: 5
        !           106: 
        !           107: =over
        !           108: 
        !           109: =item $cnum - course "number"
        !           110: 
        !           111: =item $cdom - course domain
        !           112: 
        !           113: =item $crstype - course type: Community or Course
        !           114: 
        !           115: =item $reqdmajor - major version requirements based on constraints 
        !           116:                    considered so far (parameters).
        !           117: 
        !           118: =item $reqdminor - minor version requirements based on constraints 
        !           119:                    considered so far (parameters).
        !           120:  
        !           121: =back
        !           122: 
        !           123: 
        !           124: =item &commblock_constraints()
        !           125: 
        !           126: Returns major version and minor version requirements for a course,
        !           127: taking into account use of communication blocking (blocks for
        !           128: printouts, specified folders/resources, and/or triggering of block
        !           129: by a student starting a timed quiz.
        !           130: 
        !           131: Inputs: 4
        !           132: 
        !           133: =over
        !           134: 
        !           135: =item $cnum - course "number"
        !           136: 
        !           137: =item $cdom - course domain
        !           138: 
        !           139: =item $reqdmajor - major version requirements based on constraints 
        !           140:                    considered so far (parameters and course type).
        !           141: 
        !           142: =item $reqdminor - minor version requirements based on constraints
        !           143:                    considered so far (parameters and course type).
        !           144: 
        !           145: =back
        !           146: 
        !           147: 
        !           148: =item &coursecontent_constraints()
        !           149: 
        !           150: Returns major version and minor version requirements for a course,
        !           151: taking into responsetypes in use in published assessment items
        !           152: imported into a course.
        !           153: 
        !           154: Inputs: 4
        !           155: 
        !           156: =over
        !           157: 
        !           158: =item $cnum - course "number"
        !           159: 
        !           160: =item $cdom - course domain
        !           161: 
        !           162: =item $reqdmajor - major version requirements based on constraints
        !           163:                    considered so far (parameters, course type, blocks).
        !           164: 
        !           165: =item $reqdminor - minor version requirements based on constraints
        !           166:                    considered so far (parameters, course type, blocks).
        !           167: 
        !           168: =back
        !           169: 
        !           170: 
        !           171: =item &update_reqd_loncaparev()
        !           172: 
        !           173: Returns major version and minor version requirements for a course,
        !           174: taking into account new constraint type.
        !           175: 
        !           176: Inputs: 4
        !           177: 
        !           178: =over
        !           179: 
        !           180: =item $major - major version requirements from new constraint type
        !           181: 
        !           182: =item $minor - minor version requirements from new constraint type
        !           183: 
        !           184: =item $reqdmajor - major version requirements from constraints
        !           185:                    considered so far.
        !           186: 
        !           187: =item $reqdminor - minor version requirements from constraints
        !           188:                    considered so far.
        !           189: 
        !           190: =back
        !           191: 
        !           192: 
        !           193: =item &read_paramdata()
        !           194: 
        !           195: Returns a reference to a hash populated with parameter settings in a
        !           196: course (set both generally, and for specific students).
        !           197: 
        !           198: Inputs: 2
        !           199: 
        !           200: =over
        !           201: 
        !           202: =item $cnum - course "number"
        !           203: 
        !           204: =item $cdom - course domain
        !           205: 
        !           206: =back
        !           207: 
        !           208: 
        !           209: =item &modify_course_relreq()
        !           210: 
        !           211: Updates course's minimum version requirement (internal.releaserequired) in 
        !           212: course's environment.db, and in user's current session, and in course's
        !           213: record in nohist_courseids.db on course's home server.  This can include
        !           214: deleting an existing version requirement, downgrading to an earlier version,
        !           215: or updating to a newer version.
        !           216: 
        !           217: Note: if the current server's LON-CAPA version is older than the course's
        !           218: current version requirement, and a downgrade to an earlier version is being
        !           219: proposed, the change will NOT be made, because of the possibility that the
        !           220: current server has not checked for an attribute only available with a more 
        !           221: recent version of LON-CAPA.
        !           222: 
        !           223: Inputs: 9
        !           224: 
        !           225: =over
        !           226: 
        !           227: =item $newmajor - (optional) major version requirements
        !           228: 
        !           229: =item $newminor - (optional) minor version requirements
        !           230: 
        !           231: =item $cnum - course "number"
        !           232: 
        !           233: =item $cdom - course domain
        !           234: 
        !           235: =item $chome - lonHostID of course's home server
        !           236: 
        !           237: =item $crstype - course type: Community or Course
        !           238: 
        !           239: =item $cid - course ID
        !           240: 
        !           241: =item $readmap - boolean; if true, read course's top level map, and any
        !           242:                  included maps recursively.
        !           243: 
        !           244: =item $getrelreq - boolean; if true, call &get_release_req() to 
        !           245:       return the current major version and minor version requirements.
        !           246:       (needed if optional args: $newmajor and $newminor are not passed).
        !           247: 
        !           248: =back
        !           249: 
        !           250: =back
        !           251: 
        !           252: =cut
        !           253: 
        !           254: #################################################
        !           255: 
        !           256: package Apache::lonrelrequtils;
        !           257: 
        !           258: use strict;
        !           259: use Apache::lonnet;
        !           260: use Apache::loncommon();
        !           261: use Apache::lonuserstate();
        !           262: use Apache::loncoursedata();
        !           263: use Apache::lonnavmaps();
        !           264: use LONCAPA qw(:DEFAULT :match);
        !           265: 
        !           266: sub init_global_hashes {
        !           267:     %Apache::lonrelrequtils::checkparms = ();
        !           268:     %Apache::lonrelrequtils::checkresponsetypes = ();
        !           269:     %Apache::lonrelrequtils::checkcrstypes = ();
        !           270:     %Apache::lonrelrequtils::anonsurvey = ();
        !           271:     %Apache::lonrelrequtils::randomizetry = ();
        !           272: 
        !           273:     foreach my $key (keys(%Apache::lonnet::needsrelease)) {
        !           274:         my ($item,$name,$value) = split(/:/,$key);
        !           275:         if ($item eq 'parameter') {
        !           276:             if (ref($Apache::lonrelrequtils::checkparms{$name}) eq 'ARRAY') {
        !           277:                 unless(grep(/^\Q$name\E$/,@{$Apache::lonrelrequtils::checkparms{$name}})) {
        !           278:                     push(@{$Apache::lonrelrequtils::checkparms{$name}},$value);
        !           279:                 }
        !           280:             } else {
        !           281:                 push(@{$Apache::lonrelrequtils::checkparms{$name}},$value);
        !           282:             }
        !           283:         } elsif ($item eq 'resourcetag') {
        !           284:             if ($name eq 'responsetype') {
        !           285:                 $Apache::lonrelrequtils::checkresponsetypes{$value} = $Apache::lonnet::needsrelease{$key}
        !           286:             }
        !           287:         } elsif ($item eq 'course') {
        !           288:             if ($name eq 'crstype') {
        !           289:                 $Apache::lonrelrequtils::checkcrstypes{$value} = $Apache::lonnet::needsrelease{$key};
        !           290:             }
        !           291:         }
        !           292:     }
        !           293:     ($Apache::lonrelrequtils::anonsurvey{major},$Apache::lonrelrequtils::anonsurvey{minor}) =
        !           294:         split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
        !           295:     ($Apache::lonrelrequtils::randomizetry{major},$Apache::lonrelrequtils::randomizetry{minor}) =
        !           296:         split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
        !           297:     return;
        !           298: }
        !           299: 
        !           300: sub get_release_req {
        !           301:     my ($cnum,$cdom,$crstype,$readmap,$globals_set) = @_;
        !           302:     if ($readmap) {
        !           303:         &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
        !           304:     }
        !           305:     unless ($globals_set) {
        !           306:         &init_global_hashes();
        !           307:     }
        !           308:     # check all parameters
        !           309:     my ($reqdmajor,$reqdminor) = &parameter_constraints($cnum,$cdom);
        !           310: 
        !           311:     # check course type
        !           312:     ($reqdmajor,$reqdminor) = &coursetype_constraints($cnum,$cdom,$crstype,$reqdmajor,
        !           313:                                                       $reqdminor);
        !           314:     # check communication blocks
        !           315:     ($reqdmajor,$reqdminor) = &commblock_constraints($cnum,$cdom,$reqdmajor,$reqdminor);
        !           316: 
        !           317:     # check course contents
        !           318:     ($reqdmajor,$reqdminor) = &coursecontent_constraints($cnum,$cdom,$reqdmajor,$reqdminor);
        !           319:     return ($reqdmajor,$reqdminor);
        !           320: }
        !           321: 
        !           322: sub parameter_constraints {
        !           323:     my ($cnum,$cdom) = @_;
        !           324:     my ($reqdmajor,$reqdminor);
        !           325:     my $resourcedata=&read_paramdata($cnum,$cdom);
        !           326:     if (ref($resourcedata) eq 'HASH') {
        !           327:         foreach my $key (keys(%{$resourcedata})) {
        !           328:             foreach my $item (keys(%Apache::lonrelrequtils::checkparms)) {
        !           329:                 if ($key =~ /(\Q$item\E)$/) {
        !           330:                     if (ref($Apache::lonrelrequtils::checkparms{$item}) eq 'ARRAY') {
        !           331:                         my $value = $resourcedata->{$key};
        !           332:                         if ($item eq 'examcode') {
        !           333:                             if (&Apache::lonnet::validCODE($value)) {
        !           334:                                 $value = 'valid';
        !           335:                             } else {
        !           336:                                 $value = '';
        !           337:                             }
        !           338:                         }
        !           339:                         if (grep(/^\Q$value\E$/,@{$Apache::lonrelrequtils::checkparms{$item}})) {
        !           340:                             my ($major,$minor) = split(/\./,$Apache::lonnet::needsrelease{'parameter:'.$item.':'.$value});
        !           341:                             ($reqdmajor,$reqdminor) =
        !           342:                                 &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           343:                         }
        !           344:                     }
        !           345:                 }
        !           346:             }
        !           347:         }
        !           348:     }
        !           349:     return ($reqdmajor,$reqdminor);
        !           350: }
        !           351: 
        !           352: sub coursetype_constraints {
        !           353:     my ($cnum,$cdom,$crstype,$reqdmajor,$reqdminor) = @_;
        !           354:     if (defined($Apache::lonrelrequtils::checkcrstypes{$crstype})) {
        !           355:         my ($major,$minor) = split(/\./,$Apache::lonrelrequtils::checkcrstypes{$crstype});
        !           356:         ($reqdmajor,$reqdminor) =
        !           357:             &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           358:     }
        !           359:     return ($reqdmajor,$reqdminor);
        !           360: }
        !           361: 
        !           362: sub commblock_constraints {
        !           363:     my ($cnum,$cdom,$reqdmajor,$reqdminor) = @_;
        !           364:     my %comm_blocks =  &Apache::lonnet::dump('comm_block',$cdom,$cnum);
        !           365:     my $now = time;
        !           366:     if (keys(%comm_blocks) > 0) {
        !           367:         foreach my $block (keys(%comm_blocks)) {
        !           368:             if ($block =~ /^firstaccess____(.+)$/) {
        !           369:                 my ($major,$minor) = split(/\./,$Apache::lonnet::needsrelease{'course:commblock:timer'});
        !           370:                 ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           371:                 last;
        !           372:             } elsif ($block =~ /^(\d+)____(\d+)$/) {
        !           373:                 my ($start,$end) = ($1,$2);
        !           374:                 next if ($end < $now);
        !           375:             }
        !           376:             if (ref($comm_blocks{$block}) eq 'HASH') {
        !           377:                 if (ref($comm_blocks{$block}{'blocks'}) eq 'HASH') {
        !           378:                     if (ref($comm_blocks{$block}{'blocks'}{'docs'}) eq 'HASH') {
        !           379:                         if (keys(%{$comm_blocks{$block}{'blocks'}{'docs'}}) > 0) {
        !           380:                             my ($major,$minor) = split(/\./,$Apache::lonnet::needsrelease{'course:commblock:docs'});
        !           381:                             ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           382:                             last;
        !           383:                         }
        !           384:                     }
        !           385:                     if ($comm_blocks{$block}{'blocks'}{'printout'} eq 'on') {
        !           386:                         my ($major,$minor) = split(/\./,$Apache::lonnet::needsrelease{'course:commblock:printout'});
        !           387:                         ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           388:                         last;
        !           389:                     }
        !           390:                 }
        !           391:             }
        !           392:         }
        !           393:     }
        !           394:     return ($reqdmajor,$reqdminor);
        !           395: }
        !           396: 
        !           397: sub coursecontent_constraints {
        !           398:     my ($cnum,$cdom,$reqdmajor,$reqdminor) = @_;
        !           399:     my $navmap = Apache::lonnavmaps::navmap->new();
        !           400:     if (defined($navmap)) {
        !           401:         my %anonsubmissions =  &Apache::lonnet::dump('nohist_anonsurveys',
        !           402:                                                      $cdom,$cnum);
        !           403:         my %randomizetrysubm = &Apache::lonnet::dump('nohist_randomizetry',
        !           404:                                                      $cdom,$cnum);
        !           405:         my %allresponses;
        !           406:         my ($anonsurv_subm,$randbytry_subm);
        !           407:         foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() },1,0)) {
        !           408:             my %responses = $res->responseTypes();
        !           409:             foreach my $key (keys(%responses)) {
        !           410:                 next unless(exists($Apache::lonrelrequtils::checkresponsetypes{$key}));
        !           411:                 $allresponses{$key} += $responses{$key};
        !           412:             }
        !           413:             my @parts = @{$res->parts()};
        !           414:             my $symb = $res->symb();
        !           415:             foreach my $part (@parts) {
        !           416:                 if (exists($anonsubmissions{$symb."\0".$part})) {
        !           417:                     $anonsurv_subm = 1;
        !           418:                 }
        !           419:                 if (exists($randomizetrysubm{$symb."\0".$part})) {
        !           420:                     $randbytry_subm = 1;
        !           421:                 }
        !           422:             }
        !           423:         }
        !           424:         foreach my $key (keys(%allresponses)) {
        !           425:             my ($major,$minor) = split(/\./,$Apache::lonrelrequtils::checkresponsetypes{$key});
        !           426:             ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
        !           427:         }
        !           428:         if ($anonsurv_subm) {
        !           429:             ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($Apache::lonrelrequtils::anonsurvey{major},
        !           430:                                           $Apache::lonrelrequtils::anonsurvey{minor},$reqdmajor,$reqdminor);
        !           431:         }
        !           432:         if ($randbytry_subm) {
        !           433:             ($reqdmajor,$reqdminor) = &update_reqd_loncaparev($Apache::lonrelrequtils::randomizetry{major},
        !           434:                                           $Apache::lonrelrequtils::randomizetry{minor},$reqdmajor,$reqdminor);
        !           435:         }
        !           436:     }
        !           437:     return ($reqdmajor,$reqdminor);
        !           438: }
        !           439: 
        !           440: sub update_reqd_loncaparev {
        !           441:     my ($major,$minor,$reqdmajor,$reqdminor) = @_;
        !           442:     if (($major ne '' && $major !~ /\D/) & ($minor ne '' && $minor !~ /\D/)) {
        !           443:         if ($reqdmajor eq '' || $reqdminor eq '') {
        !           444:             $reqdmajor = $major;
        !           445:             $reqdminor = $minor;
        !           446:         } elsif (($major > $reqdmajor) ||
        !           447:             ($major == $reqdmajor && $minor > $reqdminor))  {
        !           448:             $reqdmajor = $major;
        !           449:             $reqdminor = $minor;
        !           450:         }
        !           451:     }
        !           452:     return ($reqdmajor,$reqdminor);
        !           453: }
        !           454: 
        !           455: sub read_paramdata {
        !           456:     my ($cnum,$cdom)=@_;
        !           457:     my $resourcedata=&Apache::lonnet::get_courseresdata($cnum,$cdom);
        !           458:     my $classlist=&Apache::loncoursedata::get_classlist();
        !           459:     foreach my $student (keys(%{$classlist})) {
        !           460:         if ($student =~/^($LONCAPA::match_username)\:($LONCAPA::match_domain)$/) {
        !           461:             my ($tuname,$tudom)=($1,$2);
        !           462:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
        !           463:             foreach my $userkey (keys(%{$useropt})) {
        !           464:                 if ($userkey=~/^\Q$cdom\E_\Q$cnum\E/) {
        !           465:                     my $newkey=$userkey;
        !           466:                     $newkey=~s/^(\Q$cdom\E_\Q$cnum\E\.)/$1\[useropt\:$tuname\:$tudom\]\./;
        !           467:                     $$resourcedata{$newkey}=$$useropt{$userkey};
        !           468:                 }
        !           469:             }
        !           470:         }
        !           471:     }
        !           472:     return $resourcedata;
        !           473: }
        !           474: 
        !           475: sub modify_course_relreq {
        !           476:     my ($newmajor,$newminor,$cnum,$cdom,$chome,$crstype,$cid,$readmap,$getrelreq) = @_;
        !           477:     if ($cnum eq '' || $cdom eq '' || $chome eq '' || $crstype eq '' || $cid eq '') {
        !           478:         $cid = $env{'request.course.id'};
        !           479:         $cdom = $env{'course.'.$cid.'.domain'};
        !           480:         $cnum = $env{'course.'.$cid.'.num'};
        !           481:         $chome = $env{'course.'.$cid.'.home'};
        !           482:         $crstype = $env{'course.'.$cid.'.type'};
        !           483:         if ($crstype eq '') {
        !           484:             $crstype = 'Course';
        !           485:         }
        !           486:     }
        !           487:     if ($getrelreq) {
        !           488:         ($newmajor,$newminor) = &get_release_req($cnum,$cdom,$crstype,$readmap);
        !           489:     }
        !           490:     my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
        !           491:     my $needsupdate;
        !           492:     if ($curr_reqd_hash{'internal.releaserequired'} eq '') {
        !           493:         if (($newmajor ne '') && ($newminor ne '')) { 
        !           494:             $needsupdate = 1;
        !           495:         }
        !           496:     } else {
        !           497:         my ($currmajor,$currminor) = split(/\./,$curr_reqd_hash{'internal.releaserequired'});
        !           498:         my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
        !           499:         my $serverdom = $Apache::lonnet::perlvar{'lonDefDomain'};
        !           500:         my $serverrev = &Apache::lonnet::get_server_loncaparev($serverdom,$lonhost);
        !           501:         my ($servermajor,$serverminor) = split(/\./,$serverrev);     
        !           502:         unless (($currmajor > $servermajor) || (($currmajor == $servermajor) && ($currminor > $serverminor))) {
        !           503:             if (($currmajor != $newmajor) || ($currminor != $newminor)) {
        !           504:                 $needsupdate = 1;
        !           505:             }
        !           506:         }
        !           507:     }
        !           508:     if ($needsupdate) {
        !           509:         my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
        !           510:         my $result;
        !           511:         if (($newmajor eq '') && ($newminor eq '')) {
        !           512:             $result = &Apache::lonnet::del('environment',['internal.releaserequired'],$cdom,$cnum);
        !           513:             if ($result eq 'ok') {
        !           514:                 &Apache::lonnet::delenv('course.'.$cid.'.internal.releaserequired');
        !           515:                 $crsinfo{$cid}{'releaserequired'} = '';
        !           516:             }
        !           517:         } else {
        !           518:             my %needshash = (
        !           519:                               'internal.releaserequired' => $newmajor.'.'.$newminor,
        !           520:                             );
        !           521:             $result = &Apache::lonnet::put('environment',\%needshash,$cdom,$cnum);
        !           522:             if ($result eq 'ok') {
        !           523:                 &Apache::lonnet::appenv({'course.'.$cid.'.internal.releaserequired' => $newmajor.'.'.$newminor});
        !           524:                 if (ref($crsinfo{$cid}) eq 'HASH') {
        !           525:                     $crsinfo{$cid}{'releaserequired'} = $newmajor.'.'.$newminor
        !           526:                 }
        !           527:             }
        !           528:         }
        !           529:         if ($result eq 'ok') {
        !           530:             &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
        !           531:         }
        !           532:     }
        !           533:     return;
        !           534: }
        !           535: 
        !           536: 1;

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