Annotation of loncom/interface/lonparmset.pm, revision 1.588

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.588   ! raeburn     4: # $Id: lonparmset.pm,v 1.587 2018/11/13 03:59:00 raeburn Exp $
1.40      albertel    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: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {string} $name - the parameter name (unused)
                    980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       981: sub valout {
1.554     raeburn   982:     my ($value,$type,$name,$editable)=@_;
1.59      matthew   983:     my $result = '';
                    984:     # Values of zero are valid.
                    985:     if (! $value && $value ne '0') {
1.528     bisitz    986:         if ($editable) {
                    987:             $result =
                    988:                 '<img src="/res/adm/pages/editmap.png"'
                    989:                .' alt="'.&mt('Change').'"'
1.539     raeburn   990:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    991:         } else {
                    992:             $result='&nbsp;';
                    993:         }
1.59      matthew   994:     } else {
1.66      www       995:         if ($type eq 'date_interval') {
1.559     raeburn   996:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    997:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    998:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    999:                 $donebuttontext = $1;
                   1000:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1001:                 $usesdone = 'done';
                   1002:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1003:                 $donebuttontext = &mt('Done');
                   1004:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1005:             }
1.554     raeburn  1006:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1007:             my @timer;
1.66      www      1008:             $year=$year-70;
                   1009:             $mday--;
                   1010:             if ($year) {
1.413     bisitz   1011: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1012:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1013:             }
                   1014:             if ($mon) {
1.413     bisitz   1015: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1016:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1017:             }
                   1018:             if ($mday) {
1.413     bisitz   1019: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1020:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1021:             }
                   1022:             if ($hour) {
1.413     bisitz   1023: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1024:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1025:             }
                   1026:             if ($min) {
1.413     bisitz   1027: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1028:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1029:             }
                   1030:             if ($sec) {
1.413     bisitz   1031: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1032:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1033:             }
1.413     bisitz   1034: #           $result=~s/\s+$//;
                   1035:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1036:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1037:             }
                   1038:             $result.=join(", ",@timer);
1.559     raeburn  1039:             if ($usesdone eq 'done') {
1.558     raeburn  1040:                 if ($secretkey) {
1.559     raeburn  1041:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1042:                 } else {
1.559     raeburn  1043:                     $result .= ' + "'.$donebuttontext.'"';
                   1044:                 }
1.554     raeburn  1045:             }
1.213     www      1046:         } elsif (&isdateparm($type)) {
1.361     albertel 1047:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1048:                 &date_sanity_info($value);
1.59      matthew  1049:         } else {
                   1050:             $result = $value;
1.517     www      1051:             $result=~s/\,/\, /gs;
1.560     damieng  1052:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1053:         }
                   1054:     }
                   1055:     return $result;
1.9       www      1056: }
                   1057: 
1.59      matthew  1058: 
1.561     damieng  1059: # Returns HTML containing a link on a parameter value, for table mode.
                   1060: # The link uses the javascript function 'pjump'.
                   1061: #
                   1062: # @param {string} $type - parameter type
                   1063: # @param {string} $dis - dialog title for editing the parameter value and type
                   1064: # @param {string} $value - parameter value
                   1065: # @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.
                   1066: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1067: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588   ! raeburn  1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
        !          1069: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1070: sub plink {
1.588   ! raeburn  1071:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1072:     my $winvalue=$value;
                   1073:     unless ($winvalue) {
1.560     damieng  1074:         if (&isdateparm($type)) {
1.190     albertel 1075:             $winvalue=$env{'form.recent_'.$type};
1.23      www      1076:         } else {
1.190     albertel 1077:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1078:         }
                   1079:     }
1.229     www      1080:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1081:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1082:     unless (defined($winvalue)) { $winvalue=$val; }
1.554     raeburn  1083:     my $valout = &valout($value,$type,$parmname,1);
1.429     raeburn  1084:     my $unencmarker = $marker;
1.378     albertel 1085:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588   ! raeburn  1086:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1087:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1088:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1089:     }
1.429     raeburn  1090:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1091:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588   ! raeburn  1092:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1093:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1094:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1095: 
1.5       www      1096: }
                   1097: 
1.561     damieng  1098: # Javascript for table mode.
1.280     albertel 1099: sub page_js {
                   1100: 
1.81      www      1101:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1102:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1103: 
                   1104:     return(<<ENDJS);
                   1105: <script type="text/javascript">
1.454     bisitz   1106: // <![CDATA[
1.44      albertel 1107: 
1.88      matthew  1108:     $pjump_def
1.44      albertel 1109: 
                   1110:     function psub() {
                   1111:         if (document.parmform.pres_marker.value!='') {
                   1112:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1113:             var typedef=new Array();
                   1114:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1115:             if (document.parmform.pres_type.value!='') {
                   1116:                 if (typedef[0]=='date') {
                   1117:                     eval('document.parmform.recent_'+
                   1118:                         document.parmform.pres_type.value+
                   1119:                         '.value=document.parmform.pres_value.value;');
                   1120:                 } else {
                   1121:                     eval('document.parmform.recent_'+typedef[0]+
                   1122:                         '.value=document.parmform.pres_value.value;');
                   1123:                 }
1.44      albertel 1124:             }
                   1125:             document.parmform.submit();
                   1126:         } else {
                   1127:             document.parmform.pres_value.value='';
                   1128:             document.parmform.pres_marker.value='';
                   1129:         }
                   1130:     }
                   1131: 
1.57      albertel 1132:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1133:         var options = "width=" + w + ",height=" + h + ",";
                   1134:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1135:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1136:         var newWin = window.open(url, wdwName, options);
                   1137:         newWin.focus();
                   1138:     }
1.523     raeburn  1139: 
1.454     bisitz   1140: // ]]>
1.523     raeburn  1141: 
1.44      albertel 1142: </script>
1.81      www      1143: $selscript
1.280     albertel 1144: ENDJS
                   1145: 
                   1146: }
1.507     www      1147: 
1.561     damieng  1148: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1149: # for table and overview modes.
1.523     raeburn  1150: sub showhide_js {
                   1151:     return <<"COURSECONTENTSCRIPT";
                   1152: 
                   1153: function showHide_courseContent() {
                   1154:     var parmlevValue=document.getElementById("parmlev").value;
                   1155:     if (parmlevValue == 'general') {
                   1156:         document.getElementById('mapmenu').style.display="none";
                   1157:     } else {
                   1158:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1159:             document.getElementById('mapmenu').style.display ="";
                   1160:         } else {
                   1161:             document.getElementById('mapmenu').style.display="none";
                   1162:         }
                   1163:     }
                   1164:     return;
                   1165: }
                   1166: 
                   1167: COURSECONTENTSCRIPT
                   1168: }
                   1169: 
1.561     damieng  1170: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1171: sub toggleparmtextbox_js {
                   1172:     return <<"ENDSCRIPT";
                   1173: 
                   1174: if (!document.getElementsByClassName) {
                   1175:     function getElementsByClassName(node, classname) {
                   1176:         var a = [];
                   1177:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1178:         var els = node.getElementsByTagName("*");
                   1179:         for(var i=0,j=els.length; i<j; i++)
                   1180:             if(re.test(els[i].className))a.push(els[i]);
                   1181:         return a;
                   1182:     }
                   1183: }
                   1184: 
                   1185: function showHideLenient() {
                   1186:     var lenients;
                   1187:     var setRegExp = /^set_/;
                   1188:     if (document.getElementsByClassName) {
                   1189:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1190:     } else {
                   1191:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1192:     }
                   1193:     if (lenients != 'undefined') {
                   1194:         for (var i=0; i<lenients.length; i++) {
                   1195:             if (lenients[i].checked) {
                   1196:                 if (lenients[i].value == 'weighted') {
                   1197:                     if (setRegExp.test(lenients[i].name)) {
                   1198:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1199:                         toggleParmTextbox(document.parmform,identifier);
                   1200:                     }
                   1201:                 }
                   1202:             }
                   1203:         }
                   1204:     }
                   1205:     return;
                   1206: }
                   1207: 
                   1208: function toggleParmTextbox(form,key) {
                   1209:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1210:     if (divfortext) {
                   1211:         var caller = form.elements['set_'+key];
                   1212:         if (caller.length) {
                   1213:             for (i=0; i<caller.length; i++) {
                   1214:                 if (caller[i].checked) {
                   1215:                     if (caller[i].value == 'weighted') {
                   1216:                         divfortext.style.display = 'inline';
                   1217:                     } else {
                   1218:                         divfortext.style.display = 'none';
                   1219:                     }
                   1220:                 }
                   1221:             }
                   1222:         }
                   1223:     }
                   1224:     return;
                   1225: }
                   1226: 
                   1227: ENDSCRIPT
                   1228: }
                   1229: 
1.561     damieng  1230: # Javascript function validateParms, for overview mode
1.549     raeburn  1231: sub validateparms_js {
                   1232:     return <<'ENDSCRIPT';
                   1233: 
                   1234: function validateParms() {
                   1235:     var textRegExp = /^settext_/;
                   1236:     var tailLenient = /\.lenient$/;
                   1237:     var patternRelWeight = /^\-?[\d.]+$/;
                   1238:     var patternLenientStd = /^(yes|no|default)$/;
                   1239:     var ipallowRegExp = /^setipallow_/;
                   1240:     var ipdenyRegExp = /^setipdeny_/; 
1.588   ! raeburn  1241:     var deeplinkRegExp = /^deeplink_(listing|scope)_/;
        !          1242:     var deeplinkUrlsRegExp = /^deeplink_urls_/;
        !          1243:     var deeplinkltiRegExp = /^deeplink_lti_/;
        !          1244:     var deeplinkkeyRegExp = /^deeplink_key_/;
1.549     raeburn  1245:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1246:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1247:         if (document.parmform.elements.length) {
                   1248:             for (i=0; i<document.parmform.elements.length; i++) {
                   1249:                 var name=document.parmform.elements[i].name;
1.588   ! raeburn  1250:                 if (textRegExp.test(name)) {
1.549     raeburn  1251:                     var identifier = name.replace(textRegExp,'');
                   1252:                     if (tailLenient.test(identifier)) {
                   1253:                         if (document.parmform.elements['set_'+identifier].length) {
                   1254:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1255:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1256:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1257:                                         var relweight = document.parmform.elements[i].value;
                   1258:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1259:                                         if (!patternRelWeight.test(relweight)) {
                   1260:                                             relweight = '0.0';
                   1261:                                         }
                   1262:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1263:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1264:                                         } else {
                   1265:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1266:                                         }
                   1267:                                     }
                   1268:                                     break;
                   1269:                                 }
                   1270:                             }
                   1271:                         }
                   1272:                     }
1.588   ! raeburn  1273:                 } else if (ipallowRegExp.test(name)) {
        !          1274:                     var identifier = name.replace(ipallowRegExp,'');
        !          1275:                     var possallow = document.parmform.elements[i].value;
        !          1276:                     possallow = possallow.replace(/^\s+|\s+$/g,'');
        !          1277:                     if (patternIP.test(possallow)) {
        !          1278:                         if (document.parmform.elements['set_'+identifier].value) {
        !          1279:                             possallow = ','+possallow;
        !          1280:                         }
        !          1281:                         document.parmform.elements['set_'+identifier].value += possallow;
        !          1282:                     }
        !          1283:                 } else if (ipdenyRegExp.test(name)) {
        !          1284:                     var identifier = name.replace(ipdenyRegExp,'');
        !          1285:                     var possdeny = document.parmform.elements[i].value;
        !          1286:                     possdeny = possdeny.replace(/^\s+|\s+$/g,'');
        !          1287:                     if (patternIP.test(possdeny)) {
        !          1288:                         possdeny = '!'+possdeny;
        !          1289:                         if (document.parmform.elements['set_'+identifier].value) {
        !          1290:                             possdeny = ','+possdeny;
        !          1291:                         }
        !          1292:                         document.parmform.elements['set_'+identifier].value += possdeny;
        !          1293:                     }
        !          1294:                 } else if (deeplinkRegExp.test(name)) {
        !          1295:                     var identifier =  name.replace(deeplinkRegExp,'');
        !          1296:                     var possdeeplink = document.parmform.elements[i].value;
        !          1297:                     possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
        !          1298:                     if (document.parmform.elements['set_'+identifier].value) {
        !          1299:                         possdeeplink = ','+possdeeplink;
        !          1300:                     }
        !          1301:                     document.parmform.elements['set_'+identifier].value += possdeeplink;
        !          1302:                 } else if (deeplinkUrlsRegExp.test(name)) {
        !          1303:                     if (document.parmform.elements[i].checked) {
        !          1304:                         var identifier =  name.replace(deeplinkUrlsRegExp,'');
        !          1305:                         var posslinkurl = document.parmform.elements[i].value;
        !          1306:                         posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
        !          1307:                         if (document.parmform.elements['set_'+identifier].value) {
        !          1308:                             posslinkurl = ','+posslinkurl;
        !          1309:                         }
        !          1310:                         document.parmform.elements['set_'+identifier].value += posslinkurl;
        !          1311:                     }
        !          1312:                 } else if (deeplinkltiRegExp.test(name)) {
        !          1313:                     var identifier = name.replace(deeplinkltiRegExp,'');
        !          1314:                     var posslti = document.parmform.elements[i].value;
        !          1315:                     posslti = posslti.replace(/\D+/g,'');
        !          1316:                     if (document.parmform.elements['set_'+identifier].value) {
        !          1317:                         posslti = ':'+posslti;
        !          1318:                     }
        !          1319:                     document.parmform.elements['set_'+identifier].value += posslti;
        !          1320:                 } else if (deeplinkkeyRegExp.test(name)) {
        !          1321:                     var identifier = name.replace(deeplinkkeyRegExp,'');
        !          1322:                     var posskey = document.parmform.elements[i].value;
        !          1323:                     posskey = posskey.replace(/\W+/g,'');
        !          1324:                     if (document.parmform.elements['set_'+identifier].value) {
        !          1325:                         posslti = ':'+posskey;
1.549     raeburn  1326:                     }
1.588   ! raeburn  1327:                     document.parmform.elements['set_'+identifier].value += posskey;
1.549     raeburn  1328:                 }
                   1329:             }
                   1330:         }
                   1331:     }
                   1332:     return true;
                   1333: }
                   1334: 
                   1335: ENDSCRIPT
                   1336: }
                   1337: 
1.561     damieng  1338: # Javascript initialization, for overview mode
1.549     raeburn  1339: sub ipacc_boxes_js  {
                   1340:     my $remove = &mt('Remove');
                   1341:     return <<"END";
                   1342: \$(document).ready(function() {
                   1343:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1344:     var add_button      = \$(".LC_add_ipacc_button");
                   1345:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1346: 
                   1347:     \$(add_button).click(function(e){
                   1348:         e.preventDefault();
                   1349:         var identifier = \$(this).closest("div").attr("id");
                   1350:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1351:         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549     raeburn  1352:     });
                   1353: 
                   1354:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1355:         e.preventDefault(); \$(this).closest("div").remove();
                   1356:     })
                   1357: });
                   1358: 
                   1359: 
                   1360: END
                   1361: }
                   1362: 
1.561     damieng  1363: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1364: sub done_proctor_js {
                   1365:     return <<"END";
                   1366: function toggleSecret(form,radio,key) {
                   1367:     var radios = form[radio+key];
                   1368:     if (radios.length) {
                   1369:         for (var i=0; i<radios.length; i++) {
                   1370:             if (radios[i].checked) {
                   1371:                 if (radios[i].value == '_done_proctor') {
                   1372:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1373:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1374:                     }
                   1375:                 } else {
                   1376:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1377:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1378:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1379:                     }
                   1380:                 }
                   1381:             }
                   1382:         }
                   1383:     }
                   1384: }
                   1385: END
                   1386: 
                   1387: }
                   1388: 
1.588   ! raeburn  1389: # Javascript function toggle
        !          1390: sub deeplink_js {
        !          1391:     return <<"END";
        !          1392: function toggleDeepLink(form,item,key) {
        !          1393:     var radios = form['deeplink_'+item+'_'+key];
        !          1394:     if (radios.length) {
        !          1395:         var keybox;
        !          1396:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
        !          1397:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
        !          1398:         }
        !          1399:         var ltidiv;
        !          1400:         if (document.getElementById('deeplinkdiv_lti_'+item+'_'+key)) {
        !          1401:             ltidiv = document.getElementById('deeplinkdiv_lti_'+item+'_'+key);
        !          1402:         }
        !          1403:         for (var i=0; i<radios.length; i++) {
        !          1404:             if (radios[i].checked) {
        !          1405:                 if (radios[i].value == 'lti') {
        !          1406:                     ltidiv.style.display = 'inline-block';
        !          1407:                     keybox.type = 'hidden';
        !          1408:                     keybox.value = '';
        !          1409:                 } else {
        !          1410:                     if (ltidiv != '') {
        !          1411:                         ltidiv.style.display = 'none';
        !          1412:                         form['deeplink_lti_'+key].selectedIndex = 0;
        !          1413:                     }
        !          1414:                     if (radios[i].value == 'key') {
        !          1415:                         keybox.type = 'text';
        !          1416:                     } else {
        !          1417:                         keybox.type = 'hidden';
        !          1418:                     }
        !          1419:                 }
        !          1420:             }
        !          1421:         }
        !          1422:     }
        !          1423: }
        !          1424: END
        !          1425: 
        !          1426: }
        !          1427: 
1.561     damieng  1428: # Prints HTML page start for table mode.
                   1429: # @param {Apache2::RequestRec} $r - the Apache request
                   1430: # @param {string} $psymb - resource symb
                   1431: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1432: sub startpage {
1.531     raeburn  1433:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1434: 
1.515     raeburn  1435:     my %loaditems = (
                   1436:                       'onload'   => "group_or_section('cgroup')",
                   1437:                     );
                   1438:     if (!$psymb) {
1.523     raeburn  1439:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1440:     }
1.280     albertel 1441: 
1.560     damieng  1442:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1443:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1444:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1445:             text=>"Problem Parameters"});
1.414     droeschl 1446:     } else {
1.560     damieng  1447:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1448:             text=>"Table Mode",
                   1449:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1450:     }
1.523     raeburn  1451:     my $js = &page_js().'
                   1452: <script type="text/javascript">
                   1453: // <![CDATA[
                   1454: '.
                   1455:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1456: // ]]>
                   1457: </script>
                   1458: ';
1.446     bisitz   1459:     my $start_page =
1.523     raeburn  1460:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1461:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1462:     my $breadcrumbs =
1.473     amueller 1463:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1464:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1465:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1466:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1467:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1468:     $r->print(<<ENDHEAD);
1.193     albertel 1469: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1470: <input type="hidden" value="" name="pres_value" />
                   1471: <input type="hidden" value="" name="pres_type" />
                   1472: <input type="hidden" value="" name="pres_marker" />
                   1473: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1474: <input type="hidden" value="$escfilter" name="filter" />
                   1475: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1476: ENDHEAD
                   1477: }
                   1478: 
1.209     www      1479: 
1.561     damieng  1480: # Prints a row for table mode (except for the tr start).
                   1481: # Every time a hash reference is passed, a single entry is used, so print_row
                   1482: # could just use these values, but why make it simple when it can be complicated ?
                   1483: #
                   1484: # @param {Apache2::RequestRec} $r - the Apache request
                   1485: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1486: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1487: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1488: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1489: # @param {string} $rid - resource id
                   1490: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1491: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1492: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1493: # @param {string} $defbgone - user level and other levels background color
                   1494: # @param {string} $defbgtwo - section level background color, also used for part number
                   1495: # @param {string} $defbgthree - group level background color
                   1496: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1497: # @param {string} $uname - user name
                   1498: # @param {string} $udom - user domain
                   1499: # @param {string} $csec - section name
                   1500: # @param {string} $cgroup - group name
                   1501: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1502: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1503: # @param {boolean} $readonly - true if no editing allowed.
                   1504: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1505: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1506: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1507: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1508: sub print_row {
1.201     www      1509:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1510:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1511:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1512:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1513:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1514:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1515:     my $numlinks = 0;
1.553     raeburn  1516: 
1.560     damieng  1517:     # get the values for the parameter in cascading order
                   1518:     # empty levels will remain empty
1.44      albertel 1519:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1520:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1521:     # get the type for the parameters
                   1522:     # problem: these may not be set for all levels
1.66      www      1523:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1524:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1525:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1526:     # cascade down manually
1.182     albertel 1527:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1528:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1529:         if ($typeoutpar[$i]) {
1.66      www      1530:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1531:         } else {
1.66      www      1532:             $typeoutpar[$i]=$cascadetype;
                   1533:         }
                   1534:     }
1.57      albertel 1535:     my $parm=$$display{$which};
                   1536: 
1.203     www      1537:     if ($parmlev eq 'full') {
1.419     bisitz   1538:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1539:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1540:     } else {
1.57      albertel 1541:         $parm=~s|\[.*\]\s||g;
                   1542:     }
1.231     www      1543:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1544:     if ($automatic) {
1.560     damieng  1545:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1546:     }
1.427     bisitz   1547:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1548: 
1.44      albertel 1549:     my $thismarker=$which;
                   1550:     $thismarker=~s/^parameter\_//;
                   1551:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1552:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1553:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588   ! raeburn  1554:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1555:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1556:         if ($result eq '') {
                   1557:             $recurse_check = 1;
                   1558:         } elsif (($uname ne '') && ($result > 3)) {
                   1559:             $recurse_check = 1;
                   1560:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1561:             $recurse_check = 1;
                   1562:         } elsif (($csec ne '') && ($result > 11)) {
                   1563:             $recurse_check = 1;
                   1564:         } elsif ($result > 17) {
                   1565:             $recurse_check = 1;
                   1566:         }
                   1567:         if ($recurse_check) {
                   1568:             my $what = $$part{$which}.'.'.$$name{$which};
                   1569:             my $prefix;
                   1570:             if (($uname ne '') && ($udom ne '')) {
                   1571:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1572:                 $prefix = $env{'request.course.id'};
                   1573:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1574:                 if (ref($recursinfo) eq 'ARRAY') {
                   1575:                     $effparm_rec = 1;
                   1576:                     $effparm_level = &mt('user: [_1]',$uname);
                   1577:                 }
                   1578:             }
                   1579:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1580:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1581:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1582:                 if (ref($recursinfo) eq 'ARRAY') {
                   1583:                     $effparm_rec = 1;
                   1584:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1585:                 }
                   1586:             }
                   1587:             if (($csec ne '') && (!$effparm_rec)) {
                   1588:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1589:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1590:                 if (ref($recursinfo) eq 'ARRAY') {
                   1591:                     $effparm_rec = 1;
                   1592:                     $effparm_level = &mt('section: [_1]',$csec);
                   1593:                 }
                   1594:             }
                   1595:             if (!$effparm_rec) {
                   1596:                 $prefix = $env{'request.course.id'};
                   1597:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1598:                 if (ref($recursinfo) eq 'ARRAY') {
                   1599:                     $effparm_rec = 1;
                   1600:                 }
                   1601:             }
                   1602:         }
                   1603:     }
                   1604:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1605:         $effparm_rec = 1;
                   1606:     }
                   1607:     if ((!$effparm_rec) && 
                   1608:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1609:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1610:         $effparm_rec = 1;
                   1611:     }
1.588   ! raeburn  1612:     if ($parmname eq 'deeplink') {
        !          1613:         my %posslti;
        !          1614:         my %lti =
        !          1615:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
        !          1616:                                             'provider');
        !          1617:         foreach my $item (keys(%lti)) {
        !          1618:             if (ref($lti{$item}) eq 'HASH') {
        !          1619:                 unless ($lti{$item}{'requser'}) {
        !          1620:                     $posslti{$item} = $lti{$item}{'consumer'};
        !          1621:                 }
        !          1622:             }
        !          1623:         }
        !          1624:         if (keys(%posslti)) {
        !          1625:             $extra = 'lti_';
        !          1626:             foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
        !          1627:                 $extra .= $lti.':'.&js_escape($posslti{$lti}).',';
        !          1628:             }
        !          1629:             $extra =~ s/,$//;
        !          1630:         }
        !          1631:     }
1.57      albertel 1632:     if ($parmlev eq 'general') {
                   1633:         if ($uname) {
1.588   ! raeburn  1634:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1635:         } elsif ($cgroup) {
1.588   ! raeburn  1636:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1637:         } elsif ($csec) {
1.588   ! raeburn  1638:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1639:         } else {
1.588   ! raeburn  1640:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1641:         }
                   1642:     } elsif ($parmlev eq 'map') {
                   1643:         if ($uname) {
1.588   ! raeburn  1644:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1645:         } elsif ($cgroup) {
1.588   ! raeburn  1646:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1647:         } elsif ($csec) {
1.588   ! raeburn  1648:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1649:         } else {
1.588   ! raeburn  1650:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1651:         }
                   1652:     } else {
1.275     raeburn  1653:         if ($uname) {
                   1654:             if (@{$usersgroups} > 1) {
1.582     raeburn  1655:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1656:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1657:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1658:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1659:                     if (defined($controlgrp)) {
                   1660:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1661:                             $eff_groupparm = $grp_parm;
                   1662:                             undef($result);
                   1663:                             undef($effparm_rec);
                   1664:                             if ($grp_is_rec) {
                   1665:                                  $effparm_rec = 1;
                   1666:                             }
1.275     raeburn  1667:                         }
                   1668:                     }
                   1669:                 }
                   1670:             }
                   1671:         }
1.57      albertel 1672: 
1.588   ! raeburn  1673:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
        !          1674:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
        !          1675:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
        !          1676:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
        !          1677:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1678: 
                   1679:         if ($csec) {
1.588   ! raeburn  1680:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
        !          1681:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
        !          1682:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1683:         }
1.269     raeburn  1684: 
                   1685:         if ($cgroup) {
1.588   ! raeburn  1686:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
        !          1687:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
        !          1688:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1689:         }
1.446     bisitz   1690: 
1.548     raeburn  1691:         if ($uname) {
1.275     raeburn  1692:             if ($othergrp) {
                   1693:                 $r->print($othergrp);
                   1694:             }
1.588   ! raeburn  1695:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
        !          1696:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
        !          1697:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1698:         }
1.57      albertel 1699:     } # end of $parmlev if/else
1.582     raeburn  1700:     if (ref($recursinfo) eq 'ARRAY') {
                   1701:         my $rectitle = &mt('recursive');
                   1702:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1703:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1704:                 $rectitle = &mt('set in: [_1]','"'.
                   1705:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1706:                                                               "'$parmname','$$part{$which}'".');">'.
                   1707:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1708:               
                   1709:                 $numlinks ++;
                   1710:             }
                   1711:         }
                   1712:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1713:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1],$parmname);
                   1714:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1715:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1716:                   $effparm_level.'</span></td>');
                   1717:     } else {
                   1718:         if ($result) {
                   1719:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result],$parmname);
                   1720:         }
                   1721:         if ($eff_groupparm) {
                   1722:             $effective_parm = $eff_groupparm;
                   1723:         }
                   1724:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1725:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1726:                                 '</span>':'').'</td>');
                   1727:     }
1.203     www      1728:     if ($parmlev eq 'full') {
1.136     albertel 1729:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1730:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1731:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1732:         if (!defined($sessionvaltype)) {
                   1733:             $sessionvaltype=$$defaulttype{$which};
                   1734:         }
1.419     bisitz   1735:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.554     raeburn  1736:                   &valout($sessionval,$sessionvaltype,$$name{$which}).'&nbsp;'.
1.57      albertel 1737:                   '</font></td>');
1.136     albertel 1738:     }
1.44      albertel 1739:     $r->print('</tr>');
1.57      albertel 1740:     $r->print("\n");
1.582     raeburn  1741:     if (($numlinks) && (ref($reclinks))) {
                   1742:         $$reclinks = $numlinks;
                   1743:     }
1.44      albertel 1744: }
1.59      matthew  1745: 
1.561     damieng  1746: # Prints a cell for table mode.
                   1747: #
                   1748: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1749: # Also, it would make more sense to pass the display for this cell rather
                   1750: # than the full display hash and the key to use.
                   1751: #
                   1752: # @param {Apache2::RequestRec} $r - the Apache request
                   1753: # @param {integer} $which - level
                   1754: # @param {string} $defbg - cell background color
                   1755: # @param {integer} $result - the most specific level that is defined for that parameter
                   1756: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1757: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1758: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1759: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1760: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1761: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1762: # @param {boolean} $readonly -true if editing not allowed.
1.588   ! raeburn  1763: # @param {boolean} $ismaplevel - true if level is for a map.
        !          1764: # @param {strring} $extra - extra informatio to pass to plink.
1.44      albertel 1765: sub print_td {
1.578     raeburn  1766:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588   ! raeburn  1767:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1768:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1769:     $ineffect = 0;
                   1770:     $currval = $$outpar[$which];
                   1771:     $currtype = $$typeoutpar[$which];
                   1772:     $currlevel = $which;
                   1773:     if (($result) && ($result == $which)) {
                   1774:         $ineffect = 1;
                   1775:     } 
                   1776:     if ($ismaplevel) {
                   1777:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1778:             if (($result) && ($result == $which)) {
                   1779:                 $recursive = 1;
                   1780:             }
                   1781:         } elsif ($$outpar[$which+1] ne '') {
                   1782:             $recursive = 1;
                   1783:             $currlevel = $which+1;
                   1784:             $currval = $$outpar[$currlevel];
                   1785:             $currtype = $$typeoutpar[$currlevel];
                   1786:             if (($result) && ($result == $currlevel)) {
                   1787:                 $ineffect = 1;
                   1788:             }
                   1789:         }
                   1790:     }
                   1791:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1792:               ';" align="center">');
1.437     raeburn  1793:     my $nolink = 0;
1.568     raeburn  1794:     if ($readonly) {
1.552     raeburn  1795:         $nolink = 1;
1.568     raeburn  1796:     } else { 
1.578     raeburn  1797:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1798:             $nolink = 1;
1.568     raeburn  1799:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1800:             $nolink = 1;
1.568     raeburn  1801:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1802:             if ($noeditgrp) {
                   1803:                 $nolink = 1;
                   1804:             }
                   1805:         } elsif ($mprefix =~ /availablestudent\&$/) {
                   1806:             if ($which > 4) {
                   1807:                 $nolink = 1;
                   1808:             }
                   1809:         } elsif ($mprefix =~ /examcode\&$/) {
                   1810:             unless ($which == 2) {
                   1811:                 $nolink = 1;
                   1812:             }
1.533     raeburn  1813:         }
1.437     raeburn  1814:     }
                   1815:     if ($nolink) {
1.577     raeburn  1816:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.578     raeburn  1817:         $r->print(&valout($currval,$currtype,$parmname));
1.114     www      1818:     } else {
1.578     raeburn  1819:         $r->print(&plink($currtype,
                   1820:                          $$display{$value},$currval,
1.588   ! raeburn  1821:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
        !          1822:                          $extra));
1.114     www      1823:     }
                   1824:     $r->print('</td>'."\n");
1.57      albertel 1825: }
                   1826: 
1.561     damieng  1827: # Returns HTML and other info for the cell added when a user is selected
                   1828: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1829: #
                   1830: # @param {string} $what - parameter part.'.'.parameter name
                   1831: # @param {string} $rid - resource id
                   1832: # @param {string} $cgroup - group name
                   1833: # @param {string} $defbg - cell background color
                   1834: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1835: # @param {integer} $result - level
                   1836: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1837: # @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)
1.580     raeburn  1838: sub check_other_groups {
                   1839:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1840:     my $courseid = $env{'request.course.id'};
                   1841:     my $output;
                   1842:     my $symb = &symbcache($rid);
                   1843:     my $symbparm=$symb.'.'.$what;
                   1844:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1845:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1846:     my $mapparm=$map.'___(all).'.$what;
                   1847:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1848:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1849:                               $recurseparm,$what,$courseopt);
1.275     raeburn  1850:     my $bgcolor = $defbg;
1.582     raeburn  1851:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   1852:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  1853:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  1854:         if ($result > 3) {
1.419     bisitz   1855:             $bgcolor = '#AAFFAA';
1.275     raeburn  1856:         }
1.582     raeburn  1857:         $grp_parm = &valout($coursereply,$resulttype,$parmname);
1.419     bisitz   1858:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  1859:         if ($resultgroup && $resultlevel) {
1.582     raeburn  1860:             if ($resultlevel eq 'recursive') {
                   1861:                 $resultlevel = 'map/folder';
                   1862:                 $grp_is_rec = 1;
                   1863:             }
                   1864:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   1865:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   1866:              
1.275     raeburn  1867:         } else {
                   1868:             $output .= '&nbsp;';
                   1869:         }
                   1870:         $output .= '</td>';
                   1871:     } else {
1.419     bisitz   1872:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  1873:     }
1.582     raeburn  1874:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  1875: }
                   1876: 
1.561     damieng  1877: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  1878: # Used by check_other_groups.
1.561     damieng  1879: #
                   1880: # @param {string} $courseid - the course id
                   1881: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1882: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   1883: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   1884: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   1885: # @param {string} $what - parameter part.'.'.parameter name
                   1886: # @param {hash reference} $courseopt - course parameters hash
                   1887: # @returns {Array} - (parameter value for the group, course parameter hash key for the parameter, name of the group, level name, parameter type)
1.275     raeburn  1888: sub parm_control_group {
1.556     raeburn  1889:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  1890:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1891:     my $grpfound = 0;
1.556     raeburn  1892:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   1893:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  1894:     foreach my $group (@{$usersgroups}) {
                   1895:         if ($grpfound) { last; }
                   1896:         for (my $i=0; $i<@levels; $i++) {
                   1897:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   1898:             if (defined($$courseopt{$item})) {
                   1899:                 $coursereply = $$courseopt{$item};
                   1900:                 $resultitem = $item;
                   1901:                 $resultgroup = $group;
                   1902:                 $resultlevel = $levelnames[$i];
                   1903:                 $resulttype = $$courseopt{$item.'.type'};
                   1904:                 $grpfound = 1;
                   1905:                 last;
                   1906:             }
                   1907:         }
                   1908:     }
                   1909:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1910: }
1.201     www      1911: 
1.63      bowersj2 1912: 
                   1913: 
1.562     damieng  1914: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   1915: # All the parameters are references and are filled by the sub.
                   1916: #
1.566     damieng  1917: # @param {array reference} $ids - resource and map ids
                   1918: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   1919: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  1920: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   1921: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  1922: # @param {hash reference} $allmaps - hash map pc -> map src
                   1923: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   1924: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   1925: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   1926: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  1927: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   1928: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63      bowersj2 1929: sub extractResourceInformation {
                   1930:     my $ids = shift;
                   1931:     my $typep = shift;
                   1932:     my $keyp = shift;
                   1933:     my $allparms = shift;
                   1934:     my $allparts = shift;
                   1935:     my $allmaps = shift;
                   1936:     my $mapp = shift;
                   1937:     my $symbp = shift;
1.82      www      1938:     my $maptitles=shift;
1.196     www      1939:     my $uris=shift;
1.210     www      1940:     my $keyorder=shift;
1.211     www      1941:     my $defkeytype=shift;
1.196     www      1942: 
1.210     www      1943:     my $keyordercnt=100;
1.63      bowersj2 1944: 
1.196     www      1945:     my $navmap = Apache::lonnavmaps::navmap->new();
                   1946:     my @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   1947:     foreach my $resource (@allres) {
1.480     amueller 1948:         my $id=$resource->id();
1.196     www      1949:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 1950:         if ($mapid eq '0') { next; }
                   1951:         $$ids[$#$ids+1]=$id;
                   1952:         my $srcf=$resource->src();
                   1953:         $srcf=~/\.(\w+)$/;
                   1954:         $$typep{$id}=$1;
1.584     raeburn  1955:         my $toolsymb;
                   1956:         if ($srcf =~ /ext\.tool$/) {
                   1957:             $toolsymb = $resource->symb();
                   1958:         }
1.480     amueller 1959:         $$keyp{$id}='';
1.196     www      1960:         $$uris{$id}=$srcf;
1.512     foxr     1961: 
1.584     raeburn  1962:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 1963:             next if ($key!~/^parameter_/);
1.363     albertel 1964: 
1.209     www      1965: # Hidden parameters
1.584     raeburn  1966:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      1967: #
                   1968: # allparms is a hash of parameter names
                   1969: #
1.584     raeburn  1970:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 1971:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   1972:                 my ($display,$parmdis);
                   1973:                 $display = &standard_parameter_names($name);
                   1974:                 if ($display eq '') {
1.584     raeburn  1975:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 1976:                     $parmdis = $display;
                   1977:                     $parmdis =~ s/\s*\[Part.*$//g;
                   1978:                 } else {
                   1979:                     $parmdis = &mt($display);
                   1980:                 }
                   1981:                 $$allparms{$name}=$parmdis;
                   1982:                 if (ref($defkeytype)) {
                   1983:                     $$defkeytype{$name}=
1.584     raeburn  1984:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 1985:                 }
                   1986:             }
1.363     albertel 1987: 
1.209     www      1988: #
                   1989: # allparts is a hash of all parts
                   1990: #
1.584     raeburn  1991:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 1992:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      1993: #
                   1994: # Remember all keys going with this resource
                   1995: #
1.480     amueller 1996:             if ($$keyp{$id}) {
                   1997:                 $$keyp{$id}.=','.$key;
                   1998:             } else {
                   1999:                 $$keyp{$id}=$key;
                   2000:             }   
1.210     www      2001: #
                   2002: # Put in order
1.446     bisitz   2003: #
1.480     amueller 2004:             unless ($$keyorder{$key}) {
                   2005:                 $$keyorder{$key}=$keyordercnt;
                   2006:                 $keyordercnt++;
                   2007:             }
1.473     amueller 2008:         }
                   2009: 
                   2010: 
1.480     amueller 2011:         if (!exists($$mapp{$mapid})) {
                   2012:             $$mapp{$id}=
                   2013:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2014:             $$mapp{$mapid}=$$mapp{$id};
                   2015:             $$allmaps{$mapid}=$$mapp{$id};
                   2016:             if ($mapid eq '1') {
1.532     raeburn  2017:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2018:             } else {
                   2019:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2020:             }
                   2021:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2022:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2023:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2024:                                                      # are commented out in rev. 1.57
1.473     amueller 2025:         } else {
1.480     amueller 2026:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2027:         }
1.480     amueller 2028:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2029:     }
                   2030: }
                   2031: 
1.582     raeburn  2032: sub get_recursive {
                   2033:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2034:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2035:         foreach my $item (@{$recurseup}) {
                   2036:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2037:             if (defined($resdata->{$norecursechk})) {
                   2038:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2039:                     my $type = $resdata->{$norecursechk.'.type'};
                   2040:                     return [$resdata->{$norecursechk},$type,$item];
                   2041:                 } else {
                   2042:                     last;
                   2043:                 }
                   2044:             }
                   2045:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2046:             if (defined($resdata->{$recursechk})) {
                   2047:                 my $type = $resdata->{$recursechk.'.type'};
                   2048:                 return [$resdata->{$recursechk},$type,$item];
                   2049:             }
                   2050:         }
                   2051:     }
                   2052:     return;
                   2053: }
                   2054: 
1.208     www      2055: 
1.562     damieng  2056: # Tells if a parameter type is a date.
                   2057: #
                   2058: # @param {string} type - parameter type
                   2059: # @returns{boolean} - true if it is a date
1.213     www      2060: sub isdateparm {
                   2061:     my $type=shift;
                   2062:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2063: }
                   2064: 
1.562     damieng  2065: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2066: #
1.581     raeburn  2067: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2068: sub parmmenu {
1.581     raeburn  2069:     my ($r)=@_;
1.208     www      2070:     $r->print(<<ENDSCRIPT);
                   2071: <script type="text/javascript">
1.454     bisitz   2072: // <![CDATA[
1.208     www      2073:     function checkall(value, checkName) {
1.453     schualex 2074: 
                   2075:         var li = "_li";
                   2076:         var displayOverview = "";
                   2077:         
                   2078:         if (value == false) {
                   2079:             displayOverview = "none"
                   2080:         }
                   2081: 
1.562     damieng  2082:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2083:             ele = document.forms.parmform.elements[i];
                   2084:             if (ele.name == checkName) {
                   2085:                 document.forms.parmform.elements[i].checked=value;
                   2086:             }
                   2087:         }
                   2088:     }
1.210     www      2089: 
                   2090:     function checkthis(thisvalue, checkName) {
1.562     damieng  2091:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2092:             ele = document.forms.parmform.elements[i];
                   2093:             if (ele.name == checkName) {
1.562     damieng  2094:                 if (ele.value == thisvalue) {
                   2095:                     document.forms.parmform.elements[i].checked=true;
                   2096:                 }
1.210     www      2097:             }
                   2098:         }
                   2099:     }
                   2100: 
                   2101:     function checkdates() {
1.562     damieng  2102:         checkthis('duedate','pscat');
                   2103:         checkthis('opendate','pscat');
                   2104:         checkthis('answerdate','pscat');
1.218     www      2105:     }
                   2106: 
                   2107:     function checkdisset() {
1.562     damieng  2108:         checkthis('discussend','pscat');
                   2109:         checkthis('discusshide','pscat');
                   2110:         checkthis('discussvote','pscat');
1.218     www      2111:     }
                   2112: 
                   2113:     function checkcontdates() {
1.562     damieng  2114:         checkthis('contentopen','pscat');
                   2115:         checkthis('contentclose','pscat');
1.218     www      2116:     }
1.446     bisitz   2117: 
1.210     www      2118:     function checkvisi() {
1.562     damieng  2119:         checkthis('hiddenresource','pscat');
                   2120:         checkthis('encrypturl','pscat');
                   2121:         checkthis('problemstatus','pscat');
                   2122:         checkthis('contentopen','pscat');
                   2123:         checkthis('opendate','pscat');
1.210     www      2124:     }
                   2125: 
                   2126:     function checkparts() {
1.562     damieng  2127:         checkthis('hiddenparts','pscat');
                   2128:         checkthis('display','pscat');
                   2129:         checkthis('ordered','pscat');
1.210     www      2130:     }
                   2131: 
                   2132:     function checkstandard() {
                   2133:         checkall(false,'pscat');
1.562     damieng  2134:         checkdates();
                   2135:         checkthis('weight','pscat');
                   2136:         checkthis('maxtries','pscat');
                   2137:         checkthis('type','pscat');
                   2138:         checkthis('problemstatus','pscat');
1.210     www      2139:     }
                   2140: 
1.454     bisitz   2141: // ]]>
1.208     www      2142: </script>
                   2143: ENDSCRIPT
1.453     schualex 2144: 
1.491     bisitz   2145:     $r->print('<hr />');
1.581     raeburn  2146:     &shortCuts($r);
1.491     bisitz   2147:     $r->print('<hr />');
1.453     schualex 2148: }
1.562     damieng  2149: 
                   2150: # Returns parameter categories.
                   2151: #
                   2152: # @returns {hash} - category name -> title in English
1.465     amueller 2153: sub categories {
                   2154:     return ('time_settings' => 'Time Settings',
                   2155:     'grading' => 'Grading',
                   2156:     'tries' => 'Tries',
                   2157:     'problem_appearance' => 'Problem Appearance',
                   2158:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2159:     'hiding' => 'Hiding',
                   2160:     'high_level_randomization' => 'High Level Randomization',
                   2161:     'slots' => 'Slots',
                   2162:     'file_submission' => 'File Submission',
                   2163:     'misc' => 'Miscellaneous' ); 
                   2164: }
                   2165: 
1.562     damieng  2166: # Returns the category for each parameter.
                   2167: #
                   2168: # @returns {hash} - parameter name -> category name
1.465     amueller 2169: sub lookUpTableParameter {
                   2170:  
                   2171:     return ( 
                   2172:         'opendate' => 'time_settings',
                   2173:         'duedate' => 'time_settings',
                   2174:         'answerdate' => 'time_settings',
                   2175:         'interval' => 'time_settings',
                   2176:         'contentopen' => 'time_settings',
                   2177:         'contentclose' => 'time_settings',
                   2178:         'discussend' => 'time_settings',
1.560     damieng  2179:         'printstartdate' => 'time_settings',
                   2180:         'printenddate' => 'time_settings',
1.465     amueller 2181:         'weight' => 'grading',
                   2182:         'handgrade' => 'grading',
                   2183:         'maxtries' => 'tries',
                   2184:         'hinttries' => 'tries',
1.503     raeburn  2185:         'randomizeontries' => 'tries',
1.465     amueller 2186:         'type' => 'problem_appearance',
                   2187:         'problemstatus' => 'problem_appearance',
                   2188:         'display' => 'problem_appearance',
                   2189:         'ordered' => 'problem_appearance',
                   2190:         'numbubbles' => 'problem_appearance',
                   2191:         'tol' => 'behaviour_of_input_fields',
                   2192:         'sig' => 'behaviour_of_input_fields',
                   2193:         'turnoffunit' => 'behaviour_of_input_fields',
                   2194:         'hiddenresource' => 'hiding',
                   2195:         'hiddenparts' => 'hiding',
                   2196:         'discusshide' => 'hiding',
                   2197:         'buttonshide' => 'hiding',
                   2198:         'turnoffeditor' => 'hiding',
                   2199:         'encrypturl' => 'hiding',
1.587     raeburn  2200:         'deeplink' => 'hiding',
1.465     amueller 2201:         'randomorder' => 'high_level_randomization',
                   2202:         'randompick' => 'high_level_randomization',
                   2203:         'available' => 'slots',
                   2204:         'useslots' => 'slots',
                   2205:         'availablestudent' => 'slots',
                   2206:         'uploadedfiletypes' => 'file_submission',
                   2207:         'maxfilesize' => 'file_submission',
                   2208:         'cssfile' => 'misc',
                   2209:         'mapalias' => 'misc',
                   2210:         'acc' => 'misc',
                   2211:         'maxcollaborators' => 'misc',
                   2212:         'scoreformat' => 'misc',
1.514     raeburn  2213:         'lenient' => 'grading',
1.519     raeburn  2214:         'retrypartial' => 'tries',
1.521     raeburn  2215:         'discussvote'  => 'misc',
1.584     raeburn  2216:         'examcode' => 'high_level_randomization',
1.575     raeburn  2217:     );
1.465     amueller 2218: }
                   2219: 
1.562     damieng  2220: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2221: #
                   2222: # @param {string} $name - parameter name
                   2223: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2224: sub whatIsMyCategory {
                   2225:     my $name = shift;
                   2226:     my $catList = shift;
                   2227:     my @list;
                   2228:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2229:     my $cat = $lookUpList{$name};
                   2230:     if (defined($cat)) {
                   2231:         if (!defined($$catList{$cat})){
                   2232:             push @list, ($name);
                   2233:             $$catList{$cat} = \@list;
                   2234:         } else {
                   2235:             push @{${$catList}{$cat}}, ($name);     
                   2236:         }
                   2237:     } else {
                   2238:         if (!defined($$catList{'misc'})){
                   2239:             push @list, ($name);
                   2240:             $$catList{'misc'} = \@list;
                   2241:         } else {
                   2242:             push @{${$catList}{'misc'}}, ($name);     
                   2243:         }
                   2244:     }        
                   2245: }
                   2246: 
1.562     damieng  2247: # Sorts parameter names based on appearance order.
                   2248: #
                   2249: # @param {array reference} name - array reference of parameter names
                   2250: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2251: # @returns {Array} - array of parameter names
1.465     amueller 2252: sub keysindisplayorderCategory {
                   2253:     my ($name,$keyorder)=@_;
                   2254:     return sort {
1.473     amueller 2255:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2256:     } ( @{$name});
                   2257: }
                   2258: 
1.562     damieng  2259: # Returns a hash category name -> order, starting at 1 (integer)
                   2260: #
                   2261: # @returns {hash}
1.467     amueller 2262: sub category_order {
                   2263:     return (
                   2264:         'time_settings' => 1,
                   2265:         'grading' => 2,
                   2266:         'tries' => 3,
                   2267:         'problem_appearance' => 4,
                   2268:         'hiding' => 5,
                   2269:         'behaviour_of_input_fields' => 6,
                   2270:         'high_level_randomization'  => 7,
                   2271:         'slots' => 8,
                   2272:         'file_submission' => 9,
                   2273:         'misc' => 10
                   2274:     );
                   2275: 
                   2276: }
1.453     schualex 2277: 
1.562     damieng  2278: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2279: #
                   2280: # @param {Apache2::RequestRec} $r - the Apache request
                   2281: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2282: # @param {array reference} $pscat - list of selected parameter names
                   2283: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2284: sub parmboxes {
                   2285:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2286:     my %categories = &categories();
1.467     amueller 2287:     my %category_order = &category_order();
1.465     amueller 2288:     my %categoryList = (
                   2289:         'time_settings' => [],
                   2290:         'grading' => [],
                   2291:         'tries' => [],
                   2292:         'problem_appearance' => [],
                   2293:         'behaviour_of_input_fields' => [],
                   2294:         'hiding' => [],
                   2295:         'high_level_randomization' => [],
                   2296:         'slots' => [],
                   2297:         'file_submission' => [],
                   2298:         'misc' => [],
1.489     bisitz   2299:     );
1.510     www      2300: 
1.548     raeburn  2301:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2302:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2303:     }
1.453     schualex 2304:     #part to print the parm-list
1.536     raeburn  2305:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2306:         next if (@{$categoryList{$key}} == 0);
                   2307:         next if ($key eq '');
                   2308:         $r->print('<div class="LC_Box LC_400Box">'
                   2309:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2310:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2311:             next if ($tempkey eq '');
1.536     raeburn  2312:             $r->print('<span class="LC_nobreak">'
                   2313:                      .'<label><input type="checkbox" name="pscat" '
                   2314:                      .'value="'.$tempkey.'" ');
                   2315:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2316:                 $r->print( ' checked="checked"');
                   2317:             }
                   2318:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2319:                                                       : $tempkey)
1.536     raeburn  2320:                      .'</label></span><br />'."\n");
1.465     amueller 2321:         }
1.536     raeburn  2322:         $r->print('</div>');
1.465     amueller 2323:     }
1.536     raeburn  2324:     $r->print("\n");
1.453     schualex 2325: }
1.562     damieng  2326: 
                   2327: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2328: #
1.562     damieng  2329: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2330: sub shortCuts {
1.581     raeburn  2331:     my ($r)=@_;
1.453     schualex 2332: 
1.491     bisitz   2333:     # Parameter Selection
                   2334:     $r->print(
                   2335:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2336:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2337:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2338:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2339:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2340:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2341:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2342:        .&Apache::lonhtmlcommon::end_funclist()
                   2343:     );
                   2344: 
                   2345:     # Add Selection for...
                   2346:     $r->print(
                   2347:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2348:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2349:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2350:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2351:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2352:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2353:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2354:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2355:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2356:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2357:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2358:        .&Apache::lonhtmlcommon::end_funclist()
                   2359:     );
1.208     www      2360: }
                   2361: 
1.562     damieng  2362: # Prints HTML to select parts to view (except for the title).
                   2363: # Used by table and overview modes.
                   2364: #
                   2365: # @param {Apache2::RequestRec} $r - the Apache request
                   2366: # @param {hash reference} $allparts - hash parameter part -> part title
                   2367: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2368: sub partmenu {
1.446     bisitz   2369:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2370:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2371:     if ($selsize > 8) {
                   2372:         $selsize = 8;
                   2373:     }
1.446     bisitz   2374: 
1.523     raeburn  2375:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2376:     $r->print('<option value="all"');
1.562     damieng  2377:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2378:     $r->print('>'.&mt('All Parts').'</option>');
                   2379:     my %temphash=();
                   2380:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2381:     foreach my $tempkey (sort {
1.560     damieng  2382:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2383:             } keys(%{$allparts})) {
                   2384:         unless ($tempkey =~ /\./) {
                   2385:             $r->print('<option value="'.$tempkey.'"');
                   2386:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2387:                 $r->print(' selected="selected"');
                   2388:             }
                   2389:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2390:         }
1.208     www      2391:     }
1.446     bisitz   2392:     $r->print('</select>');
1.209     www      2393: }
                   2394: 
1.562     damieng  2395: # Prints HTML to select a user and/or a group.
                   2396: # Used by table mode.
                   2397: #
                   2398: # @param {Apache2::RequestRec} $r - the Apache request
                   2399: # @param {string} $uname - selected user name
                   2400: # @param {string} $id - selected Student/Employee ID
                   2401: # @param {string} $udom - selected user domain
                   2402: # @param {string} $csec - selected section name
                   2403: # @param {string} $cgroup - selected group name
                   2404: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2405: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2406: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2407: sub usermenu {
1.553     raeburn  2408:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2409:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
                   2410:         &Apache::loncommon::selectstudent_link('parmform','uname','udom');
                   2411:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.412     bisitz   2412: 
1.209     www      2413:     my $sections='';
1.300     albertel 2414:     my %sectionhash = &Apache::loncommon::get_sections();
                   2415: 
1.269     raeburn  2416:     my $groups;
1.553     raeburn  2417:     my %grouphash;
                   2418:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2419:         %grouphash = &Apache::longroup::coursegroups();
                   2420:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2421:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2422:     }
1.299     albertel 2423: 
1.412     bisitz   2424:     my $g_s_header='';
                   2425:     my $g_s_footer='';
1.446     bisitz   2426: 
1.552     raeburn  2427:     my $currsec = $env{'request.course.sec'};
                   2428:     if ($currsec) {
                   2429:         $sections=&mt('Section:').' '.$currsec;
                   2430:         if (%grouphash) {
                   2431:             $sections .= ';'.('&nbsp;' x2);
                   2432:         }
                   2433:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2434:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2435:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2436:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2437:         }
                   2438:         $sections .= '>';
1.548     raeburn  2439:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2440:         $sections.='<option value="'.$section.'" '.
                   2441:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2442:                                                               '</option>';
1.209     www      2443:         }
                   2444:         $sections.='</select>';
1.269     raeburn  2445:     }
1.412     bisitz   2446: 
1.552     raeburn  2447:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2448:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2449:         $sections .= qq|
                   2450: <script type="text/javascript">
1.454     bisitz   2451: // <![CDATA[
1.269     raeburn  2452: function group_or_section(caller) {
                   2453:    if (caller == "cgroup") {
                   2454:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2455:            document.parmform.csec.selectedIndex = 0;
                   2456:        }
                   2457:    } else {
                   2458:        if (document.parmform.csec.selectedIndex != 0) {
                   2459:            document.parmform.cgroup.selectedIndex = 0;
                   2460:        }
                   2461:    }
                   2462: }
1.454     bisitz   2463: // ]]>
1.269     raeburn  2464: </script>
                   2465: |;
1.554     raeburn  2466:     } else {
1.269     raeburn  2467:         $sections .= qq|
                   2468: <script type="text/javascript">
1.454     bisitz   2469: // <![CDATA[
1.269     raeburn  2470: function group_or_section(caller) {
                   2471:     return;
                   2472: }
1.454     bisitz   2473: // ]]>
1.269     raeburn  2474: </script>
                   2475: |;
1.446     bisitz   2476:     }
1.299     albertel 2477: 
                   2478:     if (%grouphash) {
1.412     bisitz   2479:         $groups=&mt('Group:').' <select name="cgroup"';
1.552     raeburn  2480:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2481:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2482:         }
                   2483:         $groups .= '>';
1.548     raeburn  2484:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2485:             $groups.='<option value="'.$grp.'" ';
                   2486:             if ($grp eq $cgroup) {
                   2487:                 unless ((defined($uname)) && ($grp eq '')) {
                   2488:                     $groups .=  'selected="selected" ';
                   2489:                 }
                   2490:             } elsif (!defined($cgroup)) {
                   2491:                 if (@{$usersgroups} == 1) {
                   2492:                     if ($grp eq $$usersgroups[0]) {
                   2493:                         $groups .=  'selected="selected" ';
                   2494:                     }
                   2495:                 }
                   2496:             }
                   2497:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2498:         }
                   2499:         $groups.='</select>';
                   2500:     }
1.412     bisitz   2501: 
1.445     neumanie 2502:     if (%sectionhash || %grouphash) {
1.446     bisitz   2503:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2504:         $r->print($sections.$groups);
1.448     bisitz   2505:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2506:     } else {
                   2507:         $r->print($sections); 
1.445     neumanie 2508:     }
1.446     bisitz   2509: 
                   2510:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2511:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2512:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2513:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2514:                  ,$chooseopt));
1.209     www      2515: }
                   2516: 
1.562     damieng  2517: # Prints HTML to select parameters from a list of all parameters.
                   2518: # Uses parmmenu and parmboxes.
                   2519: # Used by table and overview modes.
1.468     amueller 2520: #
1.562     damieng  2521: # @param {Apache2::RequestRec} $r - the Apache request
                   2522: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2523: # @param {array reference} $pscat - list of selected parameter names
                   2524: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2525: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2526: sub displaymenu {
1.581     raeburn  2527:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2528: 
1.445     neumanie 2529:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2530:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2531: 
1.581     raeburn  2532:     &parmmenu($r);
1.536     raeburn  2533:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2534:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2535:     $r->print(&Apache::loncommon::end_scrollbox());
                   2536: 
                   2537:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2538:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2539:  
1.209     www      2540: }
                   2541: 
1.562     damieng  2542: # Prints HTML to select a map.
                   2543: # Used by table mode and overview mode.
                   2544: #
                   2545: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2546: # @param {hash reference} $allmaps - hash map pc -> map src
                   2547: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2548: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2549: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2550: sub mapmenu {
1.499     raeburn  2551:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2552:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2553:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2554:     my $tree=[];
                   2555:     my $treeinfo={};
                   2556:     if (defined($navmap)) {
1.499     raeburn  2557:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2558:         my $curRes;
                   2559:         my $depth = 0;
1.468     amueller 2560:         my %parent = ();
                   2561:         my $startcount = 5;
                   2562:         my $lastcontainer = $startcount;
                   2563: # preparing what is to show ...
1.461     neumanie 2564:         while ($curRes = $it->next()) {
                   2565:             if ($curRes == $it->BEGIN_MAP()) {
                   2566:                 $depth++;
1.468     amueller 2567:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2568:             }
                   2569:             if ($curRes == $it->END_MAP()) {
                   2570:                 $depth--;
1.468     amueller 2571:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2572:             }
                   2573:             if (ref($curRes)) {
1.468     amueller 2574:                 my $symb = $curRes->symb();
                   2575:                 my $ressymb = $symb;
1.461     neumanie 2576:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2577:                     my $type = 'sequence';
                   2578:                     if ($curRes->is_page()) {
                   2579:                         $type = 'page';
                   2580:                     }
                   2581:                     my $id= $curRes->id();
1.468     amueller 2582:                     my $srcf = $curRes->src();
                   2583:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2584:                     if(!exists($treeinfo->{$id})) {
                   2585:                         push(@$tree,$id);
1.473     amueller 2586:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2587:                         $treeinfo->{$id} = {
1.461     neumanie 2588:                                     depth => $depth,
                   2589:                                     type  => $type,
1.468     amueller 2590:                                     name  => $resource_name,
                   2591:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2592:                                     };
1.462     neumanie 2593:                     }
1.461     neumanie 2594:                 }
                   2595:             }
                   2596:         }
1.462     neumanie 2597:     }
1.473     amueller 2598: # Show it ...    
1.484     amueller 2599:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2600:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2601:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2602:         my $whitespace =
                   2603:             '<img src="'
                   2604:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2605:            .'" alt="" />';
                   2606: 
1.498     bisitz   2607:         # Info about selectable folders/maps
                   2608:         $r->print(
                   2609:             '<div class="LC_info">'
1.508     www      2610:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2611:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2612:            .'</div>'
                   2613:         );
                   2614: 
1.536     raeburn  2615:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2616:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2617: 
1.498     bisitz   2618:         # Display row: "All Maps or Folders"
                   2619:         $r->print(
1.523     raeburn  2620:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2621:            .'<td>'
                   2622:            .'<label>'
                   2623:            .'<input type="radio" name="pschp"'
1.497     bisitz   2624:         );
                   2625:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2626:         $r->print(
                   2627:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2628:            .&mt('All Maps or Folders')
                   2629:            .'</label>'
                   2630:            .'<hr /></td>'
                   2631:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2632:         );
1.497     bisitz   2633: 
1.532     raeburn  2634:         # Display row: "Main Content"
1.468     amueller 2635:         if (exists($$allmaps{1})) {
1.498     bisitz   2636:             $r->print(
                   2637:                 &Apache::loncommon::start_data_table_row()
                   2638:                .'<td>'
                   2639:                .'<label>'
                   2640:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2641:             );
1.497     bisitz   2642:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2643:             $r->print(
                   2644:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2645:                .$$maptitles{1}
                   2646:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2647:                .'</label>'
                   2648:                .'</td>'
                   2649:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2650:             );
                   2651:         }
1.497     bisitz   2652: 
                   2653:         # Display rows for all course maps and folders
1.468     amueller 2654:         foreach my $id (@{$tree}) {
                   2655:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2656:             # Indentation
1.468     amueller 2657:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2658:             my $indent;
                   2659:             for (my $i = 0; $i < $depth; $i++) {
                   2660:                 $indent.= $whitespace;
                   2661:             }
1.461     neumanie 2662:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2663:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2664:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2665:             }
1.468     amueller 2666:             my $symb_name = $$symbp{$id};
                   2667:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2668:             $symb_name = $tail;
1.498     bisitz   2669:             $r->print(
                   2670:                 &Apache::loncommon::start_data_table_row()
                   2671:                .'<td>'
                   2672:                .'<label>'
1.463     bisitz   2673:             );
1.498     bisitz   2674:             # Only offer radio button for folders/maps which can be parameterized
                   2675:             if ($allmaps_inverted{$symb_name}) {
                   2676:                 $r->print(
                   2677:                     '<input type ="radio" name="pschp"'
                   2678:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2679:                 );
                   2680:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2681:                 $r->print('/>');
                   2682:             } else {
                   2683:                 $r->print($whitespace);
1.461     neumanie 2684:             }
1.498     bisitz   2685:             $r->print(
                   2686:                 $indent.$icon.'&nbsp;'
                   2687:                .$treeinfo->{$id}->{name}
                   2688:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2689:                .'</label>'
                   2690:                .'</td>'
                   2691:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2692:             );
1.461     neumanie 2693:         }
1.497     bisitz   2694: 
1.523     raeburn  2695:         $r->print(&Apache::loncommon::end_data_table().
                   2696:                   '<br style="line-height:2px;" />'.
                   2697:                   &Apache::loncommon::end_scrollbox());
1.209     www      2698:     }
                   2699: }
                   2700: 
1.563     damieng  2701: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2702: # Used by table and overview modes.
                   2703: #
                   2704: # @param {Apache2::RequestRec} $r - the Apache request
                   2705: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2706: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2707: sub levelmenu {
1.446     bisitz   2708:     my ($r,$alllevs,$parmlev)=@_;
                   2709: 
1.548     raeburn  2710:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2711:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2712:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2713:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2714:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2715:         if ($parmlev eq $$alllevs{$lev}) {
                   2716:             $r->print(' selected="selected"');
                   2717:         }
                   2718:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2719:     }
1.446     bisitz   2720:     $r->print("</select>");
1.208     www      2721: }
                   2722: 
1.211     www      2723: 
1.563     damieng  2724: # Returns HTML to select a section (with a select HTML element).
                   2725: # Used by overview mode.
                   2726: #
                   2727: # @param {array reference} $selectedsections - list of selected section ids
                   2728: # @returns {string}
1.211     www      2729: sub sectionmenu {
1.553     raeburn  2730:     my ($selectedsections)=@_;
1.300     albertel 2731:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2732:     return '' if (!%sectionhash);
1.300     albertel 2733: 
1.552     raeburn  2734:     my (@possibles,$disabled);
                   2735:     if ($env{'request.course.sec'} ne '') {
                   2736:         @possibles = ($env{'request.course.sec'});
                   2737:         $selectedsections = [$env{'request.course.sec'}];
                   2738:         $disabled = ' disabled="disabled"';
                   2739:     } else {
                   2740:         @possibles = ('all',sort(keys(%sectionhash)));
                   2741:     }
1.553     raeburn  2742:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2743:     foreach my $s (@possibles) {
1.553     raeburn  2744:         $output .= '    <option value="'.$s.'"';
                   2745:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2746:             $output .= ' selected="selected"';
1.473     amueller 2747:         }
1.553     raeburn  2748:         $output .= '>'."$s</option>\n";
1.300     albertel 2749:     }
1.553     raeburn  2750:     $output .= "</select>\n";
                   2751:     return $output;
1.269     raeburn  2752: }
                   2753: 
1.563     damieng  2754: # Returns HTML to select a group (with a select HTML element).
                   2755: # Used by overview mode.
                   2756: #
                   2757: # @param {array reference} $selectedgroups - list of selected group names
                   2758: # @returns {string}
1.269     raeburn  2759: sub groupmenu {
1.553     raeburn  2760:     my ($selectedgroups)=@_;
                   2761:     my %grouphash;
                   2762:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2763:         %grouphash = &Apache::longroup::coursegroups();
                   2764:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2765:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2766:     }
                   2767:     return '' if (!%grouphash);
1.299     albertel 2768: 
1.553     raeburn  2769:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2770:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2771:         $output .= '    <option value="'.$group.'"';
                   2772:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2773:             $output .=  ' selected="selected"';
1.473     amueller 2774:         }
1.553     raeburn  2775:         $output .= '>'."$group</option>\n";
1.211     www      2776:     }
1.553     raeburn  2777:     $output .= "</select>\n";
                   2778:     return $output;
1.211     www      2779: }
                   2780: 
1.563     damieng  2781: # Returns an array with the given parameter split by comma.
                   2782: # Used by assessparms (table mode).
                   2783: #
                   2784: # @param {string} $keyp - the string to split
                   2785: # @returns {Array<string>}
1.210     www      2786: sub keysplit {
                   2787:     my $keyp=shift;
                   2788:     return (split(/\,/,$keyp));
                   2789: }
                   2790: 
1.563     damieng  2791: # Returns the keys in $name, sorted using $keyorder.
                   2792: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2793: # Used by assessparms (table mode) for resource level.
                   2794: #
                   2795: # @param {hash reference} $name - parameter key -> parameter name
                   2796: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2797: # @returns {Array<string>}
1.210     www      2798: sub keysinorder {
                   2799:     my ($name,$keyorder)=@_;
                   2800:     return sort {
1.560     damieng  2801:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2802:     } (keys(%{$name}));
1.210     www      2803: }
                   2804: 
1.563     damieng  2805: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   2806: # Used by assessparms (table mode) for map and general levels.
                   2807: #
                   2808: # @param {hash reference} $name - parameter key -> parameter name
                   2809: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2810: # @returns {Array<string>}
1.236     albertel 2811: sub keysinorder_bytype {
                   2812:     my ($name,$keyorder)=@_;
                   2813:     return sort {
1.563     damieng  2814:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  2815:         my $tb=(split('_',$b))[-1];
                   2816:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   2817:             return ($a cmp $b);
                   2818:         }
                   2819:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  2820:     } (keys(%{$name}));
1.236     albertel 2821: }
                   2822: 
1.563     damieng  2823: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   2824: # Used by defaultsetter (parameter settings default actions).
                   2825: #
                   2826: # @param {hash reference} $name - hash parameter name -> parameter title
                   2827: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2828: # @returns {Array<string>}
1.211     www      2829: sub keysindisplayorder {
                   2830:     my ($name,$keyorder)=@_;
                   2831:     return sort {
1.560     damieng  2832:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  2833:     } (keys(%{$name}));
1.211     www      2834: }
                   2835: 
1.563     damieng  2836: # Prints HTML with a choice to sort results by realm or student first.
                   2837: # Used by overview mode.
                   2838: #
                   2839: # @param {Apache2::RequestRec} $r - the Apache request
                   2840: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      2841: sub sortmenu {
                   2842:     my ($r,$sortorder)=@_;
1.236     albertel 2843:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      2844:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   2845:        $r->print(' checked="checked"');
1.214     www      2846:     }
                   2847:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 2848:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      2849:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   2850:        $r->print(' checked="checked"');
1.214     www      2851:     }
1.236     albertel 2852:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 2853:           '</label>');
1.214     www      2854: }
                   2855: 
1.563     damieng  2856: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   2857: #
                   2858: # @returns {hash}
1.211     www      2859: sub standardkeyorder {
                   2860:     return ('parameter_0_opendate' => 1,
1.473     amueller 2861:         'parameter_0_duedate' => 2,
                   2862:         'parameter_0_answerdate' => 3,
                   2863:         'parameter_0_interval' => 4,
                   2864:         'parameter_0_weight' => 5,
                   2865:         'parameter_0_maxtries' => 6,
                   2866:         'parameter_0_hinttries' => 7,
                   2867:         'parameter_0_contentopen' => 8,
                   2868:         'parameter_0_contentclose' => 9,
                   2869:         'parameter_0_type' => 10,
                   2870:         'parameter_0_problemstatus' => 11,
                   2871:         'parameter_0_hiddenresource' => 12,
                   2872:         'parameter_0_hiddenparts' => 13,
                   2873:         'parameter_0_display' => 14,
                   2874:         'parameter_0_ordered' => 15,
                   2875:         'parameter_0_tol' => 16,
                   2876:         'parameter_0_sig' => 17,
                   2877:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  2878:         'parameter_0_discussend' => 19,
                   2879:         'parameter_0_discusshide' => 20,
                   2880:         'parameter_0_discussvote' => 21,
1.560     damieng  2881:         'parameter_0_printstartdate'  =>  22,
                   2882:         'parameter_0_printenddate' =>  23);
1.211     www      2883: }
                   2884: 
1.59      matthew  2885: 
1.560     damieng  2886: # Table mode UI.
1.563     damieng  2887: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   2888: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   2889: #
                   2890: # Parameters used from the request:
                   2891: # action - handler action (see handler), usermenu is checking for value 'settable'
                   2892: # cgroup - selected group
                   2893: # command - 'set': direct access to table mode for a resource
                   2894: # csec - selected section
                   2895: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   2896: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   2897: # id - student/employee ID
                   2898: # parmlev - selected level (full|map|general)
                   2899: # part - selected part (unused ?)
                   2900: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   2901: # pres_type - &&&-separated parameter types
                   2902: # pres_value - &&&-separated parameter values
                   2903: # prevvisit - '1' if the user has submitted the form before
                   2904: # pscat (multiple values) - selected parameter names
1.566     damieng  2905: # pschp - selected map pc, or 'all'
1.563     damieng  2906: # psprt (multiple values) - list of selected parameter parts
                   2907: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   2908: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   2909: # symb - resource symb (when a single resource is selected)
                   2910: # udom - selected user domain
                   2911: # uname - selected user name
                   2912: # url - used only with command 'set', the resource url
                   2913: #
                   2914: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  2915: # @param $parm_permission - ref to hash of permissions
                   2916: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      2917: sub assessparms {
1.1       www      2918: 
1.568     raeburn  2919:     my ($r,$parm_permission) = @_;
1.201     www      2920: 
1.512     foxr     2921: 
                   2922: # -------------------------------------------------------- Variable declaration
1.566     damieng  2923:     my @ids=(); # resource and map ids
                   2924:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   2925:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   2926:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   2927:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   2928:     my %uris=(); # hash resource/map id -> resource src
                   2929:     my %maptitles=(); # hash map pc or src -> map title
                   2930:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  2931:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  2932:     my %alllevs=(); # hash English level title -> value
                   2933: 
                   2934:     my $uname; # selected user name
                   2935:     my $udom; # selected user domain
                   2936:     my $uhome; # server with the user's files, or 'no_host'
                   2937:     my $csec; # selected section name
                   2938:     my $cgroup; # selected group name
                   2939:     my @usersgroups = (); # list of the user groups
1.582     raeburn  2940:     my $numreclinks = 0;
1.446     bisitz   2941: 
1.190     albertel 2942:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      2943: 
1.57      albertel 2944:     $alllevs{'Resource Level'}='full';
1.215     www      2945:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 2946:     $alllevs{'Course Level'}='general';
                   2947: 
1.563     damieng  2948:     my %allparms; # hash parameter name -> parameter title
                   2949:     my %allparts; # hash parameter part -> part title
1.512     foxr     2950: # ------------------------------------------------------------------------------
                   2951: 
1.210     www      2952: #
                   2953: # Order in which these parameters will be displayed
                   2954: #
1.211     www      2955:     my %keyorder=&standardkeyorder();
                   2956: 
1.512     foxr     2957: #    @ids=();
                   2958: #    %symbp=();       # These seem defined above already.
                   2959: #    %typep=();
1.43      albertel 2960: 
                   2961:     my $message='';
                   2962: 
1.190     albertel 2963:     $csec=$env{'form.csec'};
1.552     raeburn  2964:     if ($env{'request.course.sec'} ne '') {
                   2965:         $csec = $env{'request.course.sec'};    
                   2966:     }
                   2967: 
1.553     raeburn  2968: # Check group privs.
1.269     raeburn  2969:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  2970:     my $noeditgrp; 
                   2971:     if ($cgroup ne '') {
                   2972:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2973:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  2974:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  2975:                 $noeditgrp = 1;
                   2976:             }
                   2977:         }
                   2978:     }
1.188     www      2979: 
1.190     albertel 2980:     if      ($udom=$env{'form.udom'}) {
                   2981:     } elsif ($udom=$env{'request.role.domain'}) {
                   2982:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 2983:     } else {
1.473     amueller 2984:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 2985:     }
1.468     amueller 2986:     
1.43      albertel 2987: 
1.134     albertel 2988:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 2989:     my $pschp=$env{'form.pschp'};
1.506     www      2990: 
                   2991: 
1.134     albertel 2992:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      2993:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      2994:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 2995: 
1.43      albertel 2996:     my $pssymb='';
1.57      albertel 2997:     my $parmlev='';
1.446     bisitz   2998: 
1.190     albertel 2999:     unless ($env{'form.parmlev'}) {
1.57      albertel 3000:         $parmlev = 'map';
                   3001:     } else {
1.190     albertel 3002:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3003:     }
1.26      www      3004: 
1.29      www      3005: # ----------------------------------------------- Was this started from grades?
                   3006: 
1.560     damieng  3007:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3008:             (!$env{'form.dis'})) {
1.473     amueller 3009:         my $url=$env{'form.url'};
                   3010:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3011:         $pssymb=&Apache::lonnet::symbread($url);
                   3012:         if (!@pscat) { @pscat=('all'); }
                   3013:         $pschp='';
1.57      albertel 3014:         $parmlev = 'full';
1.190     albertel 3015:     } elsif ($env{'form.symb'}) {
1.473     amueller 3016:         $pssymb=$env{'form.symb'};
                   3017:         if (!@pscat) { @pscat=('all'); }
                   3018:         $pschp='';
1.57      albertel 3019:         $parmlev = 'full';
1.43      albertel 3020:     } else {
1.473     amueller 3021:         $env{'form.url'}='';
1.43      albertel 3022:     }
                   3023: 
1.190     albertel 3024:     my $id=$env{'form.id'};
1.43      albertel 3025:     if (($id) && ($udom)) {
1.555     raeburn  3026:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3027:         if ($uname) {
                   3028:             $id='';
                   3029:         } else {
                   3030:             $message=
1.540     bisitz   3031:                 '<p class="LC_warning">'.
                   3032:                 &mt('Unknown ID [_1] at domain [_2]',
                   3033:                     "'".$id."'","'".$udom."'").
                   3034:                 '</p>';
1.473     amueller 3035:         }
1.43      albertel 3036:     } else {
1.473     amueller 3037:         $uname=$env{'form.uname'};
1.43      albertel 3038:     }
                   3039:     unless ($udom) { $uname=''; }
                   3040:     $uhome='';
                   3041:     if ($uname) {
1.473     amueller 3042:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3043:         if ($uhome eq 'no_host') {
1.473     amueller 3044:             $message=
1.540     bisitz   3045:                 '<p class="LC_warning">'.
                   3046:                 &mt('Unknown user [_1] at domain [_2]',
                   3047:                     "'".$uname."'","'".$udom."'").
                   3048:                 '</p>';
1.473     amueller 3049:             $uname='';
1.12      www      3050:         } else {
1.473     amueller 3051:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3052:                           $env{'request.course.id'});
                   3053:             if ($csec eq '-1') {
1.540     bisitz   3054:                 $message=
                   3055:                     '<p class="LC_warning">'.
                   3056:                     &mt('User [_1] at domain [_2] not in this course',
                   3057:                         "'".$uname."'","'".$udom."'").
                   3058:                     '</p>';
1.473     amueller 3059:                 $uname='';
                   3060:                 $csec=$env{'form.csec'};
1.269     raeburn  3061:                 $cgroup=$env{'form.cgroup'};
1.473     amueller 3062:             } else {
                   3063:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3064:                   ('firstname','middlename','lastname','generation','id'));
                   3065:                 $message="\n<p>\n".&mt("Full Name").": ".
                   3066:                 $name{'firstname'}.' '.$name{'middlename'}.' '
                   3067:                 .$name{'lastname'}.' '.$name{'generation'}.
1.501     bisitz   3068:                 "<br />\n".&mt('Student/Employee ID').": ".$name{'id'}.'<p>';
1.473     amueller 3069:             }
1.297     raeburn  3070:             @usersgroups = &Apache::lonnet::get_users_groups(
1.275     raeburn  3071:                                        $udom,$uname,$env{'request.course.id'});
1.297     raeburn  3072:             if (@usersgroups > 0) {
1.306     albertel 3073:                 unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
1.275     raeburn  3074:                     $cgroup = $usersgroups[0];
1.297     raeburn  3075:                 }
1.269     raeburn  3076:             }
1.12      www      3077:         }
1.43      albertel 3078:     }
1.2       www      3079: 
1.43      albertel 3080:     unless ($csec) { $csec=''; }
1.269     raeburn  3081:     unless ($cgroup) { $cgroup=''; }
1.12      www      3082: 
1.14      www      3083: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3084:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3085:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   3086:                 \%keyorder);
1.63      bowersj2 3087: 
1.582     raeburn  3088:     %allmaps_inverted = reverse(%allmaps);
                   3089: 
1.57      albertel 3090:     $mapp{'0.0'} = '';
                   3091:     $symbp{'0.0'} = '';
1.99      albertel 3092: 
1.14      www      3093: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3094:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3095:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3096:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3097:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3098:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3099:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3100:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3101:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3102:         my $totalstored = 0;
1.546     raeburn  3103:         my $now = time;
1.473     amueller 3104:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3105:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3106:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3107:                 next if ($csec ne $env{'request.course.sec'});
                   3108:             }
1.556     raeburn  3109:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3110:                 next if ($noeditgrp);
1.557     raeburn  3111:             }
                   3112:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3113:                 $namematch = 'maplevelrecurse';
                   3114:             }
1.556     raeburn  3115:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3116:                 my (@ok_slots,@fail_slots,@del_slots);
                   3117:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3118:                 my ($level,@all) =
                   3119:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3120:                                      $csec,$cgroup,$courseopt);
                   3121:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3122:                     next if ($slot_name eq '');
                   3123:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3124:                         push(@ok_slots,$slot_name);
                   3125: 
                   3126:                     } else {
                   3127:                         push(@fail_slots,$slot_name);
                   3128:                     }
                   3129:                 }
                   3130:                 if (@ok_slots) {
                   3131:                     $values[$i] = join(':',@ok_slots);
                   3132:                 } else {
                   3133:                     $values[$i] = '';
                   3134:                 }
                   3135:                 if ($all[$level] ne '') {
                   3136:                     my @existing = split(/:/,$all[$level]);
                   3137:                     foreach my $slot_name (@existing) {
                   3138:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3139:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3140:                                 push(@del_slots,$slot_name);
                   3141:                             }
                   3142:                         }
                   3143:                     }
                   3144:                 }
1.554     raeburn  3145:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3146:                 $name = $1;
1.533     raeburn  3147:                 my $val = $values[$i];
1.549     raeburn  3148:                 my $valmatch = '';
1.533     raeburn  3149:                 if ($name eq 'examcode') {
1.544     raeburn  3150:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3151:                         $val = 'valid';
                   3152:                     }
1.546     raeburn  3153:                 } elsif ($name eq 'printstartdate') {
                   3154:                     if ($val =~ /^\d+$/) {
                   3155:                         if ($val > $now) {
                   3156:                             $val = 'future';
                   3157:                         }
                   3158:                     } 
                   3159:                 } elsif ($name eq 'printenddate') {
                   3160:                     if ($val =~ /^\d+$/) {
                   3161:                         if ($val < $now) {
                   3162:                             $val = 'past';
                   3163:                         }
                   3164:                     }
1.549     raeburn  3165:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3166:                     my $stringtype = &get_stringtype($name);
                   3167:                     my $stringmatch = &standard_string_matches($stringtype);
                   3168:                     if (ref($stringmatch) eq 'ARRAY') {
                   3169:                         foreach my $item (@{$stringmatch}) {
                   3170:                             if (ref($item) eq 'ARRAY') {
                   3171:                                 my ($regexpname,$pattern) = @{$item};
                   3172:                                 if ($pattern ne '') {
                   3173:                                     if ($val =~ /$pattern/) {
                   3174:                                         $valmatch = $regexpname;
                   3175:                                         $val = '';
                   3176:                                         last;
                   3177:                                     }
                   3178:                                 }
                   3179:                             }
                   3180:                         }
                   3181:                     }
1.554     raeburn  3182:                 } elsif ($name eq 'interval') {
                   3183:                     my $intervaltype = &get_intervaltype($name);
                   3184:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3185:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3186:                         foreach my $item (@{$intervalmatch}) {
                   3187:                             if (ref($item) eq 'ARRAY') {
                   3188:                                 my ($regexpname,$pattern) = @{$item};
                   3189:                                 if ($pattern ne '') {
                   3190:                                     if ($val =~ /$pattern/) {
                   3191:                                         $valmatch = $regexpname;
                   3192:                                         $val = '';
                   3193:                                         last;
                   3194:                                     }
                   3195:                                 }
                   3196:                             }
                   3197:                         }
                   3198:                     }
1.533     raeburn  3199:                 }
1.504     raeburn  3200:                 $needsrelease =
1.557     raeburn  3201:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3202:                 if ($needsrelease) {
1.505     raeburn  3203:                     unless ($got_chostname) {
1.514     raeburn  3204:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3205:                         $got_chostname = 1;
1.546     raeburn  3206:                     } 
1.557     raeburn  3207:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3208:                                                           $needsrelease,
                   3209:                                                           $cmajor,$cminor);
1.500     raeburn  3210:                 }
1.437     raeburn  3211:             }
1.504     raeburn  3212:             if ($needsnewer) {
1.557     raeburn  3213:                 undef($namematch);
                   3214:             } else {
                   3215:                 my $currneeded;
                   3216:                 if ($needsrelease) {
                   3217:                     $currneeded = $needsrelease;
                   3218:                 }
                   3219:                 if ($namematch) {
                   3220:                     $needsrelease =
                   3221:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3222:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3223:                         unless ($got_chostname) {
                   3224:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3225:                             $got_chostname = 1;
                   3226:                         }
                   3227:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3228:                                                               $needsrelease,
                   3229:                                                               $cmajor,$cminor);
                   3230:                     } else {
                   3231:                         undef($namematch);
                   3232:                     }
                   3233:                 }
                   3234:             }
                   3235:             if ($needsnewer) {
                   3236:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3237:                                                 $cminor,$needsrelease);
                   3238:             } else {
                   3239:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3240:                                      $values[$i],
                   3241:                                      $types[$i],
                   3242:                                      $uname,$udom,$csec,$cgroup);
                   3243:                 $totalstored ++;
                   3244:             }
1.473     amueller 3245:         }
1.68      www      3246: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3247:         if ($totalstored) {
                   3248:             $message.='<p class="LC_warning">'
                   3249:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3250:                      .&Apache::loncommon::help_open_topic('Caching')
                   3251:                      .'</p>';
                   3252:         }
1.68      www      3253:     }
1.584     raeburn  3254: 
1.57      albertel 3255: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3256:     if ($pscat[0] eq "all") {
                   3257:         @pscat = (keys(%allparms));
                   3258:     }
                   3259:     if (!@pscat) {
                   3260:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3261:     };
                   3262:     if ($psprt[0] eq "all" || !@psprt) {
                   3263:         @psprt = (keys(%allparts));
                   3264:     }
1.2       www      3265: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3266: 
1.531     raeburn  3267:     my $crstype = &Apache::loncommon::course_type();
                   3268:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3269: 
1.548     raeburn  3270:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.563     damieng  3271:             'date_interval','int','float','string') {
1.473     amueller 3272:         $r->print('<input type="hidden" value="'.
1.563     damieng  3273:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3274:             '" name="recent_'.$item.'" />');
1.44      albertel 3275:     }
1.446     bisitz   3276: 
1.459     bisitz   3277:     # ----- Start Parameter Selection
                   3278: 
                   3279:     # Hide parm selection?
                   3280:     $r->print(<<ENDPARMSELSCRIPT);
                   3281: <script type="text/javascript">
                   3282: // <![CDATA[
                   3283: function parmsel_show() {
1.562     damieng  3284:     document.getElementById('parmsel').style.display = "";
                   3285:     document.getElementById('parmsellink').style.display = "none";
1.459     bisitz   3286: }
                   3287: // ]]>
                   3288: </script>
                   3289: ENDPARMSELSCRIPT
1.474     amueller 3290:     
1.445     neumanie 3291:     if (!$pssymb) {
1.563     damieng  3292:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3293:         my $parmselhiddenstyle=' style="display:none"';
                   3294:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3295:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3296:         } else  {
                   3297:            $r->print('<div id="parmsel">');
                   3298:         }
                   3299: 
1.491     bisitz   3300:         # Step 1
1.523     raeburn  3301:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3302:         $r->print('
1.474     amueller 3303: <script type="text/javascript">
1.523     raeburn  3304: // <![CDATA['.
                   3305:                  &showhide_js().'
1.474     amueller 3306: // ]]>
                   3307: </script>
1.523     raeburn  3308: ');
                   3309:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3310:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3311:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3312:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3313:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3314:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3315:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3316:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3317:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3318: 
                   3319:         # Step 2
1.523     raeburn  3320:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3321:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3322: 
                   3323:         # Step 3
1.523     raeburn  3324:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3325:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3326:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3327:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3328:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3329: 
                   3330:         # Update Display Button
1.486     www      3331:         $r->print('<p>'
                   3332:              .'<input type="submit" name="dis"'
1.511     www      3333:              .' value="'.&mt('Update Display').'" />'
1.486     www      3334:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3335:              .'</p>');
                   3336:         $r->print('</div>');
1.491     bisitz   3337: 
1.486     www      3338:         # Offer link to display parameter selection again
                   3339:         $r->print('<p id="parmsellink"');
                   3340:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3341:            $r->print($parmselhiddenstyle);
                   3342:         }
                   3343:         $r->print('>'
                   3344:              .'<a href="javascript:parmsel_show()">'
                   3345:              .&mt('Change Parameter Selection')
                   3346:              .'</a>'
                   3347:              .'</p>');
1.44      albertel 3348:     } else {
1.478     amueller 3349:         # parameter screen for a single resource. 
1.486     www      3350:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3351:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3352:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3353:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3354:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3355:                   '<br />');
                   3356:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3357:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3358:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3359:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3360:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3361:         $r->print('<p>'
1.459     bisitz   3362:              .'<input type="submit" name="dis"'
1.511     www      3363:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3364:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3365:              .'</p>');
1.459     bisitz   3366:     }
1.478     amueller 3367:     
1.486     www      3368:     # ----- End Parameter Selection
1.57      albertel 3369: 
1.459     bisitz   3370:     # Display Messages
                   3371:     $r->print('<div>'.$message.'</div>');
1.210     www      3372: 
1.57      albertel 3373: 
                   3374:     my @temp_pscat;
                   3375:     map {
                   3376:         my $cat = $_;
                   3377:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3378:     } @pscat;
                   3379: 
                   3380:     @pscat = @temp_pscat;
                   3381: 
1.548     raeburn  3382: 
1.209     www      3383:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3384: # ----------------------------------------------------------------- Start Table
1.57      albertel 3385:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3386:         my $csuname=$env{'user.name'};
                   3387:         my $csudom=$env{'user.domain'};
1.568     raeburn  3388:         my $readonly = 1;
                   3389:         if ($parm_permission->{'edit'}) {
                   3390:             undef($readonly); 
                   3391:         }
1.57      albertel 3392: 
1.203     www      3393:         if ($parmlev eq 'full') {
1.506     www      3394: #
                   3395: # This produces the cascading table output of parameters
                   3396: #
1.578     raeburn  3397:             my $coursespan=$csec?8:5;
                   3398:             my $userspan=3;
1.560     damieng  3399:             if ($cgroup ne '') {
1.578     raeburn  3400:                 $coursespan += 3;
1.560     damieng  3401:             }
1.473     amueller 3402: 
1.560     damieng  3403:             $r->print(&Apache::loncommon::start_data_table());
                   3404:             #
                   3405:             # This produces the headers
                   3406:             #
                   3407:             $r->print('<tr><td colspan="5"></td>');
                   3408:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3409:             if ($uname) {
1.473     amueller 3410:                 if (@usersgroups > 1) {
1.560     damieng  3411:                     $userspan ++;
                   3412:                 }
                   3413:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3414:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3415:             }
                   3416:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3417:                 'pie'    => "Parameter in Effect",
                   3418:                 'csv'    => "Current Session Value",
1.472     amueller 3419:                 'rl'     => "Resource Level",
1.473     amueller 3420:                 'ic'     => 'in Course',
                   3421:                 'aut'    => "Assessment URL and Title",
                   3422:                 'type'   => 'Type',
                   3423:                 'emof'   => "Enclosing Map or Folder",
                   3424:                 'part'   => 'Part',
1.472     amueller 3425:                 'pn'     => 'Parameter Name',
1.473     amueller 3426:                 'def'    => 'default',
                   3427:                 'femof'  => 'from Enclosing Map or Folder',
                   3428:                 'gen'    => 'general',
                   3429:                 'foremf' => 'for Enclosing Map or Folder',
                   3430:                 'fr'     => 'for Resource'
                   3431:             );
1.560     damieng  3432:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3433: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3434: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3435: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3436: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3437: 
1.10      www      3438: ENDTABLETWO
1.560     damieng  3439:             if ($csec) {
1.578     raeburn  3440:                 $r->print('<th colspan="3">'.
1.560     damieng  3441:                 &mt("in Section")." $csec</th>");
                   3442:             }
                   3443:             if ($cgroup) {
1.578     raeburn  3444:                 $r->print('<th colspan="3">'.
1.472     amueller 3445:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3446:             }
                   3447:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3448: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3449: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3450: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3451: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3452: ENDTABLEHEADFOUR
1.57      albertel 3453: 
1.560     damieng  3454:             if ($csec) {
1.578     raeburn  3455:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3456:             }
1.473     amueller 3457: 
1.560     damieng  3458:             if ($cgroup) {
1.578     raeburn  3459:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3460:             }
                   3461: 
                   3462:             if ($uname) {
                   3463:                 if (@usersgroups > 1) {
                   3464:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3465:                 }
1.578     raeburn  3466:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3467:             }
                   3468: 
                   3469:             $r->print('</tr>');
1.506     www      3470: #
                   3471: # Done with the headers
                   3472: # 
1.560     damieng  3473:             my $defbgone='';
                   3474:             my $defbgtwo='';
                   3475:             my $defbgthree = '';
1.57      albertel 3476: 
1.560     damieng  3477:             foreach my $rid (@ids) {
1.57      albertel 3478: 
                   3479:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3480:                 if ((!$pssymb &&
1.560     damieng  3481:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3482:                         ||
                   3483:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3484: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3485:                     if ($defbgone eq '#E0E099') {
                   3486:                         $defbgone='#E0E0DD';
1.57      albertel 3487:                     } else {
1.419     bisitz   3488:                         $defbgone='#E0E099';
1.57      albertel 3489:                     }
1.419     bisitz   3490:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3491:                         $defbgtwo='#FFFFDD';
1.57      albertel 3492:                     } else {
1.473     amueller 3493:                         $defbgtwo='#FFFF99';
1.57      albertel 3494:                     }
1.419     bisitz   3495:                     if ($defbgthree eq '#FFBB99') {
                   3496:                         $defbgthree='#FFBBDD';
1.269     raeburn  3497:                     } else {
1.419     bisitz   3498:                         $defbgthree='#FFBB99';
1.269     raeburn  3499:                     }
                   3500: 
1.57      albertel 3501:                     my $thistitle='';
                   3502:                     my %name=   ();
                   3503:                     undef %name;
                   3504:                     my %part=   ();
                   3505:                     my %display=();
                   3506:                     my %type=   ();
                   3507:                     my %default=();
1.196     www      3508:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3509:                     my $toolsymb;
                   3510:                     if ($uri =~ /ext\.tool$/) {
                   3511:                         $toolsymb = $symbp{$rid};
                   3512:                     }
1.57      albertel 3513: 
1.506     www      3514:                     my $filter=$env{'form.filter'};
1.548     raeburn  3515:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3516:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3517:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3518:     # We may only want certain parameters listed
                   3519:                             if ($filter) {
                   3520:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3521:                             }
                   3522:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3523:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3524: 
1.584     raeburn  3525:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3526:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3527:                                 my $identifier;
                   3528:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3529:                                     $identifier = $1;
                   3530:                                 }
                   3531:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3532:                             } else {
                   3533:                                 $display{$tempkeyp} = $parmdis;
                   3534:                             }
                   3535:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3536:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3537:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3538:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3539:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3540:                         }
                   3541:                     }
1.548     raeburn  3542:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3543:                     if ($totalparms>0) {
1.560     damieng  3544:                         my $firstrow=1;
1.473     amueller 3545:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3546:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3547:                         my @recurseup;
                   3548:                         if (ref($navmap) && $mapp{$rid}) {
                   3549:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3550:                         }
1.419     bisitz   3551:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3552:                              ' rowspan='.$totalparms.
1.419     bisitz   3553:                              '><tt><font size="-1">'.
1.57      albertel 3554:                              join(' / ',split(/\//,$uri)).
                   3555:                              '</font></tt><p><b>'.
1.154     albertel 3556:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3557:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3558:                           &escape($symbp{$rid}).
1.336     albertel 3559:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3560:                              " target=\"_self\">$title");
1.57      albertel 3561: 
                   3562:                         if ($thistitle) {
1.473     amueller 3563:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3564:                         }
                   3565:                         $r->print('</a></b></td>');
1.419     bisitz   3566:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3567:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3568:                                       '</td>');
                   3569: 
1.419     bisitz   3570:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3571:                                       ' rowspan='.$totalparms.
1.238     www      3572:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3573:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3574:                             unless ($firstrow) {
                   3575:                                 $r->print('<tr>');
                   3576:                             } else {
                   3577:                                 undef $firstrow;
                   3578:                             }
1.548     raeburn  3579:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3580:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3581:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3582:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3583:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3584:                                        \$numreclinks);
1.57      albertel 3585:                         }
                   3586:                     }
                   3587:                 }
                   3588:             } # end foreach ids
1.43      albertel 3589: # -------------------------------------------------- End entry for one resource
1.517     www      3590:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3591:         } # end of  full
1.57      albertel 3592: #--------------------------------------------------- Entry for parm level map
                   3593:         if ($parmlev eq 'map') {
1.419     bisitz   3594:             my $defbgone = '#E0E099';
                   3595:             my $defbgtwo = '#FFFF99';
                   3596:             my $defbgthree = '#FFBB99';
1.57      albertel 3597: 
                   3598:             my %maplist;
                   3599: 
                   3600:             if ($pschp eq 'all') {
1.446     bisitz   3601:                 %maplist = %allmaps;
1.57      albertel 3602:             } else {
                   3603:                 %maplist = ($pschp => $mapp{$pschp});
                   3604:             }
                   3605: 
                   3606: #-------------------------------------------- for each map, gather information
                   3607:             my $mapid;
1.560     damieng  3608:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3609:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3610: 
                   3611: #-----------------------  loop through ids and get all parameter types for map
                   3612: #-----------------------------------------          and associated information
                   3613:                 my %name = ();
                   3614:                 my %part = ();
                   3615:                 my %display = ();
                   3616:                 my %type = ();
                   3617:                 my %default = ();
                   3618:                 my $map = 0;
                   3619: 
1.473     amueller 3620: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3621: 
1.548     raeburn  3622:                 foreach my $id (@ids) {
                   3623:                     ($map)=($id =~ /([\d]*?)\./);
                   3624:                     my $rid = $id;
1.446     bisitz   3625: 
1.57      albertel 3626: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3627: 
1.560     damieng  3628:                     if ($map eq $mapid) {
1.473     amueller 3629:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3630:                         my $toolsymb;
                   3631:                         if ($uri =~ /ext\.tool$/) {
                   3632:                             $toolsymb = $symbp{$rid};
                   3633:                         }
1.582     raeburn  3634: 
1.57      albertel 3635: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3636: 
                   3637: #--------------------------------------------------------------------
                   3638: # @catmarker contains list of all possible parameters including part #s
                   3639: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3640: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3641: # When storing information, store as part 0
                   3642: # When requesting information, request from full part
                   3643: #-------------------------------------------------------------------
1.548     raeburn  3644:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3645:                             my $tempkeyp = $fullkeyp;
                   3646:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3647: 
1.548     raeburn  3648:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3649:                                 $part{$tempkeyp}="0";
1.584     raeburn  3650:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3651:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3652:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3653:                                     my $identifier;
                   3654:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3655:                                         $identifier = $1;
                   3656:                                     }
                   3657:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3658:                                 } else {
                   3659:                                     $display{$tempkeyp} = $parmdis;
                   3660:                                 }
                   3661:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3662:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3663:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3664:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3665:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 3666:                               }
                   3667:                         } # end loop through keys
1.560     damieng  3668:                     }
1.57      albertel 3669:                 } # end loop through ids
1.446     bisitz   3670: 
1.57      albertel 3671: #---------------------------------------------------- print header information
1.133     www      3672:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      3673:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   3674:                 my $tmp="";
1.57      albertel 3675:                 if ($uname) {
1.473     amueller 3676:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   3677:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   3678:                         &mt('in')." \n";
1.57      albertel 3679:                 } else {
1.401     bisitz   3680:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 3681:                 }
1.269     raeburn  3682:                 if ($cgroup) {
1.401     bisitz   3683:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   3684:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3685:                     $csec = '';
                   3686:                 } elsif ($csec) {
1.401     bisitz   3687:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   3688:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3689:                 }
1.401     bisitz   3690:                 $r->print('<div align="center"><h4>'
                   3691:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   3692:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   3693:                              ,$tmp
                   3694:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   3695:                              )
                   3696:                          ."<br /></h4>\n"
1.422     bisitz   3697:                 );
1.57      albertel 3698: #---------------------------------------------------------------- print table
1.419     bisitz   3699:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3700:                          .&Apache::loncommon::start_data_table_header_row()
                   3701:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  3702:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   3703:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   3704:                          .&Apache::loncommon::end_data_table_header_row()
                   3705:                 );
1.57      albertel 3706: 
1.582     raeburn  3707:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   3708:                 my @recurseup;
                   3709:                 if (ref($navmap)) {
                   3710:                      my $mapres = $navmap->getByMapPc($mapid);
                   3711:                      if (ref($mapres)) {
                   3712:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   3713:                      }
                   3714:                 }
                   3715: 
                   3716: 
1.548     raeburn  3717:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 3718:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3719:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  3720:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  3721:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  3722:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   3723:                            \$numreclinks);
1.57      albertel 3724:                 }
1.422     bisitz   3725:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   3726:                          .'</div>'
                   3727:                 );
1.57      albertel 3728:             } # end each map
                   3729:         } # end of $parmlev eq map
                   3730: #--------------------------------- Entry for parm level general (Course level)
                   3731:         if ($parmlev eq 'general') {
1.473     amueller 3732:             my $defbgone = '#E0E099';
1.419     bisitz   3733:             my $defbgtwo = '#FFFF99';
                   3734:             my $defbgthree = '#FFBB99';
1.57      albertel 3735: 
                   3736: #-------------------------------------------- for each map, gather information
                   3737:             my $mapid="0.0";
                   3738: #-----------------------  loop through ids and get all parameter types for map
                   3739: #-----------------------------------------          and associated information
                   3740:             my %name = ();
                   3741:             my %part = ();
                   3742:             my %display = ();
                   3743:             my %type = ();
                   3744:             my %default = ();
1.446     bisitz   3745: 
1.548     raeburn  3746:             foreach $id (@ids) {
                   3747:                 my $rid = $id;
1.446     bisitz   3748: 
1.196     www      3749:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3750:                 my $toolsymb;
                   3751:                 if ($uri =~ /ext\.tool$/) {
                   3752:                     $toolsymb = $symbp{$rid};
                   3753:                 }
1.57      albertel 3754: 
                   3755: #--------------------------------------------------------------------
                   3756: # @catmarker contains list of all possible parameters including part #s
                   3757: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3758: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3759: # When storing information, store as part 0
                   3760: # When requesting information, request from full part
                   3761: #-------------------------------------------------------------------
1.548     raeburn  3762:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3763:                     my $tempkeyp = $fullkeyp;
                   3764:                     $tempkeyp =~ s/_\w+_/_0_/;
                   3765:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3766:                         $part{$tempkeyp}="0";
1.584     raeburn  3767:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3768:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3769:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   3770:                             my $identifier;
                   3771:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3772:                                 $identifier = $1;
                   3773:                             }
                   3774:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3775:                         } else {
                   3776:                             $display{$tempkeyp} = $parmdis;
                   3777:                         }
                   3778:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3779:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3780:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3781:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3782:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  3783:                     }
1.57      albertel 3784:                 } # end loop through keys
                   3785:             } # end loop through ids
1.446     bisitz   3786: 
1.57      albertel 3787: #---------------------------------------------------- print header information
1.473     amueller 3788:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 3789:             $r->print(<<ENDMAPONE);
1.419     bisitz   3790: <center>
                   3791: <h4>$setdef
1.135     albertel 3792: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 3793: ENDMAPONE
                   3794:             if ($uname) {
1.473     amueller 3795:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 3796:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 3797:             } else {
1.135     albertel 3798:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 3799:             }
1.446     bisitz   3800: 
1.135     albertel 3801:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 3802:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 3803:             $r->print("</h4>\n");
1.57      albertel 3804: #---------------------------------------------------------------- print table
1.419     bisitz   3805:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3806:                      .&Apache::loncommon::start_data_table_header_row()
                   3807:                      .'<th>'.&mt('Parameter Name').'</th>'
                   3808:                      .'<th>'.&mt('Default Value').'</th>'
                   3809:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   3810:                      .&Apache::loncommon::end_data_table_header_row()
                   3811:             );
1.57      albertel 3812: 
1.548     raeburn  3813:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   3814:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3815:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  3816:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   3817:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3818:                            $readonly);
1.57      albertel 3819:             }
1.419     bisitz   3820:             $r->print(&Apache::loncommon::end_data_table()
                   3821:                      .'</p>'
                   3822:                      .'</center>'
                   3823:             );
1.57      albertel 3824:         } # end of $parmlev eq general
1.43      albertel 3825:     }
1.507     www      3826:     $r->print('</form>');
1.582     raeburn  3827:     if ($numreclinks) {
                   3828:         $r->print(<<"END");
                   3829: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   3830: <input type="hidden" name="pschp" />
                   3831: <input type="hidden" name="pscat" />
                   3832: <input type="hidden" name="psprt" />
                   3833: <input type="hidden" name="hideparmsel" value="hidden" />
                   3834: </form>
                   3835: <script type="text/javascript">
                   3836: function pjumprec(rid,name,part) {
                   3837:     document.forms.recurseform.pschp.value = rid;
                   3838:     document.forms.recurseform.pscat.value = name;
                   3839:     document.forms.recurseform.psprt.value = part;
                   3840:     document.forms.recurseform.submit();
                   3841:     return false;
                   3842: }
                   3843: </script>
                   3844: END
                   3845:     }
1.507     www      3846:     &endSettingsScreen($r);
                   3847:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 3848: } # end sub assessparms
1.30      www      3849: 
1.560     damieng  3850: 
                   3851: 
1.120     www      3852: ##################################################
1.560     damieng  3853: # OVERVIEW MODE
1.207     www      3854: ##################################################
1.124     www      3855: 
1.563     damieng  3856: my $tableopen; # boolean, true if HTML table is already opened
                   3857: 
                   3858: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   3859: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   3860: # @returns {string}
1.124     www      3861: sub tablestart {
1.576     raeburn  3862:     my ($readonly,$is_map) = @_;
1.124     www      3863:     if ($tableopen) {
1.552     raeburn  3864:         return '';
1.124     www      3865:     } else {
1.552     raeburn  3866:         $tableopen=1;
                   3867:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   3868:         if ($readonly) {
                   3869:             $output .= '<th>'.&mt('Current value').'</th>';
                   3870:         } else {
1.576     raeburn  3871:             $output .= '<th>'.&mt('Delete').'</th>'.
                   3872:                        '<th>'.&mt('Set to ...').'</th>';
                   3873:             if ($is_map) {
                   3874:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   3875:             }
1.552     raeburn  3876:         }
                   3877:         $output .= '</tr>';
                   3878:         return $output;
1.124     www      3879:     }
                   3880: }
                   3881: 
1.563     damieng  3882: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   3883: # @returns {string}
1.124     www      3884: sub tableend {
                   3885:     if ($tableopen) {
1.560     damieng  3886:         $tableopen=0;
                   3887:         return &Apache::loncommon::end_data_table();
1.124     www      3888:     } else {
1.560     damieng  3889:         return'';
1.124     www      3890:     }
                   3891: }
                   3892: 
1.563     damieng  3893: # Reads course and user information.
                   3894: # If the context is looking for a scalar, returns the course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db) with added student data from lonnet::get_userresdata (which reads the user's resourcedata.db).
                   3895: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   3896: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   3897: # @param {string} $crs - course number
                   3898: # @param {string} $dom - course domain
                   3899: # @returns {hash reference|Array}
1.207     www      3900: sub readdata {
                   3901:     my ($crs,$dom)=@_;
                   3902: # Read coursedata
                   3903:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   3904: # Read userdata
                   3905: 
                   3906:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  3907:     foreach my $user (keys(%$classlist)) {
                   3908:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   3909:             my ($tuname,$tudom)=($1,$2);
                   3910:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   3911:             foreach my $userkey (keys(%{$useropt})) {
                   3912:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      3913:                     my $newkey=$userkey;
1.548     raeburn  3914:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   3915:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   3916:                 }
                   3917:             }
1.473     amueller 3918:         }
                   3919:     }
1.552     raeburn  3920:     if (wantarray) {
                   3921:         return ($resourcedata,$classlist);
                   3922:     } else {
                   3923:         return $resourcedata;
                   3924:     }
1.207     www      3925: }
                   3926: 
                   3927: 
1.563     damieng  3928: # Stores parameter data, using form parameters directly.
                   3929: #
                   3930: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588   ! raeburn  3931: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  3932: # del_* - remove a parameter
                   3933: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   3934: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   3935: # key_* - date values
                   3936: # days_* - for date intervals
                   3937: # hours_* - for date intervals
                   3938: # minutes_* - for date intervals
                   3939: # seconds_* - for date intervals
                   3940: # done_* - for date intervals
                   3941: # typeof_* - parameter type
                   3942: # 
                   3943: # @param {Apache2::RequestRec} $r - the Apache request
                   3944: # @param {string} $crs - course number
                   3945: # @param {string} $dom - course domain
1.208     www      3946: sub storedata {
                   3947:     my ($r,$crs,$dom)=@_;
1.207     www      3948: # Set userlevel immediately
                   3949: # Do an intermediate store of course level
                   3950:     my $olddata=&readdata($crs,$dom);
1.124     www      3951:     my %newdata=();
                   3952:     undef %newdata;
                   3953:     my @deldata=();
1.576     raeburn  3954:     my @delrec=();
                   3955:     my @delnonrec=();
1.124     www      3956:     undef @deldata;
1.504     raeburn  3957:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  3958:     my $now = time;
1.560     damieng  3959:     foreach my $key (keys(%env)) {
                   3960:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   3961:             my $cmd=$1;
                   3962:             my $thiskey=$2;
1.576     raeburn  3963:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588   ! raeburn  3964:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  3965:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   3966:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   3967:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   3968:                     $altkey = $thiskey;
                   3969:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   3970:                     if ($env{'form.rec_'.$thiskey}) {
                   3971:                         $recursive = 1;
                   3972:                     }
                   3973:                 }
                   3974:             }
1.560     damieng  3975:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 3976:             if ($tuname) {
1.576     raeburn  3977:                 $tkey=$thiskey;
1.560     damieng  3978:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  3979:                 if ($altkey) {
                   3980:                     $tkeynonrec = $tkey; 
                   3981:                     $tkeyrec = $altkey;
                   3982:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   3983:                 }
1.560     damieng  3984:             }
                   3985:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  3986:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   3987:                 if ($cmd eq 'set') {
                   3988:                     $data=$env{$key};
                   3989:                     $valmatch = '';
                   3990:                     $valchk = $data;
                   3991:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3992:                     $text = &mt('Saved modified parameter for');
                   3993:                     if ($typeof eq 'string_questiontype') {
                   3994:                         $name = 'type';
1.588   ! raeburn  3995:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
        !          3996:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  3997:                         my $stringmatch = &standard_string_matches($typeof);
                   3998:                         if (ref($stringmatch) eq 'ARRAY') {
                   3999:                             foreach my $item (@{$stringmatch}) {
                   4000:                                 if (ref($item) eq 'ARRAY') {
                   4001:                                     my ($regexpname,$pattern) = @{$item};
                   4002:                                     if ($pattern ne '') {
                   4003:                                         if ($data =~ /$pattern/) {
                   4004:                                             $valmatch = $regexpname;
                   4005:                                             $valchk = '';
                   4006:                                             last;
                   4007:                                         }
1.560     damieng  4008:                                     }
1.549     raeburn  4009:                                 }
                   4010:                             }
                   4011:                         }
1.563     damieng  4012:                     } elsif ($typeof eq 'string_discussvote') {
                   4013:                         $name = 'discussvote';
                   4014:                     } elsif ($typeof eq 'string_examcode') {
                   4015:                         $name = 'examcode';
                   4016:                         if (&Apache::lonnet::validCODE($data)) {
                   4017:                             $valchk = 'valid';
                   4018:                         }
                   4019:                     } elsif ($typeof eq 'string_yesno') {
                   4020:                         if ($thiskey =~ /\.retrypartial$/) {
                   4021:                             $name = 'retrypartial';
                   4022:                         }
1.549     raeburn  4023:                     }
1.563     damieng  4024:                 } elsif ($cmd eq 'datepointer') {
                   4025:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4026:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4027:                     $text = &mt('Saved modified date for');
                   4028:                     if ($typeof eq 'date_start') {
                   4029:                         if ($thiskey =~ /\.printstartdate$/) {
                   4030:                             $name = 'printstartdate';
                   4031:                             if (($data) && ($data > $now)) {
                   4032:                                 $valchk = 'future';
                   4033:                             }
1.560     damieng  4034:                         }
1.563     damieng  4035:                     } elsif ($typeof eq 'date_end') {
                   4036:                         if ($thiskey =~ /\.printenddate$/) {
                   4037:                             $name = 'printenddate';
                   4038:                             if (($data) && ($data < $now)) {
                   4039:                                 $valchk = 'past';
                   4040:                             }
1.560     damieng  4041:                         }
1.504     raeburn  4042:                     }
1.563     damieng  4043:                 } elsif ($cmd eq 'dateinterval') {
                   4044:                     $data=&get_date_interval_from_form($thiskey);
                   4045:                     if ($thiskey =~ /\.interval$/) {
                   4046:                         $name = 'interval';
                   4047:                         my $intervaltype = &get_intervaltype($name);
                   4048:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4049:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4050:                             foreach my $item (@{$intervalmatch}) {
                   4051:                                 if (ref($item) eq 'ARRAY') {
                   4052:                                     my ($regexpname,$pattern) = @{$item};
                   4053:                                     if ($pattern ne '') {
                   4054:                                         if ($data =~ /$pattern/) {
                   4055:                                             $valmatch = $regexpname;
                   4056:                                             $valchk = '';
                   4057:                                             last;
                   4058:                                         }
1.560     damieng  4059:                                     }
1.554     raeburn  4060:                                 }
                   4061:                             }
                   4062:                         }
                   4063:                     }
1.563     damieng  4064:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4065:                     $text = &mt('Saved modified date for');
1.554     raeburn  4066:                 }
1.576     raeburn  4067:                 if ($recursive) {
1.563     damieng  4068:                     $namematch = 'maplevelrecurse';
1.560     damieng  4069:                 }
1.563     damieng  4070:                 if (($name ne '') || ($namematch ne '')) {
                   4071:                     my ($needsrelease,$needsnewer);
                   4072:                     if ($name ne '') {
                   4073:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4074:                         if ($needsrelease) {
                   4075:                             unless ($got_chostname) {
1.563     damieng  4076:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4077:                                 $got_chostname = 1;
                   4078:                             }
1.563     damieng  4079:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4080:                                                                 $needsrelease,
                   4081:                                                                 $cmajor,$cminor);
                   4082:                         }
                   4083:                     }
                   4084:                     if ($namematch ne '') {
                   4085:                         if ($needsnewer) {
                   4086:                             undef($namematch);
1.560     damieng  4087:                         } else {
1.563     damieng  4088:                             my $currneeded;
                   4089:                             if ($needsrelease) {
                   4090:                                 $currneeded = $needsrelease;
                   4091:                             }
                   4092:                             $needsrelease =
                   4093:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4094:                             if (($needsrelease) &&
                   4095:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4096:                                 unless ($got_chostname) {
                   4097:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4098:                                     $got_chostname = 1;
                   4099:                                 }
                   4100:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4101:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4102:                             } else {
                   4103:                                 undef($namematch);
                   4104:                             }
1.560     damieng  4105:                         }
1.557     raeburn  4106:                     }
1.563     damieng  4107:                     if ($needsnewer) {
                   4108:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4109:                                                             $chostname,$cmajor,
                   4110:                                                             $cminor,$needsrelease));
                   4111:                         next;
                   4112:                     }
1.504     raeburn  4113:                 }
1.576     raeburn  4114:                 my ($reconlychg,$haschange,$storekey);
                   4115:                 if ($tuname) {
                   4116:                     my $ustorekey;
                   4117:                     if ($altkey) {
                   4118:                         if ($recursive) {
                   4119:                             if (exists($$olddata{$thiskey})) {
                   4120:                                 if ($$olddata{$thiskey} eq $data) {
                   4121:                                     $reconlychg = 1;
                   4122:                                 }
                   4123:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4124:                             }
                   4125:                             if (exists($$olddata{$altkey})) {
                   4126:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4127:                                     $haschange = 1;
                   4128:                                 }
                   4129:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4130:                                 $haschange = 1;
                   4131:                             }
                   4132:                             $ustorekey = $tkeyrec;
                   4133:                         } else {
                   4134:                             if (exists($$olddata{$altkey})) {
                   4135:                                 if ($$olddata{$altkey} eq $data) {
                   4136:                                     $reconlychg = 1;
                   4137:                                 }
                   4138:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4139:                             }
                   4140:                             if (exists($$olddata{$thiskey})) {
                   4141:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4142:                                     $haschange = 1;
                   4143:                                 }
                   4144:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4145:                                 $haschange = 1;
                   4146:                             }
                   4147:                             $ustorekey = $tkeynonrec;
                   4148:                         }
                   4149:                     } else {
                   4150:                         if (exists($$olddata{$tkey})) {
                   4151:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4152:                                 $haschange = 1;
                   4153:                             }
                   4154:                             $ustorekey = $tkey;
                   4155:                         }
                   4156:                     }
                   4157:                     if ($haschange || $reconlychg)  {
                   4158:                         unless ($env{'form.del_'.$thiskey}) {
                   4159:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4160:                                                                      $ustorekey.'.type' => $typeof},
                   4161:                                                                      $tudom,$tuname) eq 'ok') {
                   4162:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4163:                                 $r->print('<br />'.$text.' '.
                   4164:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4165:                             } else {
                   4166:                                 $r->print('<div class="LC_error">'.
                   4167:                                           &mt('Error saving parameters').'</div>');
                   4168:                             }
                   4169:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4170:                         }
                   4171:                     }
                   4172:                 } else {
                   4173:                     if ($altkey) {
                   4174:                         if ($recursive) {
                   4175:                             if (exists($$olddata{$thiskey})) {
                   4176:                                 if ($$olddata{$thiskey} eq $data) {
                   4177:                                     $reconlychg = 1;
                   4178:                                 }
                   4179:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4180:                             }
                   4181:                             if (exists($$olddata{$altkey})) {
                   4182:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4183:                                     $haschange = 1;
                   4184:                                 }
                   4185:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4186:                                 $haschange = 1;
                   4187:                             }
                   4188:                             $storekey = $altkey;
1.563     damieng  4189:                         } else {
1.576     raeburn  4190:                             if (exists($$olddata{$altkey})) {
                   4191:                                 if ($$olddata{$altkey} eq $data) {
                   4192:                                     $reconlychg = 1;
                   4193:                                 }
                   4194:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4195:                             } 
                   4196:                             if (exists($$olddata{$thiskey})) {
                   4197:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4198:                                     $haschange = 1;
                   4199:                                 }
                   4200:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4201:                                 $haschange = 1;
                   4202:                             }
                   4203:                             $storekey = $thiskey;
1.563     damieng  4204:                         }
1.560     damieng  4205:                     } else {
1.576     raeburn  4206:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4207:                             $haschange = 1;
                   4208:                             $storekey = $thiskey;
                   4209:                         }
                   4210:                     }
                   4211:                 }
                   4212:                 if ($reconlychg || $haschange) {
                   4213:                     unless ($env{'form.del_'.$thiskey}) {
                   4214:                         $newdata{$storekey}=$data;
                   4215:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4216:                     }
                   4217:                 }
                   4218:             } elsif ($cmd eq 'del') {
                   4219:                 if ($tuname) {
1.576     raeburn  4220:                     my $error;
                   4221:                     if ($altkey) {  
                   4222:                         if (exists($$olddata{$altkey})) {
                   4223:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4224:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4225:                                 if ($recursive) {
                   4226:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4227:                                 }
                   4228:                             } elsif ($recursive) {
                   4229:                                 $error = 1;
                   4230:                             }
                   4231:                         }
                   4232:                         if (exists($$olddata{$thiskey})) {
                   4233:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4234:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4235:                                 unless ($recursive) {
                   4236:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4237:                                 }
                   4238:                             } elsif (!$recursive) {
                   4239:                                 $error = 1;
                   4240:                             }
                   4241:                         }
1.560     damieng  4242:                     } else {
1.576     raeburn  4243:                         if (exists($$olddata{$thiskey})) {
                   4244:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4245:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4246:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4247:                             } else {
                   4248:                                 $error = 1;
                   4249:                             }
                   4250:                         }
                   4251:                     }
                   4252:                     if ($error) { 
1.560     damieng  4253:                         $r->print('<div class="LC_error">'.
                   4254:                             &mt('Error deleting parameters').'</div>');
                   4255:                     }
                   4256:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4257:                 } else {
1.576     raeburn  4258:                     if ($altkey) {
                   4259:                         if (exists($$olddata{$altkey})) {
                   4260:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4261:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4262:                             }
                   4263:                         }
                   4264:                         if (exists($$olddata{$thiskey})) {
                   4265:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4266:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4267:                             }
                   4268:                         }
                   4269:                     } elsif (exists($$olddata{$thiskey})) {
                   4270:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4271:                     }
1.560     damieng  4272:                 }
1.473     amueller 4273:             }
                   4274:         }
                   4275:     }
1.207     www      4276: # Store all course level
1.144     www      4277:     my $delentries=$#deldata+1;
1.576     raeburn  4278:     my @alldels;
                   4279:     if (@delrec) {
                   4280:         push(@alldels,@delrec);
                   4281:     }
                   4282:     if (@delnonrec) {
                   4283:         push(@alldels,@delnonrec);
                   4284:     }
                   4285:     if (@deldata) {
                   4286:         push(@alldels,@deldata);
                   4287:     }
1.548     raeburn  4288:     my @newdatakeys=keys(%newdata);
1.144     www      4289:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4290:     my ($delresult,$devalidate);
                   4291:     if (@alldels) {
                   4292:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4293:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4294:             &log_parmset(\%loghash,1);
1.576     raeburn  4295:             if ($delentries) {
                   4296:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4297:             }
                   4298:         } elsif ($delentries) {
1.560     damieng  4299:             $r->print('<div class="LC_error">'.
                   4300:                 &mt('Error deleting parameters').'</div>');
                   4301:         }
1.576     raeburn  4302:         $devalidate = 1; 
1.144     www      4303:     }
                   4304:     if ($putentries) {
1.560     damieng  4305:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4306:                     &log_parmset(\%newdata,0);
                   4307:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4308:         } else {
                   4309:             $r->print('<div class="LC_error">'.
                   4310:                 &mt('Error saving parameters').'</div>');
                   4311:         }
1.576     raeburn  4312:         $devalidate = 1; 
                   4313:     }
                   4314:     if ($devalidate) {
1.560     damieng  4315:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4316:     }
1.208     www      4317: }
1.207     www      4318: 
1.563     damieng  4319: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4320: #
                   4321: # @param {string} $key - the key
                   4322: # @returns {Array}
1.208     www      4323: sub extractuser {
                   4324:     my $key=shift;
1.350     albertel 4325:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4326: }
1.206     www      4327: 
1.563     damieng  4328: # Parses a parameter key and returns the components.
                   4329: #
                   4330: # @param {string} $key - 
                   4331: # @param {hash reference} $listdata - 
                   4332: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4333: sub parse_listdata_key {
                   4334:     my ($key,$listdata) = @_;
                   4335:     # split into student/section affected, and
                   4336:     # the realm (folder/resource part and parameter
1.446     bisitz   4337:     my ($student,$realm) =
1.473     amueller 4338:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4339:     # if course wide student would be undefined
                   4340:     if (!defined($student)) {
1.560     damieng  4341:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4342:     }
                   4343:     # strip off the .type if it's not the Question type parameter
                   4344:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4345:         $realm=~s/\.type//;
1.381     albertel 4346:     }
                   4347:     # split into resource+part and parameter name
1.388     albertel 4348:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4349:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4350:     return ($student,$res,$part,$parm);
                   4351: }
                   4352: 
1.563     damieng  4353: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4354: #
                   4355: # @param {Apache2::RequestRec} $r - the Apache request
                   4356: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4357: # @param {hash reference} $listdata - data created in secgroup_lister, course id.[section id].part.name -> 1 or course id.[section id].part.name.type -> parameter type
                   4358: # @param {string} $sortorder - realmstudent|studentrealm
                   4359: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4360: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4361: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  4362: # @returns{integer} - number of $listdata parameters processed
1.208     www      4363: sub listdata {
1.568     raeburn  4364:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  4365:     
1.207     www      4366: # Start list output
1.206     www      4367: 
1.122     www      4368:     my $oldsection='';
                   4369:     my $oldrealm='';
                   4370:     my $oldpart='';
1.123     www      4371:     my $pointer=0;
1.124     www      4372:     $tableopen=0;
1.145     www      4373:     my $foundkeys=0;
1.248     albertel 4374:     my %keyorder=&standardkeyorder();
1.381     albertel 4375: 
1.552     raeburn  4376:     my ($secidx,%grouphash);
                   4377:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4378:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4379:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4380:             %grouphash = &Apache::longroup::coursegroups();
                   4381:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4382:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4383:         }
1.552     raeburn  4384:     }
                   4385: 
1.576     raeburn  4386:     foreach my $key (sort {
1.560     damieng  4387:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4388:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 4389: 
1.560     damieng  4390:         # get the numerical order for the param
                   4391:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4392:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4393: 
1.560     damieng  4394:         my $result=0;
1.381     albertel 4395: 
1.560     damieng  4396:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4397:             if ($ares     ne $bres    ) {
1.560     damieng  4398:                 $result = ($ares     cmp $bres);
1.446     bisitz   4399:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4400:                 $result = ($astudent cmp $bstudent);
                   4401:             } elsif ($apart    ne $bpart   ) {
                   4402:                 $result = ($apart    cmp $bpart);
                   4403:             }
                   4404:         } else {
                   4405:             if      ($astudent ne $bstudent) {
                   4406:                 $result = ($astudent cmp $bstudent);
                   4407:             } elsif ($ares     ne $bres    ) {
                   4408:                 $result = ($ares     cmp $bres);
                   4409:             } elsif ($apart    ne $bpart   ) {
                   4410:                 $result = ($apart    cmp $bpart);
                   4411:             }
1.473     amueller 4412:         }
1.446     bisitz   4413: 
1.560     damieng  4414:         if (!$result) {
1.381     albertel 4415:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4416:                 $result = ($aparm <=> $bparm);
1.381     albertel 4417:             } elsif (defined($aparm)) {
1.560     damieng  4418:                 $result = -1;
1.381     albertel 4419:             } elsif (defined($bparm)) {
1.560     damieng  4420:                 $result = 1;
                   4421:             }
1.473     amueller 4422:         }
1.381     albertel 4423: 
1.560     damieng  4424:         $result;
                   4425:         
1.576     raeburn  4426:     } keys(%{$listdata})) { # foreach my $key
                   4427:         my $thiskey = $key;
1.560     damieng  4428:         if ($$listdata{$thiskey.'.type'}) {
                   4429:             my $thistype=$$listdata{$thiskey.'.type'};
                   4430:             if ($$resourcedata{$thiskey.'.type'}) {
                   4431:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4432:             }
                   4433:             my ($middle,$part,$name)=
1.572     damieng  4434:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4435:             my $section=&mt('All Students');
1.576     raeburn  4436:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4437:             if ($middle=~/^\[(.*)\]/) {
                   4438:                 my $issection=$1;
                   4439:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4440:                     my ($stuname,$studom) = ($1,$2);
                   4441:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4442:                         if (ref($classlist) eq 'HASH') {
                   4443:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4444:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4445:                             }
                   4446:                         }
                   4447:                     }
                   4448:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
                   4449:                 } else {
                   4450:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4451:                         if (exists($grouphash{$issection})) {
                   4452:                             $section=&mt('Group').': '.$issection;
                   4453:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4454:                             $section = &mt('Section').': '.$issection;
                   4455:                         } else {
                   4456:                             next; 
1.552     raeburn  4457:                         }
1.560     damieng  4458:                     } else {
                   4459:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4460:                     }
                   4461:                 }
1.560     damieng  4462:                 $middle=~s/^\[(.*)\]//;
                   4463:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4464:                 $readonly = 1;
                   4465:             }
                   4466:             $middle=~s/\.+$//;
                   4467:             $middle=~s/^\.+//;
                   4468:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4469:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4470:             if ($caller eq 'overview') {
                   4471:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4472:                     $mapurl = $1;
                   4473:                     $maplevel = $2;
                   4474:                     $is_map = 1;
                   4475:                 }
                   4476:             } elsif ($caller eq 'newoverview') {
                   4477:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4478:                     $mapurl = $1;
                   4479:                     $maplevel = $2;
                   4480:                     $is_map = 1;
                   4481:                 }
                   4482:             }
                   4483:             if ($is_map) {
1.560     damieng  4484:                 my $leveltitle = &mt('Folder/Map');
1.576     raeburn  4485:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4486:                     if ($caller eq 'newoverview') {
                   4487:                         my $altkey = $thiskey;
                   4488:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4489:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4490:                             $is_recursive = 1;
                   4491:                             if ($$resourcedata{$altkey.'.type'}) {
                   4492:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4493:                             }
                   4494:                             $showval = $$resourcedata{$altkey};
                   4495:                         }
                   4496:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4497:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4498:                         $is_recursive = 1;
                   4499:                     }
1.560     damieng  4500:                 }
                   4501:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   4502:             } elsif ($middle) {
                   4503:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   4504:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4505:                     ': '.&Apache::lonnet::gettitle($middle).
                   4506:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4507:                     $id.')</span></span>';
                   4508:             }
                   4509:             if ($sortorder eq 'realmstudent') {
                   4510:                 if ($realm ne $oldrealm) {
                   4511:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4512:                     $oldrealm=$realm;
                   4513:                     $oldsection='';
                   4514:                 }
                   4515:                 if ($section ne $oldsection) {
                   4516:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4517:                     $oldsection=$section;
                   4518:                     $oldpart='';
                   4519:                 }
1.552     raeburn  4520:             } else {
1.560     damieng  4521:                 if ($section ne $oldsection) {
                   4522:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4523:                     $oldsection=$section;
                   4524:                     $oldrealm='';
                   4525:                 }
                   4526:                 if ($realm ne $oldrealm) {
                   4527:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4528:                     $oldrealm=$realm;
                   4529:                     $oldpart='';
1.552     raeburn  4530:                 }
                   4531:             }
1.560     damieng  4532:             if ($part ne $oldpart) {
                   4533:                 $r->print(&tableend().
                   4534:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4535:                 $oldpart=$part;
1.556     raeburn  4536:             }
1.560     damieng  4537:     #
                   4538:     # Ready to print
                   4539:     #
1.470     raeburn  4540:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4541:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4542:                 &Apache::loncommon::start_data_table_row().
                   4543:                 '<td><b>'.&mt($parmitem).
                   4544:                 '</b></td>');
                   4545:             unless ($readonly) {
                   4546:                 $r->print('<td><input type="checkbox" name="del_'.
                   4547:                         $thiskey.'" /></td>');
                   4548:             }
                   4549:             $r->print('<td>');
                   4550:             $foundkeys++;
                   4551:             if (&isdateparm($thistype)) {
                   4552:                 my $jskey='key_'.$pointer;
                   4553:                 my $state;
                   4554:                 $pointer++;
                   4555:                 if ($readonly) {
                   4556:                     $state = 'disabled';
                   4557:                 }
                   4558:                 $r->print(
                   4559:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4560:                                                         $jskey,
1.576     raeburn  4561:                                                         $showval,
1.560     damieng  4562:                                                         '',1,$state));
                   4563:                 unless  ($readonly) {
                   4564:                     $r->print(
                   4565:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4566:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4567:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4568:     &date_sanity_info($showval)
1.560     damieng  4569:                     );
                   4570:                 }
                   4571:             } elsif ($thistype eq 'date_interval') {
                   4572:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4573:                           $showval,$readonly));
1.560     damieng  4574:             } elsif ($thistype =~ m/^string/) {
                   4575:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4576:                           $showval,$name,$readonly));
1.560     damieng  4577:             } else {
1.576     raeburn  4578:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  4579:             }
1.560     damieng  4580:             unless ($readonly) {
                   4581:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4582:                         $thistype.'" />');
1.552     raeburn  4583:             }
1.576     raeburn  4584:             $r->print('</td>');
                   4585:             if ($is_map) {
                   4586:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   4587:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   4588:                 } else {
                   4589:                     my ($disabled,$recon,$recoff);
                   4590:                     if ($readonly) {
                   4591:                         $disabled = ' disabled="disabled"';
                   4592:                     }
                   4593:                     if ($is_recursive) {
                   4594:                         $recon = ' checked="checked"';
                   4595:                     } else {
                   4596:                         $recoff = ' checked="checked"';
                   4597:                     }
                   4598:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   4599:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   4600:                 }
                   4601:             }
                   4602:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 4603:         }
1.121     www      4604:     }
1.208     www      4605:     return $foundkeys;
                   4606: }
                   4607: 
1.563     damieng  4608: # Returns a string representing the interval, directly using form data matching the given key.
                   4609: # The returned string may also include information related to proctored exams.
                   4610: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4611: #
                   4612: # @param {string} $key - suffix for form fields related to the interval
                   4613: # @returns {string}
1.385     albertel 4614: sub get_date_interval_from_form {
                   4615:     my ($key) = @_;
                   4616:     my $seconds = 0;
                   4617:     foreach my $which (['days', 86400],
1.473     amueller 4618:                ['hours', 3600],
                   4619:                ['minutes', 60],
                   4620:                ['seconds',  1]) {
1.560     damieng  4621:         my ($name, $factor) = @{ $which };
                   4622:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4623:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4624:         }
1.473     amueller 4625:     }
1.560     damieng  4626:     if (($key =~ /\.interval$/) &&
                   4627:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4628:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4629:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4630:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4631:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4632:                 $seconds .= '_proctor';
                   4633:             }
                   4634:         } else {
                   4635:             $seconds .= $env{'form.done_'.$key}; 
                   4636:         }
                   4637:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4638:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4639:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4640:         }
1.554     raeburn  4641:     }
1.385     albertel 4642:     return $seconds;
                   4643: }
                   4644: 
                   4645: 
1.563     damieng  4646: # Returns HTML to enter a text value for a parameter.
                   4647: #
                   4648: # @param {string} $thiskey - parameter key
                   4649: # @param {string} $showval - the current value
                   4650: # @param {boolean} $readonly - true if the field should not be made editable
                   4651: # @returns {string}
1.383     albertel 4652: sub default_selector {
1.552     raeburn  4653:     my ($thiskey, $showval, $readonly) = @_;
                   4654:     my $disabled;
                   4655:     if ($readonly) {
                   4656:         $disabled = ' disabled="disabled"';
                   4657:     }
                   4658:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4659: }
                   4660: 
1.563     damieng  4661: # Returns HTML to enter allow/deny rules related to IP addresses.
                   4662: #
                   4663: # @param {string} $thiskey - parameter key
                   4664: # @param {string} $showval - the current value
                   4665: # @param {boolean} $readonly - true if the fields should not be made editable
                   4666: # @returns {string}
1.549     raeburn  4667: sub string_ip_selector {
1.552     raeburn  4668:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  4669:     my %access = (
                   4670:                    allow => [],
                   4671:                    deny  => [],
                   4672:                  );
                   4673:     if ($showval ne '') {
                   4674:         my @current;
                   4675:         if ($showval =~ /,/) {
                   4676:             @current = split(/,/,$showval);
                   4677:         } else {
                   4678:             @current = ($showval);
                   4679:         }
                   4680:         foreach my $item (@current) {
                   4681:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4682:                 push(@{$access{'deny'}},$1);
                   4683:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4684:                 push(@{$access{'allow'}},$item);
                   4685:             }
                   4686:         }
                   4687:     }
                   4688:     if (!@{$access{'allow'}}) {
                   4689:         @{$access{'allow'}} = ('');
                   4690:     }
                   4691:     if (!@{$access{'deny'}}) {
                   4692:         @{$access{'deny'}} = ('');
                   4693:     }
1.552     raeburn  4694:     my ($disabled,$addmore);
1.567     raeburn  4695:     if ($readonly) {
1.552     raeburn  4696:         $disabled=' disabled="disabled"';
                   4697:     } else {
                   4698:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   4699:     }
1.549     raeburn  4700:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   4701: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   4702:     foreach my $acctype ('allow','deny') {
                   4703:         $output .= '
                   4704: <td valign="top">
                   4705: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   4706:   <div class="LC_string_ipacc_inner">'."\n";
                   4707:         my $num = 0;
                   4708:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  4709:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  4710:             if ($num > 0) {
                   4711:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   4712:             }
                   4713:             $output .= '</div>'."\n";
                   4714:             $num ++;
                   4715:         }
                   4716:         $output .= '
1.552     raeburn  4717:   </div>'.$addmore.'
1.549     raeburn  4718: </div>
                   4719: </td>';
                   4720:    }
                   4721:    $output .= '
                   4722: </tr>
                   4723: </table>'."\n";
                   4724:     return $output;
                   4725: }
                   4726: 
1.588   ! raeburn  4727: sub string_deeplink_selector {
        !          4728:     my ($thiskey, $showval, $readonly) = @_;
        !          4729:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,%posslti);
        !          4730:     @components = ('listing','scope','urls');
        !          4731:     %titles = &Apache::lonlocal::texthash (
        !          4732:                   listing => 'In Contents and/or Gradebook',
        !          4733:                   scope   => 'Access scope for link',
        !          4734:                   urls    => 'Supported link types',
        !          4735:               );
        !          4736:     %options = (
        !          4737:                    listing => ['full','absent','grades','details','datestatus'],
        !          4738:                    scope   => ['res','map','rec'],
        !          4739:                    urls    => ['any','only','key','lti'],
        !          4740:                );
        !          4741:     %optiontext = &Apache::lonlocal::texthash (
        !          4742:                     full       => 'Listed (linked) in both',
        !          4743:                     absent     => 'Not listed',
        !          4744:                     grades     => 'Listed in grades only',
        !          4745:                     details    => 'Listed (unlinked) in both',
        !          4746:                     datestatus => 'Listed (unlinked) inc. status in both',
        !          4747:                     res        => 'resource only',
        !          4748:                     map        => 'enclosing map/folder',
        !          4749:                     rec        => 'recursive map/folder',
        !          4750:                     any        => 'regular + deep',
        !          4751:                     only       => 'deep only',
        !          4752:                     key        => 'deep with key',
        !          4753:                     lti        => 'deep with LTI launch',
        !          4754:                   );
        !          4755:     if ($showval =~ /,/) {
        !          4756:         @current = split(/,/,$showval);
        !          4757:         ($values{'listing'}) = ($current[0] =~ /^(full|absent|grades|details|datestatus)$/);
        !          4758:         ($values{'scope'}) = ($current[1] =~ /^(res|map|rec)$/);
        !          4759:         ($values{'urls'}) = ($current[2] =~ /^(any|only|key:\w+|lti:\d+)$/);
        !          4760:     } else {
        !          4761:         $defaults{'listing'} = 'full';
        !          4762:         $defaults{'scope'} = 'res';
        !          4763:         $defaults{'urls'} = 'any';
        !          4764:     }
        !          4765:     my $disabled;
        !          4766:     if ($readonly) {
        !          4767:         $disabled=' disabled="disabled"';
        !          4768:     }
        !          4769:     my %lti = 
        !          4770:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
        !          4771:                                         'provider');
        !          4772:     foreach my $item (keys(%lti)) {
        !          4773:         if (ref($lti{$item}) eq 'HASH') {
        !          4774:             unless ($lti{$item}{'requser'}) {
        !          4775:                 $posslti{$item} = $lti{$item}{'consumer'};
        !          4776:             }
        !          4777:         }
        !          4778:     }
        !          4779:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
        !          4780:     foreach my $item ('listing','scope','urls') {
        !          4781:         $output .= '<th>'.$titles{$item}.'</th>';
        !          4782:     }
        !          4783:     $output .= '</tr><tr>';
        !          4784:     foreach my $item (@components) {
        !          4785:         $output .= '<td>';
        !          4786:         if ($item eq 'urls') {
        !          4787:             my $selected = $values{$item};
        !          4788:             foreach my $option (@{$options{$item}}) {
        !          4789:                 if ($option eq 'lti') {
        !          4790:                     next unless (keys(%posslti));
        !          4791:                 }
        !          4792:                 my $checked;
        !          4793:                 if ($selected =~ /^\Q$option\E/) {
        !          4794:                     $checked = ' checked="checked"';
        !          4795:                 }
        !          4796:                 my $onclick;
        !          4797:                 unless ($readonly) {
        !          4798:                     my $esc_key = &js_escape($thiskey);
        !          4799:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
        !          4800:                 }
        !          4801:                 $output .= '<span class="LC_nobreak"><label>'.
        !          4802:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
        !          4803:                            $optiontext{$option}.'</label>';
        !          4804:                 if ($option eq 'key') {
        !          4805:                     my $visibility="hidden";
        !          4806:                     my $currkey;
        !          4807:                     if ($checked) {
        !          4808:                         $visibility = "text";
        !          4809:                         $currkey = (split(/\:/,$values{$item}))[1];
        !          4810:                     }
        !          4811:                     $output .= '&nbsp;'.
        !          4812:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="6"'.$disabled.' />';
        !          4813:                 } elsif ($option eq 'lti') {
        !          4814:                     my $display="none";
        !          4815:                     my ($currlti,$blankcheck);
        !          4816:                     if ($checked) {
        !          4817:                         $display = 'inline-block';
        !          4818:                         $currlti = (split(/\:/,$values{$item}))[1];
        !          4819:                     } else {
        !          4820:                         $blankcheck = ' selected="selected"';
        !          4821:                     }
        !          4822:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
        !          4823:                                ' style="display: '.$display.'">&nbsp;<select name="'.
        !          4824:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>'.
        !          4825:                                '<option value=""'.$blankcheck.'>'.&mt('Select Provider').'</option>'."\n";
        !          4826:                     foreach my $lti (sort { $a <=> $b } keys(%posslti)) {
        !          4827:                         my $selected;
        !          4828:                         if ($lti == $currlti) {
        !          4829:                             $selected = ' selected="selected"';
        !          4830:                         }
        !          4831:                         $output .= '<option value="'.$lti.'"'.$selected.'>'.$posslti{$lti}.'</option>';
        !          4832:                     }
        !          4833:                     $output .= '</select></div>';
        !          4834:                 }
        !          4835:                 $output .= '</span> ';
        !          4836:             }
        !          4837:         } else {
        !          4838:             my $selected = $values{$item};
        !          4839:             my $defsel;
        !          4840:             if ($selected eq '') {
        !          4841:                 $defsel = ' selected="selected"';
        !          4842:             }
        !          4843:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
        !          4844:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
        !          4845:             foreach my $option (@{$options{$item}}) {
        !          4846:                 $output .= '<option value="'.$option.'"';
        !          4847:                 if ($option eq $selected) {
        !          4848:                     $output .= ' selected="selected"';
        !          4849:                 }
        !          4850:                 $output .= '>'.$optiontext{$option}.'</option>';
        !          4851:             }
        !          4852:             $output .= '</select>';
        !          4853:         }
        !          4854:         $output .= '</td>';
        !          4855:     }
        !          4856:     $output .= '</tr></table>'."\n";
        !          4857:     return $output;
        !          4858: }
        !          4859: 
1.560     damieng  4860: 
                   4861: { # block using some constants related to parameter types (overview mode)
                   4862: 
1.446     bisitz   4863: my %strings =
1.383     albertel 4864:     (
                   4865:      'string_yesno'
                   4866:              => [[ 'yes', 'Yes' ],
1.560     damieng  4867:                  [ 'no', 'No' ]],
1.383     albertel 4868:      'string_problemstatus'
                   4869:              => [[ 'yes', 'Yes' ],
1.473     amueller 4870:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   4871:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   4872:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  4873:      'string_questiontype'
                   4874:              => [[ 'problem', 'Standard Problem'],
                   4875:                  [ 'survey', 'Survey'],
                   4876:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   4877:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  4878:                  [ 'anonsurvey', 'Anonymous Survey'],
                   4879:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   4880:                  [ 'practice', 'Practice'],
                   4881:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  4882:      'string_lenient'
                   4883:              => [['yes', 'Yes' ],
                   4884:                  [ 'no', 'No' ],
1.549     raeburn  4885:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   4886:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  4887:      'string_discussvote'
                   4888:              => [['yes','Yes'],
                   4889:                  ['notended','Yes, unless discussion ended'],
                   4890:                  ['no','No']],
1.549     raeburn  4891:      'string_ip'
                   4892:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  4893:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   4894:      'string_deeplink'
1.588   ! raeburn  4895:              => [['on','Set choices for link protection, resource listing, and access scope']],
1.587     raeburn  4896:     );
                   4897:    
1.383     albertel 4898: 
1.549     raeburn  4899: my %stringmatches = (
                   4900:          'string_lenient'
                   4901:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   4902:          'string_ip'
                   4903:               => [['_allowfrom_','[^\!]+'],
                   4904:                   ['_denyfrom_','\!']],
1.588   ! raeburn  4905:          'string_deeplink'
        !          4906:               => [['on','^(full|absent|grades|details|datestatus)\,(res|map|rec)\,(any|only|key\:\w+|lti\:\d+)$']],
1.549     raeburn  4907:     );
                   4908: 
                   4909: my %stringtypes = (
                   4910:                     type         => 'string_questiontype',
                   4911:                     lenient      => 'string_lenient',
                   4912:                     retrypartial => 'string_yesno',
                   4913:                     discussvote  => 'string_discussvote',
                   4914:                     examcode     => 'string_examcode',
                   4915:                     acc          => 'string_ip',
1.587     raeburn  4916:                     deeplink     => 'string_deeplink',
1.549     raeburn  4917:                   );
                   4918: 
1.563     damieng  4919: # Returns the possible values and titles for a given string type, or undef if there are none.
                   4920: # Used by courseprefs.
                   4921: #
                   4922: # @param {string} $string_type - a parameter type for strings
                   4923: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  4924: sub standard_string_options {
                   4925:     my ($string_type) = @_;
                   4926:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   4927:         return $strings{$string_type};
                   4928:     }
                   4929:     return;
                   4930: }
1.383     albertel 4931: 
1.563     damieng  4932: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   4933: #
                   4934: # @param {string} $string_type - a parameter type for strings
                   4935: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  4936: sub standard_string_matches {
                   4937:     my ($string_type) = @_;
                   4938:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   4939:         return $stringmatches{$string_type};
                   4940:     }
                   4941:     return;
                   4942: }
                   4943: 
1.563     damieng  4944: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   4945: #
                   4946: # @param {string} $name - parameter name
                   4947: # @returns {string}
1.549     raeburn  4948: sub get_stringtype {
                   4949:     my ($name) = @_;
                   4950:     if (exists($stringtypes{$name})) {
                   4951:         return $stringtypes{$name};
                   4952:     }
                   4953:     return;
                   4954: }
                   4955: 
1.563     damieng  4956: # Returns HTML to edit a string parameter.
                   4957: #
                   4958: # @param {string} $thistype - parameter type
                   4959: # @param {string} $thiskey - parameter key
                   4960: # @param {string} $showval - parameter current value
                   4961: # @param {string} $name - parameter name
                   4962: # @param {boolean} $readonly - true if the values should not be made editable
                   4963: # @returns {string}
1.383     albertel 4964: sub string_selector {
1.552     raeburn  4965:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   4966: 
1.383     albertel 4967:     if (!exists($strings{$thistype})) {
1.552     raeburn  4968:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 4969:     }
                   4970: 
1.504     raeburn  4971:     my %skiptype;
1.514     raeburn  4972:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  4973:             ($thistype eq 'string_lenient') ||
                   4974:             ($thistype eq 'string_discussvote') ||
                   4975:             ($thistype eq 'string_ip') ||
1.588   ! raeburn  4976:             ($thistype eq 'string_deeplink') ||
1.560     damieng  4977:             ($name eq 'retrypartial')) {
1.504     raeburn  4978:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   4979:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4980:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  4981:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  4982:             my $parmmatch;
                   4983:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   4984:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   4985:                     if (ref($item) eq 'ARRAY') {
                   4986:                         if ($parmval eq $item->[0]) {
                   4987:                             $parmmatch = $parmval;
                   4988:                             $parmval = '';
                   4989:                             last;
                   4990:                         }
                   4991:                     }
                   4992:                 }
                   4993:             }
                   4994:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  4995:             if ($needsrelease) {
                   4996:                 unless ($got_chostname) {
1.514     raeburn  4997:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  4998:                     $got_chostname = 1;
                   4999:                 }
1.557     raeburn  5000:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5001:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5002:                 if ($needsnewer) {
1.549     raeburn  5003:                     if ($parmmatch ne '') {
                   5004:                         $skiptype{$parmmatch} = 1;
                   5005:                     } elsif ($parmval ne '') {
                   5006:                         $skiptype{$parmval} = 1;
                   5007:                     }
1.504     raeburn  5008:                 }
                   5009:             }
                   5010:         }
                   5011:     }
1.549     raeburn  5012: 
                   5013:     if ($thistype eq 'string_ip') {
1.552     raeburn  5014:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588   ! raeburn  5015:     } elsif ($thistype eq 'string_deeplink') {
        !          5016:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5017:     }
1.504     raeburn  5018: 
1.552     raeburn  5019:     my ($result,$disabled);
                   5020: 
                   5021:     if ($readonly) {
                   5022:         $disabled = ' disabled="disabled"';
                   5023:     }
1.504     raeburn  5024:     my $numinrow = 3;
                   5025:     if ($thistype eq 'string_problemstatus') {
                   5026:         $numinrow = 2;
                   5027:     } elsif ($thistype eq 'string_questiontype') {
                   5028:         if (keys(%skiptype) > 0) {
                   5029:              $numinrow = 4;
                   5030:         }
                   5031:     }
                   5032:     my $rem;
                   5033:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5034:         my $i=0;
                   5035:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5036:             next unless (ref($possibilities) eq 'ARRAY');
                   5037:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5038:             next if ($skiptype{$name});
1.504     raeburn  5039:             $rem = $i%($numinrow);
                   5040:             if ($rem == 0) {
                   5041:                 if ($i > 0) {
                   5042:                     $result .= '</tr>';
                   5043:                 }
                   5044:                 $result .= '<tr>';
                   5045:             }
1.549     raeburn  5046:             my $colspan;
                   5047:             if ($i == @{ $strings{$thistype} }-1) {
                   5048:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5049:                 if ($rem) {
                   5050:                     my $colsleft = $numinrow - $rem;
                   5051:                     if ($colsleft) {
                   5052:                         $colspan = $colsleft+1;
                   5053:                         $colspan = ' colspan="'.$colspan.'"';
                   5054:                     }
                   5055:                 }
                   5056:             }
                   5057:             my ($add,$onchange,$css_class);
                   5058:             if ($thistype eq 'string_lenient') {
                   5059:                 if ($name eq 'weighted') {
                   5060:                     my $display;
                   5061:                     my %relatives = &Apache::lonlocal::texthash(
                   5062:                                         corrchkd     => 'Correct (checked)',
                   5063:                                         corrunchkd   => 'Correct (unchecked)',
                   5064:                                         incorrchkd   => 'Incorrect (checked)',
                   5065:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5066:                     );
                   5067:                     my %textval = (
                   5068:                                     corrchkd     => '1.0',
                   5069:                                     corrunchkd   => '1.0',
                   5070:                                     incorrchkd   => '0.0',
                   5071:                                     incorrunchkd => '0.0',
                   5072:                     );
                   5073:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5074:                         $textval{'corrchkd'} = $1;
                   5075:                         $textval{'corrunchkd'} = $2;
                   5076:                         $textval{'incorrchkd'} = $3;
                   5077:                         $textval{'incorrunchkd'} = $4;
                   5078:                         $display = 'inline';
                   5079:                         $showval = $name;
                   5080:                     } else {
                   5081:                         $display = 'none';
                   5082:                     }
                   5083:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5084:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5085:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5086:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5087:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5088:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5089:                                 '</td></tr>';
                   5090:                     }
                   5091:                     $add .= '</table></div>'."\n";
                   5092:                 }
                   5093:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5094:                 $css_class = ' class="LC_lenient_radio"';
                   5095:             }
                   5096:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5097:                        '<span class="LC_nobreak"><label>'.
                   5098:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5099:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5100:             if ($showval eq $name) {
                   5101:                 $result .= ' checked="checked"';
                   5102:             }
1.549     raeburn  5103:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5104:             $i++;
                   5105:         }
                   5106:         $result .= '</tr>';
1.473     amueller 5107:     }
1.504     raeburn  5108:     if ($result) {
                   5109:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5110:     }
                   5111:     return $result;
                   5112: }
                   5113: 
1.554     raeburn  5114: my %intervals =
                   5115:     (
                   5116:      'date_interval'
                   5117:              => [[ 'done', 'Yes' ],
1.558     raeburn  5118:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5119:                  [ '', 'No' ]],
                   5120:     );
                   5121: 
                   5122: my %intervalmatches = (
                   5123:          'date_interval'
1.559     raeburn  5124:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5125:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5126:     );
                   5127: 
                   5128: my %intervaltypes = (
                   5129:                       interval => 'date_interval',
                   5130:     );
                   5131: 
1.563     damieng  5132: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5133: #
                   5134: # @param {string} $interval_type - a parameter type for intervals
                   5135: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5136: sub standard_interval_matches {
                   5137:     my ($interval_type) = @_;
                   5138:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5139:         return $intervalmatches{$interval_type};
                   5140:     }
                   5141:     return;
                   5142: }
                   5143: 
1.563     damieng  5144: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5145: #
                   5146: # @param {string} $name - parameter name
                   5147: # @returns {string}
1.554     raeburn  5148: sub get_intervaltype {
                   5149:     my ($name) = @_;
                   5150:     if (exists($intervaltypes{$name})) {
                   5151:         return $intervaltypes{$name};
                   5152:     }
                   5153:     return;
                   5154: }
                   5155: 
1.563     damieng  5156: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5157: # Used by courseprefs.
                   5158: #
                   5159: # @param {string} $interval_type - a parameter type for intervals
                   5160: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5161: sub standard_interval_options {
                   5162:     my ($interval_type) = @_;
                   5163:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5164:         return $intervals{$interval_type};
                   5165:     }
                   5166:     return;
                   5167: }
                   5168: 
1.563     damieng  5169: # Returns HTML to edit a date interval parameter.
                   5170: #
                   5171: # @param {string} $thiskey - parameter key
                   5172: # @param {string} $name - parameter name
                   5173: # @param {string} $showval - parameter current value
                   5174: # @param {boolean} $readonly - true if the values should not be made editable
                   5175: # @returns {string}
1.554     raeburn  5176: sub date_interval_selector {
                   5177:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5178:     my ($result,%skipval);
                   5179:     if ($name eq 'interval') {
                   5180:         my $intervaltype = &get_intervaltype($name);
                   5181:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5182:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5183:             next unless (ref($possibilities) eq 'ARRAY');
                   5184:             my ($parmval, $description) = @{ $possibilities };
                   5185:             my $parmmatch;
                   5186:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5187:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5188:                     if (ref($item) eq 'ARRAY') {
                   5189:                         if ($parmval eq $item->[0]) {
                   5190:                             $parmmatch = $parmval;
                   5191:                             $parmval = '';
                   5192:                             last;
                   5193:                         }
                   5194:                     }
                   5195:                 }
                   5196:             }
                   5197:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5198:             if ($needsrelease) {
                   5199:                 unless ($got_chostname) {
                   5200:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5201:                     $got_chostname = 1;
                   5202:                 }
1.557     raeburn  5203:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5204:                                                        $needsrelease,$cmajor,$cminor);
                   5205:                 if ($needsnewer) {
                   5206:                     if ($parmmatch ne '') {
                   5207:                         $skipval{$parmmatch} = 1;
                   5208:                     } elsif ($parmval ne '') {
                   5209:                         $skipval{$parmval} = 1;
                   5210:                     }
                   5211:                 }
                   5212:             }
                   5213:         }
                   5214:     }
                   5215: 
                   5216:     my $currval = $showval;
                   5217:     foreach my $which (['days', 86400, 31],
                   5218:                ['hours', 3600, 23],
                   5219:                ['minutes', 60, 59],
                   5220:                ['seconds',  1, 59]) {
1.560     damieng  5221:         my ($name, $factor, $max) = @{ $which };
                   5222:         my $amount = int($showval/$factor);
                   5223:         $showval  %= $factor;
                   5224:         my %select = ((map {$_ => $_} (0..$max)),
                   5225:                 'select_form_order' => [0..$max]);
                   5226:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5227:                             \%select,'',$readonly);
                   5228:         $result .= ' '.&mt($name);
1.554     raeburn  5229:     }
                   5230:     if ($name eq 'interval') {
                   5231:         unless ($skipval{'done'}) {
                   5232:             my $checkedon = '';
1.558     raeburn  5233:             my $checkedproc = '';
                   5234:             my $currproctorkey = '';
                   5235:             my $currprocdisplay = 'hidden';
1.559     raeburn  5236:             my $currdonetext = &mt('Done');
1.554     raeburn  5237:             my $checkedoff = ' checked="checked"';
1.559     raeburn  5238:             if ($currval =~ /^(?:\d+)_done$/) {
                   5239:                 $checkedon = ' checked="checked"';
                   5240:                 $checkedoff = '';
                   5241:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5242:                 $currdonetext = $1;
1.554     raeburn  5243:                 $checkedon = ' checked="checked"';
                   5244:                 $checkedoff = '';
1.558     raeburn  5245:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5246:                 $currproctorkey = $1;
                   5247:                 $checkedproc = ' checked="checked"';
                   5248:                 $checkedoff = '';
                   5249:                 $currprocdisplay = 'text';
1.559     raeburn  5250:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5251:                 $currdonetext = $1;
                   5252:                 $currproctorkey = $2;
                   5253:                 $checkedproc = ' checked="checked"';
                   5254:                 $checkedoff = '';
                   5255:                 $currprocdisplay = 'text';
1.554     raeburn  5256:             }
1.558     raeburn  5257:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5258:             my $disabled;
                   5259:             if ($readonly) {
                   5260:                 $disabled = ' disabled="disabled"';
                   5261:             }
1.558     raeburn  5262:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5263:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5264:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5265:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5266:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5267:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5268:                        &mt('Yes, with proctor key').'</label>'.
                   5269:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5270:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5271:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  5272:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5273:         }
                   5274:     }
                   5275:     unless ($readonly) {
                   5276:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5277:     }
                   5278:     return $result;
                   5279: }
                   5280: 
1.563     damieng  5281: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5282: #
                   5283: # @param {string} $name - parameter name
                   5284: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5285: # @param {string} $value - parameter value
                   5286: # @param {string} $chostname - course server name
                   5287: # @param {integer} $cmajor - major version number
                   5288: # @param {integer} $cminor - minor version number
                   5289: # @param {string} $needsrelease - release version needed (major.minor)
                   5290: # @returns {string}
1.549     raeburn  5291: sub oldversion_warning {
1.557     raeburn  5292:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5293:     my $standard_name = &standard_parameter_names($name);
                   5294:     if ($namematch) {
                   5295:         my $level = &standard_parameter_levels($namematch);
                   5296:         my $msg = '';
                   5297:         if ($level) {
                   5298:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5299:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5300:         } else {
                   5301:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5302:                       $standard_name,'<b>','</b>');
                   5303:         }
                   5304:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5305:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5306:                    $cmajor.'.'.$cminor,$chostname,
                   5307:                    $needsrelease).
                   5308:                    '</p>';
                   5309:     }
1.549     raeburn  5310:     my $desc;
                   5311:     my $stringtype = &get_stringtype($name);
                   5312:     if ($stringtype ne '') {
                   5313:         if ($name eq 'examcode') {
                   5314:             $desc = $value;
                   5315:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5316:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5317:                 next unless (ref($possibilities) eq 'ARRAY');
                   5318:                 my ($parmval, $description) = @{ $possibilities };
                   5319:                 my $parmmatch;
                   5320:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5321:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5322:                         if (ref($item) eq 'ARRAY') {
                   5323:                             my ($regexpname,$pattern) = @{$item};
                   5324:                             if ($parmval eq $regexpname) {
                   5325:                                 if ($value =~ /$pattern/) {
                   5326:                                     $desc = $description; 
                   5327:                                     $parmmatch = 1;
                   5328:                                     last;
                   5329:                                 }
                   5330:                             }
                   5331:                         }
                   5332:                     }
                   5333:                     last if ($parmmatch);
                   5334:                 } elsif ($parmval eq $value) {
                   5335:                     $desc = $description;
                   5336:                     last;
                   5337:                 }
                   5338:             }
                   5339:         }
                   5340:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5341:         my $now = time;
                   5342:         if ($value =~ /^\d+$/) {
                   5343:             if ($name eq 'printstartdate') {
                   5344:                 if ($value > $now) {
                   5345:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5346:                 }
                   5347:             } elsif ($name eq 'printenddate') {
                   5348:                 if ($value < $now) {
                   5349:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5350:                 }
                   5351:             }
                   5352:         }
                   5353:     }
                   5354:     return '<p class="LC_warning">'.
1.557     raeburn  5355:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5356:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5357:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5358:        $cmajor.'.'.$cminor,$chostname,
                   5359:        $needsrelease).
                   5360:        '</p>';
1.549     raeburn  5361: }
                   5362: 
1.560     damieng  5363: } # end of block using some constants related to parameter types
                   5364: 
1.549     raeburn  5365: 
1.563     damieng  5366: 
                   5367: # Shifts all start and end dates in the current course by $shift.
1.389     www      5368: #
1.563     damieng  5369: # @param {integer} $shift - time to shift, in seconds
                   5370: # @returns {string} - error name or 'ok'
1.389     www      5371: sub dateshift {
                   5372:     my ($shift)=@_;
                   5373:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5374:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5375:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5376: # ugly retro fix for broken version of types
1.548     raeburn  5377:     foreach my $key (keys(%data)) {
1.389     www      5378:         if ($key=~/\wtype$/) {
                   5379:             my $newkey=$key;
                   5380:             $newkey=~s/type$/\.type/;
                   5381:             $data{$newkey}=$data{$key};
                   5382:             delete $data{$key};
                   5383:         }
                   5384:     }
1.391     www      5385:     my %storecontent=();
1.389     www      5386: # go through all parameters and look for dates
1.548     raeburn  5387:     foreach my $key (keys(%data)) {
1.389     www      5388:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
                   5389:           my $newdate=$data{$key}+$shift;
1.391     www      5390:           $storecontent{$key}=$newdate;
1.389     www      5391:        }
                   5392:     }
1.391     www      5393:     my $reply=&Apache::lonnet::cput
                   5394:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5395:     if ($reply eq 'ok') {
                   5396:        &log_parmset(\%storecontent);
                   5397:     }
                   5398:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5399:     return $reply;
1.389     www      5400: }
                   5401: 
1.563     damieng  5402: # Overview mode UI to edit course parameters.
                   5403: #
                   5404: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5405: sub newoverview {
1.568     raeburn  5406:     my ($r,$parm_permission) = @_;
1.280     albertel 5407: 
1.208     www      5408:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5409:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5410:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5411:     my $readonly = 1;
                   5412:     if ($parm_permission->{'edit'}) {
                   5413:         undef($readonly);
                   5414:     }
1.414     droeschl 5415:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5416:         text=>"Overview Mode"});
1.523     raeburn  5417: 
                   5418:     my %loaditems = (
1.549     raeburn  5419:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5420:                     );
                   5421:     my $js = '
                   5422: <script type="text/javascript">
                   5423: // <![CDATA[
                   5424: '.
                   5425:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5426:             &showhide_js()."\n".
1.549     raeburn  5427:             &toggleparmtextbox_js()."\n".
                   5428:             &validateparms_js()."\n".
                   5429:             &ipacc_boxes_js()."\n".
1.558     raeburn  5430:             &done_proctor_js()."\n".
1.588   ! raeburn  5431:             &deeplink_js()."\n".
1.523     raeburn  5432: '// ]]>
                   5433: </script>
                   5434: ';
1.549     raeburn  5435: 
1.523     raeburn  5436:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5437:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5438:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5439:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5440:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5441:     $r->print(<<ENDOVER);
1.549     raeburn  5442: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5443: ENDOVER
1.211     www      5444:     my @ids=();
                   5445:     my %typep=();
                   5446:     my %keyp=();
                   5447:     my %allparms=();
                   5448:     my %allparts=();
                   5449:     my %allmaps=();
                   5450:     my %mapp=();
                   5451:     my %symbp=();
                   5452:     my %maptitles=();
                   5453:     my %uris=();
                   5454:     my %keyorder=&standardkeyorder();
                   5455:     my %defkeytype=();
                   5456: 
                   5457:     my %alllevs=();
                   5458:     $alllevs{'Resource Level'}='full';
1.215     www      5459:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5460:     $alllevs{'Course Level'}='general';
                   5461: 
                   5462:     my $csec=$env{'form.csec'};
1.269     raeburn  5463:     my $cgroup=$env{'form.cgroup'};
1.211     www      5464: 
                   5465:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5466:     my $pschp=$env{'form.pschp'};
1.506     www      5467: 
1.211     www      5468:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5469:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5470: 
1.446     bisitz   5471:     my @selected_sections =
1.473     amueller 5472:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      5473:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 5474:     foreach my $sec (@selected_sections) {
                   5475:         if ($sec eq 'all') {
1.211     www      5476:             @selected_sections = ('all');
                   5477:         }
                   5478:     }
1.552     raeburn  5479:     if ($env{'request.course.sec'} ne '') {
                   5480:         @selected_sections = ($env{'request.course.sec'});
                   5481:     }
1.269     raeburn  5482:     my @selected_groups =
                   5483:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      5484: 
                   5485:     my $pssymb='';
                   5486:     my $parmlev='';
1.446     bisitz   5487: 
1.211     www      5488:     unless ($env{'form.parmlev'}) {
                   5489:         $parmlev = 'map';
                   5490:     } else {
                   5491:         $parmlev = $env{'form.parmlev'};
                   5492:     }
                   5493: 
1.446     bisitz   5494:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5495:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   5496:                 \%keyorder,\%defkeytype);
1.211     www      5497: 
1.374     albertel 5498:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 5499:         @psprt = keys(%allparts);
1.374     albertel 5500:     }
1.211     www      5501: # Menu to select levels, etc
                   5502: 
1.456     bisitz   5503:     $r->print('<div class="LC_Box">');
1.445     neumanie 5504:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   5505:     $r->print('<div>');
1.523     raeburn  5506:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      5507:     &levelmenu($r,\%alllevs,$parmlev);
                   5508:     if ($parmlev ne 'general') {
1.447     bisitz   5509:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 5510:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      5511:     }
1.447     bisitz   5512:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5513:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5514:     $r->print('</div></div>');
1.446     bisitz   5515: 
1.456     bisitz   5516:     $r->print('<div class="LC_Box">');
1.452     bisitz   5517:     $r->print('<div>');
1.581     raeburn  5518:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 5519:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   5520:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  5521:     my $sectionselector = &sectionmenu(\@selected_sections);
                   5522:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 5523:     $r->print('<table>'.
1.553     raeburn  5524:               '<tr><th>'.&mt('Parts').'</th>');
                   5525:     if ($sectionselector) {
                   5526:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   5527:     }
                   5528:     if ($groupselector) {
                   5529:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   5530:     }
                   5531:     $r->print('</tr><tr><td>');
1.211     www      5532:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  5533:     $r->print('</td>');
                   5534:     if ($sectionselector) { 
                   5535:         $r->print('<td>'.$sectionselector.'</td>');
                   5536:     }
                   5537:     if ($groupselector) {
                   5538:         $r->print('<td>'.$groupselector.'</td>');
                   5539:     }
                   5540:     $r->print('</tr></table>');
1.447     bisitz   5541:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5542:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5543:     $r->print('</div></div>');
                   5544: 
1.456     bisitz   5545:     $r->print('<div class="LC_Box">');
1.452     bisitz   5546:     $r->print('<div>');
1.214     www      5547:     my $sortorder=$env{'form.sortorder'};
                   5548:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5549:     &sortmenu($r,$sortorder);
1.445     neumanie 5550:     $r->print('</div></div>');
1.446     bisitz   5551: 
1.214     www      5552:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   5553: 
1.211     www      5554: # Build the list data hash from the specified parms
                   5555: 
                   5556:     my $listdata;
                   5557:     %{$listdata}=();
                   5558: 
                   5559:     foreach my $cat (@pscat) {
1.269     raeburn  5560:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   5561:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      5562:     }
                   5563: 
1.212     www      5564:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      5565: 
1.481     amueller 5566:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      5567: 
                   5568: # Read modified data
                   5569: 
1.481     amueller 5570:         my $resourcedata=&readdata($crs,$dom);
1.211     www      5571: 
                   5572: # List data
                   5573: 
1.568     raeburn  5574:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   5575:     }
                   5576:     $r->print(&tableend());
                   5577:     unless ($readonly) {
                   5578:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      5579:     }
1.568     raeburn  5580:     $r->print('</form>');
1.507     www      5581:     &endSettingsScreen($r);
                   5582:     $r->print(&Apache::loncommon::end_page());
1.208     www      5583: }
                   5584: 
1.563     damieng  5585: # Fills $listdata with parameter information.
                   5586: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   5587: # The non-type value is always 1.
                   5588: #
                   5589: # @param {string} $cat - parameter name
1.566     damieng  5590: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  5591: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   5592: # @param {hash reference} $listdata - the parameter data that will be modified
                   5593: # @param {array reference} $psprt - selected parts
                   5594: # @param {array reference} $selections - selected sections
                   5595: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  5596: # @param {hash reference} $allmaps - hash map pc -> map src
                   5597: # @param {array reference} $ids - resource and map ids
                   5598: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  5599: sub secgroup_lister {
                   5600:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   5601:     foreach my $item (@{$selections}) {
                   5602:         foreach my $part (@{$psprt}) {
                   5603:             my $rootparmkey=$env{'request.course.id'};
                   5604:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   5605:                 $rootparmkey.='.['.$item.']';
                   5606:             }
                   5607:             if ($parmlev eq 'general') {
                   5608: # course-level parameter
                   5609:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   5610:                 $$listdata{$newparmkey}=1;
                   5611:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5612:             } elsif ($parmlev eq 'map') {
                   5613: # map-level parameter
1.548     raeburn  5614:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  5615:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   5616:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   5617:                     $$listdata{$newparmkey}=1;
                   5618:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5619:                 }
                   5620:             } else {
                   5621: # resource-level parameter
                   5622:                 foreach my $rid (@{$ids}) {
                   5623:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   5624:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   5625:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   5626:                     $$listdata{$newparmkey}=1;
                   5627:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5628:                 }
                   5629:             }
                   5630:         }
                   5631:     }
                   5632: }
                   5633: 
1.563     damieng  5634: # UI to edit parameter settings starting with a list of all existing parameters.
                   5635: # (called by setoverview action)
                   5636: #
                   5637: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5638: sub overview {
1.568     raeburn  5639:     my ($r,$parm_permission) = @_;
1.208     www      5640:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5641:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5642:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5643:     my $readonly = 1;
                   5644:     if ($parm_permission->{'edit'}) {
                   5645:         undef($readonly);
                   5646:     }
1.549     raeburn  5647:     my $js = '<script type="text/javascript">'."\n".
                   5648:              '// <![CDATA['."\n".
                   5649:              &toggleparmtextbox_js()."\n".
                   5650:              &validateparms_js()."\n".
                   5651:              &ipacc_boxes_js()."\n".
1.558     raeburn  5652:              &done_proctor_js()."\n".
1.588   ! raeburn  5653:              &deeplink_js()."\n".
1.549     raeburn  5654:              '// ]]>'."\n".
                   5655:              '</script>'."\n";
1.414     droeschl 5656:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5657:     text=>"Overview Mode"});
1.549     raeburn  5658:     my %loaditems = (
                   5659:                       'onload'   => "showHideLenient();",
                   5660:                     );
                   5661: 
                   5662:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 5663:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5664:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5665:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  5666:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      5667: 
1.208     www      5668: # Store modified
                   5669: 
1.568     raeburn  5670:     unless ($readonly) {
                   5671:         &storedata($r,$crs,$dom);
                   5672:     }
1.208     www      5673: 
                   5674: # Read modified data
                   5675: 
1.552     raeburn  5676:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      5677: 
1.214     www      5678: 
                   5679:     my $sortorder=$env{'form.sortorder'};
                   5680:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5681:     &sortmenu($r,$sortorder);
                   5682: 
1.568     raeburn  5683:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   5684: 
                   5685:     if ($readonly) {
                   5686:         $r->print('<p>'.$submitbutton.'</p>');
                   5687:     }
                   5688: 
1.208     www      5689: # List data
                   5690: 
1.568     raeburn  5691:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   5692:     $r->print(&tableend().'<p>');
                   5693:     if ($foundkeys) {
                   5694:         unless ($readonly) {
                   5695:             $r->print('<p>'.$submitbutton.'</p>');
                   5696:         }
                   5697:     } else {
                   5698:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   5699:     }
                   5700:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      5701: }
1.121     www      5702: 
1.560     damieng  5703: # Unused sub.
1.563     damieng  5704: #
                   5705: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 5706: sub clean_parameters {
                   5707:     my ($r) = @_;
                   5708:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5709:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5710: 
1.414     droeschl 5711:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 5712:         text=>"Clean Parameters"});
1.333     albertel 5713:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   5714:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   5715:     $r->print(<<ENDOVER);
                   5716: $start_page
                   5717: $breadcrumbs
                   5718: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   5719: ENDOVER
                   5720: # Store modified
                   5721: 
                   5722:     &storedata($r,$crs,$dom);
                   5723: 
                   5724: # Read modified data
                   5725: 
                   5726:     my $resourcedata=&readdata($crs,$dom);
                   5727: 
                   5728: # List data
                   5729: 
                   5730:     $r->print('<h3>'.
1.473     amueller 5731:           &mt('These parameters refer to resources that do not exist.').
                   5732:           '</h3>'.
                   5733:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   5734:           '<br />');
1.333     albertel 5735:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 5736:           '<tr>'.
                   5737:           '<th>'.&mt('Delete').'</th>'.
                   5738:           '<th>'.&mt('Parameter').'</th>'.
                   5739:           '</tr>');
1.333     albertel 5740:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  5741:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   5742:             && $thiskey=~/\.type$/);
                   5743:         my %data = &parse_key($thiskey);
                   5744:         if (1) { #exists($data{'realm_exists'})
                   5745:             #&& !$data{'realm_exists'}) {
                   5746:             $r->print(&Apache::loncommon::start_data_table_row().
                   5747:                 '<tr>'.
                   5748:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   5749: 
                   5750:             $r->print('<td>');
                   5751:             my $display_value = $resourcedata->{$thiskey};
                   5752:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   5753:             $display_value =
                   5754:                 &Apache::lonlocal::locallocaltime($display_value);
                   5755:             }
1.470     raeburn  5756:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   5757:             $parmitem = &mt($parmitem);
1.560     damieng  5758:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   5759:                 $parmitem,$resourcedata->{$thiskey}));
                   5760:             $r->print('<br />');
                   5761:             if ($data{'scope_type'} eq 'all') {
                   5762:                 $r->print(&mt('All users'));
                   5763:             } elsif ($data{'scope_type'} eq 'user') {
                   5764:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  5765:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   5766:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  5767:             }
                   5768:             $r->print('<br />');
                   5769:             if ($data{'realm_type'} eq 'all') {
                   5770:                 $r->print(&mt('All Resources'));
                   5771:             } elsif ($data{'realm_type'} eq 'folder') {
                   5772:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   5773:             } elsif ($data{'realm_type'} eq 'symb') {
                   5774:             my ($map,$resid,$url) =
                   5775:                 &Apache::lonnet::decode_symb($data{'realm'});
                   5776:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   5777:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   5778:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   5779:             }
                   5780:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   5781:             $r->print('</td></tr>');
                   5782: 
1.473     amueller 5783:         }
1.333     albertel 5784:     }
                   5785:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 5786:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      5787:           '</p></form>');
                   5788:     &endSettingsScreen($r);
                   5789:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 5790: }
                   5791: 
1.563     damieng  5792: # UI to shift all dates (called by dateshift1 action).
                   5793: # Used by overview mode.
                   5794: #
                   5795: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5796: sub date_shift_one {
                   5797:     my ($r) = @_;
                   5798:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5799:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5800:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.390     www      5801: 
1.414     droeschl 5802:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5803:         text=>"Shifting Dates"});
1.390     www      5804:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5805:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5806:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5807:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   5808:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      5809:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   5810:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   5811:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   5812:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      5813:                                                         'timeshifted',
                   5814:                                                         $env{'form.timebase'},,
                   5815:                                                         '').
                   5816:               '</td></tr></table>'.
                   5817:               '<input type="hidden" name="action" value="dateshift2" />'.
                   5818:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
                   5819:               '<input type="submit" value="'.&mt('Shift all dates accordingly').'" /></form>');
1.507     www      5820:     &endSettingsScreen($r);
1.390     www      5821:     $r->print(&Apache::loncommon::end_page());
                   5822: }
                   5823: 
1.563     damieng  5824: # UI to shift all dates (second form).
                   5825: #
                   5826: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5827: sub date_shift_two {
                   5828:     my ($r) = @_;
                   5829:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5830:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5831:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 5832:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5833:         text=>"Shifting Dates"});
1.390     www      5834:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5835:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5836:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5837:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      5838:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.543     bisitz   5839:     $r->print('<h2>'.&mt('Shift Dates').'</h2>'.
                   5840:               '<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
1.390     www      5841:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
1.543     bisitz   5842:               &Apache::lonlocal::locallocaltime($timeshifted)).'</p>');
1.390     www      5843:     my $delta=$timeshifted-$env{'form.timebase'};
                   5844:     &dateshift($delta);
1.543     bisitz   5845:     $r->print(
                   5846:         &Apache::lonhtmlcommon::confirm_success(&mt('Done')).
                   5847:         '<br /><br />'.
                   5848:         &Apache::lonhtmlcommon::actionbox(
                   5849:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      5850:     &endSettingsScreen($r);
1.390     www      5851:     $r->print(&Apache::loncommon::end_page());
                   5852: }
                   5853: 
1.563     damieng  5854: # Returns the different components of a resourcedata key.
                   5855: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   5856: #       realm_exists, parameter_part, parameter_name.
                   5857: # Was used by clean_parameters (which is unused).
                   5858: #
                   5859: # @param {string} $key - the parameter key
                   5860: # @returns {hash}
1.333     albertel 5861: sub parse_key {
                   5862:     my ($key) = @_;
                   5863:     my %data;
                   5864:     my ($middle,$part,$name)=
1.572     damieng  5865:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 5866:     $data{'scope_type'} = 'all';
                   5867:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5868:         $data{'scope'} = $1;
                   5869:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   5870:             $data{'scope_type'} = 'user';
                   5871:             $data{'scope'} = [$1,$2];
                   5872:         } else {
1.581     raeburn  5873:             $data{'scope_type'} = 'secgroup';
1.560     damieng  5874:         }
                   5875:         $middle=~s/^\[(.*)\]//;
1.333     albertel 5876:     }
                   5877:     $middle=~s/\.+$//;
                   5878:     $middle=~s/^\.+//;
                   5879:     $data{'realm_type'}='all';
                   5880:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  5881:         $data{'realm'} = $1;
                   5882:         $data{'realm_type'} = 'folder';
                   5883:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5884:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 5885:     } elsif ($middle) {
1.560     damieng  5886:         $data{'realm'} = $middle;
                   5887:         $data{'realm_type'} = 'symb';
                   5888:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5889:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   5890:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 5891:     }
1.446     bisitz   5892: 
1.333     albertel 5893:     $data{'parameter_part'} = $part;
                   5894:     $data{'parameter_name'} = $name;
                   5895: 
                   5896:     return %data;
                   5897: }
                   5898: 
1.239     raeburn  5899: 
1.563     damieng  5900: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      5901: sub header {
1.507     www      5902:     return &Apache::loncommon::start_page('Settings');
1.416     jms      5903: }
1.193     albertel 5904: 
                   5905: 
                   5906: 
1.560     damieng  5907: ##################################################
                   5908: # MAIN MENU
                   5909: ##################################################
                   5910: 
1.563     damieng  5911: # Content and problem settings main menu.
                   5912: #
                   5913: # @param {Apache2::RequestRec} $r - the Apache request
                   5914: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 5915: sub print_main_menu {
                   5916:     my ($r,$parm_permission)=@_;
                   5917:     #
1.414     droeschl 5918:     $r->print(&header());
1.507     www      5919:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  5920:     my $crstype = &Apache::loncommon::course_type();
                   5921:     my $lc_crstype = lc($crstype);
                   5922: 
                   5923:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 5924:     $r->print(<<ENDMAINFORMHEAD);
                   5925: <form method="post" enctype="multipart/form-data"
                   5926:       action="/adm/parmset" name="studentform">
                   5927: ENDMAINFORMHEAD
                   5928: #
1.195     albertel 5929:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5930:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 5931:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 5932:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  5933:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  5934:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   5935:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  5936:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   5937:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   5938:                                         '/'.$env{'request.course.sec'});
                   5939:     }
1.568     raeburn  5940:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   5941:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   5942:                                         '/'.$env{'request.course.sec'});
                   5943:     }
                   5944:     my (%linktext,%linktitle,%url);
                   5945:     if ($parm_permission->{'edit'}) {
                   5946:         %linktext = (
                   5947:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   5948:                      settable        => 'Edit Resource Parameters - Table Mode',
                   5949:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   5950:                     );
                   5951:         %linktitle = (
                   5952:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   5953:                      settable        => 'Set/Modify resource parameters in table mode.',
                   5954:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   5955:                      );
                   5956:     } else {
                   5957:         %linktext = (
                   5958:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   5959:                      settable        => 'View Resource Parameters - Table Mode',
                   5960:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   5961:                    );
                   5962:         %linktitle = (
                   5963:                      newoverview     => 'Display resource parameters in overview mode.',
                   5964:                      settable        => 'Display resource parameters in table mode.',
                   5965:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   5966:                      );
                   5967:     }
                   5968:     if ($mgr) {
                   5969:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   5970:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   5971:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   5972:     } elsif ($vgr) {
                   5973:         $linktext{'resettimes'} = 'Display Student Access Times',
                   5974:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   5975:         $url{'resettimes'} = '/adm/accesstimes';
                   5976:     }
1.193     albertel 5977:     my @menu =
1.507     www      5978:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 5979:         items => [
                   5980:           { linktext => 'Portfolio Metadata',
                   5981:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  5982:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  5983:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 5984:             icon =>'contact-new.png'   ,
                   5985:             },
1.568     raeburn  5986:           { linktext => $linktext{'resettimes'},
                   5987:             url => $url{'resettimes'},
                   5988:             permission => ($vgr || $mgr),
                   5989:             linktitle => $linktitle{'resettimes'},
                   5990:             icon => 'start-here.png',
1.473     amueller 5991:             },
1.520     raeburn  5992:           { linktext => 'Blocking Communication/Resource Access',
                   5993:             url => '/adm/setblock',
1.568     raeburn  5994:             permission => ($vcb || $dcm),
1.520     raeburn  5995:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   5996:             icon => 'comblock.png',
                   5997:             },
1.473     amueller 5998:           { linktext => 'Set Parameter Setting Default Actions',
                   5999:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6000:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6001:             linktitle =>'Set default actions for parameters.'  ,
                   6002:             icon => 'folder-new.png'  ,
                   6003:             }]},
                   6004:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6005:         items => [
                   6006:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6007:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6008:             permission => $parm_permission->{'helper'},
1.473     amueller 6009:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6010:             icon => 'dialog-information.png'  ,
                   6011:             #help => 'Parameter_Helper',
                   6012:             },
1.568     raeburn  6013:           { linktext => $linktext{'newoverview'},
1.473     amueller 6014:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6015:             permission => $parm_permission->{'newoverview'},
                   6016:             linktitle => $linktitle{'newoverview'},
                   6017:             icon => 'edit-find.png',
1.473     amueller 6018:             #help => 'Parameter_Overview',
                   6019:             },
1.568     raeburn  6020:           { linktext => $linktext{'settable'},
1.473     amueller 6021:             url => '/adm/parmset?action=settable',
1.568     raeburn  6022:             permission => $parm_permission->{'settable'},
                   6023:             linktitle => $linktitle{'settable'},
                   6024:             icon => 'edit-copy.png',
1.473     amueller 6025:             #help => 'Table_Mode',
                   6026:             }]},
1.417     droeschl 6027:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6028:          items => [
1.570     raeburn  6029:           { linktext => $linktext{'setoverview'},
1.473     amueller 6030:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6031:             permission => $parm_permission->{'setoverview'},
                   6032:             linktitle => $linktitle{'setoverview'},
                   6033:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6034:             #help => 'Parameter_Overview',
                   6035:             },
                   6036:           { linktext => 'Change Log',
                   6037:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6038:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6039:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6040:             icon => 'document-properties.png',
1.473     amueller 6041:             }]}
1.193     albertel 6042:           );
1.414     droeschl 6043:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6044:     $r->print('</form>');
1.507     www      6045:     &endSettingsScreen($r);
1.539     raeburn  6046:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6047:     return;
                   6048: }
1.414     droeschl 6049: 
1.416     jms      6050: 
                   6051: 
1.560     damieng  6052: ##################################################
                   6053: # PORTFOLIO METADATA
                   6054: ##################################################
                   6055: 
1.563     damieng  6056: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6057: # It looks like field titles are not localized.
                   6058: #
                   6059: # @param {Apache2::RequestRec} $r - the Apache request
                   6060: # @param {string} $field_name - metadata field name
                   6061: # @param {string} $field_text - metadata field title, in English unless manually added
                   6062: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6063: sub output_row {
1.347     banghart 6064:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6065:     my $output;
1.263     banghart 6066:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6067:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6068:     if (!defined($options)) {
1.254     banghart 6069:         $options = 'active,stuadd';
1.261     banghart 6070:         $values = '';
1.252     banghart 6071:     }
1.337     banghart 6072:     if (!($options =~ /deleted/)) {
                   6073:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6074:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6075:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6076: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6077:         if ($added_flag) {
                   6078:             push @options,['deleted', 'Delete Metadata Field'];
                   6079:         }
1.351     banghart 6080:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6081:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6082:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6083:         foreach my $opt (@options) {
1.560     damieng  6084:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6085:             $output .= &Apache::loncommon::continue_data_table_row();
                   6086:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6087:                     <input type="checkbox" name="'.
                   6088:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6089:                     &mt($opt->[1]).'</label></td>';
                   6090:             $output .= &Apache::loncommon::end_data_table_row();
                   6091:         }
1.351     banghart 6092:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6093:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6094:         $output .= &Apache::loncommon::end_data_table_row();
                   6095:         my $multiple_checked;
                   6096:         my $single_checked;
                   6097:         if ($options =~ m/onlyone/) {
1.422     bisitz   6098:             $multiple_checked = '';
1.423     bisitz   6099:             $single_checked = ' checked="checked"';
1.351     banghart 6100:         } else {
1.423     bisitz   6101:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6102:             $single_checked = '';
1.351     banghart 6103:         }
1.560     damieng  6104:         $output .= &Apache::loncommon::continue_data_table_row();
                   6105:         $output .= '<td>'.('&nbsp;' x 10).'
                   6106:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6107:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6108:         $output .= &Apache::loncommon::end_data_table_row();
                   6109:         $output .= &Apache::loncommon::continue_data_table_row();
                   6110:         $output .= '<td>'.('&nbsp;' x 10).'
                   6111:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6112:                     '.&mt('Student may select only one choice from list').'</td>';
                   6113:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6114:     }
                   6115:     return ($output);
                   6116: }
1.416     jms      6117: 
                   6118: 
1.560     damieng  6119: # UI to order portfolio metadata fields.
1.563     damieng  6120: # Currently useless because addmetafield does not work.
                   6121: #
                   6122: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6123: sub order_meta_fields {
                   6124:     my ($r)=@_;
                   6125:     my $idx = 1;
                   6126:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6127:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6128:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6129:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6130:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6131:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6132:         text=>"Add Metadata Field"});
1.560     damieng  6133:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6134:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6135:         text=>"Restrict Metadata"},
                   6136:         {text=>"Order Metadata"});
1.345     banghart 6137:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6138:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6139:     if ($env{'form.storeorder'}) {
                   6140:         my $newpos = $env{'form.newpos'} - 1;
                   6141:         my $currentpos = $env{'form.currentpos'} - 1;
                   6142:         my @neworder = ();
1.548     raeburn  6143:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6144:         my $i;
1.341     banghart 6145:         if ($newpos > $currentpos) {
1.340     banghart 6146:         # moving stuff up
                   6147:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6148:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6149:             }
                   6150:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6151:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6152:             }
                   6153:             $neworder[$newpos]=$oldorder[$currentpos];
                   6154:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6155:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6156:             }
                   6157:         } else {
                   6158:         # moving stuff down
1.473     amueller 6159:             for ($i=0;$i<$newpos;$i++) {
                   6160:                 $neworder[$i]=$oldorder[$i];
                   6161:             }
                   6162:             $neworder[$newpos]=$oldorder[$currentpos];
                   6163:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6164:                 $neworder[$i]=$oldorder[$i-1];
                   6165:             }
                   6166:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6167:                 $neworder[$i]=$oldorder[$i];
                   6168:             }
1.340     banghart 6169:         }
1.560     damieng  6170:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6171:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6172:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6173:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6174:     }
1.357     raeburn  6175:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6176:     my $ordered_fields;
1.548     raeburn  6177:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6178:     if (!@fields_in_order) {
                   6179:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6180:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6181:             push @fields_in_order, $key;
1.341     banghart 6182:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6183:         }
1.341     banghart 6184:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6185:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6186:     }
1.340     banghart 6187:     $r->print('<table>');
                   6188:     my $num_fields = scalar(@fields_in_order);
                   6189:     foreach my $key (@fields_in_order) {
                   6190:         $r->print('<tr><td>');
                   6191:         $r->print('<form method="post" action="">');
1.537     bisitz   6192:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6193:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6194:             if ($i eq $idx) {
                   6195:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6196:             } else {
                   6197:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6198:             }
                   6199:         }
                   6200:         $r->print('</select></td><td>');
                   6201:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6202:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6203:         $r->print('</form>');
                   6204:         $r->print($$fields{$key}.'</td></tr>');
                   6205:         $idx ++;
                   6206:     }
                   6207:     $r->print('</table>');
1.507     www      6208:     &endSettingsScreen($r);
1.340     banghart 6209:     return 'ok';
                   6210: }
1.416     jms      6211: 
                   6212: 
1.563     damieng  6213: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6214: # @returns {string}
1.359     banghart 6215: sub continue {
                   6216:     my $output;
                   6217:     $output .= '<form action="" method="post">';
                   6218:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6219:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6220:     return ($output);
                   6221: }
1.416     jms      6222: 
                   6223: 
1.563     damieng  6224: # UI to add a metadata field.
                   6225: # Currenly does not work because of an HTML error (the field is not visible).
                   6226: #
                   6227: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6228: sub addmetafield {
                   6229:     my ($r)=@_;
1.414     droeschl 6230:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6231:         text=>"Add Metadata Field"});
1.334     banghart 6232:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6233:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6234:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6235:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6236:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6237:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6238:     if (exists($env{'form.undelete'})) {
1.358     banghart 6239:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6240:         foreach my $meta_field(@meta_fields) {
                   6241:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6242:             $options =~ s/deleted//;
                   6243:             $options =~ s/,,/,/;
                   6244:             my $put_result = &Apache::lonnet::put('environment',
                   6245:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6246: 
1.586     raeburn  6247:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6248:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6249:                           '</strong>',$put_result).
                   6250:                       '<br />');
1.339     banghart 6251:         }
1.359     banghart 6252:         $r->print(&continue());
1.339     banghart 6253:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6254:         my $meta_field = $env{'form.fieldname'};
                   6255:         my $display_field = $env{'form.fieldname'};
                   6256:         $meta_field =~ s/\W/_/g;
1.338     banghart 6257:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6258:         my $put_result = &Apache::lonnet::put('environment',
                   6259:                             {'metadata.'.$meta_field.'.values'=>"",
                   6260:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6261:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6262:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6263:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6264:                   '<br />');
1.359     banghart 6265:         $r->print(&continue());
1.335     banghart 6266:     } else {
1.357     raeburn  6267:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6268:         if ($fields) {
1.586     raeburn  6269:             $r->print(&mt('You may undelete previously deleted fields.').
                   6270:                       '<br />'.
                   6271:                       &mt('Check those you wish to undelete and click Undelete.').
                   6272:                       '<br />');
1.339     banghart 6273:             $r->print('<form method="post" action="">');
                   6274:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6275:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6276:             }
1.586     raeburn  6277:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6278:             $r->print('</form>');
                   6279:         }
1.586     raeburn  6280:         $r->print('<hr />'.
                   6281:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6282:                       '<strong>','</strong>').
1.581     raeburn  6283:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6284:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6285:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6286:         $r->print('</form>');
1.334     banghart 6287:     }
1.507     www      6288:     &endSettingsScreen($r);
1.334     banghart 6289: }
1.416     jms      6290: 
                   6291: 
                   6292: 
1.560     damieng  6293: # Display or save portfolio metadata.
1.563     damieng  6294: #
                   6295: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6296: sub setrestrictmeta {
1.240     banghart 6297:     my ($r)=@_;
1.242     banghart 6298:     my $next_meta;
1.244     banghart 6299:     my $output;
1.245     banghart 6300:     my $item_num;
1.246     banghart 6301:     my $put_result;
1.414     droeschl 6302:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6303:         text=>"Restrict Metadata"});
1.280     albertel 6304:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6305:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6306:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6307:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6308:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6309:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6310:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6311:     my $save_field = '';
1.586     raeburn  6312:     my %lt = &Apache::lonlocal::texthash(
                   6313:                                            addm => 'Add Metadata Field',
                   6314:                                            ordm => 'Order Metadata Fields',
                   6315:                                            save => 'Save',
                   6316:                                         );
1.259     banghart 6317:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6318:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6319:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6320:                 my $options;
1.252     banghart 6321:                 my $meta_field = $1;
                   6322:                 my $meta_key = $2;
1.253     banghart 6323:                 if ($save_field ne $meta_field) {
1.252     banghart 6324:                     $save_field = $meta_field;
1.473     amueller 6325:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6326:                         $options.='stuadd,';
                   6327:                     }
                   6328:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6329:                         $options.='choices,';
                   6330:                     }
                   6331:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6332:                         $options.='onlyone,';
                   6333:                     }
                   6334:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6335:                         $options.='active,';
                   6336:                     }
                   6337:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6338:                         $options.='deleted,';
                   6339:                     }
1.259     banghart 6340:                     my $name = $save_field;
1.560     damieng  6341:                     $put_result = &Apache::lonnet::put('environment',
                   6342:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6343:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6344:                         },$dom,$crs);
1.252     banghart 6345:                 }
                   6346:             }
                   6347:         }
                   6348:     }
1.296     albertel 6349:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6350:                        {'freshen_cache' => 1});
1.335     banghart 6351:     # Get the default metadata fields
1.258     albertel 6352:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6353:     # Now get possible added metadata fields
1.357     raeburn  6354:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6355:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6356:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6357:         if ($field ne 'courserestricted') {
1.586     raeburn  6358:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6359:         }
1.255     banghart 6360:     }
1.351     banghart 6361:     my $buttons = (<<ENDButtons);
1.586     raeburn  6362:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6363:         </form><br />
                   6364:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6365:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6366:         </form>
                   6367:         <br />
                   6368:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6369:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6370: ENDButtons
1.337     banghart 6371:     my $added_flag = 1;
1.335     banghart 6372:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6373:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6374:     }
1.347     banghart 6375:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6376:     $r->print(<<ENDenv);
1.259     banghart 6377:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6378:         $output
1.351     banghart 6379:         $buttons
1.340     banghart 6380:         </form>
1.244     banghart 6381: ENDenv
1.507     www      6382:     &endSettingsScreen($r);
1.280     albertel 6383:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6384:     return 'ok';
                   6385: }
1.416     jms      6386: 
                   6387: 
1.563     damieng  6388: # Returns metadata fields that have been manually added.
                   6389: #
                   6390: # @param {string} $cid - course id
                   6391: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6392: sub get_added_meta_fieldnames {
1.357     raeburn  6393:     my ($cid) = @_;
1.335     banghart 6394:     my %fields;
                   6395:     foreach my $key(%env) {
1.357     raeburn  6396:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6397:             my $field_name = $1;
                   6398:             my ($display_field_name) = $env{$key};
                   6399:             $fields{$field_name} = $display_field_name;
                   6400:         }
                   6401:     }
                   6402:     return \%fields;
                   6403: }
1.416     jms      6404: 
                   6405: 
1.563     damieng  6406: # Returns metadata fields that have been manually added and deleted.
                   6407: #
                   6408: # @param {string} $cid - course id
                   6409: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6410: sub get_deleted_meta_fieldnames {
1.357     raeburn  6411:     my ($cid) = @_;
1.339     banghart 6412:     my %fields;
                   6413:     foreach my $key(%env) {
1.357     raeburn  6414:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6415:             my $field_name = $1;
                   6416:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6417:                 my ($display_field_name) = $env{$key};
                   6418:                 $fields{$field_name} = $display_field_name;
                   6419:             }
                   6420:         }
                   6421:     }
                   6422:     return \%fields;
                   6423: }
1.560     damieng  6424: 
                   6425: 
                   6426: ##################################################
                   6427: # PARAMETER SETTINGS DEFAULT ACTIONS
                   6428: ##################################################
                   6429: 
                   6430: # UI to change parameter setting default actions
1.563     damieng  6431: #
                   6432: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      6433: sub defaultsetter {
1.280     albertel 6434:     my ($r) = @_;
                   6435: 
1.414     droeschl 6436:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 6437:         text=>"Set Defaults"});
1.531     raeburn  6438:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6439:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6440:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   6441:     my $start_page =
1.531     raeburn  6442:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 6443:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      6444:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6445:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      6446:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 6447: 
1.221     www      6448:     my @ids=();
                   6449:     my %typep=();
                   6450:     my %keyp=();
                   6451:     my %allparms=();
                   6452:     my %allparts=();
                   6453:     my %allmaps=();
                   6454:     my %mapp=();
                   6455:     my %symbp=();
                   6456:     my %maptitles=();
                   6457:     my %uris=();
                   6458:     my %keyorder=&standardkeyorder();
                   6459:     my %defkeytype=();
                   6460: 
1.446     bisitz   6461:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6462:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   6463:                 \%keyorder,\%defkeytype);
1.224     www      6464:     if ($env{'form.storerules'}) {
1.560     damieng  6465:         my %newrules=();
                   6466:         my @delrules=();
                   6467:         my %triggers=();
                   6468:         foreach my $key (keys(%env)) {
1.225     albertel 6469:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  6470:                 my $tempkey=$1;
                   6471:                 my $action=$env{$key};
1.226     www      6472:                 if ($action) {
1.560     damieng  6473:                     $newrules{$tempkey.'_action'}=$action;
                   6474:                     if ($action ne 'default') {
                   6475:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   6476:                         $triggers{$whichparm}.=$tempkey.':';
                   6477:                     }
                   6478:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   6479:                     if (&isdateparm($defkeytype{$tempkey})) {
                   6480:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   6481:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   6482:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   6483:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   6484:                     } else {
                   6485:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   6486:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   6487:                     }
                   6488:                 } else {
                   6489:                     push(@delrules,$tempkey.'_action');
                   6490:                     push(@delrules,$tempkey.'_type');
                   6491:                     push(@delrules,$tempkey.'_hours');
                   6492:                     push(@delrules,$tempkey.'_min');
                   6493:                     push(@delrules,$tempkey.'_sec');
                   6494:                     push(@delrules,$tempkey.'_value');
                   6495:                 }
1.473     amueller 6496:             }
                   6497:         }
1.560     damieng  6498:         foreach my $key (keys(%allparms)) {
                   6499:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 6500:         }
1.560     damieng  6501:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   6502:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   6503:         &resetrulescache();
1.224     www      6504:     }
1.227     www      6505:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 6506:                        'hours' => 'Hours',
                   6507:                        'min' => 'Minutes',
                   6508:                        'sec' => 'Seconds',
                   6509:                        'yes' => 'Yes',
                   6510:                        'no' => 'No');
1.222     www      6511:     my @standardoptions=('','default');
                   6512:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   6513:     my @dateoptions=('','default');
                   6514:     my @datedisplay=('',&mt('Default value when manually setting'));
                   6515:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6516:         unless ($tempkey) { next; }
                   6517:         push @standardoptions,'when_setting_'.$tempkey;
                   6518:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   6519:         if (&isdateparm($defkeytype{$tempkey})) {
                   6520:             push @dateoptions,'later_than_'.$tempkey;
                   6521:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   6522:             push @dateoptions,'earlier_than_'.$tempkey;
                   6523:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   6524:         }
1.222     www      6525:     }
1.563     damieng  6526:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   6527:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 6528:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 6529:           &Apache::loncommon::start_data_table_header_row().
                   6530:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   6531:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   6532:           &Apache::loncommon::end_data_table_header_row());
1.221     www      6533:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6534:         unless ($tempkey) { next; }
                   6535:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   6536:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   6537:         my $action=&rulescache($tempkey.'_action');
                   6538:         $r->print('<select name="'.$tempkey.'_action">');
                   6539:         if (&isdateparm($defkeytype{$tempkey})) {
                   6540:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   6541:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   6542:             $r->print("\n<option value='$dateoptions[$i]'".
                   6543:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   6544:                 ">$datedisplay[$i]</option>");
                   6545:             }
                   6546:         } else {
                   6547:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   6548:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   6549:             $r->print("\n<option value='$standardoptions[$i]'".
                   6550:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   6551:                 ">$standarddisplay[$i]</option>");
                   6552:             }
1.473     amueller 6553:         }
1.560     damieng  6554:         $r->print('</select>');
                   6555:         unless (&isdateparm($defkeytype{$tempkey})) {
                   6556:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   6557:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 6558:         }
1.560     damieng  6559:         $r->print("\n</td><td>\n");
1.222     www      6560: 
1.221     www      6561:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  6562:             my $days=&rulescache($tempkey.'_days');
                   6563:             my $hours=&rulescache($tempkey.'_hours');
                   6564:             my $min=&rulescache($tempkey.'_min');
                   6565:             my $sec=&rulescache($tempkey.'_sec');
                   6566:             $r->print(<<ENDINPUTDATE);
                   6567:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   6568:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   6569:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   6570:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  6571: ENDINPUTDATE
1.560     damieng  6572:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   6573:                 my $yeschecked='';
                   6574:                 my $nochecked='';
                   6575:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   6576:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   6577: 
                   6578:             $r->print(<<ENDYESNO);
                   6579:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   6580:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  6581: ENDYESNO
1.221     www      6582:         } else {
1.560     damieng  6583:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   6584:         }
1.318     albertel 6585:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      6586:     }
1.318     albertel 6587:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 6588:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      6589:           &mt('Save').'" /></form>'."\n");
                   6590:     &endSettingsScreen($r);
                   6591:     $r->print(&Apache::loncommon::end_page());
1.220     www      6592:     return;
                   6593: }
1.193     albertel 6594: 
1.560     damieng  6595: ##################################################
                   6596: # PARAMETER CHANGES LOG
                   6597: ##################################################
                   6598: 
1.563     damieng  6599: # Returns some info for a parameter log entry.
                   6600: # Returned entries:
                   6601: # $realm - HTML title for the parameter level and resource
                   6602: # $section - parameter section
                   6603: # $name - parameter name
                   6604: # $part - parameter part
                   6605: # $what - $part.'.'.$name
                   6606: # $middle - resource symb ?
                   6607: # $uname - user name (same as given)
                   6608: # $udom - user domain (same as given)
                   6609: # $issection - section or group name
                   6610: # $realmdescription - title for the parameter level and resource (without using HTML)
                   6611: #
                   6612: # @param {string} $key - parameter log key
                   6613: # @param {string} $uname - user name
                   6614: # @param {string} $udom - user domain
                   6615: # @param {boolean} $typeflag - .type log entry
                   6616: # @returns {Array}
1.290     www      6617: sub components {
1.581     raeburn  6618:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 6619: 
                   6620:     if ($typeflag) {
1.560     damieng  6621:         $key=~s/\.type$//;
1.290     www      6622:     }
1.330     albertel 6623: 
                   6624:     my ($middle,$part,$name)=
1.572     damieng  6625:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      6626:     my $issection;
1.330     albertel 6627: 
1.290     www      6628:     my $section=&mt('All Students');
                   6629:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6630:         $issection=$1;
                   6631:         $section=&mt('Group/Section').': '.$issection;
                   6632:         $middle=~s/^\[(.*)\]//;
1.290     www      6633:     }
                   6634:     $middle=~s/\.+$//;
                   6635:     $middle=~s/^\.+//;
1.291     www      6636:     if ($uname) {
1.560     damieng  6637:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   6638:         $issection='';
1.291     www      6639:     }
1.316     albertel 6640:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   6641:     my $realmdescription=&mt('all resources');
1.556     raeburn  6642:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   6643:         my $mapurl = $1;
                   6644:         my $maplevel = $2;
                   6645:         my $leveltitle = &mt('Folder/Map');
                   6646:         if ($maplevel eq 'rec') {
                   6647:             $leveltitle = &mt('Recursive');
                   6648:         }
1.560     damieng  6649:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   6650:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   6651:             $mapurl.')</span></span>';
                   6652:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   6653:     } elsif ($middle) {
                   6654:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   6655:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   6656:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   6657:             ' in '.$map.' id: '.$id.')</span></span>';
                   6658:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      6659:     }
1.291     www      6660:     my $what=$part.'.'.$name;
1.330     albertel 6661:     return ($realm,$section,$name,$part,
1.473     amueller 6662:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      6663: }
1.293     www      6664: 
1.563     damieng  6665: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   6666: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      6667: 
1.563     damieng  6668: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 6669: sub load_parameter_names {
1.583     raeburn  6670:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 6671:     while (my $configline=<$config>) {
1.560     damieng  6672:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   6673:         chomp($configline);
                   6674:         my ($short,$plain)=split(/:/,$configline);
                   6675:         my (undef,$name,$type)=split(/\&/,$short,3);
                   6676:         if ($type eq 'display') {
                   6677:             $standard_parms{$name} = $plain;
1.469     raeburn  6678:         } elsif ($type eq 'type') {
1.560     damieng  6679:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  6680:         }
1.328     albertel 6681:     }
                   6682:     close($config);
                   6683:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   6684:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  6685:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 6686: }
                   6687: 
1.563     damieng  6688: # Returns a parameter title for standard parameters, the name for others.
                   6689: #
                   6690: # @param {string} $name - parameter name
                   6691: # @returns {string}
1.292     www      6692: sub standard_parameter_names {
                   6693:     my ($name)=@_;
1.328     albertel 6694:     if (!%standard_parms) {
1.560     damieng  6695:         &load_parameter_names();
1.328     albertel 6696:     }
1.292     www      6697:     if ($standard_parms{$name}) {
1.560     damieng  6698:         return $standard_parms{$name};
1.446     bisitz   6699:     } else {
1.560     damieng  6700:         return $name;
1.292     www      6701:     }
                   6702: }
1.290     www      6703: 
1.563     damieng  6704: # Returns a parameter type for standard parameters, undef for others.
                   6705: #
                   6706: # @param {string} $name - parameter name
                   6707: # @returns {string}
1.469     raeburn  6708: sub standard_parameter_types {
                   6709:     my ($name)=@_;
                   6710:     if (!%standard_parms_types) {
                   6711:         &load_parameter_names();
                   6712:     }
                   6713:     if ($standard_parms_types{$name}) {
                   6714:         return $standard_parms_types{$name};
                   6715:     }
                   6716:     return;
                   6717: }
1.309     www      6718: 
1.563     damieng  6719: # Returns a parameter level title (not localized) from the parameter level name.
                   6720: #
                   6721: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   6722: # @returns {string}
1.557     raeburn  6723: sub standard_parameter_levels {
                   6724:     my ($name)=@_;
                   6725:     my %levels = (
                   6726:                     'resourcelevel'   => 'a single resource',
                   6727:                     'maplevel'        => 'the enclosing map/folder', 
                   6728:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   6729:                     'courselevel'     => 'the general (course) level',
                   6730:                  );
                   6731:     if ($levels{$name}) {
                   6732:         return $levels{$name};
                   6733:     }
                   6734:     return;
                   6735: }
                   6736: 
1.560     damieng  6737: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  6738: #
                   6739: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 6740: sub parm_change_log {
1.568     raeburn  6741:     my ($r,$parm_permission)=@_;
1.531     raeburn  6742:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6743:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  6744:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6745:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 6746:     text=>"Parameter Change Log"});
1.522     raeburn  6747:     my $js = '<script type="text/javascript">'."\n".
                   6748:              '// <![CDATA['."\n".
                   6749:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   6750:              '// ]]>'."\n".
                   6751:              '</script>'."\n";
                   6752:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 6753:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  6754:     &startSettingsScreen($r,'parmset',$crstype);
                   6755:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 6756: 
1.301     www      6757:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 6758: 
1.522     raeburn  6759:     $r->print('<div class="LC_left_float">'.
                   6760:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   6761:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 6762:                      method="post" name="parameterlog">');
1.446     bisitz   6763: 
1.311     albertel 6764:     my %saveable_parameters = ('show' => 'scalar',);
                   6765:     &Apache::loncommon::store_course_settings('parameter_log',
                   6766:                                               \%saveable_parameters);
                   6767:     &Apache::loncommon::restore_course_settings('parameter_log',
                   6768:                                                 \%saveable_parameters);
1.522     raeburn  6769:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   6770:               '<input type="submit" value="'.&mt('Display').'" />'.
                   6771:               '</form></fieldset></div><br clear="all" />');
1.301     www      6772: 
1.568     raeburn  6773:     my $readonly = 1;
                   6774:     if ($parm_permission->{'edit'}) {
                   6775:         undef($readonly);
                   6776:     }
1.531     raeburn  6777:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      6778:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 6779:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  6780:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   6781:     unless ($readonly) {
                   6782:         $r->print('<th>'.&mt('Announce').'</th>');
                   6783:     }
                   6784:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      6785:     my $shown=0;
1.349     www      6786:     my $folder='';
                   6787:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  6788:         my $last='';
                   6789:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   6790:                 &GDBM_READER(),0640)) {
                   6791:             $last=$hash{'last_known'};
                   6792:             untie(%hash);
                   6793:         }
                   6794:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   6795:     }
                   6796:     foreach my $id (sort {
                   6797:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   6798:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   6799:                 }
                   6800:                 my $aid = (split('00000',$a))[-1];
                   6801:                 my $bid = (split('00000',$b))[-1];
                   6802:                 return $bid<=>$aid;
1.473     amueller 6803:             } (keys(%parmlog))) {
1.294     www      6804:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  6805:         my $count = 0;
                   6806:         my $time =
                   6807:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   6808:         my $plainname =
                   6809:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   6810:                         $parmlog{$id}{'exe_udom'});
                   6811:         my $about_me_link =
                   6812:             &Apache::loncommon::aboutmewrapper($plainname,
                   6813:                             $parmlog{$id}{'exe_uname'},
                   6814:                             $parmlog{$id}{'exe_udom'});
                   6815:         my $send_msg_link='';
1.568     raeburn  6816:         if ((!$readonly) && 
                   6817:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  6818:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   6819:             $send_msg_link ='<br />'.
                   6820:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   6821:                             $parmlog{$id}{'exe_uname'},
                   6822:                             $parmlog{$id}{'exe_udom'});
                   6823:         }
                   6824:         my $row_start=&Apache::loncommon::start_data_table_row();
                   6825:         my $makenewrow=0;
                   6826:         my %istype=();
                   6827:         my $output;
                   6828:         foreach my $changed (reverse(sort(@changes))) {
                   6829:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   6830:             my $typeflag = ($changed =~/\.type$/ &&
                   6831:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 6832:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  6833:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  6834:             if ($env{'request.course.sec'} ne '') {
                   6835:                 next if (($issection ne '') && ($issection ne $env{'request.course.sec'}));
                   6836:                 if ($uname ne '') {
                   6837:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   6838:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   6839:                 }
                   6840:             }
                   6841:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   6842:                 if ($folder) {
                   6843:                     if ($middle!~/^\Q$folder\E/) { next; }
                   6844:                 }
                   6845:             }
                   6846:             if ($typeflag) {
                   6847:                 $istype{$parmname}=$value;
                   6848:                 if (!$env{'form.includetypes'}) { next; }
                   6849:             }
                   6850:             $count++;
                   6851:             if ($makenewrow) {
                   6852:                 $output .= $row_start;
                   6853:             } else {
                   6854:                 $makenewrow=1;
                   6855:             }
1.470     raeburn  6856:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  6857:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   6858:                 &mt($parmitem).'</td><td>'.
                   6859:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   6860:             my $stillactive=0;
                   6861:             if ($parmlog{$id}{'delflag'}) {
                   6862:                 $output .= &mt('Deleted');
                   6863:             } else {
                   6864:                 if ($typeflag) {
1.470     raeburn  6865:                     my $parmitem = &standard_parameter_names($value); 
                   6866:                     $parmitem = &mt($parmitem);
1.560     damieng  6867:                     $output .= &mt('Type: [_1]',$parmitem);
                   6868:                 } else {
1.584     raeburn  6869:                     my $toolsymb;
                   6870:                     if ($middle =~ /ext\.tool$/) {
                   6871:                         $toolsymb = $middle;
                   6872:                     }
1.560     damieng  6873:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  6874:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  6875:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  6876:                     my $showvalue = $value;
                   6877:                     if ($istype{$parmname} eq '') {
                   6878:                         my $type = &standard_parameter_types($parmname);
                   6879:                         if ($type ne '') {
                   6880:                             if (&isdateparm($type)) {
                   6881:                                 $showvalue =
                   6882:                                     &Apache::lonlocal::locallocaltime($value);
                   6883:                             }
                   6884:                         }
                   6885:                     } else {
1.560     damieng  6886:                         if (&isdateparm($istype{$parmname})) {
                   6887:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   6888:                         }
1.469     raeburn  6889:                     }
                   6890:                     $output .= $showvalue;
1.560     damieng  6891:                     if ($value ne $all[$level]) {
                   6892:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   6893:                     } else {
                   6894:                         $stillactive=1;
                   6895:                     }
                   6896:                 }
1.473     amueller 6897:             }
1.568     raeburn  6898:             $output .= '</td>';
                   6899: 
                   6900:             unless ($readonly) { 
                   6901:                 $output .= '<td>';
                   6902:                 if ($stillactive) {
                   6903:                     my $parmitem = &standard_parameter_names($parmname);
                   6904:                     $parmitem = &mt($parmitem);
                   6905:                     my $title=&mt('Changed [_1]',$parmitem);
                   6906:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   6907:                         $parmitem,$realmdescription,
                   6908:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   6909:                     if (($uname) && ($udom)) {
                   6910:                         $output .=
                   6911:                         &Apache::loncommon::messagewrapper('Notify User',
                   6912:                                                            $uname,$udom,$title,
                   6913:                                                            $description);
                   6914:                     } else {
                   6915:                         $output .=
                   6916:                             &Apache::lonrss::course_blog_link($id,$title,
                   6917:                                                               $description);
                   6918:                     }
1.560     damieng  6919:                 }
1.568     raeburn  6920:                 $output .= '</td>';
1.560     damieng  6921:             }
1.568     raeburn  6922:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 6923:         }
1.560     damieng  6924:         if ($env{'form.displayfilter'} eq 'containing') {
                   6925:             my $wholeentry=$about_me_link.':'.
                   6926:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   6927:             $output;
                   6928:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 6929:         }
1.349     www      6930:         if ($count) {
1.560     damieng  6931:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   6932:                         <td rowspan="'.$count.'">'.$about_me_link.
                   6933:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   6934:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   6935:             $send_msg_link.'</td>'.$output);
                   6936:             $shown++;
                   6937:         }
                   6938:         if (!($env{'form.show'} eq &mt('all')
                   6939:             || $shown<=$env{'form.show'})) { last; }
1.286     www      6940:     }
1.301     www      6941:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      6942:     &endSettingsScreen($r);
1.284     www      6943:     $r->print(&Apache::loncommon::end_page());
                   6944: }
                   6945: 
1.560     damieng  6946: ##################################################
                   6947: # MISC !
                   6948: ##################################################
                   6949: 
1.563     damieng  6950: # Stores slot information.
1.560     damieng  6951: # Used by table UI
1.563     damieng  6952: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6953: #
                   6954: # @param {string} $slot_name - slot name
                   6955: # @param {string} $cdom - course domain
                   6956: # @param {string} $cnum - course number
                   6957: # @param {string} $symb - resource symb
                   6958: # @param {string} $uname - user name
                   6959: # @param {string} $udom - user domain
                   6960: # @returns {string} - 'ok' or error name
1.437     raeburn  6961: sub update_slots {
                   6962:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   6963:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   6964:     if (!keys(%slot)) {
                   6965:         return 'error: slot does not exist';
                   6966:     }
                   6967:     my $max=$slot{'maxspace'};
                   6968:     if (!defined($max)) { $max=99999; }
                   6969: 
                   6970:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   6971:                                        "^$slot_name\0");
                   6972:     my ($tmp)=%consumed;
                   6973:     if ($tmp=~/^error: 2 / ) {
                   6974:         return 'error: unable to determine current slot status';
                   6975:     }
                   6976:     my $last=0;
                   6977:     foreach my $key (keys(%consumed)) {
                   6978:         my $num=(split('\0',$key))[1];
                   6979:         if ($num > $last) { $last=$num; }
                   6980:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6981:             return 'ok';
                   6982:         }
                   6983:     }
                   6984: 
                   6985:     if (scalar(keys(%consumed)) >= $max) {
                   6986:         return 'error: no space left in slot';
                   6987:     }
                   6988:     my $wanted=$last+1;
                   6989: 
                   6990:     my %reservation=('name'      => $uname.':'.$udom,
                   6991:                      'timestamp' => time,
                   6992:                      'symb'      => $symb);
                   6993: 
                   6994:     my $success=&Apache::lonnet::newput('slot_reservations',
                   6995:                                         {"$slot_name\0$wanted" =>
                   6996:                                              \%reservation},
                   6997:                                         $cdom, $cnum);
1.438     raeburn  6998:     if ($success eq 'ok') {
                   6999:         my %storehash = (
                   7000:                           symb    => $symb,
                   7001:                           slot    => $slot_name,
                   7002:                           action  => 'reserve',
                   7003:                           context => 'parameter',
                   7004:                         );
1.526     raeburn  7005:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7006:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7007: 
1.526     raeburn  7008:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7009:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7010:     }
1.437     raeburn  7011:     return $success;
                   7012: }
                   7013: 
1.563     damieng  7014: # Deletes a slot reservation.
1.560     damieng  7015: # Used by table UI
1.563     damieng  7016: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7017: #
                   7018: # @param {string} $slot_name - slot name
                   7019: # @param {string} $cdom - course domain
                   7020: # @param {string} $cnum - course number
                   7021: # @param {string} $uname - user name
                   7022: # @param {string} $udom - user domain
                   7023: # @param {string} $symb - resource symb
                   7024: # @returns {string} - 'ok' or error name
1.437     raeburn  7025: sub delete_slots {
                   7026:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7027:     my $delresult;
                   7028:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7029:                                          $cnum, "^$slot_name\0");
                   7030:     if (&Apache::lonnet::error(%consumed)) {
                   7031:         return 'error: unable to determine current slot status';
                   7032:     }
                   7033:     my ($tmp)=%consumed;
                   7034:     if ($tmp=~/^error: 2 /) {
                   7035:         return 'error: unable to determine current slot status';
                   7036:     }
                   7037:     foreach my $key (keys(%consumed)) {
                   7038:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7039:             my $num=(split('\0',$key))[1];
                   7040:             my $entry = $slot_name.'\0'.$num;
                   7041:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7042:                                               $cdom,$cnum);
                   7043:             if ($delresult eq 'ok') {
                   7044:                 my %storehash = (
                   7045:                                   symb    => $symb,
                   7046:                                   slot    => $slot_name,
                   7047:                                   action  => 'release',
                   7048:                                   context => 'parameter',
                   7049:                                 );
1.526     raeburn  7050:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7051:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7052:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7053:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7054:             }
                   7055:         }
                   7056:     }
                   7057:     return $delresult;
                   7058: }
                   7059: 
1.563     damieng  7060: # Returns true if there is a current course.
1.560     damieng  7061: # Used by handler
1.563     damieng  7062: #
                   7063: # @returns {boolean}
1.355     albertel 7064: sub check_for_course_info {
                   7065:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7066:     return 1 if ($navmap);
                   7067:     return 0;
                   7068: }
                   7069: 
1.563     damieng  7070: # Returns the current course host and host LON-CAPA version.
                   7071: #
                   7072: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7073: sub parameter_release_vars { 
1.504     raeburn  7074:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7075:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7076:    my $chostname = &Apache::lonnet::hostname($chome);
                   7077:    my ($cmajor,$cminor) = 
                   7078:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7079:    return ($chostname,$cmajor,$cminor);
                   7080: }
                   7081: 
1.563     damieng  7082: # Checks if the course host version can handle a parameter required version,
                   7083: # and if it does, stores the release needed for the course.
                   7084: #
                   7085: # @param {string} $name - parameter name
                   7086: # @param {string} $value - parameter value
                   7087: # @param {string} $valmatch - name of the test used for checking the value
                   7088: # @param {string} $namematch - name of the test used for checking the name
                   7089: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7090: # @param {integer} $cmajor - course major version number
                   7091: # @param {integer} $cminor - course minor version number
                   7092: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7093: sub parameter_releasecheck {
1.557     raeburn  7094:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7095:     my $needsnewer;
                   7096:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7097:     if (($cmajor < $needsmajor) || 
                   7098:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7099:         $needsnewer = 1;
1.557     raeburn  7100:     } elsif ($name) {
                   7101:         if ($valmatch) {
                   7102:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7103:         } elsif ($value) { 
                   7104:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7105:         }
                   7106:     } elsif ($namematch) {
                   7107:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7108:     }
                   7109:     return $needsnewer;
                   7110: }
                   7111: 
1.568     raeburn  7112: sub get_permission {
                   7113:     my %permission;
                   7114:     my $allowed = 0;
                   7115:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7116:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7117:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7118:                   $env{'request.course.sec'}))) {
                   7119:         %permission= (
                   7120:                        'edit'               => 1,
                   7121:                        'set'                => 1,
                   7122:                        'setoverview'        => 1,
                   7123:                        'addmetadata'        => 1,
                   7124:                        'ordermetadata'      => 1,
                   7125:                        'setrestrictmeta'    => 1,
                   7126:                        'newoverview'        => 1,
                   7127:                        'setdefaults'        => 1,
                   7128:                        'settable'           => 1,
                   7129:                        'parameterchangelog' => 1,
                   7130:                        'cleanparameters'    => 1,
                   7131:                        'dateshift1'         => 1,
                   7132:                        'dateshift2'         => 1,
                   7133:                        'helper'             => 1,
                   7134:          );
                   7135:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7136:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7137:                   $env{'request.course.sec'}))) {
                   7138:         %permission = (
                   7139:                        'set'                => 1,
                   7140:                        'settable'           => 1,
                   7141:                        'newoverview'        => 1,
                   7142:                        'setoverview'        => 1,
                   7143:                        'parameterchangelog' => 1,
                   7144:                       );
                   7145:     }
                   7146:     foreach my $perm (values(%permission)) {
                   7147:         if ($perm) { $allowed=1; last; }
                   7148:     }
                   7149:     return (\%permission,$allowed);
                   7150: }
                   7151: 
1.560     damieng  7152: ##################################################
                   7153: # HANDLER
                   7154: ##################################################
                   7155: 
                   7156: # Main handler for lonparmset.
                   7157: # Sub called based on request parameters action and command:
                   7158: # no command or action: print_main_menu
                   7159: # command 'set': assessparms (direct access to table mode for a resource)
                   7160: #                (this can also be accessed simply with the symb parameter)
                   7161: # action 'setoverview': overview (display all existing parameter settings)
                   7162: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7163: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7164: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7165: # action 'newoverview': newoverview (overview mode)
                   7166: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7167: # action 'settable': assessparms (table mode)
                   7168: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7169: #                              blog postings, user notification changes)
                   7170: # action 'cleanparameters': clean_parameters (unused)
                   7171: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7172: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7173: sub handler {
1.43      albertel 7174:     my $r=shift;
1.30      www      7175: 
1.376     albertel 7176:     &reset_caches();
                   7177: 
1.414     droeschl 7178:     &Apache::loncommon::content_type($r,'text/html');
                   7179:     $r->send_http_header;
                   7180:     return OK if $r->header_only;
                   7181: 
1.193     albertel 7182:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7183:                         ['action','state',
1.205     www      7184:                                              'pres_marker',
                   7185:                                              'pres_value',
1.206     www      7186:                                              'pres_type',
1.506     www      7187:                                              'filter','part',
1.390     www      7188:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7189: 
1.83      bowersj2 7190: 
1.193     albertel 7191:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7192:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7193:                         text=>"Content and Problem Settings",
1.473     amueller 7194:                         faq=>10,
                   7195:                         bug=>'Instructor Interface',
1.442     droeschl 7196:                                             help =>
                   7197:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7198: 
1.30      www      7199: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7200:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7201:     my $exists = &check_for_course_info();
                   7202: 
1.568     raeburn  7203:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7204:         #
                   7205:         # Main switch on form.action and form.state, as appropriate
                   7206:         #
                   7207:         # Check first if coming from someone else headed directly for
                   7208:         #  the table mode
1.568     raeburn  7209:         if (($parm_permission->{'set'}) && 
                   7210:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7211:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7212:             &assessparms($r,$parm_permission);
1.193     albertel 7213:         } elsif (! exists($env{'form.action'})) {
                   7214:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7215:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7216:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7217:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7218:             &overview($r,$parm_permission);
1.560     damieng  7219:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7220:             &addmetafield($r);
                   7221:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7222:             &order_meta_fields($r);
1.414     droeschl 7223:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7224:             &setrestrictmeta($r);
1.414     droeschl 7225:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7226:             &newoverview($r,$parm_permission);
1.414     droeschl 7227:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7228:             &defaultsetter($r);
                   7229:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7230:             &assessparms($r,$parm_permission);
1.414     droeschl 7231:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7232:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7233:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7234:             &clean_parameters($r);
1.414     droeschl 7235:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7236:             &date_shift_one($r);
1.414     droeschl 7237:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7238:             &date_shift_two($r);
1.446     bisitz   7239:         }
1.43      albertel 7240:     } else {
1.1       www      7241: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7242:         if ($exists) {
                   7243:             $env{'user.error.msg'}=
                   7244:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7245:         } else {
                   7246:             $env{'user.error.msg'}=
                   7247:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7248:         }
                   7249:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7250:     }
1.376     albertel 7251:     &reset_caches();
                   7252: 
1.43      albertel 7253:     return OK;
1.1       www      7254: }
                   7255: 
                   7256: 1;
                   7257: __END__
                   7258: 
                   7259: 

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