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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.587   ! raeburn     4: # $Id: lonparmset.pm,v 1.586 2018/09/14 18:27:49 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.578     raeburn  1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive. 
1.5       www      1069: sub plink {
1.578     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.560     damieng  1073:         if (&isdateparm($type)) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.23      www      1075:         } else {
1.190     albertel 1076:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1077:         }
                   1078:     }
1.229     www      1079:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1080:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1081:     unless (defined($winvalue)) { $winvalue=$val; }
1.554     raeburn  1082:     my $valout = &valout($value,$type,$parmname,1);
1.429     raeburn  1083:     my $unencmarker = $marker;
1.378     albertel 1084:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.473     amueller 1085:               \$hour, \$min, \$sec) {
1.560     damieng  1086:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1087:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1088:     }
1.429     raeburn  1089:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1090:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
                   1091:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."'".');">'.
1.578     raeburn  1092:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1093:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1094: 
1.5       www      1095: }
                   1096: 
1.561     damieng  1097: # Javascript for table mode.
1.280     albertel 1098: sub page_js {
                   1099: 
1.81      www      1100:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1101:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1102: 
                   1103:     return(<<ENDJS);
                   1104: <script type="text/javascript">
1.454     bisitz   1105: // <![CDATA[
1.44      albertel 1106: 
1.88      matthew  1107:     $pjump_def
1.44      albertel 1108: 
                   1109:     function psub() {
                   1110:         if (document.parmform.pres_marker.value!='') {
                   1111:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1112:             var typedef=new Array();
                   1113:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1114:             if (document.parmform.pres_type.value!='') {
                   1115:                 if (typedef[0]=='date') {
                   1116:                     eval('document.parmform.recent_'+
                   1117:                         document.parmform.pres_type.value+
                   1118:                         '.value=document.parmform.pres_value.value;');
                   1119:                 } else {
                   1120:                     eval('document.parmform.recent_'+typedef[0]+
                   1121:                         '.value=document.parmform.pres_value.value;');
                   1122:                 }
1.44      albertel 1123:             }
                   1124:             document.parmform.submit();
                   1125:         } else {
                   1126:             document.parmform.pres_value.value='';
                   1127:             document.parmform.pres_marker.value='';
                   1128:         }
                   1129:     }
                   1130: 
1.57      albertel 1131:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1132:         var options = "width=" + w + ",height=" + h + ",";
                   1133:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1134:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1135:         var newWin = window.open(url, wdwName, options);
                   1136:         newWin.focus();
                   1137:     }
1.523     raeburn  1138: 
1.454     bisitz   1139: // ]]>
1.523     raeburn  1140: 
1.44      albertel 1141: </script>
1.81      www      1142: $selscript
1.280     albertel 1143: ENDJS
                   1144: 
                   1145: }
1.507     www      1146: 
1.561     damieng  1147: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1148: # for table and overview modes.
1.523     raeburn  1149: sub showhide_js {
                   1150:     return <<"COURSECONTENTSCRIPT";
                   1151: 
                   1152: function showHide_courseContent() {
                   1153:     var parmlevValue=document.getElementById("parmlev").value;
                   1154:     if (parmlevValue == 'general') {
                   1155:         document.getElementById('mapmenu').style.display="none";
                   1156:     } else {
                   1157:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1158:             document.getElementById('mapmenu').style.display ="";
                   1159:         } else {
                   1160:             document.getElementById('mapmenu').style.display="none";
                   1161:         }
                   1162:     }
                   1163:     return;
                   1164: }
                   1165: 
                   1166: COURSECONTENTSCRIPT
                   1167: }
                   1168: 
1.561     damieng  1169: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1170: sub toggleparmtextbox_js {
                   1171:     return <<"ENDSCRIPT";
                   1172: 
                   1173: if (!document.getElementsByClassName) {
                   1174:     function getElementsByClassName(node, classname) {
                   1175:         var a = [];
                   1176:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1177:         var els = node.getElementsByTagName("*");
                   1178:         for(var i=0,j=els.length; i<j; i++)
                   1179:             if(re.test(els[i].className))a.push(els[i]);
                   1180:         return a;
                   1181:     }
                   1182: }
                   1183: 
                   1184: function showHideLenient() {
                   1185:     var lenients;
                   1186:     var setRegExp = /^set_/;
                   1187:     if (document.getElementsByClassName) {
                   1188:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1189:     } else {
                   1190:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1191:     }
                   1192:     if (lenients != 'undefined') {
                   1193:         for (var i=0; i<lenients.length; i++) {
                   1194:             if (lenients[i].checked) {
                   1195:                 if (lenients[i].value == 'weighted') {
                   1196:                     if (setRegExp.test(lenients[i].name)) {
                   1197:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1198:                         toggleParmTextbox(document.parmform,identifier);
                   1199:                     }
                   1200:                 }
                   1201:             }
                   1202:         }
                   1203:     }
                   1204:     return;
                   1205: }
                   1206: 
                   1207: function toggleParmTextbox(form,key) {
                   1208:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1209:     if (divfortext) {
                   1210:         var caller = form.elements['set_'+key];
                   1211:         if (caller.length) {
                   1212:             for (i=0; i<caller.length; i++) {
                   1213:                 if (caller[i].checked) {
                   1214:                     if (caller[i].value == 'weighted') {
                   1215:                         divfortext.style.display = 'inline';
                   1216:                     } else {
                   1217:                         divfortext.style.display = 'none';
                   1218:                     }
                   1219:                 }
                   1220:             }
                   1221:         }
                   1222:     }
                   1223:     return;
                   1224: }
                   1225: 
                   1226: ENDSCRIPT
                   1227: }
                   1228: 
1.561     damieng  1229: # Javascript function validateParms, for overview mode
1.549     raeburn  1230: sub validateparms_js {
                   1231:     return <<'ENDSCRIPT';
                   1232: 
                   1233: function validateParms() {
                   1234:     var textRegExp = /^settext_/;
                   1235:     var tailLenient = /\.lenient$/;
                   1236:     var patternRelWeight = /^\-?[\d.]+$/;
                   1237:     var patternLenientStd = /^(yes|no|default)$/;
                   1238:     var ipallowRegExp = /^setipallow_/;
                   1239:     var ipdenyRegExp = /^setipdeny_/; 
                   1240:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1241:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1242:         if (document.parmform.elements.length) {
                   1243:             for (i=0; i<document.parmform.elements.length; i++) {
                   1244:                 var name=document.parmform.elements[i].name;
                   1245:                 if (textRegExp.test(name)) { 
                   1246:                     var identifier = name.replace(textRegExp,'');
                   1247:                     if (tailLenient.test(identifier)) {
                   1248:                         if (document.parmform.elements['set_'+identifier].length) {
                   1249:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1250:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1251:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1252:                                         var relweight = document.parmform.elements[i].value;
                   1253:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1254:                                         if (!patternRelWeight.test(relweight)) {
                   1255:                                             relweight = '0.0';
                   1256:                                         }
                   1257:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1258:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1259:                                         } else {
                   1260:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1261:                                         }
                   1262:                                     }
                   1263:                                     break;
                   1264:                                 }
                   1265:                             }
                   1266:                         }
                   1267:                     }
                   1268:                 } else {
                   1269:                     if (ipallowRegExp.test(name)) {
                   1270:                         var identifier = name.replace(ipallowRegExp,'');
                   1271:                         var possallow = document.parmform.elements[i].value;
                   1272:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1273:                         if (patternIP.test(possallow)) {
                   1274:                             if (document.parmform.elements['set_'+identifier].value) {
                   1275:                                 possallow = ','+possallow;
                   1276:                             }
                   1277:                             document.parmform.elements['set_'+identifier].value += possallow; 
                   1278:                         }
                   1279:                     } else {
                   1280:                         if (ipdenyRegExp.test(name)) {
                   1281:                             var identifier = name.replace(ipdenyRegExp,'');
                   1282:                             var possdeny = document.parmform.elements[i].value;
                   1283:                             possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1284:                             if (patternIP.test(possdeny)) {
                   1285:                                 possdeny = '!'+possdeny;
                   1286:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1287:                                     possdeny = ','+possdeny;
                   1288:                                 }
                   1289:                                 document.parmform.elements['set_'+identifier].value += possdeny;
                   1290:                             }
                   1291:                         }
                   1292:                     }
                   1293:                 }
                   1294:             }
                   1295:         }
                   1296:     }
                   1297:     return true;
                   1298: }
                   1299: 
                   1300: ENDSCRIPT
                   1301: }
                   1302: 
1.561     damieng  1303: # Javascript initialization, for overview mode
1.549     raeburn  1304: sub ipacc_boxes_js  {
                   1305:     my $remove = &mt('Remove');
                   1306:     return <<"END";
                   1307: \$(document).ready(function() {
                   1308:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1309:     var add_button      = \$(".LC_add_ipacc_button");
                   1310:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1311: 
                   1312:     \$(add_button).click(function(e){
                   1313:         e.preventDefault();
                   1314:         var identifier = \$(this).closest("div").attr("id");
                   1315:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1316:         \$(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  1317:     });
                   1318: 
                   1319:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1320:         e.preventDefault(); \$(this).closest("div").remove();
                   1321:     })
                   1322: });
                   1323: 
                   1324: 
                   1325: END
                   1326: }
                   1327: 
1.561     damieng  1328: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1329: sub done_proctor_js {
                   1330:     return <<"END";
                   1331: function toggleSecret(form,radio,key) {
                   1332:     var radios = form[radio+key];
                   1333:     if (radios.length) {
                   1334:         for (var i=0; i<radios.length; i++) {
                   1335:             if (radios[i].checked) {
                   1336:                 if (radios[i].value == '_done_proctor') {
                   1337:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1338:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1339:                     }
                   1340:                 } else {
                   1341:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1342:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1343:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1344:                     }
                   1345:                 }
                   1346:             }
                   1347:         }
                   1348:     }
                   1349: }
                   1350: END
                   1351: 
                   1352: }
                   1353: 
1.561     damieng  1354: # Prints HTML page start for table mode.
                   1355: # @param {Apache2::RequestRec} $r - the Apache request
                   1356: # @param {string} $psymb - resource symb
                   1357: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1358: sub startpage {
1.531     raeburn  1359:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1360: 
1.515     raeburn  1361:     my %loaditems = (
                   1362:                       'onload'   => "group_or_section('cgroup')",
                   1363:                     );
                   1364:     if (!$psymb) {
1.523     raeburn  1365:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1366:     }
1.280     albertel 1367: 
1.560     damieng  1368:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1369:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1370:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1371:             text=>"Problem Parameters"});
1.414     droeschl 1372:     } else {
1.560     damieng  1373:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1374:             text=>"Table Mode",
                   1375:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1376:     }
1.523     raeburn  1377:     my $js = &page_js().'
                   1378: <script type="text/javascript">
                   1379: // <![CDATA[
                   1380: '.
                   1381:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1382: // ]]>
                   1383: </script>
                   1384: ';
1.446     bisitz   1385:     my $start_page =
1.523     raeburn  1386:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1387:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1388:     my $breadcrumbs =
1.473     amueller 1389:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1390:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1391:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1392:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1393:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1394:     $r->print(<<ENDHEAD);
1.193     albertel 1395: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1396: <input type="hidden" value="" name="pres_value" />
                   1397: <input type="hidden" value="" name="pres_type" />
                   1398: <input type="hidden" value="" name="pres_marker" />
                   1399: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1400: <input type="hidden" value="$escfilter" name="filter" />
                   1401: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1402: ENDHEAD
                   1403: }
                   1404: 
1.209     www      1405: 
1.561     damieng  1406: # Prints a row for table mode (except for the tr start).
                   1407: # Every time a hash reference is passed, a single entry is used, so print_row
                   1408: # could just use these values, but why make it simple when it can be complicated ?
                   1409: #
                   1410: # @param {Apache2::RequestRec} $r - the Apache request
                   1411: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1412: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1413: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1414: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1415: # @param {string} $rid - resource id
                   1416: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1417: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1418: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1419: # @param {string} $defbgone - user level and other levels background color
                   1420: # @param {string} $defbgtwo - section level background color, also used for part number
                   1421: # @param {string} $defbgthree - group level background color
                   1422: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1423: # @param {string} $uname - user name
                   1424: # @param {string} $udom - user domain
                   1425: # @param {string} $csec - section name
                   1426: # @param {string} $cgroup - group name
                   1427: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1428: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1429: # @param {boolean} $readonly - true if no editing allowed.
                   1430: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1431: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1432: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1433: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1434: sub print_row {
1.201     www      1435:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1436:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1437:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1438:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1439:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1440:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1441:     my $numlinks = 0;
1.553     raeburn  1442: 
1.560     damieng  1443:     # get the values for the parameter in cascading order
                   1444:     # empty levels will remain empty
1.44      albertel 1445:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1446:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1447:     # get the type for the parameters
                   1448:     # problem: these may not be set for all levels
1.66      www      1449:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1450:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1451:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1452:     # cascade down manually
1.182     albertel 1453:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1454:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1455:         if ($typeoutpar[$i]) {
1.66      www      1456:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1457:         } else {
1.66      www      1458:             $typeoutpar[$i]=$cascadetype;
                   1459:         }
                   1460:     }
1.57      albertel 1461:     my $parm=$$display{$which};
                   1462: 
1.203     www      1463:     if ($parmlev eq 'full') {
1.419     bisitz   1464:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1465:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1466:     } else {
1.57      albertel 1467:         $parm=~s|\[.*\]\s||g;
                   1468:     }
1.231     www      1469:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1470:     if ($automatic) {
1.560     damieng  1471:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1472:     }
1.427     bisitz   1473:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1474: 
1.44      albertel 1475:     my $thismarker=$which;
                   1476:     $thismarker=~s/^parameter\_//;
                   1477:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1478:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1479:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
                   1480:         $eff_groupparm,$recurse_check,$recursinfo);
                   1481:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1482:         if ($result eq '') {
                   1483:             $recurse_check = 1;
                   1484:         } elsif (($uname ne '') && ($result > 3)) {
                   1485:             $recurse_check = 1;
                   1486:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1487:             $recurse_check = 1;
                   1488:         } elsif (($csec ne '') && ($result > 11)) {
                   1489:             $recurse_check = 1;
                   1490:         } elsif ($result > 17) {
                   1491:             $recurse_check = 1;
                   1492:         }
                   1493:         if ($recurse_check) {
                   1494:             my $what = $$part{$which}.'.'.$$name{$which};
                   1495:             my $prefix;
                   1496:             if (($uname ne '') && ($udom ne '')) {
                   1497:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1498:                 $prefix = $env{'request.course.id'};
                   1499:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1500:                 if (ref($recursinfo) eq 'ARRAY') {
                   1501:                     $effparm_rec = 1;
                   1502:                     $effparm_level = &mt('user: [_1]',$uname);
                   1503:                 }
                   1504:             }
                   1505:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1506:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1507:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1508:                 if (ref($recursinfo) eq 'ARRAY') {
                   1509:                     $effparm_rec = 1;
                   1510:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1511:                 }
                   1512:             }
                   1513:             if (($csec ne '') && (!$effparm_rec)) {
                   1514:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1515:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1516:                 if (ref($recursinfo) eq 'ARRAY') {
                   1517:                     $effparm_rec = 1;
                   1518:                     $effparm_level = &mt('section: [_1]',$csec);
                   1519:                 }
                   1520:             }
                   1521:             if (!$effparm_rec) {
                   1522:                 $prefix = $env{'request.course.id'};
                   1523:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1524:                 if (ref($recursinfo) eq 'ARRAY') {
                   1525:                     $effparm_rec = 1;
                   1526:                 }
                   1527:             }
                   1528:         }
                   1529:     }
                   1530:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1531:         $effparm_rec = 1;
                   1532:     }
                   1533:     if ((!$effparm_rec) && 
                   1534:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1535:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1536:         $effparm_rec = 1;
                   1537:     }
1.57      albertel 1538:     if ($parmlev eq 'general') {
                   1539:         if ($uname) {
1.568     raeburn  1540:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.269     raeburn  1541:         } elsif ($cgroup) {
1.568     raeburn  1542:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
1.57      albertel 1543:         } elsif ($csec) {
1.568     raeburn  1544:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1545:         } else {
1.568     raeburn  1546:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1547:         }
                   1548:     } elsif ($parmlev eq 'map') {
                   1549:         if ($uname) {
1.578     raeburn  1550:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1); 
1.269     raeburn  1551:         } elsif ($cgroup) {
1.578     raeburn  1552:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1);
1.57      albertel 1553:         } elsif ($csec) {
1.578     raeburn  1554:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
1.57      albertel 1555:         } else {
1.578     raeburn  1556:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
1.57      albertel 1557:         }
                   1558:     } else {
1.275     raeburn  1559:         if ($uname) {
                   1560:             if (@{$usersgroups} > 1) {
1.582     raeburn  1561:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1562:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1563:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1564:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1565:                     if (defined($controlgrp)) {
                   1566:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1567:                             $eff_groupparm = $grp_parm;
                   1568:                             undef($result);
                   1569:                             undef($effparm_rec);
                   1570:                             if ($grp_is_rec) {
                   1571:                                  $effparm_rec = 1;
                   1572:                             }
1.275     raeburn  1573:                         }
                   1574:                     }
                   1575:                 }
                   1576:             }
                   1577:         }
1.57      albertel 1578: 
1.568     raeburn  1579:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.578     raeburn  1580:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
1.568     raeburn  1581:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1582:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1583:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1584: 
                   1585:         if ($csec) {
1.568     raeburn  1586:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.578     raeburn  1587:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
1.568     raeburn  1588:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1589:         }
1.269     raeburn  1590: 
                   1591:         if ($cgroup) {
1.569     raeburn  1592:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
1.578     raeburn  1593:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1);
1.569     raeburn  1594:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly);
1.269     raeburn  1595:         }
1.446     bisitz   1596: 
1.548     raeburn  1597:         if ($uname) {
1.275     raeburn  1598:             if ($othergrp) {
                   1599:                 $r->print($othergrp);
                   1600:             }
1.568     raeburn  1601:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.578     raeburn  1602:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1);
1.568     raeburn  1603:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1604:         }
1.57      albertel 1605:     } # end of $parmlev if/else
1.582     raeburn  1606:     if (ref($recursinfo) eq 'ARRAY') {
                   1607:         my $rectitle = &mt('recursive');
                   1608:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1609:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1610:                 $rectitle = &mt('set in: [_1]','"'.
                   1611:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1612:                                                               "'$parmname','$$part{$which}'".');">'.
                   1613:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1614:               
                   1615:                 $numlinks ++;
                   1616:             }
                   1617:         }
                   1618:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1619:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1],$parmname);
                   1620:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1621:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1622:                   $effparm_level.'</span></td>');
                   1623:     } else {
                   1624:         if ($result) {
                   1625:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result],$parmname);
                   1626:         }
                   1627:         if ($eff_groupparm) {
                   1628:             $effective_parm = $eff_groupparm;
                   1629:         }
                   1630:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1631:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1632:                                 '</span>':'').'</td>');
                   1633:     }
1.203     www      1634:     if ($parmlev eq 'full') {
1.136     albertel 1635:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1636:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1637:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1638:         if (!defined($sessionvaltype)) {
                   1639:             $sessionvaltype=$$defaulttype{$which};
                   1640:         }
1.419     bisitz   1641:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.554     raeburn  1642:                   &valout($sessionval,$sessionvaltype,$$name{$which}).'&nbsp;'.
1.57      albertel 1643:                   '</font></td>');
1.136     albertel 1644:     }
1.44      albertel 1645:     $r->print('</tr>');
1.57      albertel 1646:     $r->print("\n");
1.582     raeburn  1647:     if (($numlinks) && (ref($reclinks))) {
                   1648:         $$reclinks = $numlinks;
                   1649:     }
1.44      albertel 1650: }
1.59      matthew  1651: 
1.561     damieng  1652: # Prints a cell for table mode.
                   1653: #
                   1654: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1655: # Also, it would make more sense to pass the display for this cell rather
                   1656: # than the full display hash and the key to use.
                   1657: #
                   1658: # @param {Apache2::RequestRec} $r - the Apache request
                   1659: # @param {integer} $which - level
                   1660: # @param {string} $defbg - cell background color
                   1661: # @param {integer} $result - the most specific level that is defined for that parameter
                   1662: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1663: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1664: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1665: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1666: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1667: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1668: # @param {boolean} $readonly -true if editing not allowed.
1.578     raeburn  1669: # @param {boolean} $ismaplevel - true if level is for a map. 
1.44      albertel 1670: sub print_td {
1.578     raeburn  1671:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
                   1672:         $noeditgrp,$readonly,$ismaplevel)=@_;
                   1673:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1674:     $ineffect = 0;
                   1675:     $currval = $$outpar[$which];
                   1676:     $currtype = $$typeoutpar[$which];
                   1677:     $currlevel = $which;
                   1678:     if (($result) && ($result == $which)) {
                   1679:         $ineffect = 1;
                   1680:     } 
                   1681:     if ($ismaplevel) {
                   1682:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1683:             if (($result) && ($result == $which)) {
                   1684:                 $recursive = 1;
                   1685:             }
                   1686:         } elsif ($$outpar[$which+1] ne '') {
                   1687:             $recursive = 1;
                   1688:             $currlevel = $which+1;
                   1689:             $currval = $$outpar[$currlevel];
                   1690:             $currtype = $$typeoutpar[$currlevel];
                   1691:             if (($result) && ($result == $currlevel)) {
                   1692:                 $ineffect = 1;
                   1693:             }
                   1694:         }
                   1695:     }
                   1696:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1697:               ';" align="center">');
1.437     raeburn  1698:     my $nolink = 0;
1.568     raeburn  1699:     if ($readonly) {
1.552     raeburn  1700:         $nolink = 1;
1.568     raeburn  1701:     } else { 
1.578     raeburn  1702:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1703:             $nolink = 1;
1.568     raeburn  1704:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1705:             $nolink = 1;
1.568     raeburn  1706:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1707:             if ($noeditgrp) {
                   1708:                 $nolink = 1;
                   1709:             }
                   1710:         } elsif ($mprefix =~ /availablestudent\&$/) {
                   1711:             if ($which > 4) {
                   1712:                 $nolink = 1;
                   1713:             }
                   1714:         } elsif ($mprefix =~ /examcode\&$/) {
                   1715:             unless ($which == 2) {
                   1716:                 $nolink = 1;
                   1717:             }
1.533     raeburn  1718:         }
1.437     raeburn  1719:     }
                   1720:     if ($nolink) {
1.577     raeburn  1721:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.578     raeburn  1722:         $r->print(&valout($currval,$currtype,$parmname));
1.114     www      1723:     } else {
1.578     raeburn  1724:         $r->print(&plink($currtype,
                   1725:                          $$display{$value},$currval,
                   1726:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive));
1.114     www      1727:     }
                   1728:     $r->print('</td>'."\n");
1.57      albertel 1729: }
                   1730: 
1.561     damieng  1731: # Returns HTML and other info for the cell added when a user is selected
                   1732: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1733: #
                   1734: # @param {string} $what - parameter part.'.'.parameter name
                   1735: # @param {string} $rid - resource id
                   1736: # @param {string} $cgroup - group name
                   1737: # @param {string} $defbg - cell background color
                   1738: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1739: # @param {integer} $result - level
                   1740: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1741: # @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  1742: sub check_other_groups {
                   1743:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1744:     my $courseid = $env{'request.course.id'};
                   1745:     my $output;
                   1746:     my $symb = &symbcache($rid);
                   1747:     my $symbparm=$symb.'.'.$what;
                   1748:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1749:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1750:     my $mapparm=$map.'___(all).'.$what;
                   1751:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1752:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1753:                               $recurseparm,$what,$courseopt);
1.275     raeburn  1754:     my $bgcolor = $defbg;
1.582     raeburn  1755:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   1756:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  1757:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  1758:         if ($result > 3) {
1.419     bisitz   1759:             $bgcolor = '#AAFFAA';
1.275     raeburn  1760:         }
1.582     raeburn  1761:         $grp_parm = &valout($coursereply,$resulttype,$parmname);
1.419     bisitz   1762:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  1763:         if ($resultgroup && $resultlevel) {
1.582     raeburn  1764:             if ($resultlevel eq 'recursive') {
                   1765:                 $resultlevel = 'map/folder';
                   1766:                 $grp_is_rec = 1;
                   1767:             }
                   1768:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   1769:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   1770:              
1.275     raeburn  1771:         } else {
                   1772:             $output .= '&nbsp;';
                   1773:         }
                   1774:         $output .= '</td>';
                   1775:     } else {
1.419     bisitz   1776:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  1777:     }
1.582     raeburn  1778:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  1779: }
                   1780: 
1.561     damieng  1781: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  1782: # Used by check_other_groups.
1.561     damieng  1783: #
                   1784: # @param {string} $courseid - the course id
                   1785: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1786: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   1787: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   1788: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   1789: # @param {string} $what - parameter part.'.'.parameter name
                   1790: # @param {hash reference} $courseopt - course parameters hash
                   1791: # @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  1792: sub parm_control_group {
1.556     raeburn  1793:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  1794:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1795:     my $grpfound = 0;
1.556     raeburn  1796:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   1797:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  1798:     foreach my $group (@{$usersgroups}) {
                   1799:         if ($grpfound) { last; }
                   1800:         for (my $i=0; $i<@levels; $i++) {
                   1801:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   1802:             if (defined($$courseopt{$item})) {
                   1803:                 $coursereply = $$courseopt{$item};
                   1804:                 $resultitem = $item;
                   1805:                 $resultgroup = $group;
                   1806:                 $resultlevel = $levelnames[$i];
                   1807:                 $resulttype = $$courseopt{$item.'.type'};
                   1808:                 $grpfound = 1;
                   1809:                 last;
                   1810:             }
                   1811:         }
                   1812:     }
                   1813:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1814: }
1.201     www      1815: 
1.63      bowersj2 1816: 
                   1817: 
1.562     damieng  1818: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   1819: # All the parameters are references and are filled by the sub.
                   1820: #
1.566     damieng  1821: # @param {array reference} $ids - resource and map ids
                   1822: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   1823: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  1824: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   1825: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  1826: # @param {hash reference} $allmaps - hash map pc -> map src
                   1827: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   1828: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   1829: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   1830: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  1831: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   1832: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63      bowersj2 1833: sub extractResourceInformation {
                   1834:     my $ids = shift;
                   1835:     my $typep = shift;
                   1836:     my $keyp = shift;
                   1837:     my $allparms = shift;
                   1838:     my $allparts = shift;
                   1839:     my $allmaps = shift;
                   1840:     my $mapp = shift;
                   1841:     my $symbp = shift;
1.82      www      1842:     my $maptitles=shift;
1.196     www      1843:     my $uris=shift;
1.210     www      1844:     my $keyorder=shift;
1.211     www      1845:     my $defkeytype=shift;
1.196     www      1846: 
1.210     www      1847:     my $keyordercnt=100;
1.63      bowersj2 1848: 
1.196     www      1849:     my $navmap = Apache::lonnavmaps::navmap->new();
                   1850:     my @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   1851:     foreach my $resource (@allres) {
1.480     amueller 1852:         my $id=$resource->id();
1.196     www      1853:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 1854:         if ($mapid eq '0') { next; }
                   1855:         $$ids[$#$ids+1]=$id;
                   1856:         my $srcf=$resource->src();
                   1857:         $srcf=~/\.(\w+)$/;
                   1858:         $$typep{$id}=$1;
1.584     raeburn  1859:         my $toolsymb;
                   1860:         if ($srcf =~ /ext\.tool$/) {
                   1861:             $toolsymb = $resource->symb();
                   1862:         }
1.480     amueller 1863:         $$keyp{$id}='';
1.196     www      1864:         $$uris{$id}=$srcf;
1.512     foxr     1865: 
1.584     raeburn  1866:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 1867:             next if ($key!~/^parameter_/);
1.363     albertel 1868: 
1.209     www      1869: # Hidden parameters
1.584     raeburn  1870:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      1871: #
                   1872: # allparms is a hash of parameter names
                   1873: #
1.584     raeburn  1874:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 1875:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   1876:                 my ($display,$parmdis);
                   1877:                 $display = &standard_parameter_names($name);
                   1878:                 if ($display eq '') {
1.584     raeburn  1879:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 1880:                     $parmdis = $display;
                   1881:                     $parmdis =~ s/\s*\[Part.*$//g;
                   1882:                 } else {
                   1883:                     $parmdis = &mt($display);
                   1884:                 }
                   1885:                 $$allparms{$name}=$parmdis;
                   1886:                 if (ref($defkeytype)) {
                   1887:                     $$defkeytype{$name}=
1.584     raeburn  1888:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 1889:                 }
                   1890:             }
1.363     albertel 1891: 
1.209     www      1892: #
                   1893: # allparts is a hash of all parts
                   1894: #
1.584     raeburn  1895:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 1896:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      1897: #
                   1898: # Remember all keys going with this resource
                   1899: #
1.480     amueller 1900:             if ($$keyp{$id}) {
                   1901:                 $$keyp{$id}.=','.$key;
                   1902:             } else {
                   1903:                 $$keyp{$id}=$key;
                   1904:             }   
1.210     www      1905: #
                   1906: # Put in order
1.446     bisitz   1907: #
1.480     amueller 1908:             unless ($$keyorder{$key}) {
                   1909:                 $$keyorder{$key}=$keyordercnt;
                   1910:                 $keyordercnt++;
                   1911:             }
1.473     amueller 1912:         }
                   1913: 
                   1914: 
1.480     amueller 1915:         if (!exists($$mapp{$mapid})) {
                   1916:             $$mapp{$id}=
                   1917:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   1918:             $$mapp{$mapid}=$$mapp{$id};
                   1919:             $$allmaps{$mapid}=$$mapp{$id};
                   1920:             if ($mapid eq '1') {
1.532     raeburn  1921:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 1922:             } else {
                   1923:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   1924:             }
                   1925:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  1926:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   1927:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   1928:                                                      # are commented out in rev. 1.57
1.473     amueller 1929:         } else {
1.480     amueller 1930:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 1931:         }
1.480     amueller 1932:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 1933:     }
                   1934: }
                   1935: 
1.582     raeburn  1936: sub get_recursive {
                   1937:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   1938:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   1939:         foreach my $item (@{$recurseup}) {
                   1940:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   1941:             if (defined($resdata->{$norecursechk})) {
                   1942:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   1943:                     my $type = $resdata->{$norecursechk.'.type'};
                   1944:                     return [$resdata->{$norecursechk},$type,$item];
                   1945:                 } else {
                   1946:                     last;
                   1947:                 }
                   1948:             }
                   1949:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   1950:             if (defined($resdata->{$recursechk})) {
                   1951:                 my $type = $resdata->{$recursechk.'.type'};
                   1952:                 return [$resdata->{$recursechk},$type,$item];
                   1953:             }
                   1954:         }
                   1955:     }
                   1956:     return;
                   1957: }
                   1958: 
1.208     www      1959: 
1.562     damieng  1960: # Tells if a parameter type is a date.
                   1961: #
                   1962: # @param {string} type - parameter type
                   1963: # @returns{boolean} - true if it is a date
1.213     www      1964: sub isdateparm {
                   1965:     my $type=shift;
                   1966:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   1967: }
                   1968: 
1.562     damieng  1969: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 1970: #
1.581     raeburn  1971: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      1972: sub parmmenu {
1.581     raeburn  1973:     my ($r)=@_;
1.208     www      1974:     $r->print(<<ENDSCRIPT);
                   1975: <script type="text/javascript">
1.454     bisitz   1976: // <![CDATA[
1.208     www      1977:     function checkall(value, checkName) {
1.453     schualex 1978: 
                   1979:         var li = "_li";
                   1980:         var displayOverview = "";
                   1981:         
                   1982:         if (value == false) {
                   1983:             displayOverview = "none"
                   1984:         }
                   1985: 
1.562     damieng  1986:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      1987:             ele = document.forms.parmform.elements[i];
                   1988:             if (ele.name == checkName) {
                   1989:                 document.forms.parmform.elements[i].checked=value;
                   1990:             }
                   1991:         }
                   1992:     }
1.210     www      1993: 
                   1994:     function checkthis(thisvalue, checkName) {
1.562     damieng  1995:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      1996:             ele = document.forms.parmform.elements[i];
                   1997:             if (ele.name == checkName) {
1.562     damieng  1998:                 if (ele.value == thisvalue) {
                   1999:                     document.forms.parmform.elements[i].checked=true;
                   2000:                 }
1.210     www      2001:             }
                   2002:         }
                   2003:     }
                   2004: 
                   2005:     function checkdates() {
1.562     damieng  2006:         checkthis('duedate','pscat');
                   2007:         checkthis('opendate','pscat');
                   2008:         checkthis('answerdate','pscat');
1.218     www      2009:     }
                   2010: 
                   2011:     function checkdisset() {
1.562     damieng  2012:         checkthis('discussend','pscat');
                   2013:         checkthis('discusshide','pscat');
                   2014:         checkthis('discussvote','pscat');
1.218     www      2015:     }
                   2016: 
                   2017:     function checkcontdates() {
1.562     damieng  2018:         checkthis('contentopen','pscat');
                   2019:         checkthis('contentclose','pscat');
1.218     www      2020:     }
1.446     bisitz   2021: 
1.210     www      2022:     function checkvisi() {
1.562     damieng  2023:         checkthis('hiddenresource','pscat');
                   2024:         checkthis('encrypturl','pscat');
                   2025:         checkthis('problemstatus','pscat');
                   2026:         checkthis('contentopen','pscat');
                   2027:         checkthis('opendate','pscat');
1.210     www      2028:     }
                   2029: 
                   2030:     function checkparts() {
1.562     damieng  2031:         checkthis('hiddenparts','pscat');
                   2032:         checkthis('display','pscat');
                   2033:         checkthis('ordered','pscat');
1.210     www      2034:     }
                   2035: 
                   2036:     function checkstandard() {
                   2037:         checkall(false,'pscat');
1.562     damieng  2038:         checkdates();
                   2039:         checkthis('weight','pscat');
                   2040:         checkthis('maxtries','pscat');
                   2041:         checkthis('type','pscat');
                   2042:         checkthis('problemstatus','pscat');
1.210     www      2043:     }
                   2044: 
1.454     bisitz   2045: // ]]>
1.208     www      2046: </script>
                   2047: ENDSCRIPT
1.453     schualex 2048: 
1.491     bisitz   2049:     $r->print('<hr />');
1.581     raeburn  2050:     &shortCuts($r);
1.491     bisitz   2051:     $r->print('<hr />');
1.453     schualex 2052: }
1.562     damieng  2053: 
                   2054: # Returns parameter categories.
                   2055: #
                   2056: # @returns {hash} - category name -> title in English
1.465     amueller 2057: sub categories {
                   2058:     return ('time_settings' => 'Time Settings',
                   2059:     'grading' => 'Grading',
                   2060:     'tries' => 'Tries',
                   2061:     'problem_appearance' => 'Problem Appearance',
                   2062:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2063:     'hiding' => 'Hiding',
                   2064:     'high_level_randomization' => 'High Level Randomization',
                   2065:     'slots' => 'Slots',
                   2066:     'file_submission' => 'File Submission',
                   2067:     'misc' => 'Miscellaneous' ); 
                   2068: }
                   2069: 
1.562     damieng  2070: # Returns the category for each parameter.
                   2071: #
                   2072: # @returns {hash} - parameter name -> category name
1.465     amueller 2073: sub lookUpTableParameter {
                   2074:  
                   2075:     return ( 
                   2076:         'opendate' => 'time_settings',
                   2077:         'duedate' => 'time_settings',
                   2078:         'answerdate' => 'time_settings',
                   2079:         'interval' => 'time_settings',
                   2080:         'contentopen' => 'time_settings',
                   2081:         'contentclose' => 'time_settings',
                   2082:         'discussend' => 'time_settings',
1.560     damieng  2083:         'printstartdate' => 'time_settings',
                   2084:         'printenddate' => 'time_settings',
1.465     amueller 2085:         'weight' => 'grading',
                   2086:         'handgrade' => 'grading',
                   2087:         'maxtries' => 'tries',
                   2088:         'hinttries' => 'tries',
1.503     raeburn  2089:         'randomizeontries' => 'tries',
1.465     amueller 2090:         'type' => 'problem_appearance',
                   2091:         'problemstatus' => 'problem_appearance',
                   2092:         'display' => 'problem_appearance',
                   2093:         'ordered' => 'problem_appearance',
                   2094:         'numbubbles' => 'problem_appearance',
                   2095:         'tol' => 'behaviour_of_input_fields',
                   2096:         'sig' => 'behaviour_of_input_fields',
                   2097:         'turnoffunit' => 'behaviour_of_input_fields',
                   2098:         'hiddenresource' => 'hiding',
                   2099:         'hiddenparts' => 'hiding',
                   2100:         'discusshide' => 'hiding',
                   2101:         'buttonshide' => 'hiding',
                   2102:         'turnoffeditor' => 'hiding',
                   2103:         'encrypturl' => 'hiding',
1.587   ! raeburn  2104:         'deeplink' => 'hiding',
1.465     amueller 2105:         'randomorder' => 'high_level_randomization',
                   2106:         'randompick' => 'high_level_randomization',
                   2107:         'available' => 'slots',
                   2108:         'useslots' => 'slots',
                   2109:         'availablestudent' => 'slots',
                   2110:         'uploadedfiletypes' => 'file_submission',
                   2111:         'maxfilesize' => 'file_submission',
                   2112:         'cssfile' => 'misc',
                   2113:         'mapalias' => 'misc',
                   2114:         'acc' => 'misc',
                   2115:         'maxcollaborators' => 'misc',
                   2116:         'scoreformat' => 'misc',
1.514     raeburn  2117:         'lenient' => 'grading',
1.519     raeburn  2118:         'retrypartial' => 'tries',
1.521     raeburn  2119:         'discussvote'  => 'misc',
1.584     raeburn  2120:         'examcode' => 'high_level_randomization',
1.575     raeburn  2121:     );
1.465     amueller 2122: }
                   2123: 
1.562     damieng  2124: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2125: #
                   2126: # @param {string} $name - parameter name
                   2127: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2128: sub whatIsMyCategory {
                   2129:     my $name = shift;
                   2130:     my $catList = shift;
                   2131:     my @list;
                   2132:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2133:     my $cat = $lookUpList{$name};
                   2134:     if (defined($cat)) {
                   2135:         if (!defined($$catList{$cat})){
                   2136:             push @list, ($name);
                   2137:             $$catList{$cat} = \@list;
                   2138:         } else {
                   2139:             push @{${$catList}{$cat}}, ($name);     
                   2140:         }
                   2141:     } else {
                   2142:         if (!defined($$catList{'misc'})){
                   2143:             push @list, ($name);
                   2144:             $$catList{'misc'} = \@list;
                   2145:         } else {
                   2146:             push @{${$catList}{'misc'}}, ($name);     
                   2147:         }
                   2148:     }        
                   2149: }
                   2150: 
1.562     damieng  2151: # Sorts parameter names based on appearance order.
                   2152: #
                   2153: # @param {array reference} name - array reference of parameter names
                   2154: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2155: # @returns {Array} - array of parameter names
1.465     amueller 2156: sub keysindisplayorderCategory {
                   2157:     my ($name,$keyorder)=@_;
                   2158:     return sort {
1.473     amueller 2159:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2160:     } ( @{$name});
                   2161: }
                   2162: 
1.562     damieng  2163: # Returns a hash category name -> order, starting at 1 (integer)
                   2164: #
                   2165: # @returns {hash}
1.467     amueller 2166: sub category_order {
                   2167:     return (
                   2168:         'time_settings' => 1,
                   2169:         'grading' => 2,
                   2170:         'tries' => 3,
                   2171:         'problem_appearance' => 4,
                   2172:         'hiding' => 5,
                   2173:         'behaviour_of_input_fields' => 6,
                   2174:         'high_level_randomization'  => 7,
                   2175:         'slots' => 8,
                   2176:         'file_submission' => 9,
                   2177:         'misc' => 10
                   2178:     );
                   2179: 
                   2180: }
1.453     schualex 2181: 
1.562     damieng  2182: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2183: #
                   2184: # @param {Apache2::RequestRec} $r - the Apache request
                   2185: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2186: # @param {array reference} $pscat - list of selected parameter names
                   2187: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2188: sub parmboxes {
                   2189:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2190:     my %categories = &categories();
1.467     amueller 2191:     my %category_order = &category_order();
1.465     amueller 2192:     my %categoryList = (
                   2193:         'time_settings' => [],
                   2194:         'grading' => [],
                   2195:         'tries' => [],
                   2196:         'problem_appearance' => [],
                   2197:         'behaviour_of_input_fields' => [],
                   2198:         'hiding' => [],
                   2199:         'high_level_randomization' => [],
                   2200:         'slots' => [],
                   2201:         'file_submission' => [],
                   2202:         'misc' => [],
1.489     bisitz   2203:     );
1.510     www      2204: 
1.548     raeburn  2205:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2206:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2207:     }
1.453     schualex 2208:     #part to print the parm-list
1.536     raeburn  2209:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2210:         next if (@{$categoryList{$key}} == 0);
                   2211:         next if ($key eq '');
                   2212:         $r->print('<div class="LC_Box LC_400Box">'
                   2213:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2214:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2215:             next if ($tempkey eq '');
1.536     raeburn  2216:             $r->print('<span class="LC_nobreak">'
                   2217:                      .'<label><input type="checkbox" name="pscat" '
                   2218:                      .'value="'.$tempkey.'" ');
                   2219:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2220:                 $r->print( ' checked="checked"');
                   2221:             }
                   2222:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2223:                                                       : $tempkey)
1.536     raeburn  2224:                      .'</label></span><br />'."\n");
1.465     amueller 2225:         }
1.536     raeburn  2226:         $r->print('</div>');
1.465     amueller 2227:     }
1.536     raeburn  2228:     $r->print("\n");
1.453     schualex 2229: }
1.562     damieng  2230: 
                   2231: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2232: #
1.562     damieng  2233: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2234: sub shortCuts {
1.581     raeburn  2235:     my ($r)=@_;
1.453     schualex 2236: 
1.491     bisitz   2237:     # Parameter Selection
                   2238:     $r->print(
                   2239:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2240:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2241:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2242:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2243:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2244:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2245:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2246:        .&Apache::lonhtmlcommon::end_funclist()
                   2247:     );
                   2248: 
                   2249:     # Add Selection for...
                   2250:     $r->print(
                   2251:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2252:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2253:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2254:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2255:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2256:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2257:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2258:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2259:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2260:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2261:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2262:        .&Apache::lonhtmlcommon::end_funclist()
                   2263:     );
1.208     www      2264: }
                   2265: 
1.562     damieng  2266: # Prints HTML to select parts to view (except for the title).
                   2267: # Used by table and overview modes.
                   2268: #
                   2269: # @param {Apache2::RequestRec} $r - the Apache request
                   2270: # @param {hash reference} $allparts - hash parameter part -> part title
                   2271: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2272: sub partmenu {
1.446     bisitz   2273:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2274:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2275:     if ($selsize > 8) {
                   2276:         $selsize = 8;
                   2277:     }
1.446     bisitz   2278: 
1.523     raeburn  2279:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2280:     $r->print('<option value="all"');
1.562     damieng  2281:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2282:     $r->print('>'.&mt('All Parts').'</option>');
                   2283:     my %temphash=();
                   2284:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2285:     foreach my $tempkey (sort {
1.560     damieng  2286:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2287:             } keys(%{$allparts})) {
                   2288:         unless ($tempkey =~ /\./) {
                   2289:             $r->print('<option value="'.$tempkey.'"');
                   2290:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2291:                 $r->print(' selected="selected"');
                   2292:             }
                   2293:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2294:         }
1.208     www      2295:     }
1.446     bisitz   2296:     $r->print('</select>');
1.209     www      2297: }
                   2298: 
1.562     damieng  2299: # Prints HTML to select a user and/or a group.
                   2300: # Used by table mode.
                   2301: #
                   2302: # @param {Apache2::RequestRec} $r - the Apache request
                   2303: # @param {string} $uname - selected user name
                   2304: # @param {string} $id - selected Student/Employee ID
                   2305: # @param {string} $udom - selected user domain
                   2306: # @param {string} $csec - selected section name
                   2307: # @param {string} $cgroup - selected group name
                   2308: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2309: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2310: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2311: sub usermenu {
1.553     raeburn  2312:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2313:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
                   2314:         &Apache::loncommon::selectstudent_link('parmform','uname','udom');
                   2315:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.412     bisitz   2316: 
1.209     www      2317:     my $sections='';
1.300     albertel 2318:     my %sectionhash = &Apache::loncommon::get_sections();
                   2319: 
1.269     raeburn  2320:     my $groups;
1.553     raeburn  2321:     my %grouphash;
                   2322:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2323:         %grouphash = &Apache::longroup::coursegroups();
                   2324:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2325:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2326:     }
1.299     albertel 2327: 
1.412     bisitz   2328:     my $g_s_header='';
                   2329:     my $g_s_footer='';
1.446     bisitz   2330: 
1.552     raeburn  2331:     my $currsec = $env{'request.course.sec'};
                   2332:     if ($currsec) {
                   2333:         $sections=&mt('Section:').' '.$currsec;
                   2334:         if (%grouphash) {
                   2335:             $sections .= ';'.('&nbsp;' x2);
                   2336:         }
                   2337:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2338:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2339:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2340:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2341:         }
                   2342:         $sections .= '>';
1.548     raeburn  2343:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2344:         $sections.='<option value="'.$section.'" '.
                   2345:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2346:                                                               '</option>';
1.209     www      2347:         }
                   2348:         $sections.='</select>';
1.269     raeburn  2349:     }
1.412     bisitz   2350: 
1.552     raeburn  2351:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2352:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2353:         $sections .= qq|
                   2354: <script type="text/javascript">
1.454     bisitz   2355: // <![CDATA[
1.269     raeburn  2356: function group_or_section(caller) {
                   2357:    if (caller == "cgroup") {
                   2358:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2359:            document.parmform.csec.selectedIndex = 0;
                   2360:        }
                   2361:    } else {
                   2362:        if (document.parmform.csec.selectedIndex != 0) {
                   2363:            document.parmform.cgroup.selectedIndex = 0;
                   2364:        }
                   2365:    }
                   2366: }
1.454     bisitz   2367: // ]]>
1.269     raeburn  2368: </script>
                   2369: |;
1.554     raeburn  2370:     } else {
1.269     raeburn  2371:         $sections .= qq|
                   2372: <script type="text/javascript">
1.454     bisitz   2373: // <![CDATA[
1.269     raeburn  2374: function group_or_section(caller) {
                   2375:     return;
                   2376: }
1.454     bisitz   2377: // ]]>
1.269     raeburn  2378: </script>
                   2379: |;
1.446     bisitz   2380:     }
1.299     albertel 2381: 
                   2382:     if (%grouphash) {
1.412     bisitz   2383:         $groups=&mt('Group:').' <select name="cgroup"';
1.552     raeburn  2384:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2385:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2386:         }
                   2387:         $groups .= '>';
1.548     raeburn  2388:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2389:             $groups.='<option value="'.$grp.'" ';
                   2390:             if ($grp eq $cgroup) {
                   2391:                 unless ((defined($uname)) && ($grp eq '')) {
                   2392:                     $groups .=  'selected="selected" ';
                   2393:                 }
                   2394:             } elsif (!defined($cgroup)) {
                   2395:                 if (@{$usersgroups} == 1) {
                   2396:                     if ($grp eq $$usersgroups[0]) {
                   2397:                         $groups .=  'selected="selected" ';
                   2398:                     }
                   2399:                 }
                   2400:             }
                   2401:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2402:         }
                   2403:         $groups.='</select>';
                   2404:     }
1.412     bisitz   2405: 
1.445     neumanie 2406:     if (%sectionhash || %grouphash) {
1.446     bisitz   2407:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2408:         $r->print($sections.$groups);
1.448     bisitz   2409:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2410:     } else {
                   2411:         $r->print($sections); 
1.445     neumanie 2412:     }
1.446     bisitz   2413: 
                   2414:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2415:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2416:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2417:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2418:                  ,$chooseopt));
1.209     www      2419: }
                   2420: 
1.562     damieng  2421: # Prints HTML to select parameters from a list of all parameters.
                   2422: # Uses parmmenu and parmboxes.
                   2423: # Used by table and overview modes.
1.468     amueller 2424: #
1.562     damieng  2425: # @param {Apache2::RequestRec} $r - the Apache request
                   2426: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2427: # @param {array reference} $pscat - list of selected parameter names
                   2428: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2429: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2430: sub displaymenu {
1.581     raeburn  2431:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2432: 
1.445     neumanie 2433:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2434:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2435: 
1.581     raeburn  2436:     &parmmenu($r);
1.536     raeburn  2437:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2438:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2439:     $r->print(&Apache::loncommon::end_scrollbox());
                   2440: 
                   2441:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2442:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2443:  
1.209     www      2444: }
                   2445: 
1.562     damieng  2446: # Prints HTML to select a map.
                   2447: # Used by table mode and overview mode.
                   2448: #
                   2449: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2450: # @param {hash reference} $allmaps - hash map pc -> map src
                   2451: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2452: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2453: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2454: sub mapmenu {
1.499     raeburn  2455:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2456:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2457:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2458:     my $tree=[];
                   2459:     my $treeinfo={};
                   2460:     if (defined($navmap)) {
1.499     raeburn  2461:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2462:         my $curRes;
                   2463:         my $depth = 0;
1.468     amueller 2464:         my %parent = ();
                   2465:         my $startcount = 5;
                   2466:         my $lastcontainer = $startcount;
                   2467: # preparing what is to show ...
1.461     neumanie 2468:         while ($curRes = $it->next()) {
                   2469:             if ($curRes == $it->BEGIN_MAP()) {
                   2470:                 $depth++;
1.468     amueller 2471:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2472:             }
                   2473:             if ($curRes == $it->END_MAP()) {
                   2474:                 $depth--;
1.468     amueller 2475:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2476:             }
                   2477:             if (ref($curRes)) {
1.468     amueller 2478:                 my $symb = $curRes->symb();
                   2479:                 my $ressymb = $symb;
1.461     neumanie 2480:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2481:                     my $type = 'sequence';
                   2482:                     if ($curRes->is_page()) {
                   2483:                         $type = 'page';
                   2484:                     }
                   2485:                     my $id= $curRes->id();
1.468     amueller 2486:                     my $srcf = $curRes->src();
                   2487:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2488:                     if(!exists($treeinfo->{$id})) {
                   2489:                         push(@$tree,$id);
1.473     amueller 2490:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2491:                         $treeinfo->{$id} = {
1.461     neumanie 2492:                                     depth => $depth,
                   2493:                                     type  => $type,
1.468     amueller 2494:                                     name  => $resource_name,
                   2495:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2496:                                     };
1.462     neumanie 2497:                     }
1.461     neumanie 2498:                 }
                   2499:             }
                   2500:         }
1.462     neumanie 2501:     }
1.473     amueller 2502: # Show it ...    
1.484     amueller 2503:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2504:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2505:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2506:         my $whitespace =
                   2507:             '<img src="'
                   2508:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2509:            .'" alt="" />';
                   2510: 
1.498     bisitz   2511:         # Info about selectable folders/maps
                   2512:         $r->print(
                   2513:             '<div class="LC_info">'
1.508     www      2514:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2515:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2516:            .'</div>'
                   2517:         );
                   2518: 
1.536     raeburn  2519:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2520:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2521: 
1.498     bisitz   2522:         # Display row: "All Maps or Folders"
                   2523:         $r->print(
1.523     raeburn  2524:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2525:            .'<td>'
                   2526:            .'<label>'
                   2527:            .'<input type="radio" name="pschp"'
1.497     bisitz   2528:         );
                   2529:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2530:         $r->print(
                   2531:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2532:            .&mt('All Maps or Folders')
                   2533:            .'</label>'
                   2534:            .'<hr /></td>'
                   2535:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2536:         );
1.497     bisitz   2537: 
1.532     raeburn  2538:         # Display row: "Main Content"
1.468     amueller 2539:         if (exists($$allmaps{1})) {
1.498     bisitz   2540:             $r->print(
                   2541:                 &Apache::loncommon::start_data_table_row()
                   2542:                .'<td>'
                   2543:                .'<label>'
                   2544:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2545:             );
1.497     bisitz   2546:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2547:             $r->print(
                   2548:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2549:                .$$maptitles{1}
                   2550:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2551:                .'</label>'
                   2552:                .'</td>'
                   2553:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2554:             );
                   2555:         }
1.497     bisitz   2556: 
                   2557:         # Display rows for all course maps and folders
1.468     amueller 2558:         foreach my $id (@{$tree}) {
                   2559:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2560:             # Indentation
1.468     amueller 2561:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2562:             my $indent;
                   2563:             for (my $i = 0; $i < $depth; $i++) {
                   2564:                 $indent.= $whitespace;
                   2565:             }
1.461     neumanie 2566:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2567:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2568:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2569:             }
1.468     amueller 2570:             my $symb_name = $$symbp{$id};
                   2571:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2572:             $symb_name = $tail;
1.498     bisitz   2573:             $r->print(
                   2574:                 &Apache::loncommon::start_data_table_row()
                   2575:                .'<td>'
                   2576:                .'<label>'
1.463     bisitz   2577:             );
1.498     bisitz   2578:             # Only offer radio button for folders/maps which can be parameterized
                   2579:             if ($allmaps_inverted{$symb_name}) {
                   2580:                 $r->print(
                   2581:                     '<input type ="radio" name="pschp"'
                   2582:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2583:                 );
                   2584:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2585:                 $r->print('/>');
                   2586:             } else {
                   2587:                 $r->print($whitespace);
1.461     neumanie 2588:             }
1.498     bisitz   2589:             $r->print(
                   2590:                 $indent.$icon.'&nbsp;'
                   2591:                .$treeinfo->{$id}->{name}
                   2592:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2593:                .'</label>'
                   2594:                .'</td>'
                   2595:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2596:             );
1.461     neumanie 2597:         }
1.497     bisitz   2598: 
1.523     raeburn  2599:         $r->print(&Apache::loncommon::end_data_table().
                   2600:                   '<br style="line-height:2px;" />'.
                   2601:                   &Apache::loncommon::end_scrollbox());
1.209     www      2602:     }
                   2603: }
                   2604: 
1.563     damieng  2605: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2606: # Used by table and overview modes.
                   2607: #
                   2608: # @param {Apache2::RequestRec} $r - the Apache request
                   2609: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2610: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2611: sub levelmenu {
1.446     bisitz   2612:     my ($r,$alllevs,$parmlev)=@_;
                   2613: 
1.548     raeburn  2614:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2615:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2616:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2617:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2618:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2619:         if ($parmlev eq $$alllevs{$lev}) {
                   2620:             $r->print(' selected="selected"');
                   2621:         }
                   2622:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2623:     }
1.446     bisitz   2624:     $r->print("</select>");
1.208     www      2625: }
                   2626: 
1.211     www      2627: 
1.563     damieng  2628: # Returns HTML to select a section (with a select HTML element).
                   2629: # Used by overview mode.
                   2630: #
                   2631: # @param {array reference} $selectedsections - list of selected section ids
                   2632: # @returns {string}
1.211     www      2633: sub sectionmenu {
1.553     raeburn  2634:     my ($selectedsections)=@_;
1.300     albertel 2635:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2636:     return '' if (!%sectionhash);
1.300     albertel 2637: 
1.552     raeburn  2638:     my (@possibles,$disabled);
                   2639:     if ($env{'request.course.sec'} ne '') {
                   2640:         @possibles = ($env{'request.course.sec'});
                   2641:         $selectedsections = [$env{'request.course.sec'}];
                   2642:         $disabled = ' disabled="disabled"';
                   2643:     } else {
                   2644:         @possibles = ('all',sort(keys(%sectionhash)));
                   2645:     }
1.553     raeburn  2646:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2647:     foreach my $s (@possibles) {
1.553     raeburn  2648:         $output .= '    <option value="'.$s.'"';
                   2649:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2650:             $output .= ' selected="selected"';
1.473     amueller 2651:         }
1.553     raeburn  2652:         $output .= '>'."$s</option>\n";
1.300     albertel 2653:     }
1.553     raeburn  2654:     $output .= "</select>\n";
                   2655:     return $output;
1.269     raeburn  2656: }
                   2657: 
1.563     damieng  2658: # Returns HTML to select a group (with a select HTML element).
                   2659: # Used by overview mode.
                   2660: #
                   2661: # @param {array reference} $selectedgroups - list of selected group names
                   2662: # @returns {string}
1.269     raeburn  2663: sub groupmenu {
1.553     raeburn  2664:     my ($selectedgroups)=@_;
                   2665:     my %grouphash;
                   2666:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2667:         %grouphash = &Apache::longroup::coursegroups();
                   2668:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2669:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2670:     }
                   2671:     return '' if (!%grouphash);
1.299     albertel 2672: 
1.553     raeburn  2673:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2674:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2675:         $output .= '    <option value="'.$group.'"';
                   2676:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2677:             $output .=  ' selected="selected"';
1.473     amueller 2678:         }
1.553     raeburn  2679:         $output .= '>'."$group</option>\n";
1.211     www      2680:     }
1.553     raeburn  2681:     $output .= "</select>\n";
                   2682:     return $output;
1.211     www      2683: }
                   2684: 
1.563     damieng  2685: # Returns an array with the given parameter split by comma.
                   2686: # Used by assessparms (table mode).
                   2687: #
                   2688: # @param {string} $keyp - the string to split
                   2689: # @returns {Array<string>}
1.210     www      2690: sub keysplit {
                   2691:     my $keyp=shift;
                   2692:     return (split(/\,/,$keyp));
                   2693: }
                   2694: 
1.563     damieng  2695: # Returns the keys in $name, sorted using $keyorder.
                   2696: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2697: # Used by assessparms (table mode) for resource level.
                   2698: #
                   2699: # @param {hash reference} $name - parameter key -> parameter name
                   2700: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2701: # @returns {Array<string>}
1.210     www      2702: sub keysinorder {
                   2703:     my ($name,$keyorder)=@_;
                   2704:     return sort {
1.560     damieng  2705:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2706:     } (keys(%{$name}));
1.210     www      2707: }
                   2708: 
1.563     damieng  2709: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   2710: # Used by assessparms (table mode) for map and general levels.
                   2711: #
                   2712: # @param {hash reference} $name - parameter key -> parameter name
                   2713: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2714: # @returns {Array<string>}
1.236     albertel 2715: sub keysinorder_bytype {
                   2716:     my ($name,$keyorder)=@_;
                   2717:     return sort {
1.563     damieng  2718:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  2719:         my $tb=(split('_',$b))[-1];
                   2720:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   2721:             return ($a cmp $b);
                   2722:         }
                   2723:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  2724:     } (keys(%{$name}));
1.236     albertel 2725: }
                   2726: 
1.563     damieng  2727: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   2728: # Used by defaultsetter (parameter settings default actions).
                   2729: #
                   2730: # @param {hash reference} $name - hash parameter name -> parameter title
                   2731: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2732: # @returns {Array<string>}
1.211     www      2733: sub keysindisplayorder {
                   2734:     my ($name,$keyorder)=@_;
                   2735:     return sort {
1.560     damieng  2736:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  2737:     } (keys(%{$name}));
1.211     www      2738: }
                   2739: 
1.563     damieng  2740: # Prints HTML with a choice to sort results by realm or student first.
                   2741: # Used by overview mode.
                   2742: #
                   2743: # @param {Apache2::RequestRec} $r - the Apache request
                   2744: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      2745: sub sortmenu {
                   2746:     my ($r,$sortorder)=@_;
1.236     albertel 2747:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      2748:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   2749:        $r->print(' checked="checked"');
1.214     www      2750:     }
                   2751:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 2752:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      2753:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   2754:        $r->print(' checked="checked"');
1.214     www      2755:     }
1.236     albertel 2756:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 2757:           '</label>');
1.214     www      2758: }
                   2759: 
1.563     damieng  2760: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   2761: #
                   2762: # @returns {hash}
1.211     www      2763: sub standardkeyorder {
                   2764:     return ('parameter_0_opendate' => 1,
1.473     amueller 2765:         'parameter_0_duedate' => 2,
                   2766:         'parameter_0_answerdate' => 3,
                   2767:         'parameter_0_interval' => 4,
                   2768:         'parameter_0_weight' => 5,
                   2769:         'parameter_0_maxtries' => 6,
                   2770:         'parameter_0_hinttries' => 7,
                   2771:         'parameter_0_contentopen' => 8,
                   2772:         'parameter_0_contentclose' => 9,
                   2773:         'parameter_0_type' => 10,
                   2774:         'parameter_0_problemstatus' => 11,
                   2775:         'parameter_0_hiddenresource' => 12,
                   2776:         'parameter_0_hiddenparts' => 13,
                   2777:         'parameter_0_display' => 14,
                   2778:         'parameter_0_ordered' => 15,
                   2779:         'parameter_0_tol' => 16,
                   2780:         'parameter_0_sig' => 17,
                   2781:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  2782:         'parameter_0_discussend' => 19,
                   2783:         'parameter_0_discusshide' => 20,
                   2784:         'parameter_0_discussvote' => 21,
1.560     damieng  2785:         'parameter_0_printstartdate'  =>  22,
                   2786:         'parameter_0_printenddate' =>  23);
1.211     www      2787: }
                   2788: 
1.59      matthew  2789: 
1.560     damieng  2790: # Table mode UI.
1.563     damieng  2791: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   2792: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   2793: #
                   2794: # Parameters used from the request:
                   2795: # action - handler action (see handler), usermenu is checking for value 'settable'
                   2796: # cgroup - selected group
                   2797: # command - 'set': direct access to table mode for a resource
                   2798: # csec - selected section
                   2799: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   2800: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   2801: # id - student/employee ID
                   2802: # parmlev - selected level (full|map|general)
                   2803: # part - selected part (unused ?)
                   2804: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   2805: # pres_type - &&&-separated parameter types
                   2806: # pres_value - &&&-separated parameter values
                   2807: # prevvisit - '1' if the user has submitted the form before
                   2808: # pscat (multiple values) - selected parameter names
1.566     damieng  2809: # pschp - selected map pc, or 'all'
1.563     damieng  2810: # psprt (multiple values) - list of selected parameter parts
                   2811: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   2812: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   2813: # symb - resource symb (when a single resource is selected)
                   2814: # udom - selected user domain
                   2815: # uname - selected user name
                   2816: # url - used only with command 'set', the resource url
                   2817: #
                   2818: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  2819: # @param $parm_permission - ref to hash of permissions
                   2820: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      2821: sub assessparms {
1.1       www      2822: 
1.568     raeburn  2823:     my ($r,$parm_permission) = @_;
1.201     www      2824: 
1.512     foxr     2825: 
                   2826: # -------------------------------------------------------- Variable declaration
1.566     damieng  2827:     my @ids=(); # resource and map ids
                   2828:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   2829:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   2830:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   2831:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   2832:     my %uris=(); # hash resource/map id -> resource src
                   2833:     my %maptitles=(); # hash map pc or src -> map title
                   2834:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  2835:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  2836:     my %alllevs=(); # hash English level title -> value
                   2837: 
                   2838:     my $uname; # selected user name
                   2839:     my $udom; # selected user domain
                   2840:     my $uhome; # server with the user's files, or 'no_host'
                   2841:     my $csec; # selected section name
                   2842:     my $cgroup; # selected group name
                   2843:     my @usersgroups = (); # list of the user groups
1.582     raeburn  2844:     my $numreclinks = 0;
1.446     bisitz   2845: 
1.190     albertel 2846:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      2847: 
1.57      albertel 2848:     $alllevs{'Resource Level'}='full';
1.215     www      2849:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 2850:     $alllevs{'Course Level'}='general';
                   2851: 
1.563     damieng  2852:     my %allparms; # hash parameter name -> parameter title
                   2853:     my %allparts; # hash parameter part -> part title
1.512     foxr     2854: # ------------------------------------------------------------------------------
                   2855: 
1.210     www      2856: #
                   2857: # Order in which these parameters will be displayed
                   2858: #
1.211     www      2859:     my %keyorder=&standardkeyorder();
                   2860: 
1.512     foxr     2861: #    @ids=();
                   2862: #    %symbp=();       # These seem defined above already.
                   2863: #    %typep=();
1.43      albertel 2864: 
                   2865:     my $message='';
                   2866: 
1.190     albertel 2867:     $csec=$env{'form.csec'};
1.552     raeburn  2868:     if ($env{'request.course.sec'} ne '') {
                   2869:         $csec = $env{'request.course.sec'};    
                   2870:     }
                   2871: 
1.553     raeburn  2872: # Check group privs.
1.269     raeburn  2873:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  2874:     my $noeditgrp; 
                   2875:     if ($cgroup ne '') {
                   2876:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2877:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  2878:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  2879:                 $noeditgrp = 1;
                   2880:             }
                   2881:         }
                   2882:     }
1.188     www      2883: 
1.190     albertel 2884:     if      ($udom=$env{'form.udom'}) {
                   2885:     } elsif ($udom=$env{'request.role.domain'}) {
                   2886:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 2887:     } else {
1.473     amueller 2888:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 2889:     }
1.468     amueller 2890:     
1.43      albertel 2891: 
1.134     albertel 2892:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 2893:     my $pschp=$env{'form.pschp'};
1.506     www      2894: 
                   2895: 
1.134     albertel 2896:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      2897:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      2898:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 2899: 
1.43      albertel 2900:     my $pssymb='';
1.57      albertel 2901:     my $parmlev='';
1.446     bisitz   2902: 
1.190     albertel 2903:     unless ($env{'form.parmlev'}) {
1.57      albertel 2904:         $parmlev = 'map';
                   2905:     } else {
1.190     albertel 2906:         $parmlev = $env{'form.parmlev'};
1.57      albertel 2907:     }
1.26      www      2908: 
1.29      www      2909: # ----------------------------------------------- Was this started from grades?
                   2910: 
1.560     damieng  2911:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   2912:             (!$env{'form.dis'})) {
1.473     amueller 2913:         my $url=$env{'form.url'};
                   2914:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   2915:         $pssymb=&Apache::lonnet::symbread($url);
                   2916:         if (!@pscat) { @pscat=('all'); }
                   2917:         $pschp='';
1.57      albertel 2918:         $parmlev = 'full';
1.190     albertel 2919:     } elsif ($env{'form.symb'}) {
1.473     amueller 2920:         $pssymb=$env{'form.symb'};
                   2921:         if (!@pscat) { @pscat=('all'); }
                   2922:         $pschp='';
1.57      albertel 2923:         $parmlev = 'full';
1.43      albertel 2924:     } else {
1.473     amueller 2925:         $env{'form.url'}='';
1.43      albertel 2926:     }
                   2927: 
1.190     albertel 2928:     my $id=$env{'form.id'};
1.43      albertel 2929:     if (($id) && ($udom)) {
1.555     raeburn  2930:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 2931:         if ($uname) {
                   2932:             $id='';
                   2933:         } else {
                   2934:             $message=
1.540     bisitz   2935:                 '<p class="LC_warning">'.
                   2936:                 &mt('Unknown ID [_1] at domain [_2]',
                   2937:                     "'".$id."'","'".$udom."'").
                   2938:                 '</p>';
1.473     amueller 2939:         }
1.43      albertel 2940:     } else {
1.473     amueller 2941:         $uname=$env{'form.uname'};
1.43      albertel 2942:     }
                   2943:     unless ($udom) { $uname=''; }
                   2944:     $uhome='';
                   2945:     if ($uname) {
1.473     amueller 2946:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 2947:         if ($uhome eq 'no_host') {
1.473     amueller 2948:             $message=
1.540     bisitz   2949:                 '<p class="LC_warning">'.
                   2950:                 &mt('Unknown user [_1] at domain [_2]',
                   2951:                     "'".$uname."'","'".$udom."'").
                   2952:                 '</p>';
1.473     amueller 2953:             $uname='';
1.12      www      2954:         } else {
1.473     amueller 2955:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   2956:                           $env{'request.course.id'});
                   2957:             if ($csec eq '-1') {
1.540     bisitz   2958:                 $message=
                   2959:                     '<p class="LC_warning">'.
                   2960:                     &mt('User [_1] at domain [_2] not in this course',
                   2961:                         "'".$uname."'","'".$udom."'").
                   2962:                     '</p>';
1.473     amueller 2963:                 $uname='';
                   2964:                 $csec=$env{'form.csec'};
1.269     raeburn  2965:                 $cgroup=$env{'form.cgroup'};
1.473     amueller 2966:             } else {
                   2967:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   2968:                   ('firstname','middlename','lastname','generation','id'));
                   2969:                 $message="\n<p>\n".&mt("Full Name").": ".
                   2970:                 $name{'firstname'}.' '.$name{'middlename'}.' '
                   2971:                 .$name{'lastname'}.' '.$name{'generation'}.
1.501     bisitz   2972:                 "<br />\n".&mt('Student/Employee ID').": ".$name{'id'}.'<p>';
1.473     amueller 2973:             }
1.297     raeburn  2974:             @usersgroups = &Apache::lonnet::get_users_groups(
1.275     raeburn  2975:                                        $udom,$uname,$env{'request.course.id'});
1.297     raeburn  2976:             if (@usersgroups > 0) {
1.306     albertel 2977:                 unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
1.275     raeburn  2978:                     $cgroup = $usersgroups[0];
1.297     raeburn  2979:                 }
1.269     raeburn  2980:             }
1.12      www      2981:         }
1.43      albertel 2982:     }
1.2       www      2983: 
1.43      albertel 2984:     unless ($csec) { $csec=''; }
1.269     raeburn  2985:     unless ($cgroup) { $cgroup=''; }
1.12      www      2986: 
1.14      www      2987: # --------------------------------------------------------- Get all assessments
1.446     bisitz   2988:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 2989:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   2990:                 \%keyorder);
1.63      bowersj2 2991: 
1.582     raeburn  2992:     %allmaps_inverted = reverse(%allmaps);
                   2993: 
1.57      albertel 2994:     $mapp{'0.0'} = '';
                   2995:     $symbp{'0.0'} = '';
1.99      albertel 2996: 
1.14      www      2997: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  2998:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      2999:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3000:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3001:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3002:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3003:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3004:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3005:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3006:         my $totalstored = 0;
1.546     raeburn  3007:         my $now = time;
1.473     amueller 3008:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3009:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3010:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3011:                 next if ($csec ne $env{'request.course.sec'});
                   3012:             }
1.556     raeburn  3013:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3014:                 next if ($noeditgrp);
1.557     raeburn  3015:             }
                   3016:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3017:                 $namematch = 'maplevelrecurse';
                   3018:             }
1.556     raeburn  3019:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3020:                 my (@ok_slots,@fail_slots,@del_slots);
                   3021:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3022:                 my ($level,@all) =
                   3023:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3024:                                      $csec,$cgroup,$courseopt);
                   3025:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3026:                     next if ($slot_name eq '');
                   3027:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3028:                         push(@ok_slots,$slot_name);
                   3029: 
                   3030:                     } else {
                   3031:                         push(@fail_slots,$slot_name);
                   3032:                     }
                   3033:                 }
                   3034:                 if (@ok_slots) {
                   3035:                     $values[$i] = join(':',@ok_slots);
                   3036:                 } else {
                   3037:                     $values[$i] = '';
                   3038:                 }
                   3039:                 if ($all[$level] ne '') {
                   3040:                     my @existing = split(/:/,$all[$level]);
                   3041:                     foreach my $slot_name (@existing) {
                   3042:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3043:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3044:                                 push(@del_slots,$slot_name);
                   3045:                             }
                   3046:                         }
                   3047:                     }
                   3048:                 }
1.554     raeburn  3049:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3050:                 $name = $1;
1.533     raeburn  3051:                 my $val = $values[$i];
1.549     raeburn  3052:                 my $valmatch = '';
1.533     raeburn  3053:                 if ($name eq 'examcode') {
1.544     raeburn  3054:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3055:                         $val = 'valid';
                   3056:                     }
1.546     raeburn  3057:                 } elsif ($name eq 'printstartdate') {
                   3058:                     if ($val =~ /^\d+$/) {
                   3059:                         if ($val > $now) {
                   3060:                             $val = 'future';
                   3061:                         }
                   3062:                     } 
                   3063:                 } elsif ($name eq 'printenddate') {
                   3064:                     if ($val =~ /^\d+$/) {
                   3065:                         if ($val < $now) {
                   3066:                             $val = 'past';
                   3067:                         }
                   3068:                     }
1.549     raeburn  3069:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3070:                     my $stringtype = &get_stringtype($name);
                   3071:                     my $stringmatch = &standard_string_matches($stringtype);
                   3072:                     if (ref($stringmatch) eq 'ARRAY') {
                   3073:                         foreach my $item (@{$stringmatch}) {
                   3074:                             if (ref($item) eq 'ARRAY') {
                   3075:                                 my ($regexpname,$pattern) = @{$item};
                   3076:                                 if ($pattern ne '') {
                   3077:                                     if ($val =~ /$pattern/) {
                   3078:                                         $valmatch = $regexpname;
                   3079:                                         $val = '';
                   3080:                                         last;
                   3081:                                     }
                   3082:                                 }
                   3083:                             }
                   3084:                         }
                   3085:                     }
1.554     raeburn  3086:                 } elsif ($name eq 'interval') {
                   3087:                     my $intervaltype = &get_intervaltype($name);
                   3088:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3089:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3090:                         foreach my $item (@{$intervalmatch}) {
                   3091:                             if (ref($item) eq 'ARRAY') {
                   3092:                                 my ($regexpname,$pattern) = @{$item};
                   3093:                                 if ($pattern ne '') {
                   3094:                                     if ($val =~ /$pattern/) {
                   3095:                                         $valmatch = $regexpname;
                   3096:                                         $val = '';
                   3097:                                         last;
                   3098:                                     }
                   3099:                                 }
                   3100:                             }
                   3101:                         }
                   3102:                     }
1.533     raeburn  3103:                 }
1.504     raeburn  3104:                 $needsrelease =
1.557     raeburn  3105:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3106:                 if ($needsrelease) {
1.505     raeburn  3107:                     unless ($got_chostname) {
1.514     raeburn  3108:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3109:                         $got_chostname = 1;
1.546     raeburn  3110:                     } 
1.557     raeburn  3111:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3112:                                                           $needsrelease,
                   3113:                                                           $cmajor,$cminor);
1.500     raeburn  3114:                 }
1.437     raeburn  3115:             }
1.504     raeburn  3116:             if ($needsnewer) {
1.557     raeburn  3117:                 undef($namematch);
                   3118:             } else {
                   3119:                 my $currneeded;
                   3120:                 if ($needsrelease) {
                   3121:                     $currneeded = $needsrelease;
                   3122:                 }
                   3123:                 if ($namematch) {
                   3124:                     $needsrelease =
                   3125:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3126:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3127:                         unless ($got_chostname) {
                   3128:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3129:                             $got_chostname = 1;
                   3130:                         }
                   3131:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3132:                                                               $needsrelease,
                   3133:                                                               $cmajor,$cminor);
                   3134:                     } else {
                   3135:                         undef($namematch);
                   3136:                     }
                   3137:                 }
                   3138:             }
                   3139:             if ($needsnewer) {
                   3140:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3141:                                                 $cminor,$needsrelease);
                   3142:             } else {
                   3143:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3144:                                      $values[$i],
                   3145:                                      $types[$i],
                   3146:                                      $uname,$udom,$csec,$cgroup);
                   3147:                 $totalstored ++;
                   3148:             }
1.473     amueller 3149:         }
1.68      www      3150: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3151:         if ($totalstored) {
                   3152:             $message.='<p class="LC_warning">'
                   3153:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3154:                      .&Apache::loncommon::help_open_topic('Caching')
                   3155:                      .'</p>';
                   3156:         }
1.68      www      3157:     }
1.584     raeburn  3158: 
1.57      albertel 3159: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3160:     if ($pscat[0] eq "all") {
                   3161:         @pscat = (keys(%allparms));
                   3162:     }
                   3163:     if (!@pscat) {
                   3164:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3165:     };
                   3166:     if ($psprt[0] eq "all" || !@psprt) {
                   3167:         @psprt = (keys(%allparts));
                   3168:     }
1.2       www      3169: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3170: 
1.531     raeburn  3171:     my $crstype = &Apache::loncommon::course_type();
                   3172:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3173: 
1.548     raeburn  3174:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.563     damieng  3175:             'date_interval','int','float','string') {
1.473     amueller 3176:         $r->print('<input type="hidden" value="'.
1.563     damieng  3177:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3178:             '" name="recent_'.$item.'" />');
1.44      albertel 3179:     }
1.446     bisitz   3180: 
1.459     bisitz   3181:     # ----- Start Parameter Selection
                   3182: 
                   3183:     # Hide parm selection?
                   3184:     $r->print(<<ENDPARMSELSCRIPT);
                   3185: <script type="text/javascript">
                   3186: // <![CDATA[
                   3187: function parmsel_show() {
1.562     damieng  3188:     document.getElementById('parmsel').style.display = "";
                   3189:     document.getElementById('parmsellink').style.display = "none";
1.459     bisitz   3190: }
                   3191: // ]]>
                   3192: </script>
                   3193: ENDPARMSELSCRIPT
1.474     amueller 3194:     
1.445     neumanie 3195:     if (!$pssymb) {
1.563     damieng  3196:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3197:         my $parmselhiddenstyle=' style="display:none"';
                   3198:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3199:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3200:         } else  {
                   3201:            $r->print('<div id="parmsel">');
                   3202:         }
                   3203: 
1.491     bisitz   3204:         # Step 1
1.523     raeburn  3205:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3206:         $r->print('
1.474     amueller 3207: <script type="text/javascript">
1.523     raeburn  3208: // <![CDATA['.
                   3209:                  &showhide_js().'
1.474     amueller 3210: // ]]>
                   3211: </script>
1.523     raeburn  3212: ');
                   3213:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3214:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3215:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3216:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3217:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3218:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3219:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3220:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3221:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3222: 
                   3223:         # Step 2
1.523     raeburn  3224:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3225:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3226: 
                   3227:         # Step 3
1.523     raeburn  3228:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3229:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3230:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3231:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3232:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3233: 
                   3234:         # Update Display Button
1.486     www      3235:         $r->print('<p>'
                   3236:              .'<input type="submit" name="dis"'
1.511     www      3237:              .' value="'.&mt('Update Display').'" />'
1.486     www      3238:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3239:              .'</p>');
                   3240:         $r->print('</div>');
1.491     bisitz   3241: 
1.486     www      3242:         # Offer link to display parameter selection again
                   3243:         $r->print('<p id="parmsellink"');
                   3244:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3245:            $r->print($parmselhiddenstyle);
                   3246:         }
                   3247:         $r->print('>'
                   3248:              .'<a href="javascript:parmsel_show()">'
                   3249:              .&mt('Change Parameter Selection')
                   3250:              .'</a>'
                   3251:              .'</p>');
1.44      albertel 3252:     } else {
1.478     amueller 3253:         # parameter screen for a single resource. 
1.486     www      3254:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3255:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3256:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3257:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3258:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3259:                   '<br />');
                   3260:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3261:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3262:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3263:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3264:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3265:         $r->print('<p>'
1.459     bisitz   3266:              .'<input type="submit" name="dis"'
1.511     www      3267:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3268:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3269:              .'</p>');
1.459     bisitz   3270:     }
1.478     amueller 3271:     
1.486     www      3272:     # ----- End Parameter Selection
1.57      albertel 3273: 
1.459     bisitz   3274:     # Display Messages
                   3275:     $r->print('<div>'.$message.'</div>');
1.210     www      3276: 
1.57      albertel 3277: 
                   3278:     my @temp_pscat;
                   3279:     map {
                   3280:         my $cat = $_;
                   3281:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3282:     } @pscat;
                   3283: 
                   3284:     @pscat = @temp_pscat;
                   3285: 
1.548     raeburn  3286: 
1.209     www      3287:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3288: # ----------------------------------------------------------------- Start Table
1.57      albertel 3289:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3290:         my $csuname=$env{'user.name'};
                   3291:         my $csudom=$env{'user.domain'};
1.568     raeburn  3292:         my $readonly = 1;
                   3293:         if ($parm_permission->{'edit'}) {
                   3294:             undef($readonly); 
                   3295:         }
1.57      albertel 3296: 
1.203     www      3297:         if ($parmlev eq 'full') {
1.506     www      3298: #
                   3299: # This produces the cascading table output of parameters
                   3300: #
1.578     raeburn  3301:             my $coursespan=$csec?8:5;
                   3302:             my $userspan=3;
1.560     damieng  3303:             if ($cgroup ne '') {
1.578     raeburn  3304:                 $coursespan += 3;
1.560     damieng  3305:             }
1.473     amueller 3306: 
1.560     damieng  3307:             $r->print(&Apache::loncommon::start_data_table());
                   3308:             #
                   3309:             # This produces the headers
                   3310:             #
                   3311:             $r->print('<tr><td colspan="5"></td>');
                   3312:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3313:             if ($uname) {
1.473     amueller 3314:                 if (@usersgroups > 1) {
1.560     damieng  3315:                     $userspan ++;
                   3316:                 }
                   3317:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3318:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3319:             }
                   3320:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3321:                 'pie'    => "Parameter in Effect",
                   3322:                 'csv'    => "Current Session Value",
1.472     amueller 3323:                 'rl'     => "Resource Level",
1.473     amueller 3324:                 'ic'     => 'in Course',
                   3325:                 'aut'    => "Assessment URL and Title",
                   3326:                 'type'   => 'Type',
                   3327:                 'emof'   => "Enclosing Map or Folder",
                   3328:                 'part'   => 'Part',
1.472     amueller 3329:                 'pn'     => 'Parameter Name',
1.473     amueller 3330:                 'def'    => 'default',
                   3331:                 'femof'  => 'from Enclosing Map or Folder',
                   3332:                 'gen'    => 'general',
                   3333:                 'foremf' => 'for Enclosing Map or Folder',
                   3334:                 'fr'     => 'for Resource'
                   3335:             );
1.560     damieng  3336:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3337: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3338: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3339: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3340: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3341: 
1.10      www      3342: ENDTABLETWO
1.560     damieng  3343:             if ($csec) {
1.578     raeburn  3344:                 $r->print('<th colspan="3">'.
1.560     damieng  3345:                 &mt("in Section")." $csec</th>");
                   3346:             }
                   3347:             if ($cgroup) {
1.578     raeburn  3348:                 $r->print('<th colspan="3">'.
1.472     amueller 3349:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3350:             }
                   3351:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3352: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3353: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3354: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3355: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3356: ENDTABLEHEADFOUR
1.57      albertel 3357: 
1.560     damieng  3358:             if ($csec) {
1.578     raeburn  3359:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3360:             }
1.473     amueller 3361: 
1.560     damieng  3362:             if ($cgroup) {
1.578     raeburn  3363:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3364:             }
                   3365: 
                   3366:             if ($uname) {
                   3367:                 if (@usersgroups > 1) {
                   3368:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3369:                 }
1.578     raeburn  3370:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3371:             }
                   3372: 
                   3373:             $r->print('</tr>');
1.506     www      3374: #
                   3375: # Done with the headers
                   3376: # 
1.560     damieng  3377:             my $defbgone='';
                   3378:             my $defbgtwo='';
                   3379:             my $defbgthree = '';
1.57      albertel 3380: 
1.560     damieng  3381:             foreach my $rid (@ids) {
1.57      albertel 3382: 
                   3383:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3384:                 if ((!$pssymb &&
1.560     damieng  3385:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3386:                         ||
                   3387:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3388: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3389:                     if ($defbgone eq '#E0E099') {
                   3390:                         $defbgone='#E0E0DD';
1.57      albertel 3391:                     } else {
1.419     bisitz   3392:                         $defbgone='#E0E099';
1.57      albertel 3393:                     }
1.419     bisitz   3394:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3395:                         $defbgtwo='#FFFFDD';
1.57      albertel 3396:                     } else {
1.473     amueller 3397:                         $defbgtwo='#FFFF99';
1.57      albertel 3398:                     }
1.419     bisitz   3399:                     if ($defbgthree eq '#FFBB99') {
                   3400:                         $defbgthree='#FFBBDD';
1.269     raeburn  3401:                     } else {
1.419     bisitz   3402:                         $defbgthree='#FFBB99';
1.269     raeburn  3403:                     }
                   3404: 
1.57      albertel 3405:                     my $thistitle='';
                   3406:                     my %name=   ();
                   3407:                     undef %name;
                   3408:                     my %part=   ();
                   3409:                     my %display=();
                   3410:                     my %type=   ();
                   3411:                     my %default=();
1.196     www      3412:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3413:                     my $toolsymb;
                   3414:                     if ($uri =~ /ext\.tool$/) {
                   3415:                         $toolsymb = $symbp{$rid};
                   3416:                     }
1.57      albertel 3417: 
1.506     www      3418:                     my $filter=$env{'form.filter'};
1.548     raeburn  3419:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3420:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3421:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3422:     # We may only want certain parameters listed
                   3423:                             if ($filter) {
                   3424:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3425:                             }
                   3426:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3427:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3428: 
1.584     raeburn  3429:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3430:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3431:                                 my $identifier;
                   3432:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3433:                                     $identifier = $1;
                   3434:                                 }
                   3435:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3436:                             } else {
                   3437:                                 $display{$tempkeyp} = $parmdis;
                   3438:                             }
                   3439:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3440:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3441:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3442:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3443:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3444:                         }
                   3445:                     }
1.548     raeburn  3446:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3447:                     if ($totalparms>0) {
1.560     damieng  3448:                         my $firstrow=1;
1.473     amueller 3449:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3450:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3451:                         my @recurseup;
                   3452:                         if (ref($navmap) && $mapp{$rid}) {
                   3453:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3454:                         }
1.419     bisitz   3455:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3456:                              ' rowspan='.$totalparms.
1.419     bisitz   3457:                              '><tt><font size="-1">'.
1.57      albertel 3458:                              join(' / ',split(/\//,$uri)).
                   3459:                              '</font></tt><p><b>'.
1.154     albertel 3460:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3461:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3462:                           &escape($symbp{$rid}).
1.336     albertel 3463:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3464:                              " target=\"_self\">$title");
1.57      albertel 3465: 
                   3466:                         if ($thistitle) {
1.473     amueller 3467:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3468:                         }
                   3469:                         $r->print('</a></b></td>');
1.419     bisitz   3470:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3471:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3472:                                       '</td>');
                   3473: 
1.419     bisitz   3474:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3475:                                       ' rowspan='.$totalparms.
1.238     www      3476:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3477:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3478:                             unless ($firstrow) {
                   3479:                                 $r->print('<tr>');
                   3480:                             } else {
                   3481:                                 undef $firstrow;
                   3482:                             }
1.548     raeburn  3483:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3484:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3485:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3486:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3487:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3488:                                        \$numreclinks);
1.57      albertel 3489:                         }
                   3490:                     }
                   3491:                 }
                   3492:             } # end foreach ids
1.43      albertel 3493: # -------------------------------------------------- End entry for one resource
1.517     www      3494:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3495:         } # end of  full
1.57      albertel 3496: #--------------------------------------------------- Entry for parm level map
                   3497:         if ($parmlev eq 'map') {
1.419     bisitz   3498:             my $defbgone = '#E0E099';
                   3499:             my $defbgtwo = '#FFFF99';
                   3500:             my $defbgthree = '#FFBB99';
1.57      albertel 3501: 
                   3502:             my %maplist;
                   3503: 
                   3504:             if ($pschp eq 'all') {
1.446     bisitz   3505:                 %maplist = %allmaps;
1.57      albertel 3506:             } else {
                   3507:                 %maplist = ($pschp => $mapp{$pschp});
                   3508:             }
                   3509: 
                   3510: #-------------------------------------------- for each map, gather information
                   3511:             my $mapid;
1.560     damieng  3512:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3513:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3514: 
                   3515: #-----------------------  loop through ids and get all parameter types for map
                   3516: #-----------------------------------------          and associated information
                   3517:                 my %name = ();
                   3518:                 my %part = ();
                   3519:                 my %display = ();
                   3520:                 my %type = ();
                   3521:                 my %default = ();
                   3522:                 my $map = 0;
                   3523: 
1.473     amueller 3524: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3525: 
1.548     raeburn  3526:                 foreach my $id (@ids) {
                   3527:                     ($map)=($id =~ /([\d]*?)\./);
                   3528:                     my $rid = $id;
1.446     bisitz   3529: 
1.57      albertel 3530: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3531: 
1.560     damieng  3532:                     if ($map eq $mapid) {
1.473     amueller 3533:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3534:                         my $toolsymb;
                   3535:                         if ($uri =~ /ext\.tool$/) {
                   3536:                             $toolsymb = $symbp{$rid};
                   3537:                         }
1.582     raeburn  3538: 
1.57      albertel 3539: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3540: 
                   3541: #--------------------------------------------------------------------
                   3542: # @catmarker contains list of all possible parameters including part #s
                   3543: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3544: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3545: # When storing information, store as part 0
                   3546: # When requesting information, request from full part
                   3547: #-------------------------------------------------------------------
1.548     raeburn  3548:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3549:                             my $tempkeyp = $fullkeyp;
                   3550:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3551: 
1.548     raeburn  3552:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3553:                                 $part{$tempkeyp}="0";
1.584     raeburn  3554:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3555:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3556:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3557:                                     my $identifier;
                   3558:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3559:                                         $identifier = $1;
                   3560:                                     }
                   3561:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3562:                                 } else {
                   3563:                                     $display{$tempkeyp} = $parmdis;
                   3564:                                 }
                   3565:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3566:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3567:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3568:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3569:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 3570:                               }
                   3571:                         } # end loop through keys
1.560     damieng  3572:                     }
1.57      albertel 3573:                 } # end loop through ids
1.446     bisitz   3574: 
1.57      albertel 3575: #---------------------------------------------------- print header information
1.133     www      3576:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      3577:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   3578:                 my $tmp="";
1.57      albertel 3579:                 if ($uname) {
1.473     amueller 3580:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   3581:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   3582:                         &mt('in')." \n";
1.57      albertel 3583:                 } else {
1.401     bisitz   3584:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 3585:                 }
1.269     raeburn  3586:                 if ($cgroup) {
1.401     bisitz   3587:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   3588:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3589:                     $csec = '';
                   3590:                 } elsif ($csec) {
1.401     bisitz   3591:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   3592:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3593:                 }
1.401     bisitz   3594:                 $r->print('<div align="center"><h4>'
                   3595:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   3596:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   3597:                              ,$tmp
                   3598:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   3599:                              )
                   3600:                          ."<br /></h4>\n"
1.422     bisitz   3601:                 );
1.57      albertel 3602: #---------------------------------------------------------------- print table
1.419     bisitz   3603:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3604:                          .&Apache::loncommon::start_data_table_header_row()
                   3605:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  3606:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   3607:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   3608:                          .&Apache::loncommon::end_data_table_header_row()
                   3609:                 );
1.57      albertel 3610: 
1.582     raeburn  3611:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   3612:                 my @recurseup;
                   3613:                 if (ref($navmap)) {
                   3614:                      my $mapres = $navmap->getByMapPc($mapid);
                   3615:                      if (ref($mapres)) {
                   3616:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   3617:                      }
                   3618:                 }
                   3619: 
                   3620: 
1.548     raeburn  3621:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 3622:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3623:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  3624:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  3625:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  3626:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   3627:                            \$numreclinks);
1.57      albertel 3628:                 }
1.422     bisitz   3629:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   3630:                          .'</div>'
                   3631:                 );
1.57      albertel 3632:             } # end each map
                   3633:         } # end of $parmlev eq map
                   3634: #--------------------------------- Entry for parm level general (Course level)
                   3635:         if ($parmlev eq 'general') {
1.473     amueller 3636:             my $defbgone = '#E0E099';
1.419     bisitz   3637:             my $defbgtwo = '#FFFF99';
                   3638:             my $defbgthree = '#FFBB99';
1.57      albertel 3639: 
                   3640: #-------------------------------------------- for each map, gather information
                   3641:             my $mapid="0.0";
                   3642: #-----------------------  loop through ids and get all parameter types for map
                   3643: #-----------------------------------------          and associated information
                   3644:             my %name = ();
                   3645:             my %part = ();
                   3646:             my %display = ();
                   3647:             my %type = ();
                   3648:             my %default = ();
1.446     bisitz   3649: 
1.548     raeburn  3650:             foreach $id (@ids) {
                   3651:                 my $rid = $id;
1.446     bisitz   3652: 
1.196     www      3653:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3654:                 my $toolsymb;
                   3655:                 if ($uri =~ /ext\.tool$/) {
                   3656:                     $toolsymb = $symbp{$rid};
                   3657:                 }
1.57      albertel 3658: 
                   3659: #--------------------------------------------------------------------
                   3660: # @catmarker contains list of all possible parameters including part #s
                   3661: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3662: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3663: # When storing information, store as part 0
                   3664: # When requesting information, request from full part
                   3665: #-------------------------------------------------------------------
1.548     raeburn  3666:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3667:                     my $tempkeyp = $fullkeyp;
                   3668:                     $tempkeyp =~ s/_\w+_/_0_/;
                   3669:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3670:                         $part{$tempkeyp}="0";
1.584     raeburn  3671:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3672:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3673:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   3674:                             my $identifier;
                   3675:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3676:                                 $identifier = $1;
                   3677:                             }
                   3678:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3679:                         } else {
                   3680:                             $display{$tempkeyp} = $parmdis;
                   3681:                         }
                   3682:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3683:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3684:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3685:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3686:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  3687:                     }
1.57      albertel 3688:                 } # end loop through keys
                   3689:             } # end loop through ids
1.446     bisitz   3690: 
1.57      albertel 3691: #---------------------------------------------------- print header information
1.473     amueller 3692:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 3693:             $r->print(<<ENDMAPONE);
1.419     bisitz   3694: <center>
                   3695: <h4>$setdef
1.135     albertel 3696: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 3697: ENDMAPONE
                   3698:             if ($uname) {
1.473     amueller 3699:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 3700:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 3701:             } else {
1.135     albertel 3702:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 3703:             }
1.446     bisitz   3704: 
1.135     albertel 3705:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 3706:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 3707:             $r->print("</h4>\n");
1.57      albertel 3708: #---------------------------------------------------------------- print table
1.419     bisitz   3709:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3710:                      .&Apache::loncommon::start_data_table_header_row()
                   3711:                      .'<th>'.&mt('Parameter Name').'</th>'
                   3712:                      .'<th>'.&mt('Default Value').'</th>'
                   3713:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   3714:                      .&Apache::loncommon::end_data_table_header_row()
                   3715:             );
1.57      albertel 3716: 
1.548     raeburn  3717:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   3718:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3719:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  3720:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   3721:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3722:                            $readonly);
1.57      albertel 3723:             }
1.419     bisitz   3724:             $r->print(&Apache::loncommon::end_data_table()
                   3725:                      .'</p>'
                   3726:                      .'</center>'
                   3727:             );
1.57      albertel 3728:         } # end of $parmlev eq general
1.43      albertel 3729:     }
1.507     www      3730:     $r->print('</form>');
1.582     raeburn  3731:     if ($numreclinks) {
                   3732:         $r->print(<<"END");
                   3733: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   3734: <input type="hidden" name="pschp" />
                   3735: <input type="hidden" name="pscat" />
                   3736: <input type="hidden" name="psprt" />
                   3737: <input type="hidden" name="hideparmsel" value="hidden" />
                   3738: </form>
                   3739: <script type="text/javascript">
                   3740: function pjumprec(rid,name,part) {
                   3741:     document.forms.recurseform.pschp.value = rid;
                   3742:     document.forms.recurseform.pscat.value = name;
                   3743:     document.forms.recurseform.psprt.value = part;
                   3744:     document.forms.recurseform.submit();
                   3745:     return false;
                   3746: }
                   3747: </script>
                   3748: END
                   3749:     }
1.507     www      3750:     &endSettingsScreen($r);
                   3751:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 3752: } # end sub assessparms
1.30      www      3753: 
1.560     damieng  3754: 
                   3755: 
1.120     www      3756: ##################################################
1.560     damieng  3757: # OVERVIEW MODE
1.207     www      3758: ##################################################
1.124     www      3759: 
1.563     damieng  3760: my $tableopen; # boolean, true if HTML table is already opened
                   3761: 
                   3762: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   3763: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   3764: # @returns {string}
1.124     www      3765: sub tablestart {
1.576     raeburn  3766:     my ($readonly,$is_map) = @_;
1.124     www      3767:     if ($tableopen) {
1.552     raeburn  3768:         return '';
1.124     www      3769:     } else {
1.552     raeburn  3770:         $tableopen=1;
                   3771:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   3772:         if ($readonly) {
                   3773:             $output .= '<th>'.&mt('Current value').'</th>';
                   3774:         } else {
1.576     raeburn  3775:             $output .= '<th>'.&mt('Delete').'</th>'.
                   3776:                        '<th>'.&mt('Set to ...').'</th>';
                   3777:             if ($is_map) {
                   3778:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   3779:             }
1.552     raeburn  3780:         }
                   3781:         $output .= '</tr>';
                   3782:         return $output;
1.124     www      3783:     }
                   3784: }
                   3785: 
1.563     damieng  3786: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   3787: # @returns {string}
1.124     www      3788: sub tableend {
                   3789:     if ($tableopen) {
1.560     damieng  3790:         $tableopen=0;
                   3791:         return &Apache::loncommon::end_data_table();
1.124     www      3792:     } else {
1.560     damieng  3793:         return'';
1.124     www      3794:     }
                   3795: }
                   3796: 
1.563     damieng  3797: # Reads course and user information.
                   3798: # 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).
                   3799: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   3800: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   3801: # @param {string} $crs - course number
                   3802: # @param {string} $dom - course domain
                   3803: # @returns {hash reference|Array}
1.207     www      3804: sub readdata {
                   3805:     my ($crs,$dom)=@_;
                   3806: # Read coursedata
                   3807:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   3808: # Read userdata
                   3809: 
                   3810:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  3811:     foreach my $user (keys(%$classlist)) {
                   3812:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   3813:             my ($tuname,$tudom)=($1,$2);
                   3814:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   3815:             foreach my $userkey (keys(%{$useropt})) {
                   3816:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      3817:                     my $newkey=$userkey;
1.548     raeburn  3818:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   3819:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   3820:                 }
                   3821:             }
1.473     amueller 3822:         }
                   3823:     }
1.552     raeburn  3824:     if (wantarray) {
                   3825:         return ($resourcedata,$classlist);
                   3826:     } else {
                   3827:         return $resourcedata;
                   3828:     }
1.207     www      3829: }
                   3830: 
                   3831: 
1.563     damieng  3832: # Stores parameter data, using form parameters directly.
                   3833: #
                   3834: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
                   3835: # set_* (except settext, setipallow, setipdeny) - set a parameter value
                   3836: # del_* - remove a parameter
                   3837: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   3838: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   3839: # key_* - date values
                   3840: # days_* - for date intervals
                   3841: # hours_* - for date intervals
                   3842: # minutes_* - for date intervals
                   3843: # seconds_* - for date intervals
                   3844: # done_* - for date intervals
                   3845: # typeof_* - parameter type
                   3846: # 
                   3847: # @param {Apache2::RequestRec} $r - the Apache request
                   3848: # @param {string} $crs - course number
                   3849: # @param {string} $dom - course domain
1.208     www      3850: sub storedata {
                   3851:     my ($r,$crs,$dom)=@_;
1.207     www      3852: # Set userlevel immediately
                   3853: # Do an intermediate store of course level
                   3854:     my $olddata=&readdata($crs,$dom);
1.124     www      3855:     my %newdata=();
                   3856:     undef %newdata;
                   3857:     my @deldata=();
1.576     raeburn  3858:     my @delrec=();
                   3859:     my @delnonrec=();
1.124     www      3860:     undef @deldata;
1.504     raeburn  3861:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  3862:     my $now = time;
1.560     damieng  3863:     foreach my $key (keys(%env)) {
                   3864:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   3865:             my $cmd=$1;
                   3866:             my $thiskey=$2;
1.576     raeburn  3867:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
                   3868:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny');
                   3869:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   3870:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   3871:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   3872:                     $altkey = $thiskey;
                   3873:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   3874:                     if ($env{'form.rec_'.$thiskey}) {
                   3875:                         $recursive = 1;
                   3876:                     }
                   3877:                 }
                   3878:             }
1.560     damieng  3879:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 3880:             if ($tuname) {
1.576     raeburn  3881:                 $tkey=$thiskey;
1.560     damieng  3882:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  3883:                 if ($altkey) {
                   3884:                     $tkeynonrec = $tkey; 
                   3885:                     $tkeyrec = $altkey;
                   3886:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   3887:                 }
1.560     damieng  3888:             }
                   3889:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  3890:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   3891:                 if ($cmd eq 'set') {
                   3892:                     $data=$env{$key};
                   3893:                     $valmatch = '';
                   3894:                     $valchk = $data;
                   3895:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3896:                     $text = &mt('Saved modified parameter for');
                   3897:                     if ($typeof eq 'string_questiontype') {
                   3898:                         $name = 'type';
                   3899:                     } elsif ($typeof eq 'string_lenient') {
                   3900:                         $name = 'lenient';
                   3901:                         my $stringmatch = &standard_string_matches($typeof);
                   3902:                         if (ref($stringmatch) eq 'ARRAY') {
                   3903:                             foreach my $item (@{$stringmatch}) {
                   3904:                                 if (ref($item) eq 'ARRAY') {
                   3905:                                     my ($regexpname,$pattern) = @{$item};
                   3906:                                     if ($pattern ne '') {
                   3907:                                         if ($data =~ /$pattern/) {
                   3908:                                             $valmatch = $regexpname;
                   3909:                                             $valchk = '';
                   3910:                                             last;
                   3911:                                         }
1.560     damieng  3912:                                     }
1.549     raeburn  3913:                                 }
                   3914:                             }
                   3915:                         }
1.563     damieng  3916:                     } elsif ($typeof eq 'string_discussvote') {
                   3917:                         $name = 'discussvote';
                   3918:                     } elsif ($typeof eq 'string_examcode') {
                   3919:                         $name = 'examcode';
                   3920:                         if (&Apache::lonnet::validCODE($data)) {
                   3921:                             $valchk = 'valid';
                   3922:                         }
                   3923:                     } elsif ($typeof eq 'string_yesno') {
                   3924:                         if ($thiskey =~ /\.retrypartial$/) {
                   3925:                             $name = 'retrypartial';
                   3926:                         }
1.549     raeburn  3927:                     }
1.563     damieng  3928:                 } elsif ($cmd eq 'datepointer') {
                   3929:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   3930:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3931:                     $text = &mt('Saved modified date for');
                   3932:                     if ($typeof eq 'date_start') {
                   3933:                         if ($thiskey =~ /\.printstartdate$/) {
                   3934:                             $name = 'printstartdate';
                   3935:                             if (($data) && ($data > $now)) {
                   3936:                                 $valchk = 'future';
                   3937:                             }
1.560     damieng  3938:                         }
1.563     damieng  3939:                     } elsif ($typeof eq 'date_end') {
                   3940:                         if ($thiskey =~ /\.printenddate$/) {
                   3941:                             $name = 'printenddate';
                   3942:                             if (($data) && ($data < $now)) {
                   3943:                                 $valchk = 'past';
                   3944:                             }
1.560     damieng  3945:                         }
1.504     raeburn  3946:                     }
1.563     damieng  3947:                 } elsif ($cmd eq 'dateinterval') {
                   3948:                     $data=&get_date_interval_from_form($thiskey);
                   3949:                     if ($thiskey =~ /\.interval$/) {
                   3950:                         $name = 'interval';
                   3951:                         my $intervaltype = &get_intervaltype($name);
                   3952:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   3953:                         if (ref($intervalmatch) eq 'ARRAY') {
                   3954:                             foreach my $item (@{$intervalmatch}) {
                   3955:                                 if (ref($item) eq 'ARRAY') {
                   3956:                                     my ($regexpname,$pattern) = @{$item};
                   3957:                                     if ($pattern ne '') {
                   3958:                                         if ($data =~ /$pattern/) {
                   3959:                                             $valmatch = $regexpname;
                   3960:                                             $valchk = '';
                   3961:                                             last;
                   3962:                                         }
1.560     damieng  3963:                                     }
1.554     raeburn  3964:                                 }
                   3965:                             }
                   3966:                         }
                   3967:                     }
1.563     damieng  3968:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3969:                     $text = &mt('Saved modified date for');
1.554     raeburn  3970:                 }
1.576     raeburn  3971:                 if ($recursive) {
1.563     damieng  3972:                     $namematch = 'maplevelrecurse';
1.560     damieng  3973:                 }
1.563     damieng  3974:                 if (($name ne '') || ($namematch ne '')) {
                   3975:                     my ($needsrelease,$needsnewer);
                   3976:                     if ($name ne '') {
                   3977:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  3978:                         if ($needsrelease) {
                   3979:                             unless ($got_chostname) {
1.563     damieng  3980:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  3981:                                 $got_chostname = 1;
                   3982:                             }
1.563     damieng  3983:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   3984:                                                                 $needsrelease,
                   3985:                                                                 $cmajor,$cminor);
                   3986:                         }
                   3987:                     }
                   3988:                     if ($namematch ne '') {
                   3989:                         if ($needsnewer) {
                   3990:                             undef($namematch);
1.560     damieng  3991:                         } else {
1.563     damieng  3992:                             my $currneeded;
                   3993:                             if ($needsrelease) {
                   3994:                                 $currneeded = $needsrelease;
                   3995:                             }
                   3996:                             $needsrelease =
                   3997:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3998:                             if (($needsrelease) &&
                   3999:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4000:                                 unless ($got_chostname) {
                   4001:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4002:                                     $got_chostname = 1;
                   4003:                                 }
                   4004:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4005:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4006:                             } else {
                   4007:                                 undef($namematch);
                   4008:                             }
1.560     damieng  4009:                         }
1.557     raeburn  4010:                     }
1.563     damieng  4011:                     if ($needsnewer) {
                   4012:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4013:                                                             $chostname,$cmajor,
                   4014:                                                             $cminor,$needsrelease));
                   4015:                         next;
                   4016:                     }
1.504     raeburn  4017:                 }
1.576     raeburn  4018:                 my ($reconlychg,$haschange,$storekey);
                   4019:                 if ($tuname) {
                   4020:                     my $ustorekey;
                   4021:                     if ($altkey) {
                   4022:                         if ($recursive) {
                   4023:                             if (exists($$olddata{$thiskey})) {
                   4024:                                 if ($$olddata{$thiskey} eq $data) {
                   4025:                                     $reconlychg = 1;
                   4026:                                 }
                   4027:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4028:                             }
                   4029:                             if (exists($$olddata{$altkey})) {
                   4030:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4031:                                     $haschange = 1;
                   4032:                                 }
                   4033:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4034:                                 $haschange = 1;
                   4035:                             }
                   4036:                             $ustorekey = $tkeyrec;
                   4037:                         } else {
                   4038:                             if (exists($$olddata{$altkey})) {
                   4039:                                 if ($$olddata{$altkey} eq $data) {
                   4040:                                     $reconlychg = 1;
                   4041:                                 }
                   4042:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4043:                             }
                   4044:                             if (exists($$olddata{$thiskey})) {
                   4045:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4046:                                     $haschange = 1;
                   4047:                                 }
                   4048:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4049:                                 $haschange = 1;
                   4050:                             }
                   4051:                             $ustorekey = $tkeynonrec;
                   4052:                         }
                   4053:                     } else {
                   4054:                         if (exists($$olddata{$tkey})) {
                   4055:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4056:                                 $haschange = 1;
                   4057:                             }
                   4058:                             $ustorekey = $tkey;
                   4059:                         }
                   4060:                     }
                   4061:                     if ($haschange || $reconlychg)  {
                   4062:                         unless ($env{'form.del_'.$thiskey}) {
                   4063:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4064:                                                                      $ustorekey.'.type' => $typeof},
                   4065:                                                                      $tudom,$tuname) eq 'ok') {
                   4066:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4067:                                 $r->print('<br />'.$text.' '.
                   4068:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4069:                             } else {
                   4070:                                 $r->print('<div class="LC_error">'.
                   4071:                                           &mt('Error saving parameters').'</div>');
                   4072:                             }
                   4073:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4074:                         }
                   4075:                     }
                   4076:                 } else {
                   4077:                     if ($altkey) {
                   4078:                         if ($recursive) {
                   4079:                             if (exists($$olddata{$thiskey})) {
                   4080:                                 if ($$olddata{$thiskey} eq $data) {
                   4081:                                     $reconlychg = 1;
                   4082:                                 }
                   4083:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4084:                             }
                   4085:                             if (exists($$olddata{$altkey})) {
                   4086:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4087:                                     $haschange = 1;
                   4088:                                 }
                   4089:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4090:                                 $haschange = 1;
                   4091:                             }
                   4092:                             $storekey = $altkey;
1.563     damieng  4093:                         } else {
1.576     raeburn  4094:                             if (exists($$olddata{$altkey})) {
                   4095:                                 if ($$olddata{$altkey} eq $data) {
                   4096:                                     $reconlychg = 1;
                   4097:                                 }
                   4098:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4099:                             } 
                   4100:                             if (exists($$olddata{$thiskey})) {
                   4101:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4102:                                     $haschange = 1;
                   4103:                                 }
                   4104:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4105:                                 $haschange = 1;
                   4106:                             }
                   4107:                             $storekey = $thiskey;
1.563     damieng  4108:                         }
1.560     damieng  4109:                     } else {
1.576     raeburn  4110:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4111:                             $haschange = 1;
                   4112:                             $storekey = $thiskey;
                   4113:                         }
                   4114:                     }
                   4115:                 }
                   4116:                 if ($reconlychg || $haschange) {
                   4117:                     unless ($env{'form.del_'.$thiskey}) {
                   4118:                         $newdata{$storekey}=$data;
                   4119:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4120:                     }
                   4121:                 }
                   4122:             } elsif ($cmd eq 'del') {
                   4123:                 if ($tuname) {
1.576     raeburn  4124:                     my $error;
                   4125:                     if ($altkey) {  
                   4126:                         if (exists($$olddata{$altkey})) {
                   4127:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4128:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4129:                                 if ($recursive) {
                   4130:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4131:                                 }
                   4132:                             } elsif ($recursive) {
                   4133:                                 $error = 1;
                   4134:                             }
                   4135:                         }
                   4136:                         if (exists($$olddata{$thiskey})) {
                   4137:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4138:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4139:                                 unless ($recursive) {
                   4140:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4141:                                 }
                   4142:                             } elsif (!$recursive) {
                   4143:                                 $error = 1;
                   4144:                             }
                   4145:                         }
1.560     damieng  4146:                     } else {
1.576     raeburn  4147:                         if (exists($$olddata{$thiskey})) {
                   4148:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4149:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4150:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4151:                             } else {
                   4152:                                 $error = 1;
                   4153:                             }
                   4154:                         }
                   4155:                     }
                   4156:                     if ($error) { 
1.560     damieng  4157:                         $r->print('<div class="LC_error">'.
                   4158:                             &mt('Error deleting parameters').'</div>');
                   4159:                     }
                   4160:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4161:                 } else {
1.576     raeburn  4162:                     if ($altkey) {
                   4163:                         if (exists($$olddata{$altkey})) {
                   4164:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4165:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4166:                             }
                   4167:                         }
                   4168:                         if (exists($$olddata{$thiskey})) {
                   4169:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4170:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4171:                             }
                   4172:                         }
                   4173:                     } elsif (exists($$olddata{$thiskey})) {
                   4174:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4175:                     }
1.560     damieng  4176:                 }
1.473     amueller 4177:             }
                   4178:         }
                   4179:     }
1.207     www      4180: # Store all course level
1.144     www      4181:     my $delentries=$#deldata+1;
1.576     raeburn  4182:     my @alldels;
                   4183:     if (@delrec) {
                   4184:         push(@alldels,@delrec);
                   4185:     }
                   4186:     if (@delnonrec) {
                   4187:         push(@alldels,@delnonrec);
                   4188:     }
                   4189:     if (@deldata) {
                   4190:         push(@alldels,@deldata);
                   4191:     }
1.548     raeburn  4192:     my @newdatakeys=keys(%newdata);
1.144     www      4193:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4194:     my ($delresult,$devalidate);
                   4195:     if (@alldels) {
                   4196:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4197:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4198:             &log_parmset(\%loghash,1);
1.576     raeburn  4199:             if ($delentries) {
                   4200:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4201:             }
                   4202:         } elsif ($delentries) {
1.560     damieng  4203:             $r->print('<div class="LC_error">'.
                   4204:                 &mt('Error deleting parameters').'</div>');
                   4205:         }
1.576     raeburn  4206:         $devalidate = 1; 
1.144     www      4207:     }
                   4208:     if ($putentries) {
1.560     damieng  4209:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4210:                     &log_parmset(\%newdata,0);
                   4211:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4212:         } else {
                   4213:             $r->print('<div class="LC_error">'.
                   4214:                 &mt('Error saving parameters').'</div>');
                   4215:         }
1.576     raeburn  4216:         $devalidate = 1; 
                   4217:     }
                   4218:     if ($devalidate) {
1.560     damieng  4219:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4220:     }
1.208     www      4221: }
1.207     www      4222: 
1.563     damieng  4223: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4224: #
                   4225: # @param {string} $key - the key
                   4226: # @returns {Array}
1.208     www      4227: sub extractuser {
                   4228:     my $key=shift;
1.350     albertel 4229:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4230: }
1.206     www      4231: 
1.563     damieng  4232: # Parses a parameter key and returns the components.
                   4233: #
                   4234: # @param {string} $key - 
                   4235: # @param {hash reference} $listdata - 
                   4236: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4237: sub parse_listdata_key {
                   4238:     my ($key,$listdata) = @_;
                   4239:     # split into student/section affected, and
                   4240:     # the realm (folder/resource part and parameter
1.446     bisitz   4241:     my ($student,$realm) =
1.473     amueller 4242:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4243:     # if course wide student would be undefined
                   4244:     if (!defined($student)) {
1.560     damieng  4245:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4246:     }
                   4247:     # strip off the .type if it's not the Question type parameter
                   4248:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4249:         $realm=~s/\.type//;
1.381     albertel 4250:     }
                   4251:     # split into resource+part and parameter name
1.388     albertel 4252:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4253:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4254:     return ($student,$res,$part,$parm);
                   4255: }
                   4256: 
1.563     damieng  4257: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4258: #
                   4259: # @param {Apache2::RequestRec} $r - the Apache request
                   4260: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4261: # @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
                   4262: # @param {string} $sortorder - realmstudent|studentrealm
                   4263: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4264: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4265: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  4266: # @returns{integer} - number of $listdata parameters processed
1.208     www      4267: sub listdata {
1.568     raeburn  4268:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  4269:     
1.207     www      4270: # Start list output
1.206     www      4271: 
1.122     www      4272:     my $oldsection='';
                   4273:     my $oldrealm='';
                   4274:     my $oldpart='';
1.123     www      4275:     my $pointer=0;
1.124     www      4276:     $tableopen=0;
1.145     www      4277:     my $foundkeys=0;
1.248     albertel 4278:     my %keyorder=&standardkeyorder();
1.381     albertel 4279: 
1.552     raeburn  4280:     my ($secidx,%grouphash);
                   4281:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4282:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4283:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4284:             %grouphash = &Apache::longroup::coursegroups();
                   4285:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4286:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4287:         }
1.552     raeburn  4288:     }
                   4289: 
1.576     raeburn  4290:     foreach my $key (sort {
1.560     damieng  4291:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4292:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 4293: 
1.560     damieng  4294:         # get the numerical order for the param
                   4295:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4296:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4297: 
1.560     damieng  4298:         my $result=0;
1.381     albertel 4299: 
1.560     damieng  4300:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4301:             if ($ares     ne $bres    ) {
1.560     damieng  4302:                 $result = ($ares     cmp $bres);
1.446     bisitz   4303:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4304:                 $result = ($astudent cmp $bstudent);
                   4305:             } elsif ($apart    ne $bpart   ) {
                   4306:                 $result = ($apart    cmp $bpart);
                   4307:             }
                   4308:         } else {
                   4309:             if      ($astudent ne $bstudent) {
                   4310:                 $result = ($astudent cmp $bstudent);
                   4311:             } elsif ($ares     ne $bres    ) {
                   4312:                 $result = ($ares     cmp $bres);
                   4313:             } elsif ($apart    ne $bpart   ) {
                   4314:                 $result = ($apart    cmp $bpart);
                   4315:             }
1.473     amueller 4316:         }
1.446     bisitz   4317: 
1.560     damieng  4318:         if (!$result) {
1.381     albertel 4319:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4320:                 $result = ($aparm <=> $bparm);
1.381     albertel 4321:             } elsif (defined($aparm)) {
1.560     damieng  4322:                 $result = -1;
1.381     albertel 4323:             } elsif (defined($bparm)) {
1.560     damieng  4324:                 $result = 1;
                   4325:             }
1.473     amueller 4326:         }
1.381     albertel 4327: 
1.560     damieng  4328:         $result;
                   4329:         
1.576     raeburn  4330:     } keys(%{$listdata})) { # foreach my $key
                   4331:         my $thiskey = $key;
1.560     damieng  4332:         if ($$listdata{$thiskey.'.type'}) {
                   4333:             my $thistype=$$listdata{$thiskey.'.type'};
                   4334:             if ($$resourcedata{$thiskey.'.type'}) {
                   4335:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4336:             }
                   4337:             my ($middle,$part,$name)=
1.572     damieng  4338:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4339:             my $section=&mt('All Students');
1.576     raeburn  4340:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4341:             if ($middle=~/^\[(.*)\]/) {
                   4342:                 my $issection=$1;
                   4343:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4344:                     my ($stuname,$studom) = ($1,$2);
                   4345:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4346:                         if (ref($classlist) eq 'HASH') {
                   4347:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4348:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4349:                             }
                   4350:                         }
                   4351:                     }
                   4352:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
                   4353:                 } else {
                   4354:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4355:                         if (exists($grouphash{$issection})) {
                   4356:                             $section=&mt('Group').': '.$issection;
                   4357:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4358:                             $section = &mt('Section').': '.$issection;
                   4359:                         } else {
                   4360:                             next; 
1.552     raeburn  4361:                         }
1.560     damieng  4362:                     } else {
                   4363:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4364:                     }
                   4365:                 }
1.560     damieng  4366:                 $middle=~s/^\[(.*)\]//;
                   4367:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4368:                 $readonly = 1;
                   4369:             }
                   4370:             $middle=~s/\.+$//;
                   4371:             $middle=~s/^\.+//;
                   4372:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4373:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4374:             if ($caller eq 'overview') {
                   4375:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4376:                     $mapurl = $1;
                   4377:                     $maplevel = $2;
                   4378:                     $is_map = 1;
                   4379:                 }
                   4380:             } elsif ($caller eq 'newoverview') {
                   4381:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4382:                     $mapurl = $1;
                   4383:                     $maplevel = $2;
                   4384:                     $is_map = 1;
                   4385:                 }
                   4386:             }
                   4387:             if ($is_map) {
1.560     damieng  4388:                 my $leveltitle = &mt('Folder/Map');
1.576     raeburn  4389:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4390:                     if ($caller eq 'newoverview') {
                   4391:                         my $altkey = $thiskey;
                   4392:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4393:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4394:                             $is_recursive = 1;
                   4395:                             if ($$resourcedata{$altkey.'.type'}) {
                   4396:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4397:                             }
                   4398:                             $showval = $$resourcedata{$altkey};
                   4399:                         }
                   4400:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4401:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4402:                         $is_recursive = 1;
                   4403:                     }
1.560     damieng  4404:                 }
                   4405:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   4406:             } elsif ($middle) {
                   4407:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   4408:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4409:                     ': '.&Apache::lonnet::gettitle($middle).
                   4410:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4411:                     $id.')</span></span>';
                   4412:             }
                   4413:             if ($sortorder eq 'realmstudent') {
                   4414:                 if ($realm ne $oldrealm) {
                   4415:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4416:                     $oldrealm=$realm;
                   4417:                     $oldsection='';
                   4418:                 }
                   4419:                 if ($section ne $oldsection) {
                   4420:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4421:                     $oldsection=$section;
                   4422:                     $oldpart='';
                   4423:                 }
1.552     raeburn  4424:             } else {
1.560     damieng  4425:                 if ($section ne $oldsection) {
                   4426:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4427:                     $oldsection=$section;
                   4428:                     $oldrealm='';
                   4429:                 }
                   4430:                 if ($realm ne $oldrealm) {
                   4431:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4432:                     $oldrealm=$realm;
                   4433:                     $oldpart='';
1.552     raeburn  4434:                 }
                   4435:             }
1.560     damieng  4436:             if ($part ne $oldpart) {
                   4437:                 $r->print(&tableend().
                   4438:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4439:                 $oldpart=$part;
1.556     raeburn  4440:             }
1.560     damieng  4441:     #
                   4442:     # Ready to print
                   4443:     #
1.470     raeburn  4444:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4445:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4446:                 &Apache::loncommon::start_data_table_row().
                   4447:                 '<td><b>'.&mt($parmitem).
                   4448:                 '</b></td>');
                   4449:             unless ($readonly) {
                   4450:                 $r->print('<td><input type="checkbox" name="del_'.
                   4451:                         $thiskey.'" /></td>');
                   4452:             }
                   4453:             $r->print('<td>');
                   4454:             $foundkeys++;
                   4455:             if (&isdateparm($thistype)) {
                   4456:                 my $jskey='key_'.$pointer;
                   4457:                 my $state;
                   4458:                 $pointer++;
                   4459:                 if ($readonly) {
                   4460:                     $state = 'disabled';
                   4461:                 }
                   4462:                 $r->print(
                   4463:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4464:                                                         $jskey,
1.576     raeburn  4465:                                                         $showval,
1.560     damieng  4466:                                                         '',1,$state));
                   4467:                 unless  ($readonly) {
                   4468:                     $r->print(
                   4469:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4470:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4471:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4472:     &date_sanity_info($showval)
1.560     damieng  4473:                     );
                   4474:                 }
                   4475:             } elsif ($thistype eq 'date_interval') {
                   4476:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4477:                           $showval,$readonly));
1.560     damieng  4478:             } elsif ($thistype =~ m/^string/) {
                   4479:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4480:                           $showval,$name,$readonly));
1.560     damieng  4481:             } else {
1.576     raeburn  4482:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  4483:             }
1.560     damieng  4484:             unless ($readonly) {
                   4485:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4486:                         $thistype.'" />');
1.552     raeburn  4487:             }
1.576     raeburn  4488:             $r->print('</td>');
                   4489:             if ($is_map) {
                   4490:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   4491:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   4492:                 } else {
                   4493:                     my ($disabled,$recon,$recoff);
                   4494:                     if ($readonly) {
                   4495:                         $disabled = ' disabled="disabled"';
                   4496:                     }
                   4497:                     if ($is_recursive) {
                   4498:                         $recon = ' checked="checked"';
                   4499:                     } else {
                   4500:                         $recoff = ' checked="checked"';
                   4501:                     }
                   4502:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   4503:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   4504:                 }
                   4505:             }
                   4506:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 4507:         }
1.121     www      4508:     }
1.208     www      4509:     return $foundkeys;
                   4510: }
                   4511: 
1.563     damieng  4512: # Returns a string representing the interval, directly using form data matching the given key.
                   4513: # The returned string may also include information related to proctored exams.
                   4514: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4515: #
                   4516: # @param {string} $key - suffix for form fields related to the interval
                   4517: # @returns {string}
1.385     albertel 4518: sub get_date_interval_from_form {
                   4519:     my ($key) = @_;
                   4520:     my $seconds = 0;
                   4521:     foreach my $which (['days', 86400],
1.473     amueller 4522:                ['hours', 3600],
                   4523:                ['minutes', 60],
                   4524:                ['seconds',  1]) {
1.560     damieng  4525:         my ($name, $factor) = @{ $which };
                   4526:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4527:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4528:         }
1.473     amueller 4529:     }
1.560     damieng  4530:     if (($key =~ /\.interval$/) &&
                   4531:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4532:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4533:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4534:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4535:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4536:                 $seconds .= '_proctor';
                   4537:             }
                   4538:         } else {
                   4539:             $seconds .= $env{'form.done_'.$key}; 
                   4540:         }
                   4541:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4542:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4543:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4544:         }
1.554     raeburn  4545:     }
1.385     albertel 4546:     return $seconds;
                   4547: }
                   4548: 
                   4549: 
1.563     damieng  4550: # Returns HTML to enter a text value for a parameter.
                   4551: #
                   4552: # @param {string} $thiskey - parameter key
                   4553: # @param {string} $showval - the current value
                   4554: # @param {boolean} $readonly - true if the field should not be made editable
                   4555: # @returns {string}
1.383     albertel 4556: sub default_selector {
1.552     raeburn  4557:     my ($thiskey, $showval, $readonly) = @_;
                   4558:     my $disabled;
                   4559:     if ($readonly) {
                   4560:         $disabled = ' disabled="disabled"';
                   4561:     }
                   4562:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4563: }
                   4564: 
1.563     damieng  4565: # Returns HTML to enter allow/deny rules related to IP addresses.
                   4566: #
                   4567: # @param {string} $thiskey - parameter key
                   4568: # @param {string} $showval - the current value
                   4569: # @param {boolean} $readonly - true if the fields should not be made editable
                   4570: # @returns {string}
1.549     raeburn  4571: sub string_ip_selector {
1.552     raeburn  4572:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  4573:     my %access = (
                   4574:                    allow => [],
                   4575:                    deny  => [],
                   4576:                  );
                   4577:     if ($showval ne '') {
                   4578:         my @current;
                   4579:         if ($showval =~ /,/) {
                   4580:             @current = split(/,/,$showval);
                   4581:         } else {
                   4582:             @current = ($showval);
                   4583:         }
                   4584:         foreach my $item (@current) {
                   4585:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4586:                 push(@{$access{'deny'}},$1);
                   4587:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4588:                 push(@{$access{'allow'}},$item);
                   4589:             }
                   4590:         }
                   4591:     }
                   4592:     if (!@{$access{'allow'}}) {
                   4593:         @{$access{'allow'}} = ('');
                   4594:     }
                   4595:     if (!@{$access{'deny'}}) {
                   4596:         @{$access{'deny'}} = ('');
                   4597:     }
1.552     raeburn  4598:     my ($disabled,$addmore);
1.567     raeburn  4599:     if ($readonly) {
1.552     raeburn  4600:         $disabled=' disabled="disabled"';
                   4601:     } else {
                   4602:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   4603:     }
1.549     raeburn  4604:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   4605: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   4606:     foreach my $acctype ('allow','deny') {
                   4607:         $output .= '
                   4608: <td valign="top">
                   4609: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   4610:   <div class="LC_string_ipacc_inner">'."\n";
                   4611:         my $num = 0;
                   4612:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  4613:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  4614:             if ($num > 0) {
                   4615:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   4616:             }
                   4617:             $output .= '</div>'."\n";
                   4618:             $num ++;
                   4619:         }
                   4620:         $output .= '
1.552     raeburn  4621:   </div>'.$addmore.'
1.549     raeburn  4622: </div>
                   4623: </td>';
                   4624:    }
                   4625:    $output .= '
                   4626: </tr>
                   4627: </table>'."\n";
                   4628:     return $output;
                   4629: }
                   4630: 
1.560     damieng  4631: 
                   4632: { # block using some constants related to parameter types (overview mode)
                   4633: 
1.446     bisitz   4634: my %strings =
1.383     albertel 4635:     (
                   4636:      'string_yesno'
                   4637:              => [[ 'yes', 'Yes' ],
1.560     damieng  4638:                  [ 'no', 'No' ]],
1.383     albertel 4639:      'string_problemstatus'
                   4640:              => [[ 'yes', 'Yes' ],
1.473     amueller 4641:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   4642:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   4643:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  4644:      'string_questiontype'
                   4645:              => [[ 'problem', 'Standard Problem'],
                   4646:                  [ 'survey', 'Survey'],
                   4647:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   4648:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  4649:                  [ 'anonsurvey', 'Anonymous Survey'],
                   4650:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   4651:                  [ 'practice', 'Practice'],
                   4652:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  4653:      'string_lenient'
                   4654:              => [['yes', 'Yes' ],
                   4655:                  [ 'no', 'No' ],
1.549     raeburn  4656:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   4657:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  4658:      'string_discussvote'
                   4659:              => [['yes','Yes'],
                   4660:                  ['notended','Yes, unless discussion ended'],
                   4661:                  ['no','No']],
1.549     raeburn  4662:      'string_ip'
                   4663:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587   ! raeburn  4664:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
        !          4665:      'string_deeplink'
        !          4666:              => [['full','Displayed (linked) in Contents and Grades'],
        !          4667:                  ['absent','Not displayed in Contents or Grades'],
        !          4668:                  ['grades','Displayed in Grades only'],
        !          4669:                  ['details','Displayed (unlinked) in Contents and Grades'],
        !          4670:                  ['datestatus','Displayed (with status), but unlinked in Contents and Grades']],
        !          4671:     );
        !          4672:    
1.383     albertel 4673: 
1.549     raeburn  4674: my %stringmatches = (
                   4675:          'string_lenient'
                   4676:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   4677:          'string_ip'
                   4678:               => [['_allowfrom_','[^\!]+'],
                   4679:                   ['_denyfrom_','\!']],
                   4680:     );
                   4681: 
                   4682: my %stringtypes = (
                   4683:                     type         => 'string_questiontype',
                   4684:                     lenient      => 'string_lenient',
                   4685:                     retrypartial => 'string_yesno',
                   4686:                     discussvote  => 'string_discussvote',
                   4687:                     examcode     => 'string_examcode',
                   4688:                     acc          => 'string_ip',
1.587   ! raeburn  4689:                     deeplink     => 'string_deeplink',
1.549     raeburn  4690:                   );
                   4691: 
1.563     damieng  4692: # Returns the possible values and titles for a given string type, or undef if there are none.
                   4693: # Used by courseprefs.
                   4694: #
                   4695: # @param {string} $string_type - a parameter type for strings
                   4696: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  4697: sub standard_string_options {
                   4698:     my ($string_type) = @_;
                   4699:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   4700:         return $strings{$string_type};
                   4701:     }
                   4702:     return;
                   4703: }
1.383     albertel 4704: 
1.563     damieng  4705: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   4706: #
                   4707: # @param {string} $string_type - a parameter type for strings
                   4708: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  4709: sub standard_string_matches {
                   4710:     my ($string_type) = @_;
                   4711:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   4712:         return $stringmatches{$string_type};
                   4713:     }
                   4714:     return;
                   4715: }
                   4716: 
1.563     damieng  4717: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   4718: #
                   4719: # @param {string} $name - parameter name
                   4720: # @returns {string}
1.549     raeburn  4721: sub get_stringtype {
                   4722:     my ($name) = @_;
                   4723:     if (exists($stringtypes{$name})) {
                   4724:         return $stringtypes{$name};
                   4725:     }
                   4726:     return;
                   4727: }
                   4728: 
1.563     damieng  4729: # Returns HTML to edit a string parameter.
                   4730: #
                   4731: # @param {string} $thistype - parameter type
                   4732: # @param {string} $thiskey - parameter key
                   4733: # @param {string} $showval - parameter current value
                   4734: # @param {string} $name - parameter name
                   4735: # @param {boolean} $readonly - true if the values should not be made editable
                   4736: # @returns {string}
1.383     albertel 4737: sub string_selector {
1.552     raeburn  4738:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   4739: 
1.383     albertel 4740:     if (!exists($strings{$thistype})) {
1.552     raeburn  4741:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 4742:     }
                   4743: 
1.504     raeburn  4744:     my %skiptype;
1.514     raeburn  4745:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  4746:             ($thistype eq 'string_lenient') ||
                   4747:             ($thistype eq 'string_discussvote') ||
                   4748:             ($thistype eq 'string_ip') ||
                   4749:             ($name eq 'retrypartial')) {
1.504     raeburn  4750:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   4751:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4752:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  4753:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  4754:             my $parmmatch;
                   4755:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   4756:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   4757:                     if (ref($item) eq 'ARRAY') {
                   4758:                         if ($parmval eq $item->[0]) {
                   4759:                             $parmmatch = $parmval;
                   4760:                             $parmval = '';
                   4761:                             last;
                   4762:                         }
                   4763:                     }
                   4764:                 }
                   4765:             }
                   4766:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  4767:             if ($needsrelease) {
                   4768:                 unless ($got_chostname) {
1.514     raeburn  4769:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  4770:                     $got_chostname = 1;
                   4771:                 }
1.557     raeburn  4772:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  4773:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  4774:                 if ($needsnewer) {
1.549     raeburn  4775:                     if ($parmmatch ne '') {
                   4776:                         $skiptype{$parmmatch} = 1;
                   4777:                     } elsif ($parmval ne '') {
                   4778:                         $skiptype{$parmval} = 1;
                   4779:                     }
1.504     raeburn  4780:                 }
                   4781:             }
                   4782:         }
                   4783:     }
1.549     raeburn  4784: 
                   4785:     if ($thistype eq 'string_ip') {
1.552     raeburn  4786:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.549     raeburn  4787:     }
1.504     raeburn  4788: 
1.552     raeburn  4789:     my ($result,$disabled);
                   4790: 
                   4791:     if ($readonly) {
                   4792:         $disabled = ' disabled="disabled"';
                   4793:     }
1.504     raeburn  4794:     my $numinrow = 3;
                   4795:     if ($thistype eq 'string_problemstatus') {
                   4796:         $numinrow = 2;
                   4797:     } elsif ($thistype eq 'string_questiontype') {
                   4798:         if (keys(%skiptype) > 0) {
                   4799:              $numinrow = 4;
                   4800:         }
                   4801:     }
                   4802:     my $rem;
                   4803:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   4804:         my $i=0;
                   4805:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4806:             next unless (ref($possibilities) eq 'ARRAY');
                   4807:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  4808:             next if ($skiptype{$name});
1.504     raeburn  4809:             $rem = $i%($numinrow);
                   4810:             if ($rem == 0) {
                   4811:                 if ($i > 0) {
                   4812:                     $result .= '</tr>';
                   4813:                 }
                   4814:                 $result .= '<tr>';
                   4815:             }
1.549     raeburn  4816:             my $colspan;
                   4817:             if ($i == @{ $strings{$thistype} }-1) {
                   4818:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   4819:                 if ($rem) {
                   4820:                     my $colsleft = $numinrow - $rem;
                   4821:                     if ($colsleft) {
                   4822:                         $colspan = $colsleft+1;
                   4823:                         $colspan = ' colspan="'.$colspan.'"';
                   4824:                     }
                   4825:                 }
                   4826:             }
                   4827:             my ($add,$onchange,$css_class);
                   4828:             if ($thistype eq 'string_lenient') {
                   4829:                 if ($name eq 'weighted') {
                   4830:                     my $display;
                   4831:                     my %relatives = &Apache::lonlocal::texthash(
                   4832:                                         corrchkd     => 'Correct (checked)',
                   4833:                                         corrunchkd   => 'Correct (unchecked)',
                   4834:                                         incorrchkd   => 'Incorrect (checked)',
                   4835:                                         incorrunchkd => 'Incorrect (unchecked)',
                   4836:                     );
                   4837:                     my %textval = (
                   4838:                                     corrchkd     => '1.0',
                   4839:                                     corrunchkd   => '1.0',
                   4840:                                     incorrchkd   => '0.0',
                   4841:                                     incorrunchkd => '0.0',
                   4842:                     );
                   4843:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   4844:                         $textval{'corrchkd'} = $1;
                   4845:                         $textval{'corrunchkd'} = $2;
                   4846:                         $textval{'incorrchkd'} = $3;
                   4847:                         $textval{'incorrunchkd'} = $4;
                   4848:                         $display = 'inline';
                   4849:                         $showval = $name;
                   4850:                     } else {
                   4851:                         $display = 'none';
                   4852:                     }
                   4853:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   4854:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   4855:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   4856:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   4857:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  4858:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  4859:                                 '</td></tr>';
                   4860:                     }
                   4861:                     $add .= '</table></div>'."\n";
                   4862:                 }
                   4863:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   4864:                 $css_class = ' class="LC_lenient_radio"';
                   4865:             }
                   4866:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  4867:                        '<span class="LC_nobreak"><label>'.
                   4868:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  4869:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  4870:             if ($showval eq $name) {
                   4871:                 $result .= ' checked="checked"';
                   4872:             }
1.549     raeburn  4873:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  4874:             $i++;
                   4875:         }
                   4876:         $result .= '</tr>';
1.473     amueller 4877:     }
1.504     raeburn  4878:     if ($result) {
                   4879:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 4880:     }
                   4881:     return $result;
                   4882: }
                   4883: 
1.554     raeburn  4884: my %intervals =
                   4885:     (
                   4886:      'date_interval'
                   4887:              => [[ 'done', 'Yes' ],
1.558     raeburn  4888:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  4889:                  [ '', 'No' ]],
                   4890:     );
                   4891: 
                   4892: my %intervalmatches = (
                   4893:          'date_interval'
1.559     raeburn  4894:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   4895:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  4896:     );
                   4897: 
                   4898: my %intervaltypes = (
                   4899:                       interval => 'date_interval',
                   4900:     );
                   4901: 
1.563     damieng  4902: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   4903: #
                   4904: # @param {string} $interval_type - a parameter type for intervals
                   4905: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  4906: sub standard_interval_matches {
                   4907:     my ($interval_type) = @_;
                   4908:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   4909:         return $intervalmatches{$interval_type};
                   4910:     }
                   4911:     return;
                   4912: }
                   4913: 
1.563     damieng  4914: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   4915: #
                   4916: # @param {string} $name - parameter name
                   4917: # @returns {string}
1.554     raeburn  4918: sub get_intervaltype {
                   4919:     my ($name) = @_;
                   4920:     if (exists($intervaltypes{$name})) {
                   4921:         return $intervaltypes{$name};
                   4922:     }
                   4923:     return;
                   4924: }
                   4925: 
1.563     damieng  4926: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   4927: # Used by courseprefs.
                   4928: #
                   4929: # @param {string} $interval_type - a parameter type for intervals
                   4930: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  4931: sub standard_interval_options {
                   4932:     my ($interval_type) = @_;
                   4933:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   4934:         return $intervals{$interval_type};
                   4935:     }
                   4936:     return;
                   4937: }
                   4938: 
1.563     damieng  4939: # Returns HTML to edit a date interval parameter.
                   4940: #
                   4941: # @param {string} $thiskey - parameter key
                   4942: # @param {string} $name - parameter name
                   4943: # @param {string} $showval - parameter current value
                   4944: # @param {boolean} $readonly - true if the values should not be made editable
                   4945: # @returns {string}
1.554     raeburn  4946: sub date_interval_selector {
                   4947:     my ($thiskey, $name, $showval, $readonly) = @_;
                   4948:     my ($result,%skipval);
                   4949:     if ($name eq 'interval') {
                   4950:         my $intervaltype = &get_intervaltype($name);
                   4951:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   4952:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   4953:             next unless (ref($possibilities) eq 'ARRAY');
                   4954:             my ($parmval, $description) = @{ $possibilities };
                   4955:             my $parmmatch;
                   4956:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   4957:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   4958:                     if (ref($item) eq 'ARRAY') {
                   4959:                         if ($parmval eq $item->[0]) {
                   4960:                             $parmmatch = $parmval;
                   4961:                             $parmval = '';
                   4962:                             last;
                   4963:                         }
                   4964:                     }
                   4965:                 }
                   4966:             }
                   4967:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   4968:             if ($needsrelease) {
                   4969:                 unless ($got_chostname) {
                   4970:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   4971:                     $got_chostname = 1;
                   4972:                 }
1.557     raeburn  4973:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  4974:                                                        $needsrelease,$cmajor,$cminor);
                   4975:                 if ($needsnewer) {
                   4976:                     if ($parmmatch ne '') {
                   4977:                         $skipval{$parmmatch} = 1;
                   4978:                     } elsif ($parmval ne '') {
                   4979:                         $skipval{$parmval} = 1;
                   4980:                     }
                   4981:                 }
                   4982:             }
                   4983:         }
                   4984:     }
                   4985: 
                   4986:     my $currval = $showval;
                   4987:     foreach my $which (['days', 86400, 31],
                   4988:                ['hours', 3600, 23],
                   4989:                ['minutes', 60, 59],
                   4990:                ['seconds',  1, 59]) {
1.560     damieng  4991:         my ($name, $factor, $max) = @{ $which };
                   4992:         my $amount = int($showval/$factor);
                   4993:         $showval  %= $factor;
                   4994:         my %select = ((map {$_ => $_} (0..$max)),
                   4995:                 'select_form_order' => [0..$max]);
                   4996:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   4997:                             \%select,'',$readonly);
                   4998:         $result .= ' '.&mt($name);
1.554     raeburn  4999:     }
                   5000:     if ($name eq 'interval') {
                   5001:         unless ($skipval{'done'}) {
                   5002:             my $checkedon = '';
1.558     raeburn  5003:             my $checkedproc = '';
                   5004:             my $currproctorkey = '';
                   5005:             my $currprocdisplay = 'hidden';
1.559     raeburn  5006:             my $currdonetext = &mt('Done');
1.554     raeburn  5007:             my $checkedoff = ' checked="checked"';
1.559     raeburn  5008:             if ($currval =~ /^(?:\d+)_done$/) {
                   5009:                 $checkedon = ' checked="checked"';
                   5010:                 $checkedoff = '';
                   5011:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5012:                 $currdonetext = $1;
1.554     raeburn  5013:                 $checkedon = ' checked="checked"';
                   5014:                 $checkedoff = '';
1.558     raeburn  5015:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5016:                 $currproctorkey = $1;
                   5017:                 $checkedproc = ' checked="checked"';
                   5018:                 $checkedoff = '';
                   5019:                 $currprocdisplay = 'text';
1.559     raeburn  5020:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5021:                 $currdonetext = $1;
                   5022:                 $currproctorkey = $2;
                   5023:                 $checkedproc = ' checked="checked"';
                   5024:                 $checkedoff = '';
                   5025:                 $currprocdisplay = 'text';
1.554     raeburn  5026:             }
1.558     raeburn  5027:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5028:             my $disabled;
                   5029:             if ($readonly) {
                   5030:                 $disabled = ' disabled="disabled"';
                   5031:             }
1.558     raeburn  5032:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5033:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5034:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5035:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5036:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5037:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5038:                        &mt('Yes, with proctor key').'</label>'.
                   5039:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5040:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5041:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  5042:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5043:         }
                   5044:     }
                   5045:     unless ($readonly) {
                   5046:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5047:     }
                   5048:     return $result;
                   5049: }
                   5050: 
1.563     damieng  5051: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5052: #
                   5053: # @param {string} $name - parameter name
                   5054: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5055: # @param {string} $value - parameter value
                   5056: # @param {string} $chostname - course server name
                   5057: # @param {integer} $cmajor - major version number
                   5058: # @param {integer} $cminor - minor version number
                   5059: # @param {string} $needsrelease - release version needed (major.minor)
                   5060: # @returns {string}
1.549     raeburn  5061: sub oldversion_warning {
1.557     raeburn  5062:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5063:     my $standard_name = &standard_parameter_names($name);
                   5064:     if ($namematch) {
                   5065:         my $level = &standard_parameter_levels($namematch);
                   5066:         my $msg = '';
                   5067:         if ($level) {
                   5068:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5069:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5070:         } else {
                   5071:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5072:                       $standard_name,'<b>','</b>');
                   5073:         }
                   5074:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5075:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5076:                    $cmajor.'.'.$cminor,$chostname,
                   5077:                    $needsrelease).
                   5078:                    '</p>';
                   5079:     }
1.549     raeburn  5080:     my $desc;
                   5081:     my $stringtype = &get_stringtype($name);
                   5082:     if ($stringtype ne '') {
                   5083:         if ($name eq 'examcode') {
                   5084:             $desc = $value;
                   5085:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5086:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5087:                 next unless (ref($possibilities) eq 'ARRAY');
                   5088:                 my ($parmval, $description) = @{ $possibilities };
                   5089:                 my $parmmatch;
                   5090:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5091:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5092:                         if (ref($item) eq 'ARRAY') {
                   5093:                             my ($regexpname,$pattern) = @{$item};
                   5094:                             if ($parmval eq $regexpname) {
                   5095:                                 if ($value =~ /$pattern/) {
                   5096:                                     $desc = $description; 
                   5097:                                     $parmmatch = 1;
                   5098:                                     last;
                   5099:                                 }
                   5100:                             }
                   5101:                         }
                   5102:                     }
                   5103:                     last if ($parmmatch);
                   5104:                 } elsif ($parmval eq $value) {
                   5105:                     $desc = $description;
                   5106:                     last;
                   5107:                 }
                   5108:             }
                   5109:         }
                   5110:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5111:         my $now = time;
                   5112:         if ($value =~ /^\d+$/) {
                   5113:             if ($name eq 'printstartdate') {
                   5114:                 if ($value > $now) {
                   5115:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5116:                 }
                   5117:             } elsif ($name eq 'printenddate') {
                   5118:                 if ($value < $now) {
                   5119:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5120:                 }
                   5121:             }
                   5122:         }
                   5123:     }
                   5124:     return '<p class="LC_warning">'.
1.557     raeburn  5125:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5126:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5127:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5128:        $cmajor.'.'.$cminor,$chostname,
                   5129:        $needsrelease).
                   5130:        '</p>';
1.549     raeburn  5131: }
                   5132: 
1.560     damieng  5133: } # end of block using some constants related to parameter types
                   5134: 
1.549     raeburn  5135: 
1.563     damieng  5136: 
                   5137: # Shifts all start and end dates in the current course by $shift.
1.389     www      5138: #
1.563     damieng  5139: # @param {integer} $shift - time to shift, in seconds
                   5140: # @returns {string} - error name or 'ok'
1.389     www      5141: sub dateshift {
                   5142:     my ($shift)=@_;
                   5143:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5144:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5145:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5146: # ugly retro fix for broken version of types
1.548     raeburn  5147:     foreach my $key (keys(%data)) {
1.389     www      5148:         if ($key=~/\wtype$/) {
                   5149:             my $newkey=$key;
                   5150:             $newkey=~s/type$/\.type/;
                   5151:             $data{$newkey}=$data{$key};
                   5152:             delete $data{$key};
                   5153:         }
                   5154:     }
1.391     www      5155:     my %storecontent=();
1.389     www      5156: # go through all parameters and look for dates
1.548     raeburn  5157:     foreach my $key (keys(%data)) {
1.389     www      5158:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
                   5159:           my $newdate=$data{$key}+$shift;
1.391     www      5160:           $storecontent{$key}=$newdate;
1.389     www      5161:        }
                   5162:     }
1.391     www      5163:     my $reply=&Apache::lonnet::cput
                   5164:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5165:     if ($reply eq 'ok') {
                   5166:        &log_parmset(\%storecontent);
                   5167:     }
                   5168:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5169:     return $reply;
1.389     www      5170: }
                   5171: 
1.563     damieng  5172: # Overview mode UI to edit course parameters.
                   5173: #
                   5174: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5175: sub newoverview {
1.568     raeburn  5176:     my ($r,$parm_permission) = @_;
1.280     albertel 5177: 
1.208     www      5178:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5179:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5180:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5181:     my $readonly = 1;
                   5182:     if ($parm_permission->{'edit'}) {
                   5183:         undef($readonly);
                   5184:     }
1.414     droeschl 5185:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5186:         text=>"Overview Mode"});
1.523     raeburn  5187: 
                   5188:     my %loaditems = (
1.549     raeburn  5189:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5190:                     );
                   5191:     my $js = '
                   5192: <script type="text/javascript">
                   5193: // <![CDATA[
                   5194: '.
                   5195:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5196:             &showhide_js()."\n".
1.549     raeburn  5197:             &toggleparmtextbox_js()."\n".
                   5198:             &validateparms_js()."\n".
                   5199:             &ipacc_boxes_js()."\n".
1.558     raeburn  5200:             &done_proctor_js()."\n".
1.523     raeburn  5201: '// ]]>
                   5202: </script>
                   5203: ';
1.549     raeburn  5204: 
1.523     raeburn  5205:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5206:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5207:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5208:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5209:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5210:     $r->print(<<ENDOVER);
1.549     raeburn  5211: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5212: ENDOVER
1.211     www      5213:     my @ids=();
                   5214:     my %typep=();
                   5215:     my %keyp=();
                   5216:     my %allparms=();
                   5217:     my %allparts=();
                   5218:     my %allmaps=();
                   5219:     my %mapp=();
                   5220:     my %symbp=();
                   5221:     my %maptitles=();
                   5222:     my %uris=();
                   5223:     my %keyorder=&standardkeyorder();
                   5224:     my %defkeytype=();
                   5225: 
                   5226:     my %alllevs=();
                   5227:     $alllevs{'Resource Level'}='full';
1.215     www      5228:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5229:     $alllevs{'Course Level'}='general';
                   5230: 
                   5231:     my $csec=$env{'form.csec'};
1.269     raeburn  5232:     my $cgroup=$env{'form.cgroup'};
1.211     www      5233: 
                   5234:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5235:     my $pschp=$env{'form.pschp'};
1.506     www      5236: 
1.211     www      5237:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5238:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5239: 
1.446     bisitz   5240:     my @selected_sections =
1.473     amueller 5241:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      5242:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 5243:     foreach my $sec (@selected_sections) {
                   5244:         if ($sec eq 'all') {
1.211     www      5245:             @selected_sections = ('all');
                   5246:         }
                   5247:     }
1.552     raeburn  5248:     if ($env{'request.course.sec'} ne '') {
                   5249:         @selected_sections = ($env{'request.course.sec'});
                   5250:     }
1.269     raeburn  5251:     my @selected_groups =
                   5252:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      5253: 
                   5254:     my $pssymb='';
                   5255:     my $parmlev='';
1.446     bisitz   5256: 
1.211     www      5257:     unless ($env{'form.parmlev'}) {
                   5258:         $parmlev = 'map';
                   5259:     } else {
                   5260:         $parmlev = $env{'form.parmlev'};
                   5261:     }
                   5262: 
1.446     bisitz   5263:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5264:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   5265:                 \%keyorder,\%defkeytype);
1.211     www      5266: 
1.374     albertel 5267:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 5268:         @psprt = keys(%allparts);
1.374     albertel 5269:     }
1.211     www      5270: # Menu to select levels, etc
                   5271: 
1.456     bisitz   5272:     $r->print('<div class="LC_Box">');
1.445     neumanie 5273:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   5274:     $r->print('<div>');
1.523     raeburn  5275:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      5276:     &levelmenu($r,\%alllevs,$parmlev);
                   5277:     if ($parmlev ne 'general') {
1.447     bisitz   5278:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 5279:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      5280:     }
1.447     bisitz   5281:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5282:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5283:     $r->print('</div></div>');
1.446     bisitz   5284: 
1.456     bisitz   5285:     $r->print('<div class="LC_Box">');
1.452     bisitz   5286:     $r->print('<div>');
1.581     raeburn  5287:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 5288:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   5289:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  5290:     my $sectionselector = &sectionmenu(\@selected_sections);
                   5291:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 5292:     $r->print('<table>'.
1.553     raeburn  5293:               '<tr><th>'.&mt('Parts').'</th>');
                   5294:     if ($sectionselector) {
                   5295:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   5296:     }
                   5297:     if ($groupselector) {
                   5298:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   5299:     }
                   5300:     $r->print('</tr><tr><td>');
1.211     www      5301:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  5302:     $r->print('</td>');
                   5303:     if ($sectionselector) { 
                   5304:         $r->print('<td>'.$sectionselector.'</td>');
                   5305:     }
                   5306:     if ($groupselector) {
                   5307:         $r->print('<td>'.$groupselector.'</td>');
                   5308:     }
                   5309:     $r->print('</tr></table>');
1.447     bisitz   5310:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5311:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5312:     $r->print('</div></div>');
                   5313: 
1.456     bisitz   5314:     $r->print('<div class="LC_Box">');
1.452     bisitz   5315:     $r->print('<div>');
1.214     www      5316:     my $sortorder=$env{'form.sortorder'};
                   5317:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5318:     &sortmenu($r,$sortorder);
1.445     neumanie 5319:     $r->print('</div></div>');
1.446     bisitz   5320: 
1.214     www      5321:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   5322: 
1.211     www      5323: # Build the list data hash from the specified parms
                   5324: 
                   5325:     my $listdata;
                   5326:     %{$listdata}=();
                   5327: 
                   5328:     foreach my $cat (@pscat) {
1.269     raeburn  5329:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   5330:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      5331:     }
                   5332: 
1.212     www      5333:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      5334: 
1.481     amueller 5335:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      5336: 
                   5337: # Read modified data
                   5338: 
1.481     amueller 5339:         my $resourcedata=&readdata($crs,$dom);
1.211     www      5340: 
                   5341: # List data
                   5342: 
1.568     raeburn  5343:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   5344:     }
                   5345:     $r->print(&tableend());
                   5346:     unless ($readonly) {
                   5347:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      5348:     }
1.568     raeburn  5349:     $r->print('</form>');
1.507     www      5350:     &endSettingsScreen($r);
                   5351:     $r->print(&Apache::loncommon::end_page());
1.208     www      5352: }
                   5353: 
1.563     damieng  5354: # Fills $listdata with parameter information.
                   5355: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   5356: # The non-type value is always 1.
                   5357: #
                   5358: # @param {string} $cat - parameter name
1.566     damieng  5359: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  5360: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   5361: # @param {hash reference} $listdata - the parameter data that will be modified
                   5362: # @param {array reference} $psprt - selected parts
                   5363: # @param {array reference} $selections - selected sections
                   5364: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  5365: # @param {hash reference} $allmaps - hash map pc -> map src
                   5366: # @param {array reference} $ids - resource and map ids
                   5367: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  5368: sub secgroup_lister {
                   5369:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   5370:     foreach my $item (@{$selections}) {
                   5371:         foreach my $part (@{$psprt}) {
                   5372:             my $rootparmkey=$env{'request.course.id'};
                   5373:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   5374:                 $rootparmkey.='.['.$item.']';
                   5375:             }
                   5376:             if ($parmlev eq 'general') {
                   5377: # course-level parameter
                   5378:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   5379:                 $$listdata{$newparmkey}=1;
                   5380:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5381:             } elsif ($parmlev eq 'map') {
                   5382: # map-level parameter
1.548     raeburn  5383:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  5384:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   5385:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   5386:                     $$listdata{$newparmkey}=1;
                   5387:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5388:                 }
                   5389:             } else {
                   5390: # resource-level parameter
                   5391:                 foreach my $rid (@{$ids}) {
                   5392:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   5393:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   5394:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   5395:                     $$listdata{$newparmkey}=1;
                   5396:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   5397:                 }
                   5398:             }
                   5399:         }
                   5400:     }
                   5401: }
                   5402: 
1.563     damieng  5403: # UI to edit parameter settings starting with a list of all existing parameters.
                   5404: # (called by setoverview action)
                   5405: #
                   5406: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5407: sub overview {
1.568     raeburn  5408:     my ($r,$parm_permission) = @_;
1.208     www      5409:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5410:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5411:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5412:     my $readonly = 1;
                   5413:     if ($parm_permission->{'edit'}) {
                   5414:         undef($readonly);
                   5415:     }
1.549     raeburn  5416:     my $js = '<script type="text/javascript">'."\n".
                   5417:              '// <![CDATA['."\n".
                   5418:              &toggleparmtextbox_js()."\n".
                   5419:              &validateparms_js()."\n".
                   5420:              &ipacc_boxes_js()."\n".
1.558     raeburn  5421:              &done_proctor_js()."\n".
1.549     raeburn  5422:              '// ]]>'."\n".
                   5423:              '</script>'."\n";
1.414     droeschl 5424:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5425:     text=>"Overview Mode"});
1.549     raeburn  5426:     my %loaditems = (
                   5427:                       'onload'   => "showHideLenient();",
                   5428:                     );
                   5429: 
                   5430:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 5431:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5432:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5433:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  5434:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      5435: 
1.208     www      5436: # Store modified
                   5437: 
1.568     raeburn  5438:     unless ($readonly) {
                   5439:         &storedata($r,$crs,$dom);
                   5440:     }
1.208     www      5441: 
                   5442: # Read modified data
                   5443: 
1.552     raeburn  5444:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      5445: 
1.214     www      5446: 
                   5447:     my $sortorder=$env{'form.sortorder'};
                   5448:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5449:     &sortmenu($r,$sortorder);
                   5450: 
1.568     raeburn  5451:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   5452: 
                   5453:     if ($readonly) {
                   5454:         $r->print('<p>'.$submitbutton.'</p>');
                   5455:     }
                   5456: 
1.208     www      5457: # List data
                   5458: 
1.568     raeburn  5459:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   5460:     $r->print(&tableend().'<p>');
                   5461:     if ($foundkeys) {
                   5462:         unless ($readonly) {
                   5463:             $r->print('<p>'.$submitbutton.'</p>');
                   5464:         }
                   5465:     } else {
                   5466:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   5467:     }
                   5468:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      5469: }
1.121     www      5470: 
1.560     damieng  5471: # Unused sub.
1.563     damieng  5472: #
                   5473: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 5474: sub clean_parameters {
                   5475:     my ($r) = @_;
                   5476:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5477:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5478: 
1.414     droeschl 5479:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 5480:         text=>"Clean Parameters"});
1.333     albertel 5481:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   5482:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   5483:     $r->print(<<ENDOVER);
                   5484: $start_page
                   5485: $breadcrumbs
                   5486: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   5487: ENDOVER
                   5488: # Store modified
                   5489: 
                   5490:     &storedata($r,$crs,$dom);
                   5491: 
                   5492: # Read modified data
                   5493: 
                   5494:     my $resourcedata=&readdata($crs,$dom);
                   5495: 
                   5496: # List data
                   5497: 
                   5498:     $r->print('<h3>'.
1.473     amueller 5499:           &mt('These parameters refer to resources that do not exist.').
                   5500:           '</h3>'.
                   5501:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   5502:           '<br />');
1.333     albertel 5503:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 5504:           '<tr>'.
                   5505:           '<th>'.&mt('Delete').'</th>'.
                   5506:           '<th>'.&mt('Parameter').'</th>'.
                   5507:           '</tr>');
1.333     albertel 5508:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  5509:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   5510:             && $thiskey=~/\.type$/);
                   5511:         my %data = &parse_key($thiskey);
                   5512:         if (1) { #exists($data{'realm_exists'})
                   5513:             #&& !$data{'realm_exists'}) {
                   5514:             $r->print(&Apache::loncommon::start_data_table_row().
                   5515:                 '<tr>'.
                   5516:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   5517: 
                   5518:             $r->print('<td>');
                   5519:             my $display_value = $resourcedata->{$thiskey};
                   5520:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   5521:             $display_value =
                   5522:                 &Apache::lonlocal::locallocaltime($display_value);
                   5523:             }
1.470     raeburn  5524:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   5525:             $parmitem = &mt($parmitem);
1.560     damieng  5526:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   5527:                 $parmitem,$resourcedata->{$thiskey}));
                   5528:             $r->print('<br />');
                   5529:             if ($data{'scope_type'} eq 'all') {
                   5530:                 $r->print(&mt('All users'));
                   5531:             } elsif ($data{'scope_type'} eq 'user') {
                   5532:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  5533:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   5534:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  5535:             }
                   5536:             $r->print('<br />');
                   5537:             if ($data{'realm_type'} eq 'all') {
                   5538:                 $r->print(&mt('All Resources'));
                   5539:             } elsif ($data{'realm_type'} eq 'folder') {
                   5540:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   5541:             } elsif ($data{'realm_type'} eq 'symb') {
                   5542:             my ($map,$resid,$url) =
                   5543:                 &Apache::lonnet::decode_symb($data{'realm'});
                   5544:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   5545:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   5546:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   5547:             }
                   5548:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   5549:             $r->print('</td></tr>');
                   5550: 
1.473     amueller 5551:         }
1.333     albertel 5552:     }
                   5553:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 5554:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      5555:           '</p></form>');
                   5556:     &endSettingsScreen($r);
                   5557:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 5558: }
                   5559: 
1.563     damieng  5560: # UI to shift all dates (called by dateshift1 action).
                   5561: # Used by overview mode.
                   5562: #
                   5563: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5564: sub date_shift_one {
                   5565:     my ($r) = @_;
                   5566:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5567:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5568:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.390     www      5569: 
1.414     droeschl 5570:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5571:         text=>"Shifting Dates"});
1.390     www      5572:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5573:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5574:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5575:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   5576:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      5577:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   5578:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   5579:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   5580:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      5581:                                                         'timeshifted',
                   5582:                                                         $env{'form.timebase'},,
                   5583:                                                         '').
                   5584:               '</td></tr></table>'.
                   5585:               '<input type="hidden" name="action" value="dateshift2" />'.
                   5586:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
                   5587:               '<input type="submit" value="'.&mt('Shift all dates accordingly').'" /></form>');
1.507     www      5588:     &endSettingsScreen($r);
1.390     www      5589:     $r->print(&Apache::loncommon::end_page());
                   5590: }
                   5591: 
1.563     damieng  5592: # UI to shift all dates (second form).
                   5593: #
                   5594: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5595: sub date_shift_two {
                   5596:     my ($r) = @_;
                   5597:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5598:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5599:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 5600:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5601:         text=>"Shifting Dates"});
1.390     www      5602:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5603:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5604:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5605:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      5606:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.543     bisitz   5607:     $r->print('<h2>'.&mt('Shift Dates').'</h2>'.
                   5608:               '<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
1.390     www      5609:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
1.543     bisitz   5610:               &Apache::lonlocal::locallocaltime($timeshifted)).'</p>');
1.390     www      5611:     my $delta=$timeshifted-$env{'form.timebase'};
                   5612:     &dateshift($delta);
1.543     bisitz   5613:     $r->print(
                   5614:         &Apache::lonhtmlcommon::confirm_success(&mt('Done')).
                   5615:         '<br /><br />'.
                   5616:         &Apache::lonhtmlcommon::actionbox(
                   5617:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      5618:     &endSettingsScreen($r);
1.390     www      5619:     $r->print(&Apache::loncommon::end_page());
                   5620: }
                   5621: 
1.563     damieng  5622: # Returns the different components of a resourcedata key.
                   5623: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   5624: #       realm_exists, parameter_part, parameter_name.
                   5625: # Was used by clean_parameters (which is unused).
                   5626: #
                   5627: # @param {string} $key - the parameter key
                   5628: # @returns {hash}
1.333     albertel 5629: sub parse_key {
                   5630:     my ($key) = @_;
                   5631:     my %data;
                   5632:     my ($middle,$part,$name)=
1.572     damieng  5633:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 5634:     $data{'scope_type'} = 'all';
                   5635:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5636:         $data{'scope'} = $1;
                   5637:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   5638:             $data{'scope_type'} = 'user';
                   5639:             $data{'scope'} = [$1,$2];
                   5640:         } else {
1.581     raeburn  5641:             $data{'scope_type'} = 'secgroup';
1.560     damieng  5642:         }
                   5643:         $middle=~s/^\[(.*)\]//;
1.333     albertel 5644:     }
                   5645:     $middle=~s/\.+$//;
                   5646:     $middle=~s/^\.+//;
                   5647:     $data{'realm_type'}='all';
                   5648:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  5649:         $data{'realm'} = $1;
                   5650:         $data{'realm_type'} = 'folder';
                   5651:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5652:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 5653:     } elsif ($middle) {
1.560     damieng  5654:         $data{'realm'} = $middle;
                   5655:         $data{'realm_type'} = 'symb';
                   5656:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5657:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   5658:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 5659:     }
1.446     bisitz   5660: 
1.333     albertel 5661:     $data{'parameter_part'} = $part;
                   5662:     $data{'parameter_name'} = $name;
                   5663: 
                   5664:     return %data;
                   5665: }
                   5666: 
1.239     raeburn  5667: 
1.563     damieng  5668: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      5669: sub header {
1.507     www      5670:     return &Apache::loncommon::start_page('Settings');
1.416     jms      5671: }
1.193     albertel 5672: 
                   5673: 
                   5674: 
1.560     damieng  5675: ##################################################
                   5676: # MAIN MENU
                   5677: ##################################################
                   5678: 
1.563     damieng  5679: # Content and problem settings main menu.
                   5680: #
                   5681: # @param {Apache2::RequestRec} $r - the Apache request
                   5682: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 5683: sub print_main_menu {
                   5684:     my ($r,$parm_permission)=@_;
                   5685:     #
1.414     droeschl 5686:     $r->print(&header());
1.507     www      5687:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  5688:     my $crstype = &Apache::loncommon::course_type();
                   5689:     my $lc_crstype = lc($crstype);
                   5690: 
                   5691:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 5692:     $r->print(<<ENDMAINFORMHEAD);
                   5693: <form method="post" enctype="multipart/form-data"
                   5694:       action="/adm/parmset" name="studentform">
                   5695: ENDMAINFORMHEAD
                   5696: #
1.195     albertel 5697:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5698:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 5699:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 5700:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  5701:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  5702:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   5703:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  5704:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   5705:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   5706:                                         '/'.$env{'request.course.sec'});
                   5707:     }
1.568     raeburn  5708:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   5709:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   5710:                                         '/'.$env{'request.course.sec'});
                   5711:     }
                   5712:     my (%linktext,%linktitle,%url);
                   5713:     if ($parm_permission->{'edit'}) {
                   5714:         %linktext = (
                   5715:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   5716:                      settable        => 'Edit Resource Parameters - Table Mode',
                   5717:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   5718:                     );
                   5719:         %linktitle = (
                   5720:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   5721:                      settable        => 'Set/Modify resource parameters in table mode.',
                   5722:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   5723:                      );
                   5724:     } else {
                   5725:         %linktext = (
                   5726:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   5727:                      settable        => 'View Resource Parameters - Table Mode',
                   5728:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   5729:                    );
                   5730:         %linktitle = (
                   5731:                      newoverview     => 'Display resource parameters in overview mode.',
                   5732:                      settable        => 'Display resource parameters in table mode.',
                   5733:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   5734:                      );
                   5735:     }
                   5736:     if ($mgr) {
                   5737:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   5738:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   5739:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   5740:     } elsif ($vgr) {
                   5741:         $linktext{'resettimes'} = 'Display Student Access Times',
                   5742:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   5743:         $url{'resettimes'} = '/adm/accesstimes';
                   5744:     }
1.193     albertel 5745:     my @menu =
1.507     www      5746:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 5747:         items => [
                   5748:           { linktext => 'Portfolio Metadata',
                   5749:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  5750:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  5751:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 5752:             icon =>'contact-new.png'   ,
                   5753:             },
1.568     raeburn  5754:           { linktext => $linktext{'resettimes'},
                   5755:             url => $url{'resettimes'},
                   5756:             permission => ($vgr || $mgr),
                   5757:             linktitle => $linktitle{'resettimes'},
                   5758:             icon => 'start-here.png',
1.473     amueller 5759:             },
1.520     raeburn  5760:           { linktext => 'Blocking Communication/Resource Access',
                   5761:             url => '/adm/setblock',
1.568     raeburn  5762:             permission => ($vcb || $dcm),
1.520     raeburn  5763:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   5764:             icon => 'comblock.png',
                   5765:             },
1.473     amueller 5766:           { linktext => 'Set Parameter Setting Default Actions',
                   5767:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  5768:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 5769:             linktitle =>'Set default actions for parameters.'  ,
                   5770:             icon => 'folder-new.png'  ,
                   5771:             }]},
                   5772:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   5773:         items => [
                   5774:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   5775:             url => '/adm/helper/parameter.helper',
1.568     raeburn  5776:             permission => $parm_permission->{'helper'},
1.473     amueller 5777:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   5778:             icon => 'dialog-information.png'  ,
                   5779:             #help => 'Parameter_Helper',
                   5780:             },
1.568     raeburn  5781:           { linktext => $linktext{'newoverview'},
1.473     amueller 5782:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  5783:             permission => $parm_permission->{'newoverview'},
                   5784:             linktitle => $linktitle{'newoverview'},
                   5785:             icon => 'edit-find.png',
1.473     amueller 5786:             #help => 'Parameter_Overview',
                   5787:             },
1.568     raeburn  5788:           { linktext => $linktext{'settable'},
1.473     amueller 5789:             url => '/adm/parmset?action=settable',
1.568     raeburn  5790:             permission => $parm_permission->{'settable'},
                   5791:             linktitle => $linktitle{'settable'},
                   5792:             icon => 'edit-copy.png',
1.473     amueller 5793:             #help => 'Table_Mode',
                   5794:             }]},
1.417     droeschl 5795:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 5796:          items => [
1.570     raeburn  5797:           { linktext => $linktext{'setoverview'},
1.473     amueller 5798:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  5799:             permission => $parm_permission->{'setoverview'},
                   5800:             linktitle => $linktitle{'setoverview'},
                   5801:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 5802:             #help => 'Parameter_Overview',
                   5803:             },
                   5804:           { linktext => 'Change Log',
                   5805:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  5806:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  5807:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 5808:             icon => 'document-properties.png',
1.473     amueller 5809:             }]}
1.193     albertel 5810:           );
1.414     droeschl 5811:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  5812:     $r->print('</form>');
1.507     www      5813:     &endSettingsScreen($r);
1.539     raeburn  5814:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 5815:     return;
                   5816: }
1.414     droeschl 5817: 
1.416     jms      5818: 
                   5819: 
1.560     damieng  5820: ##################################################
                   5821: # PORTFOLIO METADATA
                   5822: ##################################################
                   5823: 
1.563     damieng  5824: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   5825: # It looks like field titles are not localized.
                   5826: #
                   5827: # @param {Apache2::RequestRec} $r - the Apache request
                   5828: # @param {string} $field_name - metadata field name
                   5829: # @param {string} $field_text - metadata field title, in English unless manually added
                   5830: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 5831: sub output_row {
1.347     banghart 5832:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 5833:     my $output;
1.263     banghart 5834:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   5835:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 5836:     if (!defined($options)) {
1.254     banghart 5837:         $options = 'active,stuadd';
1.261     banghart 5838:         $values = '';
1.252     banghart 5839:     }
1.337     banghart 5840:     if (!($options =~ /deleted/)) {
                   5841:         my @options= ( ['active', 'Show to student'],
1.418     schafran 5842:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 5843:                     ['choices','Provide choices for students to select from']);
1.473     amueller 5844: #           ['onlyone','Student may select only one choice']);
1.337     banghart 5845:         if ($added_flag) {
                   5846:             push @options,['deleted', 'Delete Metadata Field'];
                   5847:         }
1.351     banghart 5848:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   5849:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 5850:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 5851:         foreach my $opt (@options) {
1.560     damieng  5852:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   5853:             $output .= &Apache::loncommon::continue_data_table_row();
                   5854:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   5855:                     <input type="checkbox" name="'.
                   5856:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   5857:                     &mt($opt->[1]).'</label></td>';
                   5858:             $output .= &Apache::loncommon::end_data_table_row();
                   5859:         }
1.351     banghart 5860:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   5861:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 5862:         $output .= &Apache::loncommon::end_data_table_row();
                   5863:         my $multiple_checked;
                   5864:         my $single_checked;
                   5865:         if ($options =~ m/onlyone/) {
1.422     bisitz   5866:             $multiple_checked = '';
1.423     bisitz   5867:             $single_checked = ' checked="checked"';
1.351     banghart 5868:         } else {
1.423     bisitz   5869:             $multiple_checked = ' checked="checked"';
1.422     bisitz   5870:             $single_checked = '';
1.351     banghart 5871:         }
1.560     damieng  5872:         $output .= &Apache::loncommon::continue_data_table_row();
                   5873:         $output .= '<td>'.('&nbsp;' x 10).'
                   5874:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   5875:                     '.&mt('Student may select multiple choices from list').'</td>';
                   5876:         $output .= &Apache::loncommon::end_data_table_row();
                   5877:         $output .= &Apache::loncommon::continue_data_table_row();
                   5878:         $output .= '<td>'.('&nbsp;' x 10).'
                   5879:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   5880:                     '.&mt('Student may select only one choice from list').'</td>';
                   5881:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 5882:     }
                   5883:     return ($output);
                   5884: }
1.416     jms      5885: 
                   5886: 
1.560     damieng  5887: # UI to order portfolio metadata fields.
1.563     damieng  5888: # Currently useless because addmetafield does not work.
                   5889: #
                   5890: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 5891: sub order_meta_fields {
                   5892:     my ($r)=@_;
                   5893:     my $idx = 1;
                   5894:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5895:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5896:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 5897:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  5898:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5899:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5900:         text=>"Add Metadata Field"});
1.560     damieng  5901:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5902:         {href=>"/adm/parmset?action=setrestrictmeta",
                   5903:         text=>"Restrict Metadata"},
                   5904:         {text=>"Order Metadata"});
1.345     banghart 5905:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  5906:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 5907:     if ($env{'form.storeorder'}) {
                   5908:         my $newpos = $env{'form.newpos'} - 1;
                   5909:         my $currentpos = $env{'form.currentpos'} - 1;
                   5910:         my @neworder = ();
1.548     raeburn  5911:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5912:         my $i;
1.341     banghart 5913:         if ($newpos > $currentpos) {
1.340     banghart 5914:         # moving stuff up
                   5915:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  5916:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5917:             }
                   5918:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  5919:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 5920:             }
                   5921:             $neworder[$newpos]=$oldorder[$currentpos];
                   5922:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  5923:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5924:             }
                   5925:         } else {
                   5926:         # moving stuff down
1.473     amueller 5927:             for ($i=0;$i<$newpos;$i++) {
                   5928:                 $neworder[$i]=$oldorder[$i];
                   5929:             }
                   5930:             $neworder[$newpos]=$oldorder[$currentpos];
                   5931:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   5932:                 $neworder[$i]=$oldorder[$i-1];
                   5933:             }
                   5934:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   5935:                 $neworder[$i]=$oldorder[$i];
                   5936:             }
1.340     banghart 5937:         }
1.560     damieng  5938:         my $ordered_fields = join ",", @neworder;
1.343     banghart 5939:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  5940:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5941:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 5942:     }
1.357     raeburn  5943:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 5944:     my $ordered_fields;
1.548     raeburn  5945:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5946:     if (!@fields_in_order) {
                   5947:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  5948:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 5949:             push @fields_in_order, $key;
1.341     banghart 5950:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 5951:         }
1.341     banghart 5952:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   5953:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5954:     }
1.340     banghart 5955:     $r->print('<table>');
                   5956:     my $num_fields = scalar(@fields_in_order);
                   5957:     foreach my $key (@fields_in_order) {
                   5958:         $r->print('<tr><td>');
                   5959:         $r->print('<form method="post" action="">');
1.537     bisitz   5960:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 5961:         for (my $i = 1;$i le $num_fields;$i ++) {
                   5962:             if ($i eq $idx) {
                   5963:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   5964:             } else {
                   5965:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   5966:             }
                   5967:         }
                   5968:         $r->print('</select></td><td>');
                   5969:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   5970:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   5971:         $r->print('</form>');
                   5972:         $r->print($$fields{$key}.'</td></tr>');
                   5973:         $idx ++;
                   5974:     }
                   5975:     $r->print('</table>');
1.507     www      5976:     &endSettingsScreen($r);
1.340     banghart 5977:     return 'ok';
                   5978: }
1.416     jms      5979: 
                   5980: 
1.563     damieng  5981: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   5982: # @returns {string}
1.359     banghart 5983: sub continue {
                   5984:     my $output;
                   5985:     $output .= '<form action="" method="post">';
                   5986:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  5987:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 5988:     return ($output);
                   5989: }
1.416     jms      5990: 
                   5991: 
1.563     damieng  5992: # UI to add a metadata field.
                   5993: # Currenly does not work because of an HTML error (the field is not visible).
                   5994: #
                   5995: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 5996: sub addmetafield {
                   5997:     my ($r)=@_;
1.414     droeschl 5998:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5999:         text=>"Add Metadata Field"});
1.334     banghart 6000:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6001:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6002:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6003:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6004:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6005:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6006:     if (exists($env{'form.undelete'})) {
1.358     banghart 6007:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6008:         foreach my $meta_field(@meta_fields) {
                   6009:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6010:             $options =~ s/deleted//;
                   6011:             $options =~ s/,,/,/;
                   6012:             my $put_result = &Apache::lonnet::put('environment',
                   6013:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6014: 
1.586     raeburn  6015:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6016:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6017:                           '</strong>',$put_result).
                   6018:                       '<br />');
1.339     banghart 6019:         }
1.359     banghart 6020:         $r->print(&continue());
1.339     banghart 6021:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6022:         my $meta_field = $env{'form.fieldname'};
                   6023:         my $display_field = $env{'form.fieldname'};
                   6024:         $meta_field =~ s/\W/_/g;
1.338     banghart 6025:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6026:         my $put_result = &Apache::lonnet::put('environment',
                   6027:                             {'metadata.'.$meta_field.'.values'=>"",
                   6028:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6029:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6030:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6031:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6032:                   '<br />');
1.359     banghart 6033:         $r->print(&continue());
1.335     banghart 6034:     } else {
1.357     raeburn  6035:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6036:         if ($fields) {
1.586     raeburn  6037:             $r->print(&mt('You may undelete previously deleted fields.').
                   6038:                       '<br />'.
                   6039:                       &mt('Check those you wish to undelete and click Undelete.').
                   6040:                       '<br />');
1.339     banghart 6041:             $r->print('<form method="post" action="">');
                   6042:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6043:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6044:             }
1.586     raeburn  6045:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6046:             $r->print('</form>');
                   6047:         }
1.586     raeburn  6048:         $r->print('<hr />'.
                   6049:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6050:                       '<strong>','</strong>').
1.581     raeburn  6051:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6052:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6053:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6054:         $r->print('</form>');
1.334     banghart 6055:     }
1.507     www      6056:     &endSettingsScreen($r);
1.334     banghart 6057: }
1.416     jms      6058: 
                   6059: 
                   6060: 
1.560     damieng  6061: # Display or save portfolio metadata.
1.563     damieng  6062: #
                   6063: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6064: sub setrestrictmeta {
1.240     banghart 6065:     my ($r)=@_;
1.242     banghart 6066:     my $next_meta;
1.244     banghart 6067:     my $output;
1.245     banghart 6068:     my $item_num;
1.246     banghart 6069:     my $put_result;
1.414     droeschl 6070:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6071:         text=>"Restrict Metadata"});
1.280     albertel 6072:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6073:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6074:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6075:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6076:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6077:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6078:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6079:     my $save_field = '';
1.586     raeburn  6080:     my %lt = &Apache::lonlocal::texthash(
                   6081:                                            addm => 'Add Metadata Field',
                   6082:                                            ordm => 'Order Metadata Fields',
                   6083:                                            save => 'Save',
                   6084:                                         );
1.259     banghart 6085:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6086:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6087:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6088:                 my $options;
1.252     banghart 6089:                 my $meta_field = $1;
                   6090:                 my $meta_key = $2;
1.253     banghart 6091:                 if ($save_field ne $meta_field) {
1.252     banghart 6092:                     $save_field = $meta_field;
1.473     amueller 6093:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6094:                         $options.='stuadd,';
                   6095:                     }
                   6096:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6097:                         $options.='choices,';
                   6098:                     }
                   6099:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6100:                         $options.='onlyone,';
                   6101:                     }
                   6102:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6103:                         $options.='active,';
                   6104:                     }
                   6105:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6106:                         $options.='deleted,';
                   6107:                     }
1.259     banghart 6108:                     my $name = $save_field;
1.560     damieng  6109:                     $put_result = &Apache::lonnet::put('environment',
                   6110:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6111:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6112:                         },$dom,$crs);
1.252     banghart 6113:                 }
                   6114:             }
                   6115:         }
                   6116:     }
1.296     albertel 6117:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6118:                        {'freshen_cache' => 1});
1.335     banghart 6119:     # Get the default metadata fields
1.258     albertel 6120:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6121:     # Now get possible added metadata fields
1.357     raeburn  6122:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6123:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6124:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6125:         if ($field ne 'courserestricted') {
1.586     raeburn  6126:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6127:         }
1.255     banghart 6128:     }
1.351     banghart 6129:     my $buttons = (<<ENDButtons);
1.586     raeburn  6130:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6131:         </form><br />
                   6132:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6133:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6134:         </form>
                   6135:         <br />
                   6136:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6137:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6138: ENDButtons
1.337     banghart 6139:     my $added_flag = 1;
1.335     banghart 6140:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6141:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6142:     }
1.347     banghart 6143:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6144:     $r->print(<<ENDenv);
1.259     banghart 6145:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6146:         $output
1.351     banghart 6147:         $buttons
1.340     banghart 6148:         </form>
1.244     banghart 6149: ENDenv
1.507     www      6150:     &endSettingsScreen($r);
1.280     albertel 6151:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6152:     return 'ok';
                   6153: }
1.416     jms      6154: 
                   6155: 
1.563     damieng  6156: # Returns metadata fields that have been manually added.
                   6157: #
                   6158: # @param {string} $cid - course id
                   6159: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6160: sub get_added_meta_fieldnames {
1.357     raeburn  6161:     my ($cid) = @_;
1.335     banghart 6162:     my %fields;
                   6163:     foreach my $key(%env) {
1.357     raeburn  6164:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6165:             my $field_name = $1;
                   6166:             my ($display_field_name) = $env{$key};
                   6167:             $fields{$field_name} = $display_field_name;
                   6168:         }
                   6169:     }
                   6170:     return \%fields;
                   6171: }
1.416     jms      6172: 
                   6173: 
1.563     damieng  6174: # Returns metadata fields that have been manually added and deleted.
                   6175: #
                   6176: # @param {string} $cid - course id
                   6177: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6178: sub get_deleted_meta_fieldnames {
1.357     raeburn  6179:     my ($cid) = @_;
1.339     banghart 6180:     my %fields;
                   6181:     foreach my $key(%env) {
1.357     raeburn  6182:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6183:             my $field_name = $1;
                   6184:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6185:                 my ($display_field_name) = $env{$key};
                   6186:                 $fields{$field_name} = $display_field_name;
                   6187:             }
                   6188:         }
                   6189:     }
                   6190:     return \%fields;
                   6191: }
1.560     damieng  6192: 
                   6193: 
                   6194: ##################################################
                   6195: # PARAMETER SETTINGS DEFAULT ACTIONS
                   6196: ##################################################
                   6197: 
                   6198: # UI to change parameter setting default actions
1.563     damieng  6199: #
                   6200: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      6201: sub defaultsetter {
1.280     albertel 6202:     my ($r) = @_;
                   6203: 
1.414     droeschl 6204:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 6205:         text=>"Set Defaults"});
1.531     raeburn  6206:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6207:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6208:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   6209:     my $start_page =
1.531     raeburn  6210:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 6211:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      6212:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6213:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      6214:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 6215: 
1.221     www      6216:     my @ids=();
                   6217:     my %typep=();
                   6218:     my %keyp=();
                   6219:     my %allparms=();
                   6220:     my %allparts=();
                   6221:     my %allmaps=();
                   6222:     my %mapp=();
                   6223:     my %symbp=();
                   6224:     my %maptitles=();
                   6225:     my %uris=();
                   6226:     my %keyorder=&standardkeyorder();
                   6227:     my %defkeytype=();
                   6228: 
1.446     bisitz   6229:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6230:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   6231:                 \%keyorder,\%defkeytype);
1.224     www      6232:     if ($env{'form.storerules'}) {
1.560     damieng  6233:         my %newrules=();
                   6234:         my @delrules=();
                   6235:         my %triggers=();
                   6236:         foreach my $key (keys(%env)) {
1.225     albertel 6237:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  6238:                 my $tempkey=$1;
                   6239:                 my $action=$env{$key};
1.226     www      6240:                 if ($action) {
1.560     damieng  6241:                     $newrules{$tempkey.'_action'}=$action;
                   6242:                     if ($action ne 'default') {
                   6243:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   6244:                         $triggers{$whichparm}.=$tempkey.':';
                   6245:                     }
                   6246:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   6247:                     if (&isdateparm($defkeytype{$tempkey})) {
                   6248:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   6249:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   6250:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   6251:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   6252:                     } else {
                   6253:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   6254:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   6255:                     }
                   6256:                 } else {
                   6257:                     push(@delrules,$tempkey.'_action');
                   6258:                     push(@delrules,$tempkey.'_type');
                   6259:                     push(@delrules,$tempkey.'_hours');
                   6260:                     push(@delrules,$tempkey.'_min');
                   6261:                     push(@delrules,$tempkey.'_sec');
                   6262:                     push(@delrules,$tempkey.'_value');
                   6263:                 }
1.473     amueller 6264:             }
                   6265:         }
1.560     damieng  6266:         foreach my $key (keys(%allparms)) {
                   6267:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 6268:         }
1.560     damieng  6269:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   6270:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   6271:         &resetrulescache();
1.224     www      6272:     }
1.227     www      6273:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 6274:                        'hours' => 'Hours',
                   6275:                        'min' => 'Minutes',
                   6276:                        'sec' => 'Seconds',
                   6277:                        'yes' => 'Yes',
                   6278:                        'no' => 'No');
1.222     www      6279:     my @standardoptions=('','default');
                   6280:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   6281:     my @dateoptions=('','default');
                   6282:     my @datedisplay=('',&mt('Default value when manually setting'));
                   6283:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6284:         unless ($tempkey) { next; }
                   6285:         push @standardoptions,'when_setting_'.$tempkey;
                   6286:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   6287:         if (&isdateparm($defkeytype{$tempkey})) {
                   6288:             push @dateoptions,'later_than_'.$tempkey;
                   6289:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   6290:             push @dateoptions,'earlier_than_'.$tempkey;
                   6291:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   6292:         }
1.222     www      6293:     }
1.563     damieng  6294:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   6295:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 6296:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 6297:           &Apache::loncommon::start_data_table_header_row().
                   6298:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   6299:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   6300:           &Apache::loncommon::end_data_table_header_row());
1.221     www      6301:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6302:         unless ($tempkey) { next; }
                   6303:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   6304:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   6305:         my $action=&rulescache($tempkey.'_action');
                   6306:         $r->print('<select name="'.$tempkey.'_action">');
                   6307:         if (&isdateparm($defkeytype{$tempkey})) {
                   6308:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   6309:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   6310:             $r->print("\n<option value='$dateoptions[$i]'".
                   6311:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   6312:                 ">$datedisplay[$i]</option>");
                   6313:             }
                   6314:         } else {
                   6315:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   6316:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   6317:             $r->print("\n<option value='$standardoptions[$i]'".
                   6318:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   6319:                 ">$standarddisplay[$i]</option>");
                   6320:             }
1.473     amueller 6321:         }
1.560     damieng  6322:         $r->print('</select>');
                   6323:         unless (&isdateparm($defkeytype{$tempkey})) {
                   6324:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   6325:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 6326:         }
1.560     damieng  6327:         $r->print("\n</td><td>\n");
1.222     www      6328: 
1.221     www      6329:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  6330:             my $days=&rulescache($tempkey.'_days');
                   6331:             my $hours=&rulescache($tempkey.'_hours');
                   6332:             my $min=&rulescache($tempkey.'_min');
                   6333:             my $sec=&rulescache($tempkey.'_sec');
                   6334:             $r->print(<<ENDINPUTDATE);
                   6335:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   6336:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   6337:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   6338:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  6339: ENDINPUTDATE
1.560     damieng  6340:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   6341:                 my $yeschecked='';
                   6342:                 my $nochecked='';
                   6343:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   6344:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   6345: 
                   6346:             $r->print(<<ENDYESNO);
                   6347:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   6348:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  6349: ENDYESNO
1.221     www      6350:         } else {
1.560     damieng  6351:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   6352:         }
1.318     albertel 6353:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      6354:     }
1.318     albertel 6355:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 6356:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      6357:           &mt('Save').'" /></form>'."\n");
                   6358:     &endSettingsScreen($r);
                   6359:     $r->print(&Apache::loncommon::end_page());
1.220     www      6360:     return;
                   6361: }
1.193     albertel 6362: 
1.560     damieng  6363: ##################################################
                   6364: # PARAMETER CHANGES LOG
                   6365: ##################################################
                   6366: 
1.563     damieng  6367: # Returns some info for a parameter log entry.
                   6368: # Returned entries:
                   6369: # $realm - HTML title for the parameter level and resource
                   6370: # $section - parameter section
                   6371: # $name - parameter name
                   6372: # $part - parameter part
                   6373: # $what - $part.'.'.$name
                   6374: # $middle - resource symb ?
                   6375: # $uname - user name (same as given)
                   6376: # $udom - user domain (same as given)
                   6377: # $issection - section or group name
                   6378: # $realmdescription - title for the parameter level and resource (without using HTML)
                   6379: #
                   6380: # @param {string} $key - parameter log key
                   6381: # @param {string} $uname - user name
                   6382: # @param {string} $udom - user domain
                   6383: # @param {boolean} $typeflag - .type log entry
                   6384: # @returns {Array}
1.290     www      6385: sub components {
1.581     raeburn  6386:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 6387: 
                   6388:     if ($typeflag) {
1.560     damieng  6389:         $key=~s/\.type$//;
1.290     www      6390:     }
1.330     albertel 6391: 
                   6392:     my ($middle,$part,$name)=
1.572     damieng  6393:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      6394:     my $issection;
1.330     albertel 6395: 
1.290     www      6396:     my $section=&mt('All Students');
                   6397:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6398:         $issection=$1;
                   6399:         $section=&mt('Group/Section').': '.$issection;
                   6400:         $middle=~s/^\[(.*)\]//;
1.290     www      6401:     }
                   6402:     $middle=~s/\.+$//;
                   6403:     $middle=~s/^\.+//;
1.291     www      6404:     if ($uname) {
1.560     damieng  6405:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   6406:         $issection='';
1.291     www      6407:     }
1.316     albertel 6408:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   6409:     my $realmdescription=&mt('all resources');
1.556     raeburn  6410:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   6411:         my $mapurl = $1;
                   6412:         my $maplevel = $2;
                   6413:         my $leveltitle = &mt('Folder/Map');
                   6414:         if ($maplevel eq 'rec') {
                   6415:             $leveltitle = &mt('Recursive');
                   6416:         }
1.560     damieng  6417:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   6418:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   6419:             $mapurl.')</span></span>';
                   6420:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   6421:     } elsif ($middle) {
                   6422:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   6423:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   6424:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   6425:             ' in '.$map.' id: '.$id.')</span></span>';
                   6426:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      6427:     }
1.291     www      6428:     my $what=$part.'.'.$name;
1.330     albertel 6429:     return ($realm,$section,$name,$part,
1.473     amueller 6430:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      6431: }
1.293     www      6432: 
1.563     damieng  6433: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   6434: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      6435: 
1.563     damieng  6436: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 6437: sub load_parameter_names {
1.583     raeburn  6438:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 6439:     while (my $configline=<$config>) {
1.560     damieng  6440:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   6441:         chomp($configline);
                   6442:         my ($short,$plain)=split(/:/,$configline);
                   6443:         my (undef,$name,$type)=split(/\&/,$short,3);
                   6444:         if ($type eq 'display') {
                   6445:             $standard_parms{$name} = $plain;
1.469     raeburn  6446:         } elsif ($type eq 'type') {
1.560     damieng  6447:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  6448:         }
1.328     albertel 6449:     }
                   6450:     close($config);
                   6451:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   6452:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  6453:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 6454: }
                   6455: 
1.563     damieng  6456: # Returns a parameter title for standard parameters, the name for others.
                   6457: #
                   6458: # @param {string} $name - parameter name
                   6459: # @returns {string}
1.292     www      6460: sub standard_parameter_names {
                   6461:     my ($name)=@_;
1.328     albertel 6462:     if (!%standard_parms) {
1.560     damieng  6463:         &load_parameter_names();
1.328     albertel 6464:     }
1.292     www      6465:     if ($standard_parms{$name}) {
1.560     damieng  6466:         return $standard_parms{$name};
1.446     bisitz   6467:     } else {
1.560     damieng  6468:         return $name;
1.292     www      6469:     }
                   6470: }
1.290     www      6471: 
1.563     damieng  6472: # Returns a parameter type for standard parameters, undef for others.
                   6473: #
                   6474: # @param {string} $name - parameter name
                   6475: # @returns {string}
1.469     raeburn  6476: sub standard_parameter_types {
                   6477:     my ($name)=@_;
                   6478:     if (!%standard_parms_types) {
                   6479:         &load_parameter_names();
                   6480:     }
                   6481:     if ($standard_parms_types{$name}) {
                   6482:         return $standard_parms_types{$name};
                   6483:     }
                   6484:     return;
                   6485: }
1.309     www      6486: 
1.563     damieng  6487: # Returns a parameter level title (not localized) from the parameter level name.
                   6488: #
                   6489: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   6490: # @returns {string}
1.557     raeburn  6491: sub standard_parameter_levels {
                   6492:     my ($name)=@_;
                   6493:     my %levels = (
                   6494:                     'resourcelevel'   => 'a single resource',
                   6495:                     'maplevel'        => 'the enclosing map/folder', 
                   6496:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   6497:                     'courselevel'     => 'the general (course) level',
                   6498:                  );
                   6499:     if ($levels{$name}) {
                   6500:         return $levels{$name};
                   6501:     }
                   6502:     return;
                   6503: }
                   6504: 
1.560     damieng  6505: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  6506: #
                   6507: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 6508: sub parm_change_log {
1.568     raeburn  6509:     my ($r,$parm_permission)=@_;
1.531     raeburn  6510:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6511:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  6512:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6513:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 6514:     text=>"Parameter Change Log"});
1.522     raeburn  6515:     my $js = '<script type="text/javascript">'."\n".
                   6516:              '// <![CDATA['."\n".
                   6517:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   6518:              '// ]]>'."\n".
                   6519:              '</script>'."\n";
                   6520:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 6521:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  6522:     &startSettingsScreen($r,'parmset',$crstype);
                   6523:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 6524: 
1.301     www      6525:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 6526: 
1.522     raeburn  6527:     $r->print('<div class="LC_left_float">'.
                   6528:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   6529:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 6530:                      method="post" name="parameterlog">');
1.446     bisitz   6531: 
1.311     albertel 6532:     my %saveable_parameters = ('show' => 'scalar',);
                   6533:     &Apache::loncommon::store_course_settings('parameter_log',
                   6534:                                               \%saveable_parameters);
                   6535:     &Apache::loncommon::restore_course_settings('parameter_log',
                   6536:                                                 \%saveable_parameters);
1.522     raeburn  6537:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   6538:               '<input type="submit" value="'.&mt('Display').'" />'.
                   6539:               '</form></fieldset></div><br clear="all" />');
1.301     www      6540: 
1.568     raeburn  6541:     my $readonly = 1;
                   6542:     if ($parm_permission->{'edit'}) {
                   6543:         undef($readonly);
                   6544:     }
1.531     raeburn  6545:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      6546:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 6547:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  6548:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   6549:     unless ($readonly) {
                   6550:         $r->print('<th>'.&mt('Announce').'</th>');
                   6551:     }
                   6552:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      6553:     my $shown=0;
1.349     www      6554:     my $folder='';
                   6555:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  6556:         my $last='';
                   6557:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   6558:                 &GDBM_READER(),0640)) {
                   6559:             $last=$hash{'last_known'};
                   6560:             untie(%hash);
                   6561:         }
                   6562:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   6563:     }
                   6564:     foreach my $id (sort {
                   6565:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   6566:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   6567:                 }
                   6568:                 my $aid = (split('00000',$a))[-1];
                   6569:                 my $bid = (split('00000',$b))[-1];
                   6570:                 return $bid<=>$aid;
1.473     amueller 6571:             } (keys(%parmlog))) {
1.294     www      6572:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  6573:         my $count = 0;
                   6574:         my $time =
                   6575:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   6576:         my $plainname =
                   6577:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   6578:                         $parmlog{$id}{'exe_udom'});
                   6579:         my $about_me_link =
                   6580:             &Apache::loncommon::aboutmewrapper($plainname,
                   6581:                             $parmlog{$id}{'exe_uname'},
                   6582:                             $parmlog{$id}{'exe_udom'});
                   6583:         my $send_msg_link='';
1.568     raeburn  6584:         if ((!$readonly) && 
                   6585:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  6586:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   6587:             $send_msg_link ='<br />'.
                   6588:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   6589:                             $parmlog{$id}{'exe_uname'},
                   6590:                             $parmlog{$id}{'exe_udom'});
                   6591:         }
                   6592:         my $row_start=&Apache::loncommon::start_data_table_row();
                   6593:         my $makenewrow=0;
                   6594:         my %istype=();
                   6595:         my $output;
                   6596:         foreach my $changed (reverse(sort(@changes))) {
                   6597:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   6598:             my $typeflag = ($changed =~/\.type$/ &&
                   6599:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 6600:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  6601:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  6602:             if ($env{'request.course.sec'} ne '') {
                   6603:                 next if (($issection ne '') && ($issection ne $env{'request.course.sec'}));
                   6604:                 if ($uname ne '') {
                   6605:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   6606:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   6607:                 }
                   6608:             }
                   6609:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   6610:                 if ($folder) {
                   6611:                     if ($middle!~/^\Q$folder\E/) { next; }
                   6612:                 }
                   6613:             }
                   6614:             if ($typeflag) {
                   6615:                 $istype{$parmname}=$value;
                   6616:                 if (!$env{'form.includetypes'}) { next; }
                   6617:             }
                   6618:             $count++;
                   6619:             if ($makenewrow) {
                   6620:                 $output .= $row_start;
                   6621:             } else {
                   6622:                 $makenewrow=1;
                   6623:             }
1.470     raeburn  6624:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  6625:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   6626:                 &mt($parmitem).'</td><td>'.
                   6627:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   6628:             my $stillactive=0;
                   6629:             if ($parmlog{$id}{'delflag'}) {
                   6630:                 $output .= &mt('Deleted');
                   6631:             } else {
                   6632:                 if ($typeflag) {
1.470     raeburn  6633:                     my $parmitem = &standard_parameter_names($value); 
                   6634:                     $parmitem = &mt($parmitem);
1.560     damieng  6635:                     $output .= &mt('Type: [_1]',$parmitem);
                   6636:                 } else {
1.584     raeburn  6637:                     my $toolsymb;
                   6638:                     if ($middle =~ /ext\.tool$/) {
                   6639:                         $toolsymb = $middle;
                   6640:                     }
1.560     damieng  6641:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  6642:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  6643:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  6644:                     my $showvalue = $value;
                   6645:                     if ($istype{$parmname} eq '') {
                   6646:                         my $type = &standard_parameter_types($parmname);
                   6647:                         if ($type ne '') {
                   6648:                             if (&isdateparm($type)) {
                   6649:                                 $showvalue =
                   6650:                                     &Apache::lonlocal::locallocaltime($value);
                   6651:                             }
                   6652:                         }
                   6653:                     } else {
1.560     damieng  6654:                         if (&isdateparm($istype{$parmname})) {
                   6655:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   6656:                         }
1.469     raeburn  6657:                     }
                   6658:                     $output .= $showvalue;
1.560     damieng  6659:                     if ($value ne $all[$level]) {
                   6660:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   6661:                     } else {
                   6662:                         $stillactive=1;
                   6663:                     }
                   6664:                 }
1.473     amueller 6665:             }
1.568     raeburn  6666:             $output .= '</td>';
                   6667: 
                   6668:             unless ($readonly) { 
                   6669:                 $output .= '<td>';
                   6670:                 if ($stillactive) {
                   6671:                     my $parmitem = &standard_parameter_names($parmname);
                   6672:                     $parmitem = &mt($parmitem);
                   6673:                     my $title=&mt('Changed [_1]',$parmitem);
                   6674:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   6675:                         $parmitem,$realmdescription,
                   6676:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   6677:                     if (($uname) && ($udom)) {
                   6678:                         $output .=
                   6679:                         &Apache::loncommon::messagewrapper('Notify User',
                   6680:                                                            $uname,$udom,$title,
                   6681:                                                            $description);
                   6682:                     } else {
                   6683:                         $output .=
                   6684:                             &Apache::lonrss::course_blog_link($id,$title,
                   6685:                                                               $description);
                   6686:                     }
1.560     damieng  6687:                 }
1.568     raeburn  6688:                 $output .= '</td>';
1.560     damieng  6689:             }
1.568     raeburn  6690:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 6691:         }
1.560     damieng  6692:         if ($env{'form.displayfilter'} eq 'containing') {
                   6693:             my $wholeentry=$about_me_link.':'.
                   6694:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   6695:             $output;
                   6696:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 6697:         }
1.349     www      6698:         if ($count) {
1.560     damieng  6699:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   6700:                         <td rowspan="'.$count.'">'.$about_me_link.
                   6701:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   6702:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   6703:             $send_msg_link.'</td>'.$output);
                   6704:             $shown++;
                   6705:         }
                   6706:         if (!($env{'form.show'} eq &mt('all')
                   6707:             || $shown<=$env{'form.show'})) { last; }
1.286     www      6708:     }
1.301     www      6709:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      6710:     &endSettingsScreen($r);
1.284     www      6711:     $r->print(&Apache::loncommon::end_page());
                   6712: }
                   6713: 
1.560     damieng  6714: ##################################################
                   6715: # MISC !
                   6716: ##################################################
                   6717: 
1.563     damieng  6718: # Stores slot information.
1.560     damieng  6719: # Used by table UI
1.563     damieng  6720: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6721: #
                   6722: # @param {string} $slot_name - slot name
                   6723: # @param {string} $cdom - course domain
                   6724: # @param {string} $cnum - course number
                   6725: # @param {string} $symb - resource symb
                   6726: # @param {string} $uname - user name
                   6727: # @param {string} $udom - user domain
                   6728: # @returns {string} - 'ok' or error name
1.437     raeburn  6729: sub update_slots {
                   6730:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   6731:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   6732:     if (!keys(%slot)) {
                   6733:         return 'error: slot does not exist';
                   6734:     }
                   6735:     my $max=$slot{'maxspace'};
                   6736:     if (!defined($max)) { $max=99999; }
                   6737: 
                   6738:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   6739:                                        "^$slot_name\0");
                   6740:     my ($tmp)=%consumed;
                   6741:     if ($tmp=~/^error: 2 / ) {
                   6742:         return 'error: unable to determine current slot status';
                   6743:     }
                   6744:     my $last=0;
                   6745:     foreach my $key (keys(%consumed)) {
                   6746:         my $num=(split('\0',$key))[1];
                   6747:         if ($num > $last) { $last=$num; }
                   6748:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6749:             return 'ok';
                   6750:         }
                   6751:     }
                   6752: 
                   6753:     if (scalar(keys(%consumed)) >= $max) {
                   6754:         return 'error: no space left in slot';
                   6755:     }
                   6756:     my $wanted=$last+1;
                   6757: 
                   6758:     my %reservation=('name'      => $uname.':'.$udom,
                   6759:                      'timestamp' => time,
                   6760:                      'symb'      => $symb);
                   6761: 
                   6762:     my $success=&Apache::lonnet::newput('slot_reservations',
                   6763:                                         {"$slot_name\0$wanted" =>
                   6764:                                              \%reservation},
                   6765:                                         $cdom, $cnum);
1.438     raeburn  6766:     if ($success eq 'ok') {
                   6767:         my %storehash = (
                   6768:                           symb    => $symb,
                   6769:                           slot    => $slot_name,
                   6770:                           action  => 'reserve',
                   6771:                           context => 'parameter',
                   6772:                         );
1.526     raeburn  6773:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6774:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  6775: 
1.526     raeburn  6776:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6777:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  6778:     }
1.437     raeburn  6779:     return $success;
                   6780: }
                   6781: 
1.563     damieng  6782: # Deletes a slot reservation.
1.560     damieng  6783: # Used by table UI
1.563     damieng  6784: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6785: #
                   6786: # @param {string} $slot_name - slot name
                   6787: # @param {string} $cdom - course domain
                   6788: # @param {string} $cnum - course number
                   6789: # @param {string} $uname - user name
                   6790: # @param {string} $udom - user domain
                   6791: # @param {string} $symb - resource symb
                   6792: # @returns {string} - 'ok' or error name
1.437     raeburn  6793: sub delete_slots {
                   6794:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   6795:     my $delresult;
                   6796:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   6797:                                          $cnum, "^$slot_name\0");
                   6798:     if (&Apache::lonnet::error(%consumed)) {
                   6799:         return 'error: unable to determine current slot status';
                   6800:     }
                   6801:     my ($tmp)=%consumed;
                   6802:     if ($tmp=~/^error: 2 /) {
                   6803:         return 'error: unable to determine current slot status';
                   6804:     }
                   6805:     foreach my $key (keys(%consumed)) {
                   6806:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6807:             my $num=(split('\0',$key))[1];
                   6808:             my $entry = $slot_name.'\0'.$num;
                   6809:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   6810:                                               $cdom,$cnum);
                   6811:             if ($delresult eq 'ok') {
                   6812:                 my %storehash = (
                   6813:                                   symb    => $symb,
                   6814:                                   slot    => $slot_name,
                   6815:                                   action  => 'release',
                   6816:                                   context => 'parameter',
                   6817:                                 );
1.526     raeburn  6818:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6819:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  6820:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6821:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  6822:             }
                   6823:         }
                   6824:     }
                   6825:     return $delresult;
                   6826: }
                   6827: 
1.563     damieng  6828: # Returns true if there is a current course.
1.560     damieng  6829: # Used by handler
1.563     damieng  6830: #
                   6831: # @returns {boolean}
1.355     albertel 6832: sub check_for_course_info {
                   6833:     my $navmap = Apache::lonnavmaps::navmap->new();
                   6834:     return 1 if ($navmap);
                   6835:     return 0;
                   6836: }
                   6837: 
1.563     damieng  6838: # Returns the current course host and host LON-CAPA version.
                   6839: #
                   6840: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  6841: sub parameter_release_vars { 
1.504     raeburn  6842:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6843:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   6844:    my $chostname = &Apache::lonnet::hostname($chome);
                   6845:    my ($cmajor,$cminor) = 
                   6846:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   6847:    return ($chostname,$cmajor,$cminor);
                   6848: }
                   6849: 
1.563     damieng  6850: # Checks if the course host version can handle a parameter required version,
                   6851: # and if it does, stores the release needed for the course.
                   6852: #
                   6853: # @param {string} $name - parameter name
                   6854: # @param {string} $value - parameter value
                   6855: # @param {string} $valmatch - name of the test used for checking the value
                   6856: # @param {string} $namematch - name of the test used for checking the name
                   6857: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   6858: # @param {integer} $cmajor - course major version number
                   6859: # @param {integer} $cminor - course minor version number
                   6860: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  6861: sub parameter_releasecheck {
1.557     raeburn  6862:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  6863:     my $needsnewer;
                   6864:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   6865:     if (($cmajor < $needsmajor) || 
                   6866:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   6867:         $needsnewer = 1;
1.557     raeburn  6868:     } elsif ($name) {
                   6869:         if ($valmatch) {
                   6870:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   6871:         } elsif ($value) { 
                   6872:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   6873:         }
                   6874:     } elsif ($namematch) {
                   6875:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  6876:     }
                   6877:     return $needsnewer;
                   6878: }
                   6879: 
1.568     raeburn  6880: sub get_permission {
                   6881:     my %permission;
                   6882:     my $allowed = 0;
                   6883:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   6884:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   6885:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   6886:                   $env{'request.course.sec'}))) {
                   6887:         %permission= (
                   6888:                        'edit'               => 1,
                   6889:                        'set'                => 1,
                   6890:                        'setoverview'        => 1,
                   6891:                        'addmetadata'        => 1,
                   6892:                        'ordermetadata'      => 1,
                   6893:                        'setrestrictmeta'    => 1,
                   6894:                        'newoverview'        => 1,
                   6895:                        'setdefaults'        => 1,
                   6896:                        'settable'           => 1,
                   6897:                        'parameterchangelog' => 1,
                   6898:                        'cleanparameters'    => 1,
                   6899:                        'dateshift1'         => 1,
                   6900:                        'dateshift2'         => 1,
                   6901:                        'helper'             => 1,
                   6902:          );
                   6903:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   6904:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   6905:                   $env{'request.course.sec'}))) {
                   6906:         %permission = (
                   6907:                        'set'                => 1,
                   6908:                        'settable'           => 1,
                   6909:                        'newoverview'        => 1,
                   6910:                        'setoverview'        => 1,
                   6911:                        'parameterchangelog' => 1,
                   6912:                       );
                   6913:     }
                   6914:     foreach my $perm (values(%permission)) {
                   6915:         if ($perm) { $allowed=1; last; }
                   6916:     }
                   6917:     return (\%permission,$allowed);
                   6918: }
                   6919: 
1.560     damieng  6920: ##################################################
                   6921: # HANDLER
                   6922: ##################################################
                   6923: 
                   6924: # Main handler for lonparmset.
                   6925: # Sub called based on request parameters action and command:
                   6926: # no command or action: print_main_menu
                   6927: # command 'set': assessparms (direct access to table mode for a resource)
                   6928: #                (this can also be accessed simply with the symb parameter)
                   6929: # action 'setoverview': overview (display all existing parameter settings)
                   6930: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   6931: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   6932: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   6933: # action 'newoverview': newoverview (overview mode)
                   6934: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   6935: # action 'settable': assessparms (table mode)
                   6936: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   6937: #                              blog postings, user notification changes)
                   6938: # action 'cleanparameters': clean_parameters (unused)
                   6939: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   6940: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      6941: sub handler {
1.43      albertel 6942:     my $r=shift;
1.30      www      6943: 
1.376     albertel 6944:     &reset_caches();
                   6945: 
1.414     droeschl 6946:     &Apache::loncommon::content_type($r,'text/html');
                   6947:     $r->send_http_header;
                   6948:     return OK if $r->header_only;
                   6949: 
1.193     albertel 6950:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 6951:                         ['action','state',
1.205     www      6952:                                              'pres_marker',
                   6953:                                              'pres_value',
1.206     www      6954:                                              'pres_type',
1.506     www      6955:                                              'filter','part',
1.390     www      6956:                                              'udom','uname','symb','serial','timebase']);
1.131     www      6957: 
1.83      bowersj2 6958: 
1.193     albertel 6959:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 6960:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      6961:                         text=>"Content and Problem Settings",
1.473     amueller 6962:                         faq=>10,
                   6963:                         bug=>'Instructor Interface',
1.442     droeschl 6964:                                             help =>
                   6965:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      6966: 
1.30      www      6967: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  6968:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 6969:     my $exists = &check_for_course_info();
                   6970: 
1.568     raeburn  6971:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 6972:         #
                   6973:         # Main switch on form.action and form.state, as appropriate
                   6974:         #
                   6975:         # Check first if coming from someone else headed directly for
                   6976:         #  the table mode
1.568     raeburn  6977:         if (($parm_permission->{'set'}) && 
                   6978:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   6979:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   6980:             &assessparms($r,$parm_permission);
1.193     albertel 6981:         } elsif (! exists($env{'form.action'})) {
                   6982:             &print_main_menu($r,$parm_permission);
1.568     raeburn  6983:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   6984:             &print_main_menu($r,$parm_permission);
1.414     droeschl 6985:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  6986:             &overview($r,$parm_permission);
1.560     damieng  6987:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   6988:             &addmetafield($r);
                   6989:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   6990:             &order_meta_fields($r);
1.414     droeschl 6991:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  6992:             &setrestrictmeta($r);
1.414     droeschl 6993:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  6994:             &newoverview($r,$parm_permission);
1.414     droeschl 6995:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  6996:             &defaultsetter($r);
                   6997:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  6998:             &assessparms($r,$parm_permission);
1.414     droeschl 6999:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7000:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7001:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7002:             &clean_parameters($r);
1.414     droeschl 7003:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7004:             &date_shift_one($r);
1.414     droeschl 7005:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7006:             &date_shift_two($r);
1.446     bisitz   7007:         }
1.43      albertel 7008:     } else {
1.1       www      7009: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7010:         if ($exists) {
                   7011:             $env{'user.error.msg'}=
                   7012:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7013:         } else {
                   7014:             $env{'user.error.msg'}=
                   7015:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7016:         }
                   7017:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7018:     }
1.376     albertel 7019:     &reset_caches();
                   7020: 
1.43      albertel 7021:     return OK;
1.1       www      7022: }
                   7023: 
                   7024: 1;
                   7025: __END__
                   7026: 
                   7027: 

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