--- loncom/interface/lonparmset.pm 2016/07/15 18:03:52 1.561 +++ loncom/interface/lonparmset.pm 2018/09/03 16:43:47 1.585 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set parameters for assessments # -# $Id: lonparmset.pm,v 1.561 2016/07/15 18:03:52 damieng Exp $ +# $Id: lonparmset.pm,v 1.585 2018/09/03 16:43:47 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,7 +36,8 @@ lonparmset - Handler to set parameters f =head1 SYNOPSIS -lonparmset provides an interface to setting course parameters. +lonparmset provides an interface to setting content parameters in a +course. It contains all the code for the "Content and Problem Settings" UI, except for the helpers parameter.helper and resettimes.helper, and lonhelper.pm, @@ -137,7 +138,7 @@ javascript function 'pjump'. =item print_td() -=item print_usergroups() +=item check_other_groups() =item parm_control_group() @@ -367,14 +368,14 @@ sub endSettingsScreen { ################################################## -# TABLE MODE +# (mostly) TABLE MODE # (parmval is also used for the log of parameter changes) ################################################## -# Calls parmval_by_symb, getting the symb from $id (the big hash resource id) with &symbcache. +# Calls parmval_by_symb, getting the symb from $id with &symbcache. # # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight' -# @param {string} $id - big hash resource id +# @param {string} $id - resource id or map pc # @param {string} $def - the resource's default value for this parameter # @param {string} $uname - user name # @param {string} $udom - user domain @@ -394,7 +395,7 @@ sub parmval { # (level 1 is the most specific and will have precedence) # # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight' -# @param {string} $symb - resource symb +# @param {string} $symb - resource symb or map src # @param {string} $def - the resource's default value for this parameter # @param {string} $uname - user name # @param {string} $udom - user domain @@ -597,7 +598,7 @@ sub reset_caches { } } -# cache big hash id -> symb, using lonnavmaps to find association +# cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association { my $symbsid; # course identifier, to initialize the cache only once for a course my %symbs; # hash id->symb @@ -607,7 +608,8 @@ sub reset_caches { undef(%symbs); } - # returns the symb corresponding to a big hash id (using lonnavmaps and a cache) + # returns the resource symb or map src corresponding to a resource id or map pc + # (using lonnavmaps and a cache) sub symbcache { my $id=shift; if ($symbsid ne $env{'request.course.id'}) { @@ -718,8 +720,8 @@ sub date_sanity_info { # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions. # -# @param {string} $sresid - resource big hash id -# @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight' +# @param {string} $sresid - resource id or map pc +# @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight' # @param {integer} $snum - level # @param {string} $nval - new value # @param {string} $ntype - new type @@ -737,8 +739,8 @@ my %recstack; # hash parameter name -> 1 # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions. # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error. # -# @param {string} $symb - resource symb -# @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight' +# @param {string} $symb - resource symb or map src +# @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight' # @param {integer} $snum - level # @param {string} $nval - new value # @param {string} $ntype - new type @@ -776,8 +778,7 @@ sub storeparm_by_symb { # are there restrictions? if (&rulescache($triggered.'_triggervalue')=~/\w/) { $active=0; - foreach my $possiblevalue (split(/\s*\, - \s*/,&rulescache($triggered.'_triggervalue'))) { + foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) { if (lc($possiblevalue) eq lc($nval)) { $active=1; } } } @@ -808,7 +809,7 @@ sub log_parmset { # Store a parameter value and type by symb, without using the parameter default actions. # Expire related sheets. # -# @param {string} $symb - resource symb +# @param {string} $symb - resource symb or map src # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight' # @param {integer} $snum - level # @param {string} $nval - new value @@ -846,17 +847,36 @@ sub storeparm_by_symb_inner { my $courselevelm=$env{'request.course.id'}.'.'.$mapparm; my $storeunder=''; + my $possreplace=''; if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; } - if (($snum==17) || ($snum==3)) { $storeunder=$courseleveli; } - if (($snum==16) || ($snum==2)) { $storeunder=$courselevelm; } + if (($snum==17) || ($snum==3)) { + $storeunder=$courseleveli; + $possreplace=$courselevelm; + } + if (($snum==16) || ($snum==2)) { + $storeunder=$courselevelm; + $possreplace=$courseleveli; + } if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; } if ($snum==12) { $storeunder=$seclevel; } - if ($snum==11) { $storeunder=$secleveli; } - if ($snum==10) { $storeunder=$seclevelm; } + if ($snum==11) { + $storeunder=$secleveli; + $possreplace=$seclevelm; + } + if ($snum==10) { + $storeunder=$seclevelm; + $possreplace=$secleveli; + } if ($snum==9) { $storeunder=$seclevelr; } if ($snum==8) { $storeunder=$grplevel; } - if ($snum==7) { $storeunder=$grpleveli; } - if ($snum==6) { $storeunder=$grplevelm; } + if ($snum==7) { + $storeunder=$grpleveli; + $possreplace=$grplevelm; + } + if ($snum==6) { + $storeunder=$grplevelm; + $possreplace=$grpleveli; + } if ($snum==5) { $storeunder=$grplevelr; } @@ -875,7 +895,7 @@ sub storeparm_by_symb_inner { &Apache::lonnet::expirespread('','','studentcalc'); if (($snum==13) || ($snum==9) || ($snum==5)) { &Apache::lonnet::expirespread('','','assesscalc',$symb); - } elsif (($snum==14) || ($snum==10) || ($snum==6)) { + } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) { &Apache::lonnet::expirespread('','','assesscalc',$map); } else { &Apache::lonnet::expirespread('','','assesscalc'); @@ -889,6 +909,17 @@ sub storeparm_by_symb_inner { $reply=&Apache::lonnet::cput ('resourcedata',\%storecontent,$cdom,$cnum); &log_parmset(\%storecontent); + if ($possreplace) { + my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom); + if (ref($resdata) eq 'HASH') { + if (exists($resdata->{$possreplace})) { + if (&Apache::lonnet::del + ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') { + &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1); + } + } + } + } } &Apache::lonnet::devalidatecourseresdata($cnum,$cdom); } else { @@ -899,7 +930,7 @@ sub storeparm_by_symb_inner { if ($snum==1) { &Apache::lonnet::expirespread ($uname,$udom,'assesscalc',$symb); - } elsif ($snum==2) { + } elsif (($snum==2) || ($snum==3)) { &Apache::lonnet::expirespread ($uname,$udom,'assesscalc',$map); } else { @@ -914,6 +945,18 @@ sub storeparm_by_symb_inner { $reply=&Apache::lonnet::cput ('resourcedata',\%storecontent,$udom,$uname); &log_parmset(\%storecontent,0,$uname,$udom); + if ($possreplace) { + my $resdata = &Apache::lonnet::get_userresdata($uname,$udom); + if (ref($resdata) eq 'HASH') { + if (exists($resdata->{$possreplace})) { + if (&Apache::lonnet::del + ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') { + &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1, + $uname,$udom); + } + } + } + } } &Apache::lonnet::devalidateuserresdata($uname,$udom); } @@ -1022,8 +1065,9 @@ sub valout { # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change. # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres') # @param {string} $call - javascript function to call to submit the form ('psub') +# @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive. sub plink { - my ($type,$dis,$value,$marker,$return,$call)=@_; + my ($type,$dis,$value,$marker,$return,$call,$recursive)=@_; my $winvalue=$value; unless ($winvalue) { if (&isdateparm($type)) { @@ -1045,7 +1089,9 @@ sub plink { return '
'. ''. - $valout.'
'; + $valout.''.($recursive?''. + &mt('recursive').'' : '').''; + } # Javascript for table mode. @@ -1065,16 +1111,16 @@ sub page_js { document.parmform.action+='#'+document.parmform.pres_marker.value; var typedef=new Array(); typedef=document.parmform.pres_type.value.split('_'); - if (document.parmform.pres_type.value!='') { - if (typedef[0]=='date') { - eval('document.parmform.recent_'+ - document.parmform.pres_type.value+ - '.value=document.parmform.pres_value.value;'); - } else { - eval('document.parmform.recent_'+typedef[0]+ - '.value=document.parmform.pres_value.value;'); + if (document.parmform.pres_type.value!='') { + if (typedef[0]=='date') { + eval('document.parmform.recent_'+ + document.parmform.pres_type.value+ + '.value=document.parmform.pres_value.value;'); + } else { + eval('document.parmform.recent_'+typedef[0]+ + '.value=document.parmform.pres_value.value;'); + } } - } document.parmform.submit(); } else { document.parmform.pres_value.value=''; @@ -1365,7 +1411,7 @@ ENDHEAD # @param {string} $which - parameter key ('parameter_'.part.'_'.name) # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters) # @param {hash reference} $name - parameter key -> parameter name -# @param {hash reference} $symbp - resource id -> symb +# @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb # @param {string} $rid - resource id # @param {hash reference} $default - parameter key -> resource parameter default value # @param {hash reference} $defaulttype - parameter key -> resource parameter default type @@ -1380,12 +1426,19 @@ ENDHEAD # @param {string} $cgroup - group name # @param {array reference} $usersgroups - list of groups the user belongs to, if any # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters +# @param {boolean} $readonly - true if no editing allowed. +# @param {array reference} - $recurseup - list of maps containing current one, ending at top-level. +# @param {hash reference} - $maptitles - - hash map id or src -> map title +# @param {hash reference} - $allmaps_inverted - hash map src -> map pc +# @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set sub print_row { my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone, - $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp)=@_; + $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp, + $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom); + my $numlinks = 0; # get the values for the parameter in cascading order # empty levels will remain empty @@ -1422,85 +1475,162 @@ sub print_row { my $thismarker=$which; $thismarker=~s/^parameter\_//; my $mprefix=$rid.'&'.$thismarker.'&'; - my $effective_parm = &valout($outpar[$result],$typeoutpar[$result],$thismarker); - my ($othergrp,$grp_parm,$controlgrp); - + my ($parmname)=($thismarker=~/\_([^\_]+)$/); + my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level, + $eff_groupparm,$recurse_check,$recursinfo); + if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) { + if ($result eq '') { + $recurse_check = 1; + } elsif (($uname ne '') && ($result > 3)) { + $recurse_check = 1; + } elsif (($cgroup ne '') && ($result > 7)) { + $recurse_check = 1; + } elsif (($csec ne '') && ($result > 11)) { + $recurse_check = 1; + } elsif ($result > 17) { + $recurse_check = 1; + } + if ($recurse_check) { + my $what = $$part{$which}.'.'.$$name{$which}; + my $prefix; + if (($uname ne '') && ($udom ne '')) { + my $useropt = &Apache::lonnet::get_userresdata($uname,$udom); + $prefix = $env{'request.course.id'}; + $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix); + if (ref($recursinfo) eq 'ARRAY') { + $effparm_rec = 1; + $effparm_level = &mt('user: [_1]',$uname); + } + } + if (($cgroup ne '') && (!$effparm_rec)) { + $prefix = $env{'request.course.id'}.'.['.$cgroup.']'; + $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); + if (ref($recursinfo) eq 'ARRAY') { + $effparm_rec = 1; + $effparm_level = &mt('group: [_1]',$cgroup); + } + } + if (($csec ne '') && (!$effparm_rec)) { + $prefix = $env{'request.course.id'}.'.['.$csec.']'; + $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); + if (ref($recursinfo) eq 'ARRAY') { + $effparm_rec = 1; + $effparm_level = &mt('section: [_1]',$csec); + } + } + if (!$effparm_rec) { + $prefix = $env{'request.course.id'}; + $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); + if (ref($recursinfo) eq 'ARRAY') { + $effparm_rec = 1; + } + } + } + } + if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) { + $effparm_rec = 1; + } + if ((!$effparm_rec) && + (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && + ($result == 16 || $result == 10 || $result == 6 || $result == 2)) { + $effparm_rec = 1; + } if ($parmlev eq 'general') { if ($uname) { - &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); } elsif ($cgroup) { - &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); + &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly); } elsif ($csec) { - &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); } else { - &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); } } elsif ($parmlev eq 'map') { if ($uname) { - &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); } elsif ($cgroup) { - &print_td($r,7,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); - &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); + &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1); } elsif ($csec) { - &print_td($r,11,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); } else { - &print_td($r,17,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); } } else { if ($uname) { if (@{$usersgroups} > 1) { - my ($coursereply,$grp_parm,$controlgrp); - ($coursereply,$othergrp,$grp_parm,$controlgrp) = - &print_usergroups($r,$$part{$which}.'.'.$$name{$which}, + (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) = + &check_other_groups($$part{$which}.'.'.$$name{$which}, $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt); - if ($coursereply && $result > 4) { + if (($coursereply) && ($result > 4)) { if (defined($controlgrp)) { if ($cgroup ne $controlgrp) { - $effective_parm = $grp_parm; - $result = 0; + $eff_groupparm = $grp_parm; + undef($result); + undef($effparm_rec); + if ($grp_is_rec) { + $effparm_rec = 1; + } } } } } } - &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,17,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); + &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); + &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); + &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); + &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); if ($csec) { - &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,11,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); + &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); + &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); } if ($cgroup) { - &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); - &print_td($r,7,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); - &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); - &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp); + &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly); + &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1); + &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly); } if ($uname) { if ($othergrp) { $r->print($othergrp); } - &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); - &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display); + &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); + &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); + &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); } - } # end of $parmlev if/else - $r->print(''.$effective_parm.''); - + if (ref($recursinfo) eq 'ARRAY') { + my $rectitle = &mt('recursive'); + if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) { + if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) { + $rectitle = &mt('set in: [_1]','"'. + '{$recursinfo->[2]}."',". + "'$parmname','$$part{$which}'".');">'. + $maptitles->{$recursinfo->[2]}.'"'); + + $numlinks ++; + } + } + my ($parmname)=($thismarker=~/\_([^\_]+)$/); + $effective_parm = &valout($recursinfo->[0],$recursinfo->[1],$parmname); + $r->print(''.$effective_parm. + '
'.$rectitle.' '. + $effparm_level.''); + } else { + if ($result) { + $effective_parm = &valout($outpar[$result],$typeoutpar[$result],$parmname); + } + if ($eff_groupparm) { + $effective_parm = $eff_groupparm; + } + $r->print(''.$effective_parm. + ($effparm_rec?'
'.&mt('recursive'). + '':'').''); + } if ($parmlev eq 'full') { my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}. '.'.$$name{$which},$$symbp{$rid}); @@ -1514,6 +1644,9 @@ sub print_row { } $r->print(''); $r->print("\n"); + if (($numlinks) && (ref($reclinks))) { + $$reclinks = $numlinks; + } } # Prints a cell for table mode. @@ -1532,44 +1665,72 @@ sub print_row { # @param {array reference} $typeoutpar - array level -> parameter type (when defined) # @param {hash reference} $display - parameter key -> full title for the parameter # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters +# @param {boolean} $readonly -true if editing not allowed. +# @param {boolean} $ismaplevel - true if level is for a map. sub print_td { - my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp)=@_; - $r->print(''); my $nolink = 0; - if ($which == 14 || $which == 15) { - $nolink = 1; - } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) { + if ($readonly) { $nolink = 1; - } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) { - if ($noeditgrp) { + } else { + if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) { $nolink = 1; - } - } elsif ($mprefix =~ /availablestudent\&$/) { - if ($which > 4) { - $nolink = 1; - } - } elsif ($mprefix =~ /examcode\&$/) { - unless ($which == 2) { + } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) { $nolink = 1; + } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) { + if ($noeditgrp) { + $nolink = 1; + } + } elsif ($mprefix =~ /availablestudent\&$/) { + if ($which > 4) { + $nolink = 1; + } + } elsif ($mprefix =~ /examcode\&$/) { + unless ($which == 2) { + $nolink = 1; + } } } if ($nolink) { - $r->print(&valout($$outpar[$which],$$typeoutpar[$which],$mprefix)); -# FIXME: probably a good thing that mprefix is not used in valout, because it does not look like a parameter name ! + my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/); + $r->print(&valout($currval,$currtype,$parmname)); } else { - $r->print(&plink($$typeoutpar[$which], - $$display{$value},$$outpar[$which], - $mprefix."$which",'parmform.pres','psub')); + $r->print(&plink($currtype, + $$display{$value},$currval, + $mprefix.$currlevel,'parmform.pres','psub',$recursive)); } $r->print(''."\n"); } -# FIXME: Despite the name, this does not print anything, the $r parameter is unused. # Returns HTML and other info for the cell added when a user is selected # and that user is in several groups. This is the cell with the title "Control by other group". # -# @param {Apache2::RequestRec} $r - the Apache request (unused) # @param {string} $what - parameter part.'.'.parameter name # @param {string} $rid - resource id # @param {string} $cgroup - group name @@ -1577,9 +1738,9 @@ sub print_td { # @param {array reference} $usersgroups - list of groups the user belongs to, if any # @param {integer} $result - level # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db) -# @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group) -sub print_usergroups { - my ($r,$what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_; +# @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group, true if recursive) +sub check_other_groups { + my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_; my $courseid = $env{'request.course.id'}; my $output; my $symb = &symbcache($rid); @@ -1591,16 +1752,22 @@ sub print_usergroups { &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm, $recurseparm,$what,$courseopt); my $bgcolor = $defbg; - my $grp_parm; + my ($grp_parm,$grp_is_rec); if (($coursereply) && ($cgroup ne $resultgroup)) { + my ($parmname) = ($what =~ /\.([^.]+)$/); if ($result > 3) { $bgcolor = '#AAFFAA'; - $grp_parm = &valout($coursereply,$resulttype,$what); } - $grp_parm = &valout($coursereply,$resulttype,$what); + $grp_parm = &valout($coursereply,$resulttype,$parmname); $output = ''; if ($resultgroup && $resultlevel) { - $output .= ''.$resultgroup.' ('.$resultlevel.'): '.$grp_parm; + if ($resultlevel eq 'recursive') { + $resultlevel = 'map/folder'; + $grp_is_rec = 1; + } + $output .= ''.$resultgroup.' ('.$resultlevel.'): '.$grp_parm. + ($grp_is_rec?''.&mt('recursive').'':''); + } else { $output .= ' '; } @@ -1608,11 +1775,11 @@ sub print_usergroups { } else { $output .= ' '; } - return ($coursereply,$output,$grp_parm,$resultgroup); + return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec); } # Looks for a group with a defined parameter for given user and parameter. -# Used by print_usergroups. +# Used by check_other_groups. # # @param {string} $courseid - the course id # @param {array reference} $usersgroups - list of groups the user belongs to, if any @@ -1648,7 +1815,21 @@ sub parm_control_group { -# extracts lots of information about all of the the course's resources into a variety of hashes. +# Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata. +# All the parameters are references and are filled by the sub. +# +# @param {array reference} $ids - resource and map ids +# @param {hash reference} $typep - hash resource/map id -> resource type (file extension) +# @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata +# @param {hash reference} $allparms - hash parameter name -> parameter title +# @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters) +# @param {hash reference} $allmaps - hash map pc -> map src +# @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src +# @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource +# @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes) +# @param {hash reference} $uris - hash resource/map id -> resource src +# @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer) +# @param {hash reference} $defkeytype - hash parameter name -> parameter type sub extractResourceInformation { my $ids = shift; my $typep = shift; @@ -1675,23 +1856,27 @@ sub extractResourceInformation { my $srcf=$resource->src(); $srcf=~/\.(\w+)$/; $$typep{$id}=$1; + my $toolsymb; + if ($srcf =~ /ext\.tool$/) { + $toolsymb = $resource->symb(); + } $$keyp{$id}=''; $$uris{$id}=$srcf; - foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys'))) { + foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) { next if ($key!~/^parameter_/); # Hidden parameters - next if (&Apache::lonnet::metadata($srcf,$key.'.hidden') eq 'parm'); + next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm'); # # allparms is a hash of parameter names # - my $name=&Apache::lonnet::metadata($srcf,$key.'.name'); + my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb); if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) { my ($display,$parmdis); $display = &standard_parameter_names($name); if ($display eq '') { - $display= &Apache::lonnet::metadata($srcf,$key.'.display'); + $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb); $parmdis = $display; $parmdis =~ s/\s*\[Part.*$//g; } else { @@ -1700,14 +1885,14 @@ sub extractResourceInformation { $$allparms{$name}=$parmdis; if (ref($defkeytype)) { $$defkeytype{$name}= - &Apache::lonnet::metadata($srcf,$key.'.type'); + &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb); } } # # allparts is a hash of all parts # - my $part= &Apache::lonnet::metadata($srcf,$key.'.part'); + my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb); $$allparts{$part} = &mt('Part: [_1]',$part); # # Remember all keys going with this resource @@ -1748,21 +1933,44 @@ sub extractResourceInformation { } } +sub get_recursive { + my ($recurseup,$resdata,$what,$prefix) = @_; + if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) { + foreach my $item (@{$recurseup}) { + my $norecursechk=$prefix.'.'.$item.'___(all).'.$what; + if (defined($resdata->{$norecursechk})) { + if ($what =~ /\.(encrypturl|hiddenresource)$/) { + my $type = $resdata->{$norecursechk.'.type'}; + return [$resdata->{$norecursechk},$type,$item]; + } else { + last; + } + } + my $recursechk=$prefix.'.'.$item.'___(rec).'.$what; + if (defined($resdata->{$recursechk})) { + my $type = $resdata->{$recursechk.'.type'}; + return [$resdata->{$recursechk},$type,$item]; + } + } + } + return; +} +# Tells if a parameter type is a date. +# +# @param {string} type - parameter type +# @returns{boolean} - true if it is a date sub isdateparm { my $type=shift; return (($type=~/^date/) && (!($type eq 'date_interval'))); } +# Prints the HTML and Javascript to select parameters, with various shortcuts. # -# parmmenu displays a list of the selected parameters. -# It also offers a link to show/hide the complete parameter list -# from which you can select all desired parameters. -# +# @param {Apache2::RequestRec} $r - the Apache request sub parmmenu { - my ($r,$allparms,$pscat,$keyorder)=@_; - my $tempkey; + my ($r)=@_; $r->print(< // @@ -1841,10 +2047,13 @@ sub parmmenu { ENDSCRIPT $r->print('
'); - &shortCuts($r,$allparms,$pscat,$keyorder); + &shortCuts($r); $r->print('
'); } -# return a hash + +# Returns parameter categories. +# +# @returns {hash} - category name -> title in English sub categories { return ('time_settings' => 'Time Settings', 'grading' => 'Grading', @@ -1858,7 +2067,9 @@ sub categories { 'misc' => 'Miscellaneous' ); } -# return a hash. Like a look-up table +# Returns the category for each parameter. +# +# @returns {hash} - parameter name -> category name sub lookUpTableParameter { return ( @@ -1905,10 +2116,14 @@ sub lookUpTableParameter { 'lenient' => 'grading', 'retrypartial' => 'tries', 'discussvote' => 'misc', - 'examcode' => 'high_level_randomization', - ); + 'examcode' => 'high_level_randomization', + ); } +# Adds the given parameter name to an array of arrays listing all parameters for each category. +# +# @param {string} $name - parameter name +# @param {array reference} $catList - array reference category name -> array reference of parameter names sub whatIsMyCategory { my $name = shift; my $catList = shift; @@ -1932,6 +2147,11 @@ sub whatIsMyCategory { } } +# Sorts parameter names based on appearance order. +# +# @param {array reference} name - array reference of parameter names +# @param {hash reference} $keyorder - hash parameter key -> appearance rank +# @returns {Array} - array of parameter names sub keysindisplayorderCategory { my ($name,$keyorder)=@_; return sort { @@ -1939,6 +2159,9 @@ sub keysindisplayorderCategory { } ( @{$name}); } +# Returns a hash category name -> order, starting at 1 (integer) +# +# @returns {hash} sub category_order { return ( 'time_settings' => 1, @@ -1955,6 +2178,12 @@ sub category_order { } +# Prints HTML to let the user select parameters, from a list of all parameters organized by category. +# +# @param {Apache2::RequestRec} $r - the Apache request +# @param {hash reference} $allparms - hash parameter name -> parameter title +# @param {array reference} $pscat - list of selected parameter names +# @param {hash reference} $keyorder - hash parameter key -> appearance rank sub parmboxes { my ($r,$allparms,$pscat,$keyorder)=@_; my %categories = &categories(); @@ -1982,6 +2211,7 @@ sub parmboxes { $r->print('
' .'

'.&mt($categories{$key}).'

'."\n"); foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) { + next if ($tempkey eq ''); $r->print('' .'
'. ''.&mt('Button text').': '. - '&').'" />'; + '&').'"'.$disabled.' />'; } } unless ($readonly) { @@ -4315,6 +5039,16 @@ sub date_interval_selector { return $result; } +# Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA. +# +# @param {string} $name - parameter name +# @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel) +# @param {string} $value - parameter value +# @param {string} $chostname - course server name +# @param {integer} $cmajor - major version number +# @param {integer} $cminor - minor version number +# @param {string} $needsrelease - release version needed (major.minor) +# @returns {string} sub oldversion_warning { my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_; my $standard_name = &standard_parameter_names($name); @@ -4390,10 +5124,11 @@ sub oldversion_warning { } # end of block using some constants related to parameter types -# -# Shift all start and end dates by $shift -# +# Shifts all start and end dates in the current course by $shift. +# +# @param {integer} $shift - time to shift, in seconds +# @returns {string} - error name or 'ok' sub dateshift { my ($shift)=@_; my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'}; @@ -4425,12 +5160,19 @@ sub dateshift { return $reply; } +# Overview mode UI to edit course parameters. +# +# @param {Apache2::RequestRec} $r - the Apache request sub newoverview { - my ($r) = @_; + my ($r,$parm_permission) = @_; my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $crs = $env{'course.'.$env{'request.course.id'}.'.num'}; my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'}; + my $readonly = 1; + if ($parm_permission->{'edit'}) { + undef($readonly); + } &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview', text=>"Overview Mode"}); @@ -4589,15 +5331,31 @@ ENDOVER # List data - &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview'); + &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly); } - $r->print(&tableend(). - ((($env{'form.store'}) || ($env{'form.dis'}))?'

':''). - ''); + $r->print(&tableend()); + unless ($readonly) { + $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'

':'') ); + } + $r->print(''); &endSettingsScreen($r); $r->print(&Apache::loncommon::end_page()); } +# Fills $listdata with parameter information. +# Keys use the format course id.[section id].part.name and course id.[section id].part.name.type. +# The non-type value is always 1. +# +# @param {string} $cat - parameter name +# @param {string} $pschp - selected map pc, or 'all' +# @param {string} $parmlev - selected level value (full|map|general), or '' +# @param {hash reference} $listdata - the parameter data that will be modified +# @param {array reference} $psprt - selected parts +# @param {array reference} $selections - selected sections +# @param {hash reference} $defkeytype - hash parameter name -> parameter type +# @param {hash reference} $allmaps - hash map pc -> map src +# @param {array reference} $ids - resource and map ids +# @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb sub secgroup_lister { my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_; foreach my $item (@{$selections}) { @@ -4618,9 +5376,6 @@ sub secgroup_lister { my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat; $$listdata{$newparmkey}=1; $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat}; - $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(rec).'.$part.'.'.$cat; - $$listdata{$newparmkey}=1; - $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat}; } } else { # resource-level parameter @@ -4636,12 +5391,19 @@ sub secgroup_lister { } } -# Display all existing parameter settings. +# UI to edit parameter settings starting with a list of all existing parameters. +# (called by setoverview action) +# +# @param {Apache2::RequestRec} $r - the Apache request sub overview { - my ($r) = @_; + my ($r,$parm_permission) = @_; my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $crs = $env{'course.'.$env{'request.course.id'}.'.num'}; my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'}; + my $readonly = 1; + if ($parm_permission->{'edit'}) { + undef($readonly); + } my $js = '